private void valueChanged(boolean fireEvent) {
    valueText.setText(valueOf(current));
    valueText.setCursorPosition(valueText.getText().length());

    if (fireEvent) {
      for (NumberSelectorListener listener : listeners) listener.changed(current);
    }
  }
  private void addTextFieldListeners() {
    valueText.addListener(
        new ChangeListener() {
          @Override
          public void changed(ChangeEvent event, Actor actor) {
            textChanged();
          }
        });

    valueText.addListener(
        new FocusListener() {
          @Override
          public void keyboardFocusChanged(FocusEvent event, Actor actor, boolean focused) {
            if (focused == false) {
              valueChanged(true);
              getStage().setScrollFocus(null);
            }
          }
        });

    valueText.addListener(
        new InputListener() {
          @Override
          public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
            getStage().setScrollFocus(valueText);
            return true;
          }

          @Override
          public boolean scrolled(InputEvent event, float x, float y, int amount) {
            if (amount == 1) decrement(true);
            else increment(true);

            return true;
          }

          @Override
          public boolean keyDown(InputEvent event, int keycode) {
            if (keycode == Keys.ENTER) {
              valueChanged(true);
              return true;
            }

            return false;
          }
        });
  }
  /**
   * Creates integer or float number selector depending on precision, see {@link #setPrecision(int)}
   *
   * @param name may be null
   */
  public NumberSelector(
      NumberSelectorStyle style,
      final Sizes sizes,
      String name,
      float initialValue,
      float min,
      float max,
      float step,
      int precision) {
    this.current = initialValue;
    this.max = max;
    this.min = min;
    this.step = step;

    valueText =
        new VisValidatableTextField() {
          @Override
          public float getPrefWidth() {
            return sizes.numberSelectorFieldSize;
          }
        };

    valueText.setProgrammaticChangeEvents(false);
    setPrecision(precision);
    valueText.setText(valueOf(current));

    VisTable buttonsTable = new VisTable();
    VisImageButton upButton = new VisImageButton(style.up);
    VisImageButton downButton = new VisImageButton(style.down);

    buttonsTable.add(upButton).height(sizes.numberSelectorButtonSize).row();
    buttonsTable.add(downButton).height(sizes.numberSelectorButtonSize);

    labelCell = add(new VisLabel(""));
    setSelectorName(name);

    add(valueText).fillX().expandX().height(sizes.numberSelectorButtonSize * 2).padRight(1);
    add(buttonsTable).width(sizes.numberSelectorButtonsWidth);

    addButtonsListeners(upButton, downButton);
    addTextFieldListeners();
  }
  /**
   * Sets precision of this selector. Precision defines how many digits after decimal point can be
   * entered. By default this is set to 0, meaning that only integers are allowed. Setting precision
   * to 1 would allow 0.0, precision = 2 would allow 0.00 and etc.
   */
  public void setPrecision(final int precision) {
    if (precision < 0) throw new IllegalStateException("Precision can't be < 0");
    this.precision = precision;

    valueText.getValidators().clear();
    valueText.addValidator(boundsValidator); // Both need the bounds check
    if (precision == 0) {
      valueText.addValidator(Validators.INTEGERS);
      valueText.setTextFieldFilter(new DigitsOnlyFilter());
    } else {
      valueText.addValidator(Validators.FLOATS);
      valueText.addValidator(
          new InputValidator() {
            @Override
            public boolean validateInput(String input) {
              int dotIndex = input.indexOf('.');
              if (dotIndex == -1) return true;
              return input.length() - input.indexOf('.') - 1 <= precision;
            }
          });
      valueText.setTextFieldFilter(new FloatDigitsOnlyFilter(true));
    }
  }
 private void textChanged() {
   if (valueText.getText().equals("")) current = min;
   else if (checkInputBounds(valueText.getText())) current = Float.parseFloat(valueText.getText());
 }