modules/controls/src/main/java/javafx/scene/control/skin/ScrollBarSkin.java

Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization

*** 21,56 **** * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ ! package com.sun.javafx.scene.control.skin; import javafx.geometry.Orientation; import javafx.geometry.Point2D; import javafx.scene.AccessibleAction; import javafx.scene.AccessibleAttribute; import javafx.scene.AccessibleRole; import javafx.scene.control.ScrollBar; import javafx.scene.input.MouseButton; import javafx.scene.input.ScrollEvent; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import javafx.scene.Node; import com.sun.javafx.util.Utils; import com.sun.javafx.scene.control.behavior.ScrollBarBehavior; ! public class ScrollBarSkin extends BehaviorSkinBase<ScrollBar, ScrollBarBehavior> { /*************************************************************************** * * ! * UI Subcomponents * * * **************************************************************************/ ! public final static int DEFAULT_LENGTH = 100; ! public final static int DEFAULT_WIDTH = 20; private StackPane thumb; private StackPane trackBackground; private StackPane track; private EndButton incButton; --- 21,70 ---- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ ! package javafx.scene.control.skin; + import com.sun.javafx.scene.control.Properties; + import com.sun.javafx.scene.control.behavior.BehaviorBase; + import javafx.beans.value.ObservableValue; import javafx.geometry.Orientation; import javafx.geometry.Point2D; import javafx.scene.AccessibleAction; import javafx.scene.AccessibleAttribute; import javafx.scene.AccessibleRole; + import javafx.scene.control.Accordion; + import javafx.scene.control.Button; + import javafx.scene.control.Control; import javafx.scene.control.ScrollBar; + import javafx.scene.control.SkinBase; import javafx.scene.input.MouseButton; import javafx.scene.input.ScrollEvent; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import javafx.scene.Node; import com.sun.javafx.util.Utils; import com.sun.javafx.scene.control.behavior.ScrollBarBehavior; ! import java.util.function.Consumer; ! ! /** ! * Default skin implementation for the {@link ScrollBar} control. ! * ! * @see ScrollBar ! * @since 9 ! */ ! public class ScrollBarSkin extends SkinBase<ScrollBar> { /*************************************************************************** * * ! * Private fields * * * **************************************************************************/ ! private final ScrollBarBehavior behavior; private StackPane thumb; private StackPane trackBackground; private StackPane track; private EndButton incButton;
*** 62,89 **** private double preDragThumbPos; private Point2D dragStart; // in the track's coord system private double trackPos; /*************************************************************************** * * * Constructors * * * **************************************************************************/ ! public ScrollBarSkin(ScrollBar scrollbar) { ! super(scrollbar, new ScrollBarBehavior(scrollbar)); initialize(); getSkinnable().requestLayout(); // Register listeners ! registerChangeListener(scrollbar.minProperty(), "MIN"); ! registerChangeListener(scrollbar.maxProperty(), "MAX"); ! registerChangeListener(scrollbar.valueProperty(), "VALUE"); ! registerChangeListener(scrollbar.orientationProperty(), "ORIENTATION"); ! registerChangeListener(scrollbar.visibleAmountProperty(), "VISIBLE_AMOUNT"); } /** * Initializes the ScrollBarSkin. Creates the scene and sets up all the * bindings for the group. */ private void initialize() { --- 76,321 ---- private double preDragThumbPos; private Point2D dragStart; // in the track's coord system private double trackPos; + + /*************************************************************************** * * * Constructors * * * **************************************************************************/ ! /** ! * Creates a new ScrollBarSkin instance, installing the necessary child ! * nodes into the Control {@link Control#getChildren() children} list, as ! * well as the necessary input mappings for handling key, mouse, etc events. ! * ! * @param control The control that this skin should be installed onto. ! */ ! public ScrollBarSkin(ScrollBar control) { ! super(control); ! ! // install default input map for the ScrollBar control ! this.behavior = new ScrollBarBehavior(control); ! // control.setInputMap(behavior.getInputMap()); ! initialize(); getSkinnable().requestLayout(); + // Register listeners ! final Consumer<ObservableValue<?>> consumer = e -> { ! positionThumb(); ! getSkinnable().requestLayout(); ! }; ! registerChangeListener(control.minProperty(), consumer); ! registerChangeListener(control.maxProperty(), consumer); ! registerChangeListener(control.visibleAmountProperty(), consumer); ! registerChangeListener(control.valueProperty(), e -> positionThumb()); ! registerChangeListener(control.orientationProperty(), e -> getSkinnable().requestLayout()); ! } ! ! ! ! /*************************************************************************** ! * * ! * Public API * ! * * ! **************************************************************************/ ! ! /** {@inheritDoc} */ ! @Override public void dispose() { ! super.dispose(); ! ! if (behavior != null) { ! behavior.dispose(); ! } ! } ! ! /** {@inheritDoc} */ ! @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 (!Properties.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 (!Properties.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 (!Properties.IS_TOUCH_SUPPORTED) { + incButton.setVisible(true); + decButton.setVisible(true); + } + } + else { + trackBackground.setVisible(false); + track.setVisible(false); + thumb.setVisible(false); + + if (!Properties.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); + } + } + } + } + + /* + * Minimum length is the length of the end buttons plus twice the + * minimum thumb length, which should be enough for a reasonably-sized + * track. Minimum breadth is determined by the breadths of the + * end buttons. + */ + /** {@inheritDoc} */ + @Override protected double computeMinWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { + if (getSkinnable().getOrientation() == Orientation.VERTICAL) { + return getBreadth(); + } else { + if (!Properties.IS_TOUCH_SUPPORTED) { + return decButton.minWidth(-1) + incButton.minWidth(-1) + minTrackLength()+leftInset+rightInset; + } else { + return minTrackLength()+leftInset+rightInset; + } + } + } + + /** {@inheritDoc} */ + @Override protected double computeMinHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) { + if (getSkinnable().getOrientation() == Orientation.VERTICAL) { + if (!Properties.IS_TOUCH_SUPPORTED) { + return decButton.minHeight(-1) + incButton.minHeight(-1) + minTrackLength()+topInset+bottomInset; + } else { + return minTrackLength()+topInset+bottomInset; + } + } else { + return getBreadth(); + } + } + + /* + * Preferred size. The breadth is determined by the breadth of + * the end buttons. The length is a constant default length. + * Usually applications or other components will either set a + * specific length using LayoutInfo or will stretch the length + * of the scrollbar to fit a container. + */ + /** {@inheritDoc} */ + @Override protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { + final ScrollBar s = getSkinnable(); + return s.getOrientation() == Orientation.VERTICAL ? getBreadth() : Properties.DEFAULT_LENGTH+leftInset+rightInset; + } + + /** {@inheritDoc} */ + @Override protected double computePrefHeight(double height, double topInset, double rightInset, double bottomInset, double leftInset) { + final ScrollBar s = getSkinnable(); + return s.getOrientation() == Orientation.VERTICAL ? Properties.DEFAULT_LENGTH+topInset+bottomInset : getBreadth(); + } + + /** {@inheritDoc} */ + @Override protected double computeMaxWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { + final ScrollBar s = getSkinnable(); + return s.getOrientation() == Orientation.VERTICAL ? s.prefWidth(-1) : Double.MAX_VALUE; + } + + /** {@inheritDoc} */ + @Override protected double computeMaxHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) { + final ScrollBar s = getSkinnable(); + return s.getOrientation() == Orientation.VERTICAL ? Double.MAX_VALUE : s.prefHeight(-1); + } + + + + /*************************************************************************** + * * + * Private implementation * + * * + **************************************************************************/ + /** * Initializes the ScrollBarSkin. Creates the scene and sets up all the * bindings for the group. */ private void initialize() {
*** 105,115 **** }; thumb.getStyleClass().setAll("thumb"); thumb.setAccessibleRole(AccessibleRole.THUMB); ! if (!IS_TOUCH_SUPPORTED) { incButton = new EndButton("increment-button", "increment-arrow") { @Override public void executeAccessibleAction(AccessibleAction action, Object... parameters) { switch (action) { --- 337,347 ---- }; thumb.getStyleClass().setAll("thumb"); thumb.setAccessibleRole(AccessibleRole.THUMB); ! if (!Properties.IS_TOUCH_SUPPORTED) { incButton = new EndButton("increment-button", "increment-arrow") { @Override public void executeAccessibleAction(AccessibleAction action, Object... parameters) { switch (action) {
*** 124,143 **** incButton.setOnMousePressed(me -> { /* ** if the tracklenght isn't greater than do nothing.... */ if (!thumb.isVisible() || trackLength > thumbLength) { ! getBehavior().incButtonPressed(); } me.consume(); }); incButton.setOnMouseReleased(me -> { /* ** if the tracklenght isn't greater than do nothing.... */ if (!thumb.isVisible() || trackLength > thumbLength) { ! getBehavior().incButtonReleased(); } me.consume(); }); decButton = new EndButton("decrement-button", "decrement-arrow") { --- 356,375 ---- incButton.setOnMousePressed(me -> { /* ** if the tracklenght isn't greater than do nothing.... */ if (!thumb.isVisible() || trackLength > thumbLength) { ! behavior.incButtonPressed(); } me.consume(); }); incButton.setOnMouseReleased(me -> { /* ** if the tracklenght isn't greater than do nothing.... */ if (!thumb.isVisible() || trackLength > thumbLength) { ! behavior.incButtonReleased(); } me.consume(); }); decButton = new EndButton("decrement-button", "decrement-arrow") {
*** 155,198 **** decButton.setOnMousePressed(me -> { /* ** if the tracklenght isn't greater than do nothing.... */ if (!thumb.isVisible() || trackLength > thumbLength) { ! getBehavior().decButtonPressed(); } me.consume(); }); decButton.setOnMouseReleased(me -> { /* ** if the tracklenght isn't greater than do nothing.... */ if (!thumb.isVisible() || trackLength > thumbLength) { ! getBehavior().decButtonReleased(); } me.consume(); }); } track.setOnMousePressed(me -> { if (!thumb.isPressed() && me.getButton() == MouseButton.PRIMARY) { if (getSkinnable().getOrientation() == Orientation.VERTICAL) { if (trackLength != 0) { ! getBehavior().trackPress(me.getY() / trackLength); me.consume(); } } else { if (trackLength != 0) { ! getBehavior().trackPress(me.getX() / trackLength); me.consume(); } } } }); track.setOnMouseReleased(me -> { ! getBehavior().trackRelease(); me.consume(); }); thumb.setOnMousePressed(me -> { if (me.isSynthesized()) { --- 387,430 ---- decButton.setOnMousePressed(me -> { /* ** if the tracklenght isn't greater than do nothing.... */ if (!thumb.isVisible() || trackLength > thumbLength) { ! behavior.decButtonPressed(); } me.consume(); }); decButton.setOnMouseReleased(me -> { /* ** if the tracklenght isn't greater than do nothing.... */ if (!thumb.isVisible() || trackLength > thumbLength) { ! behavior.decButtonReleased(); } me.consume(); }); } track.setOnMousePressed(me -> { if (!thumb.isPressed() && me.getButton() == MouseButton.PRIMARY) { if (getSkinnable().getOrientation() == Orientation.VERTICAL) { if (trackLength != 0) { ! behavior.trackPress(me.getY() / trackLength); me.consume(); } } else { if (trackLength != 0) { ! behavior.trackPress(me.getX() / trackLength); me.consume(); } } } }); track.setOnMouseReleased(me -> { ! behavior.trackRelease(); me.consume(); }); thumb.setOnMousePressed(me -> { if (me.isSynthesized()) {
*** 230,240 **** if (dragStart == null) { // we're getting dragged without getting a mouse press dragStart = thumb.localToParent(me.getX(), me.getY()); } double dragPos = getSkinnable().getOrientation() == Orientation.VERTICAL ? cur.getY() - dragStart.getY(): cur.getX() - dragStart.getX(); ! getBehavior().thumbDragged(preDragThumbPos + dragPos / (trackLength - thumbLength)); } me.consume(); } }); --- 462,472 ---- if (dragStart == null) { // we're getting dragged without getting a mouse press dragStart = thumb.localToParent(me.getX(), me.getY()); } double dragPos = getSkinnable().getOrientation() == Orientation.VERTICAL ? cur.getY() - dragStart.getY(): cur.getX() - dragStart.getX(); ! behavior.thumbDragged(preDragThumbPos + dragPos / (trackLength - thumbLength)); } me.consume(); } });
*** 267,277 **** if (dragStart == null) { // we're getting dragged without getting a mouse press dragStart = thumb.localToParent(event.getX(), event.getY()); } double dragPos = getSkinnable().getOrientation() == Orientation.VERTICAL ? cur.getY() - dragStart.getY(): cur.getX() - dragStart.getX(); ! getBehavior().thumbDragged(/*todo*/ preDragThumbPos + dragPos / (trackLength - thumbLength)); } event.consume(); return; } --- 499,509 ---- if (dragStart == null) { // we're getting dragged without getting a mouse press dragStart = thumb.localToParent(event.getX(), event.getY()); } double dragPos = getSkinnable().getOrientation() == Orientation.VERTICAL ? cur.getY() - dragStart.getY(): cur.getX() - dragStart.getX(); ! behavior.thumbDragged(/*todo*/ preDragThumbPos + dragPos / (trackLength - thumbLength)); } event.consume(); return; }
*** 308,318 **** * TODO: this fix causes RT-23406 ([ScrollBar, touch] Dragging scrollbar from the * track on touchscreen causes flickering) */ if (event.isDirect()) { if (trackLength > thumbLength) { ! getBehavior().thumbDragged((getSkinnable().getOrientation() == Orientation.VERTICAL ? event.getY(): event.getX()) / trackLength); event.consume(); } } else { if (delta > 0.0 && sb.getValue() > sb.getMin()) { --- 540,550 ---- * TODO: this fix causes RT-23406 ([ScrollBar, touch] Dragging scrollbar from the * track on touchscreen causes flickering) */ if (event.isDirect()) { if (trackLength > thumbLength) { ! behavior.thumbDragged((getSkinnable().getOrientation() == Orientation.VERTICAL ? event.getY() : event.getX()) / trackLength); event.consume(); } } else { if (delta > 0.0 && sb.getValue() > sb.getMin()) {
*** 325,384 **** } } }); getChildren().clear(); ! if (!IS_TOUCH_SUPPORTED) { getChildren().addAll(trackBackground, incButton, decButton, track, thumb); } else { getChildren().addAll(track, thumb); } } - - @Override protected void handleControlPropertyChanged(String p) { - super.handleControlPropertyChanged(p); - if ("ORIENTATION".equals(p)) { - getSkinnable().requestLayout(); - } else if ("MIN".equals(p) || "MAX".equals(p) || "VISIBLE_AMOUNT".equals(p)) { - positionThumb(); - getSkinnable().requestLayout(); - } else if ("VALUE".equals(p)) { - positionThumb(); - } - } - - /*************************************************************************** - * * - * Layout * - * * - **************************************************************************/ - - private static final double DEFAULT_EMBEDDED_SB_BREADTH = 8.0; - /* * 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(); } } } double minThumbLength() { --- 557,595 ---- } } }); getChildren().clear(); ! if (!Properties.IS_TOUCH_SUPPORTED) { getChildren().addAll(trackBackground, incButton, decButton, track, thumb); } else { getChildren().addAll(track, thumb); } } /* * 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 (!Properties.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(Properties.DEFAULT_EMBEDDED_SB_BREADTH, Properties.DEFAULT_EMBEDDED_SB_BREADTH)+snappedLeftInset()+snappedRightInset(); } else { ! return Math.max(Properties.DEFAULT_EMBEDDED_SB_BREADTH, Properties.DEFAULT_EMBEDDED_SB_BREADTH)+snappedTopInset()+snappedBottomInset(); } } } double minThumbLength() {
*** 387,462 **** double minTrackLength() { return 2.0f * getBreadth(); } - /* - * Minimum length is the length of the end buttons plus twice the - * minimum thumb length, which should be enough for a reasonably-sized - * track. Minimum breadth is determined by the breadths of the - * end buttons. - */ - @Override protected double computeMinWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { - if (getSkinnable().getOrientation() == Orientation.VERTICAL) { - return getBreadth(); - } else { - if (!IS_TOUCH_SUPPORTED) { - return decButton.minWidth(-1) + incButton.minWidth(-1) + minTrackLength()+leftInset+rightInset; - } else { - return minTrackLength()+leftInset+rightInset; - } - } - } - - @Override protected double computeMinHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) { - if (getSkinnable().getOrientation() == Orientation.VERTICAL) { - if (!IS_TOUCH_SUPPORTED) { - return decButton.minHeight(-1) + incButton.minHeight(-1) + minTrackLength()+topInset+bottomInset; - } else { - return minTrackLength()+topInset+bottomInset; - } - } else { - return getBreadth(); - } - } - - /* - * Preferred size. The breadth is determined by the breadth of - * the end buttons. The length is a constant default length. - * Usually applications or other components will either set a - * specific length using LayoutInfo or will stretch the length - * of the scrollbar to fit a container. - */ - @Override protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { - final ScrollBar s = getSkinnable(); - return s.getOrientation() == Orientation.VERTICAL ? getBreadth() : DEFAULT_LENGTH+leftInset+rightInset; - } - - @Override protected double computePrefHeight(double height, double topInset, double rightInset, double bottomInset, double leftInset) { - final ScrollBar s = getSkinnable(); - return s.getOrientation() == Orientation.VERTICAL ? DEFAULT_LENGTH+topInset+bottomInset : getBreadth(); - } - - @Override protected double computeMaxWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { - final ScrollBar s = getSkinnable(); - return s.getOrientation() == Orientation.VERTICAL ? s.prefWidth(-1) : Double.MAX_VALUE; - } - - @Override protected double computeMaxHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) { - final ScrollBar s = getSkinnable(); - return s.getOrientation() == Orientation.VERTICAL ? Double.MAX_VALUE : s.prefHeight(-1); - } - /** * 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); } --- 598,616 ---- double minTrackLength() { return 2.0f * getBreadth(); } /** * 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 (!Properties.IS_TOUCH_SUPPORTED) { if (s.getOrientation() == Orientation.VERTICAL) { trackPos += decButton.prefHeight(-1); } else { trackPos += decButton.prefWidth(-1); }
*** 464,600 **** thumb.setTranslateX( snapPosition(s.getOrientation() == Orientation.VERTICAL ? snappedLeftInset() : trackPos + snappedLeftInset())); thumb.setTranslateY( snapPosition(s.getOrientation() == Orientation.VERTICAL ? trackPos + snappedTopInset() : snappedTopInset())); } ! @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); ! } ! } ! } ! } ! ! ! public Node getThumb() { return thumb; } ! public Node getTrack() { return track; } ! public Node getIncButton() { return incButton; } ! public Node getDecButton() { return decButton; } private static class EndButton extends Region { private Region arrow; private EndButton(String styleClass, String arrowStyleClass) { getStyleClass().setAll(styleClass); --- 618,651 ---- thumb.setTranslateX( snapPosition(s.getOrientation() == Orientation.VERTICAL ? snappedLeftInset() : trackPos + snappedLeftInset())); thumb.setTranslateY( snapPosition(s.getOrientation() == Orientation.VERTICAL ? trackPos + snappedTopInset() : snappedTopInset())); } ! private Node getThumb() { return thumb; } ! private Node getTrack() { return track; } ! private Node getIncrementButton() { return incButton; } ! private Node getDecrementButton() { return decButton; } + + + /*************************************************************************** + * * + * Support classes * + * * + **************************************************************************/ + private static class EndButton extends Region { private Region arrow; private EndButton(String styleClass, String arrowStyleClass) { getStyleClass().setAll(styleClass);