void (int initValue, int targetValue, @NotNull Consumer<? super Integer> consumer, @Nullable Predicate<? super Integer> shouldStop, @NotNull AnimationSettings settings) { mySettings = settings; double duration = mySettings.getDuration(); if (duration == 0) { consumer.accept(targetValue); stop(); return; } boolean isSameDirection = (myTargetValue - myInitValue) * (targetValue - initValue) > 0; if (isSameDirection && myTimer.isRunning(animationId)) { myTargetValue += (targetValue - initValue); myDuration = (long)duration + max(myLastEventTime - myStartEventTime, 0); myInitValue = myCurrentValue; myStartEventTime = myLastEventTime; } else { myTargetValue = targetValue; myDuration = (long)duration; myInitValue = initValue; myStartEventTime = System.currentTimeMillis(); } myConsumer = Objects.requireNonNull(consumer); myShouldStop = shouldStop == null ? FALSE_PREDICATE : shouldStop; myCurrentValue = initValue; if (!myTimer.isRunning(animationId)) { animationId = myTimer.animate( new Animation(this::run) .setDuration(Integer.MAX_VALUE) // will not end without calling #stop() .setEasing(com.intellij.util.animation.Easing.LINEAR) ); } }