public final void start(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)
        );
      }
    }
public final void start(int initValue, int targetValue,
                            @NotNull Consumer<? super Integer> consumer,
                            @Nullable Predicate<? super Integer> shouldStop,
                            @NotNull AnimationSettings settings)