/**
   * Gets the scale factor that allows us to translate pixel values to scroll bar values and vice
   * versa. This assumes that the range of pixels spans from the last pixel of
   * <tt>scrollUpButton</tt> to the first pixel of <tt>scrollDownButton</tt> and excludes the pixels
   * taken up by <tt>handle</tt>.
   *
   * <p>To map from scroll bar values (<i>real values</i>) to pixel values, you multiply by the
   * value scale. To map from pixel values back to real values, you divide by the value scale.
   *
   * @return <tt>&lt;number of legal pixel values&gt; / &lt;number of legal real values&gt;</tt>
   */
  private float getValueScale() {
    ScrollBar scrollBar = (ScrollBar) getComponent();

    float valueScale;

    int start = scrollBar.getStart();
    int end = scrollBar.getEnd();
    int extent = scrollBar.getExtent();
    int maxLegalRealValue = end - extent;

    int numLegalRealValues = maxLegalRealValue - start + 1;
    int numLegalPixelValues;

    if (scrollBar.getOrientation() == Orientation.HORIZONTAL) {
      int availableWidth = getWidth() - scrollUpButton.getWidth() - scrollDownButton.getWidth() + 2;
      numLegalPixelValues = availableWidth - handle.getWidth() + 1;
    } else {
      int availableHeight =
          getHeight() - scrollUpButton.getHeight() - scrollDownButton.getHeight() + 2;
      numLegalPixelValues = availableHeight - handle.getHeight() + 1;
    }

    // the number of segments is one less than the number of values
    valueScale = numLegalPixelValues / ((float) numLegalRealValues - 1);

    return valueScale;
  }
    private void scroll() {
      ScrollBar scrollBar = (ScrollBar) TerraScrollBarSkin.this.getComponent();

      int start = scrollBar.getStart();
      int end = scrollBar.getEnd();
      int extent = scrollBar.getExtent();
      int value = scrollBar.getValue();

      int adjustment;

      if (incrementType == Mouse.ScrollType.UNIT) {
        adjustment = direction * scrollBar.getUnitIncrement();
      } else {
        adjustment = direction * scrollBar.getBlockIncrement();
      }

      if (adjustment < 0) {
        int newValue = Math.max(value + adjustment, start);
        scrollBar.setValue(newValue);

        if (stopValue != -1 && newValue < stopValue) {
          // We've reached the explicit stop value
          stop();
        }

        if (newValue == start) {
          // We implicit stop at the minimum scroll bar value
          stop();
        }
      } else {
        int newValue = Math.min(value + adjustment, end - extent);
        scrollBar.setValue(newValue);

        if (stopValue != -1 && newValue > stopValue) {
          // We've reached the explicit stop value
          stop();
        }

        if (newValue == end - extent) {
          // We implicitly stop at the maximum scroll bar value
          stop();
        }
      }
    }
  @Override
  public void layout() {
    ScrollBar scrollBar = (ScrollBar) getComponent();

    int width = getWidth();
    int height = getHeight();

    int start = scrollBar.getStart();
    int end = scrollBar.getEnd();
    int extent = scrollBar.getExtent();
    int value = scrollBar.getValue();

    int maxLegalRealValue = end - extent;
    int numLegalRealValues = maxLegalRealValue - start + 1;
    float extentPercentage = (float) extent / (float) (end - start);

    if (scrollBar.getOrientation() == Orientation.HORIZONTAL) {
      scrollUpButton.setSize(scrollUpButton.getPreferredWidth(-1), height);
      scrollUpButton.setLocation(0, 0);

      scrollDownButton.setSize(scrollDownButton.getPreferredWidth(-1), height);
      scrollDownButton.setLocation(width - scrollDownButton.getWidth(), 0);

      if (scrollBar.isEnabled()) {
        // Calculate the handle width first, as it dictates how much
        // room is left to represent the range of legal values. Note
        // that the handle may overlap each scroll button by 1px so
        // that its borders merge into the borders of the scroll buttons
        int availableWidth = width - scrollUpButton.getWidth() - scrollDownButton.getWidth() + 2;
        int handleWidth =
            Math.max(minimumHandleLength, Math.round(extentPercentage * availableWidth));

        // Calculate the position of the handle by calculating the
        // scale that maps logical value to pixel value
        int numLegalPixelValues = availableWidth - handleWidth + 1;
        float valueScale = (float) numLegalPixelValues / (float) numLegalRealValues;
        int handleX = (int) (value * valueScale) + scrollUpButton.getWidth() - 1;

        if (handleWidth > availableWidth) {
          // If we can't fit the handle, we hide it
          handle.setVisible(false);
        } else {
          handle.setVisible(true);

          handle.setSize(handleWidth, height);
          handle.setLocation(handleX, 0);
        }
      } else {
        handle.setVisible(false);
      }
    } else {
      scrollUpButton.setSize(width, scrollUpButton.getPreferredHeight(-1));
      scrollUpButton.setLocation(0, 0);

      scrollDownButton.setSize(width, scrollDownButton.getPreferredHeight(-1));
      scrollDownButton.setLocation(0, height - scrollDownButton.getHeight());

      if (scrollBar.isEnabled()) {
        // Calculate the handle height first, as it dictates how much
        // room is left to represent the range of legal values. Note
        // that the handle may overlap each scroll button by 1px so
        // that its borders merge into the borders of the scroll buttons
        int availableHeight =
            height - scrollUpButton.getHeight() - scrollDownButton.getHeight() + 2;
        int handleHeight =
            Math.max(minimumHandleLength, Math.round(extentPercentage * availableHeight));

        // Calculate the position of the handle by calculating the
        // scale maps logical value to pixel value
        int numLegalPixelValues = availableHeight - handleHeight + 1;
        float valueScale = (float) numLegalPixelValues / (float) numLegalRealValues;
        int handleY = (int) (value * valueScale) + scrollUpButton.getHeight() - 1;

        if (handleHeight > availableHeight) {
          // If we can't fit the handle, we hide it
          handle.setVisible(false);
        } else {
          handle.setVisible(true);

          handle.setSize(width, handleHeight);
          handle.setLocation(0, handleY);
        }
      } else {
        handle.setVisible(false);
      }
    }
  }