/** Called when ever either min, max or value changes, so thumb's layoutX, Y is recomputed. */
  void positionThumb() {
    ScrollBar s = getSkinnable();
    double clampedValue = Utils.clamp(s.getMin(), s.getValue(), s.getMax());
    trackPos =
        (s.getMax() - s.getMin() > 0)
            ? ((trackLength - thumbLength)
                * (clampedValue - s.getMin())
                / (s.getMax() - s.getMin()))
            : (0.0F);

    if (!IS_TOUCH_SUPPORTED) {
      if (s.getOrientation() == Orientation.VERTICAL) {
        trackPos += decButton.prefHeight(-1);
      } else {
        trackPos += decButton.prefWidth(-1);
      }
    }

    thumb.setTranslateX(
        snapPosition(
            s.getOrientation() == Orientation.VERTICAL
                ? snappedLeftInset()
                : trackPos + snappedLeftInset()));
    thumb.setTranslateY(
        snapPosition(
            s.getOrientation() == Orientation.VERTICAL
                ? trackPos + snappedTopInset()
                : snappedTopInset()));
  }
 /*
  * Gets the breadth of the scrollbar. The "breadth" is the distance
  * across the scrollbar, i.e. if vertical the width, otherwise the height.
  * On desktop this is determined by the greater of the breadths of the end-buttons.
  * Embedded doesn't have end-buttons, so currently we use a default breadth.
  * We should change this when we get width/height css properties.
  */
 double getBreadth() {
   if (!IS_TOUCH_SUPPORTED) {
     if (getSkinnable().getOrientation() == Orientation.VERTICAL) {
       return Math.max(decButton.prefWidth(-1), incButton.prefWidth(-1))
           + snappedLeftInset()
           + snappedRightInset();
     } else {
       return Math.max(decButton.prefHeight(-1), incButton.prefHeight(-1))
           + snappedTopInset()
           + snappedBottomInset();
     }
   } else {
     if (getSkinnable().getOrientation() == Orientation.VERTICAL) {
       return Math.max(DEFAULT_EMBEDDED_SB_BREADTH, DEFAULT_EMBEDDED_SB_BREADTH)
           + snappedLeftInset()
           + snappedRightInset();
     } else {
       return Math.max(DEFAULT_EMBEDDED_SB_BREADTH, DEFAULT_EMBEDDED_SB_BREADTH)
           + snappedTopInset()
           + snappedBottomInset();
     }
   }
 }
  @Override
  protected void layoutChildren(final double x, final double y, final double w, final double h) {

    final ScrollBar s = getSkinnable();

    /**
     * Compute the percentage length of thumb as (visibleAmount/range) if max isn't greater than min
     * then there is nothing to do here
     */
    double visiblePortion;
    if (s.getMax() > s.getMin()) {
      visiblePortion = s.getVisibleAmount() / (s.getMax() - s.getMin());
    } else {
      visiblePortion = 1.0;
    }

    if (s.getOrientation() == Orientation.VERTICAL) {
      if (!IS_TOUCH_SUPPORTED) {
        double decHeight = snapSize(decButton.prefHeight(-1));
        double incHeight = snapSize(incButton.prefHeight(-1));

        decButton.resize(w, decHeight);
        incButton.resize(w, incHeight);

        trackLength = snapSize(h - (decHeight + incHeight));
        thumbLength =
            snapSize(Utils.clamp(minThumbLength(), (trackLength * visiblePortion), trackLength));

        trackBackground.resizeRelocate(
            snapPosition(x), snapPosition(y), w, trackLength + decHeight + incHeight);
        decButton.relocate(snapPosition(x), snapPosition(y));
        incButton.relocate(snapPosition(x), snapPosition(y + h - incHeight));
        track.resizeRelocate(snapPosition(x), snapPosition(y + decHeight), w, trackLength);
        thumb.resize(
            snapSize(x >= 0 ? w : w + x),
            thumbLength); // Account for negative padding (see also RT-10719)
        positionThumb();
      } else {
        trackLength = snapSize(h);
        thumbLength =
            snapSize(Utils.clamp(minThumbLength(), (trackLength * visiblePortion), trackLength));

        track.resizeRelocate(snapPosition(x), snapPosition(y), w, trackLength);
        thumb.resize(
            snapSize(x >= 0 ? w : w + x),
            thumbLength); // Account for negative padding (see also RT-10719)
        positionThumb();
      }
    } else {
      if (!IS_TOUCH_SUPPORTED) {
        double decWidth = snapSize(decButton.prefWidth(-1));
        double incWidth = snapSize(incButton.prefWidth(-1));

        decButton.resize(decWidth, h);
        incButton.resize(incWidth, h);

        trackLength = snapSize(w - (decWidth + incWidth));
        thumbLength =
            snapSize(Utils.clamp(minThumbLength(), (trackLength * visiblePortion), trackLength));

        trackBackground.resizeRelocate(
            snapPosition(x), snapPosition(y), trackLength + decWidth + incWidth, h);
        decButton.relocate(snapPosition(x), snapPosition(y));
        incButton.relocate(snapPosition(x + w - incWidth), snapPosition(y));
        track.resizeRelocate(snapPosition(x + decWidth), snapPosition(y), trackLength, h);
        thumb.resize(
            thumbLength,
            snapSize(y >= 0 ? h : h + y)); // Account for negative padding (see also RT-10719)
        positionThumb();
      } else {
        trackLength = snapSize(w);
        thumbLength =
            snapSize(Utils.clamp(minThumbLength(), (trackLength * visiblePortion), trackLength));

        track.resizeRelocate(snapPosition(x), snapPosition(y), trackLength, h);
        thumb.resize(
            thumbLength,
            snapSize(y >= 0 ? h : h + y)); // Account for negative padding (see also RT-10719)
        positionThumb();
      }

      s.resize(snapSize(s.getWidth()), snapSize(s.getHeight()));
    }

    // things should be invisible only when well below minimum length
    if (s.getOrientation() == Orientation.VERTICAL
            && h
                >= (computeMinHeight(
                        -1, (int) y, snappedRightInset(), snappedBottomInset(), (int) x)
                    - (y + snappedBottomInset()))
        || s.getOrientation() == Orientation.HORIZONTAL
            && w
                >= (computeMinWidth(-1, (int) y, snappedRightInset(), snappedBottomInset(), (int) x)
                    - (x + snappedRightInset()))) {
      trackBackground.setVisible(true);
      track.setVisible(true);
      thumb.setVisible(true);
      if (!IS_TOUCH_SUPPORTED) {
        incButton.setVisible(true);
        decButton.setVisible(true);
      }
    } else {
      trackBackground.setVisible(false);
      track.setVisible(false);
      thumb.setVisible(false);

      if (!IS_TOUCH_SUPPORTED) {
        /*
         ** once the space is big enough for one button we
         ** can look at drawing
         */
        if (h >= decButton.computeMinWidth(-1)) {
          decButton.setVisible(true);
        } else {
          decButton.setVisible(false);
        }
        if (h >= incButton.computeMinWidth(-1)) {
          incButton.setVisible(true);
        } else {
          incButton.setVisible(false);
        }
      }
    }
  }