modules/controls/src/main/java/javafx/scene/control/skin/ScrollPaneSkin.java
Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization
*** 21,32 ****
* 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 com.sun.javafx.scene.traversal.ParentTraversalEngine;
import javafx.animation.Animation.Status;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
--- 21,34 ----
* 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 com.sun.javafx.scene.traversal.ParentTraversalEngine;
import javafx.animation.Animation.Status;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
*** 42,70 ****
import javafx.geometry.Bounds;
import javafx.geometry.Orientation;
import javafx.scene.AccessibleAttribute;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.input.TouchEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;
import com.sun.javafx.util.Utils;
import com.sun.javafx.scene.control.behavior.ScrollPaneBehavior;
- import com.sun.javafx.scene.traversal.TraverseListener;
import static com.sun.javafx.scene.control.skin.Utils.*;
import javafx.geometry.Insets;
! public class ScrollPaneSkin extends BehaviorSkinBase<ScrollPane, ScrollPaneBehavior> implements TraverseListener {
/***************************************************************************
* *
! * UI Subcomponents *
* *
**************************************************************************/
private static final double DEFAULT_PREF_SIZE = 100.0;
--- 44,82 ----
import javafx.geometry.Bounds;
import javafx.geometry.Orientation;
import javafx.scene.AccessibleAttribute;
import javafx.scene.Cursor;
import javafx.scene.Node;
+ import javafx.scene.control.Button;
+ import javafx.scene.control.Control;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
+ import javafx.scene.control.SkinBase;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.input.TouchEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;
import com.sun.javafx.util.Utils;
import com.sun.javafx.scene.control.behavior.ScrollPaneBehavior;
import static com.sun.javafx.scene.control.skin.Utils.*;
import javafx.geometry.Insets;
! import java.util.function.Consumer;
!
! /**
! * Default skin implementation for the {@link ScrollPane} control.
! *
! * @see ScrollPane
! * @since 9
! */
! public class ScrollPaneSkin extends SkinBase<ScrollPane> {
/***************************************************************************
* *
! * Static fields *
* *
**************************************************************************/
private static final double DEFAULT_PREF_SIZE = 100.0;
*** 73,85 ****
--- 85,106 ----
private static final double DEFAULT_SB_BREADTH = 12.0;
private static final double DEFAULT_EMBEDDED_SB_BREADTH = 8.0;
private static final double PAN_THRESHOLD = 0.5;
+
+
+ /***************************************************************************
+ * *
+ * Private fields *
+ * *
+ **************************************************************************/
+
// state from the control
private Node scrollNode;
+ private final BehaviorBase<ScrollPane> behavior;
private double nodeWidth;
private double nodeHeight;
private boolean nodeSizeInvalid = true;
*** 98,109 ****
private StackPane viewRect;
private StackPane viewContent;
private double contentWidth;
private double contentHeight;
private StackPane corner;
! protected ScrollBar hsb;
! protected ScrollBar vsb;
double pressX;
double pressY;
double ohvalue;
double ovvalue;
--- 119,130 ----
private StackPane viewRect;
private StackPane viewContent;
private double contentWidth;
private double contentHeight;
private StackPane corner;
! ScrollBar hsb;
! ScrollBar vsb;
double pressX;
double pressY;
double ohvalue;
double ovvalue;
*** 112,148 ****
private boolean touchDetected = false;
private boolean mouseDown = false;
Rectangle clipRect;
/***************************************************************************
* *
! * Constructors *
* *
**************************************************************************/
- public ScrollPaneSkin(final ScrollPane scrollpane) {
- super(scrollpane, new ScrollPaneBehavior(scrollpane));
- initialize();
- // Register listeners
- registerChangeListener(scrollpane.contentProperty(), "NODE");
- registerChangeListener(scrollpane.fitToWidthProperty(), "FIT_TO_WIDTH");
- registerChangeListener(scrollpane.fitToHeightProperty(), "FIT_TO_HEIGHT");
- registerChangeListener(scrollpane.hbarPolicyProperty(), "HBAR_POLICY");
- registerChangeListener(scrollpane.vbarPolicyProperty(), "VBAR_POLICY");
- registerChangeListener(scrollpane.hvalueProperty(), "HVALUE");
- registerChangeListener(scrollpane.hmaxProperty(), "HMAX");
- registerChangeListener(scrollpane.hminProperty(), "HMIN");
- registerChangeListener(scrollpane.vvalueProperty(), "VVALUE");
- registerChangeListener(scrollpane.vmaxProperty(), "VMAX");
- registerChangeListener(scrollpane.vminProperty(), "VMIN");
- registerChangeListener(scrollpane.prefViewportWidthProperty(), "VIEWPORT_SIZE_HINT");
- registerChangeListener(scrollpane.prefViewportHeightProperty(), "VIEWPORT_SIZE_HINT");
- registerChangeListener(scrollpane.minViewportWidthProperty(), "VIEWPORT_SIZE_HINT");
- registerChangeListener(scrollpane.minViewportHeightProperty(), "VIEWPORT_SIZE_HINT");
- }
-
private final InvalidationListener nodeListener = new InvalidationListener() {
@Override public void invalidated(Observable valueModel) {
if (!nodeSizeInvalid) {
final Bounds scrollNodeBounds = scrollNode.getLayoutBounds();
final double scrollNodeWidth = scrollNodeBounds.getWidth();
--- 133,160 ----
private boolean touchDetected = false;
private boolean mouseDown = false;
Rectangle clipRect;
+ Timeline sbTouchTimeline;
+ KeyFrame sbTouchKF1;
+ KeyFrame sbTouchKF2;
+ Timeline contentsToViewTimeline;
+ KeyFrame contentsToViewKF1;
+ KeyFrame contentsToViewKF2;
+ KeyFrame contentsToViewKF3;
+
+ private boolean tempVisibility;
+
+
+
/***************************************************************************
* *
! * Listeners *
* *
**************************************************************************/
private final InvalidationListener nodeListener = new InvalidationListener() {
@Override public void invalidated(Observable valueModel) {
if (!nodeSizeInvalid) {
final Bounds scrollNodeBounds = scrollNode.getLayoutBounds();
final double scrollNodeWidth = scrollNodeBounds.getWidth();
*** 226,258 ****
}
}
}
};
private void initialize() {
// requestLayout calls below should not trigger requestLayout above ScrollPane
// setManaged(false);
ScrollPane control = getSkinnable();
scrollNode = control.getContent();
ParentTraversalEngine traversalEngine = new ParentTraversalEngine(getSkinnable());
! traversalEngine.addTraverseListener(this);
getSkinnable().setImpl_traversalEngine(traversalEngine);
if (scrollNode != null) {
scrollNode.layoutBoundsProperty().addListener(nodeListener);
scrollNode.layoutBoundsProperty().addListener(boundsChangeListener);
}
viewRect = new StackPane() {
!
! @Override
! protected void layoutChildren() {
viewContent.resize(getWidth(), getHeight());
}
-
};
// prevent requestLayout requests from within scrollNode from percolating up
viewRect.setManaged(false);
viewRect.setCache(true);
viewRect.getStyleClass().add("viewport");
--- 238,646 ----
}
}
}
};
+
+
+ /***************************************************************************
+ * *
+ * Constructors *
+ * *
+ **************************************************************************/
+
+ /**
+ * Creates a new ScrollPaneSkin 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 ScrollPaneSkin(final ScrollPane control) {
+ super(control);
+
+ // install default input map for the ScrollPane control
+ behavior = new ScrollPaneBehavior(control);
+ // control.setInputMap(behavior.getInputMap());
+
+ initialize();
+
+ // Register listeners
+ Consumer<ObservableValue<?>> viewportSizeHintConsumer = e -> {
+ // change affects pref size, so requestLayout on control
+ getSkinnable().requestLayout();
+ };
+ registerChangeListener(control.contentProperty(), e -> {
+ if (scrollNode != getSkinnable().getContent()) {
+ if (scrollNode != null) {
+ scrollNode.layoutBoundsProperty().removeListener(nodeListener);
+ scrollNode.layoutBoundsProperty().removeListener(boundsChangeListener);
+ viewContent.getChildren().remove(scrollNode);
+ }
+ scrollNode = getSkinnable().getContent();
+ if (scrollNode != null) {
+ nodeWidth = snapSize(scrollNode.getLayoutBounds().getWidth());
+ nodeHeight = snapSize(scrollNode.getLayoutBounds().getHeight());
+ viewContent.getChildren().setAll(scrollNode);
+ scrollNode.layoutBoundsProperty().addListener(nodeListener);
+ scrollNode.layoutBoundsProperty().addListener(boundsChangeListener);
+ }
+ }
+ getSkinnable().requestLayout();
+ });
+ registerChangeListener(control.fitToWidthProperty(), e -> {
+ getSkinnable().requestLayout();
+ viewRect.requestLayout();
+ });
+ registerChangeListener(control.fitToHeightProperty(), e -> {
+ getSkinnable().requestLayout();
+ viewRect.requestLayout();
+ });
+ registerChangeListener(control.hbarPolicyProperty(), e -> {
+ // change might affect pref size, so requestLayout on control
+ getSkinnable().requestLayout();
+ });
+ registerChangeListener(control.vbarPolicyProperty(), e -> {
+ // change might affect pref size, so requestLayout on control
+ getSkinnable().requestLayout();
+ });
+ registerChangeListener(control.hvalueProperty(), e -> hsb.setValue(getSkinnable().getHvalue()));
+ registerChangeListener(control.hmaxProperty(), e -> hsb.setMax(getSkinnable().getHmax()));
+ registerChangeListener(control.hminProperty(), e -> hsb.setMin(getSkinnable().getHmin()));
+ registerChangeListener(control.vvalueProperty(), e -> vsb.setValue(getSkinnable().getVvalue()));
+ registerChangeListener(control.vmaxProperty(), e -> vsb.setMax(getSkinnable().getVmax()));
+ registerChangeListener(control.vminProperty(), e -> vsb.setMin(getSkinnable().getVmin()));
+ registerChangeListener(control.prefViewportWidthProperty(), viewportSizeHintConsumer);
+ registerChangeListener(control.prefViewportHeightProperty(), viewportSizeHintConsumer);
+ registerChangeListener(control.minViewportWidthProperty(), viewportSizeHintConsumer);
+ registerChangeListener(control.minViewportHeightProperty(), viewportSizeHintConsumer);
+ }
+
+
+
+ /***************************************************************************
+ * *
+ * Properties *
+ * *
+ **************************************************************************/
+
+ private DoubleProperty contentPosX;
+ private final void setContentPosX(double value) { contentPosXProperty().set(value); }
+ private final double getContentPosX() { return contentPosX == null ? 0.0 : contentPosX.get(); }
+ private final DoubleProperty contentPosXProperty() {
+ if (contentPosX == null) {
+ contentPosX = new DoublePropertyBase() {
+ @Override protected void invalidated() {
+ hsb.setValue(getContentPosX());
+ getSkinnable().requestLayout();
+ }
+
+ @Override
+ public Object getBean() {
+ return ScrollPaneSkin.this;
+ }
+
+ @Override
+ public String getName() {
+ return "contentPosX";
+ }
+ };
+ }
+ return contentPosX;
+ }
+
+ private DoubleProperty contentPosY;
+ private final void setContentPosY(double value) { contentPosYProperty().set(value); }
+ private final double getContentPosY() { return contentPosY == null ? 0.0 : contentPosY.get(); }
+ private final DoubleProperty contentPosYProperty() {
+ if (contentPosY == null) {
+ contentPosY = new DoublePropertyBase() {
+ @Override protected void invalidated() {
+ vsb.setValue(getContentPosY());
+ getSkinnable().requestLayout();
+ }
+
+ @Override
+ public Object getBean() {
+ return ScrollPaneSkin.this;
+ }
+
+ @Override
+ public String getName() {
+ return "contentPosY";
+ }
+ };
+ }
+ return contentPosY;
+ }
+
+
+
+ /***************************************************************************
+ * *
+ * Public API *
+ * *
+ **************************************************************************/
+
+ /** {@inheritDoc} */
+ @Override public void dispose() {
+ super.dispose();
+
+ if (behavior != null) {
+ behavior.dispose();
+ }
+ }
+
+ /**
+ * Returns the horizontal {@link ScrollBar} used in this ScrollPaneSkin
+ * instance.
+ */
+ public final ScrollBar getHorizontalScrollBar() {
+ return hsb;
+ }
+
+ /**
+ * Returns the vertical {@link ScrollBar} used in this ScrollPaneSkin
+ * instance.
+ */
+ public final ScrollBar getVerticalScrollBar() {
+ return vsb;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
+ final ScrollPane sp = getSkinnable();
+
+ double vsbWidth = computeVsbSizeHint(sp);
+ double minWidth = vsbWidth + snappedLeftInset() + snappedRightInset();
+
+ if (sp.getPrefViewportWidth() > 0) {
+ return (sp.getPrefViewportWidth() + minWidth);
+ }
+ else if (sp.getContent() != null) {
+ return (sp.getContent().prefWidth(height) + minWidth);
+ }
+ else {
+ return Math.max(minWidth, DEFAULT_PREF_SIZE);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected double computePrefHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {
+ final ScrollPane sp = getSkinnable();
+
+ double hsbHeight = computeHsbSizeHint(sp);
+ double minHeight = hsbHeight + snappedTopInset() + snappedBottomInset();
+
+ if (sp.getPrefViewportHeight() > 0) {
+ return (sp.getPrefViewportHeight() + minHeight);
+ }
+ else if (sp.getContent() != null) {
+ return (sp.getContent().prefHeight(width) + minHeight);
+ }
+ else {
+ return Math.max(minHeight, DEFAULT_PREF_SIZE);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected double computeMinWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
+ final ScrollPane sp = getSkinnable();
+
+ double vsbWidth = computeVsbSizeHint(sp);
+ double minWidth = vsbWidth + snappedLeftInset() + snappedRightInset();
+
+ if (sp.getMinViewportWidth() > 0) {
+ return (sp.getMinViewportWidth() + minWidth);
+ } else {
+ double w = corner.minWidth(-1);
+ return (w > 0) ? (3 * w) : (DEFAULT_MIN_SIZE);
+ }
+
+ }
+
+ /** {@inheritDoc} */
+ @Override protected double computeMinHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {
+ final ScrollPane sp = getSkinnable();
+
+ double hsbHeight = computeHsbSizeHint(sp);
+ double minHeight = hsbHeight + snappedTopInset() + snappedBottomInset();
+
+ if (sp.getMinViewportHeight() > 0) {
+ return (sp.getMinViewportHeight() + minHeight);
+ } else {
+ double h = corner.minHeight(-1);
+ return (h > 0) ? (3 * h) : (DEFAULT_MIN_SIZE);
+ }
+ }
+
+ @Override protected void layoutChildren(final double x, final double y,
+ final double w, final double h) {
+ final ScrollPane control = getSkinnable();
+ final Insets padding = control.getPadding();
+ final double rightPadding = snapSize(padding.getRight());
+ final double leftPadding = snapSize(padding.getLeft());
+ final double topPadding = snapSize(padding.getTop());
+ final double bottomPadding = snapSize(padding.getBottom());
+
+ vsb.setMin(control.getVmin());
+ vsb.setMax(control.getVmax());
+
+ //should only do this on css setup
+ hsb.setMin(control.getHmin());
+ hsb.setMax(control.getHmax());
+
+ contentWidth = w;
+ contentHeight = h;
+
+ /*
+ ** we want the scrollbars to go right to the border
+ */
+ double hsbWidth = 0;
+ double vsbHeight = 0;
+
+ computeScrollNodeSize(contentWidth, contentHeight);
+ computeScrollBarSize();
+
+ for (int i = 0; i < 2; ++i) {
+ vsbvis = determineVerticalSBVisible();
+ hsbvis = determineHorizontalSBVisible();
+
+ if (vsbvis && !Properties.IS_TOUCH_SUPPORTED) {
+ contentWidth = w - vsbWidth;
+ }
+ hsbWidth = w + leftPadding + rightPadding - (vsbvis ? vsbWidth : 0);
+ if (hsbvis && !Properties.IS_TOUCH_SUPPORTED) {
+ contentHeight = h - hsbHeight;
+ }
+ vsbHeight = h + topPadding + bottomPadding - (hsbvis ? hsbHeight : 0);
+ }
+
+
+ if (scrollNode != null && scrollNode.isResizable()) {
+ // maybe adjust size now that scrollbars may take up space
+ if (vsbvis && hsbvis) {
+ // adjust just once to accommodate
+ computeScrollNodeSize(contentWidth, contentHeight);
+
+ } else if (hsbvis && !vsbvis) {
+ computeScrollNodeSize(contentWidth, contentHeight);
+ vsbvis = determineVerticalSBVisible();
+ if (vsbvis) {
+ // now both are visible
+ contentWidth -= vsbWidth;
+ hsbWidth -= vsbWidth;
+ computeScrollNodeSize(contentWidth, contentHeight);
+ }
+ } else if (vsbvis && !hsbvis) {
+ computeScrollNodeSize(contentWidth, contentHeight);
+ hsbvis = determineHorizontalSBVisible();
+ if (hsbvis) {
+ // now both are visible
+ contentHeight -= hsbHeight;
+ vsbHeight -= hsbHeight;
+ computeScrollNodeSize(contentWidth, contentHeight);
+ }
+ }
+ }
+
+ // figure out the content area that is to be filled
+ double cx = snappedLeftInset() - leftPadding;
+ double cy = snappedTopInset() - topPadding;
+
+ vsb.setVisible(vsbvis);
+ if (vsbvis) {
+ /*
+ ** round up position of ScrollBar, round down it's size.
+ **
+ ** Positioning the ScrollBar
+ ** The Padding should go between the content and the edge,
+ ** otherwise changes in padding move the ScrollBar, and could
+ ** in extreme cases size the ScrollBar to become unusable.
+ ** The -1, +1 plus one bit :
+ ** If padding in => 1 then we allow one pixel to appear as the
+ ** outside border of the Scrollbar, and the rest on the inside.
+ ** If padding is < 1 then we just stick to the edge.
+ */
+ vsb.resizeRelocate(snappedLeftInset() + w - vsbWidth + (rightPadding < 1 ? 0 : rightPadding - 1) ,
+ cy, vsbWidth, vsbHeight);
+ }
+ updateVerticalSB();
+
+ hsb.setVisible(hsbvis);
+ if (hsbvis) {
+ /*
+ ** round up position of ScrollBar, round down it's size.
+ **
+ ** Positioning the ScrollBar
+ ** The Padding should go between the content and the edge,
+ ** otherwise changes in padding move the ScrollBar, and could
+ ** in extreme cases size the ScrollBar to become unusable.
+ ** The -1, +1 plus one bit :
+ ** If padding in => 1 then we allow one pixel to appear as the
+ ** outside border of the Scrollbar, and the rest on the inside.
+ ** If padding is < 1 then we just stick to the edge.
+ */
+ hsb.resizeRelocate(cx, snappedTopInset() + h - hsbHeight + (bottomPadding < 1 ? 0 : bottomPadding - 1),
+ hsbWidth, hsbHeight);
+ }
+ updateHorizontalSB();
+
+ viewRect.resizeRelocate(snappedLeftInset(), snappedTopInset(), snapSize(contentWidth), snapSize(contentHeight));
+ resetClip();
+
+ if (vsbvis && hsbvis) {
+ corner.setVisible(true);
+ double cornerWidth = vsbWidth;
+ double cornerHeight = hsbHeight;
+ corner.resizeRelocate(snapPosition(vsb.getLayoutX()), snapPosition(hsb.getLayoutY()), snapSize(cornerWidth), snapSize(cornerHeight));
+ } else {
+ corner.setVisible(false);
+ }
+ control.setViewportBounds(new BoundingBox(snapPosition(viewContent.getLayoutX()), snapPosition(viewContent.getLayoutY()), snapSize(contentWidth), snapSize(contentHeight)));
+ }
+
+ /** {@inheritDoc} */
+ @Override protected Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) {
+ switch (attribute) {
+ case VERTICAL_SCROLLBAR: return vsb;
+ case HORIZONTAL_SCROLLBAR: return hsb;
+ default: return super.queryAccessibleAttribute(attribute, parameters);
+ }
+ }
+
+
+
+ /***************************************************************************
+ * *
+ * Private implementation *
+ * *
+ **************************************************************************/
+
private void initialize() {
// requestLayout calls below should not trigger requestLayout above ScrollPane
// setManaged(false);
ScrollPane control = getSkinnable();
scrollNode = control.getContent();
ParentTraversalEngine traversalEngine = new ParentTraversalEngine(getSkinnable());
! traversalEngine.addTraverseListener((node, bounds) -> {
! // auto-scroll so node is within (0,0),(contentWidth,contentHeight)
! scrollBoundsIntoView(bounds);
! });
getSkinnable().setImpl_traversalEngine(traversalEngine);
if (scrollNode != null) {
scrollNode.layoutBoundsProperty().addListener(nodeListener);
scrollNode.layoutBoundsProperty().addListener(boundsChangeListener);
}
viewRect = new StackPane() {
! @Override protected void layoutChildren() {
viewContent.resize(getWidth(), getHeight());
}
};
// prevent requestLayout requests from within scrollNode from percolating up
viewRect.setManaged(false);
viewRect.setCache(true);
viewRect.getStyleClass().add("viewport");
*** 313,334 ****
/*
** listeners, and assorted housekeeping
*/
InvalidationListener vsbListener = valueModel -> {
! if (!IS_TOUCH_SUPPORTED) {
posY = Utils.clamp(getSkinnable().getVmin(), vsb.getValue(), getSkinnable().getVmax());
}
else {
posY = vsb.getValue();
}
updatePosY();
};
vsb.valueProperty().addListener(vsbListener);
InvalidationListener hsbListener = valueModel -> {
! if (!IS_TOUCH_SUPPORTED) {
posX = Utils.clamp(getSkinnable().getHmin(), hsb.getValue(), getSkinnable().getHmax());
}
else {
posX = hsb.getValue();
}
--- 701,722 ----
/*
** listeners, and assorted housekeeping
*/
InvalidationListener vsbListener = valueModel -> {
! if (!Properties.IS_TOUCH_SUPPORTED) {
posY = Utils.clamp(getSkinnable().getVmin(), vsb.getValue(), getSkinnable().getVmax());
}
else {
posY = vsb.getValue();
}
updatePosY();
};
vsb.valueProperty().addListener(vsbListener);
InvalidationListener hsbListener = valueModel -> {
! if (!Properties.IS_TOUCH_SUPPORTED) {
posX = Utils.clamp(getSkinnable().getHmin(), hsb.getValue(), getSkinnable().getHmax());
}
else {
posX = hsb.getValue();
}
*** 336,357 ****
};
hsb.valueProperty().addListener(hsbListener);
viewRect.setOnMousePressed(e -> {
mouseDown = true;
! if (IS_TOUCH_SUPPORTED) {
startSBReleasedAnimation();
}
pressX = e.getX();
pressY = e.getY();
ohvalue = hsb.getValue();
ovvalue = vsb.getValue();
});
viewRect.setOnDragDetected(e -> {
! if (IS_TOUCH_SUPPORTED) {
startSBReleasedAnimation();
}
if (getSkinnable().isPannable()) {
dragDetected = true;
if (saveCursor == null) {
--- 724,745 ----
};
hsb.valueProperty().addListener(hsbListener);
viewRect.setOnMousePressed(e -> {
mouseDown = true;
! if (Properties.IS_TOUCH_SUPPORTED) {
startSBReleasedAnimation();
}
pressX = e.getX();
pressY = e.getY();
ohvalue = hsb.getValue();
ovvalue = vsb.getValue();
});
viewRect.setOnDragDetected(e -> {
! if (Properties.IS_TOUCH_SUPPORTED) {
startSBReleasedAnimation();
}
if (getSkinnable().isPannable()) {
dragDetected = true;
if (saveCursor == null) {
*** 384,400 ****
posX > getSkinnable().getHmax() || posX < getSkinnable().getHmin()) && !touchDetected) {
startContentsToViewport();
}
});
viewRect.setOnMouseDragged(e -> {
! if (IS_TOUCH_SUPPORTED) {
startSBReleasedAnimation();
}
/*
** for mobile-touch we allow drag, even if not pannagle
*/
! if (getSkinnable().isPannable() || IS_TOUCH_SUPPORTED) {
double deltaX = pressX - e.getX();
double deltaY = pressY - e.getY();
/*
** we only drag if not all of the content is visible.
*/
--- 772,788 ----
posX > getSkinnable().getHmax() || posX < getSkinnable().getHmin()) && !touchDetected) {
startContentsToViewport();
}
});
viewRect.setOnMouseDragged(e -> {
! if (Properties.IS_TOUCH_SUPPORTED) {
startSBReleasedAnimation();
}
/*
** for mobile-touch we allow drag, even if not pannagle
*/
! if (getSkinnable().isPannable() || Properties.IS_TOUCH_SUPPORTED) {
double deltaX = pressX - e.getX();
double deltaY = pressY - e.getY();
/*
** we only drag if not all of the content is visible.
*/
*** 402,412 ****
if (Math.abs(deltaX) > PAN_THRESHOLD) {
if (isReverseNodeOrientation()) {
deltaX = -deltaX;
}
double newHVal = (ohvalue + deltaX / (nodeWidth - viewRect.getWidth()) * (hsb.getMax() - hsb.getMin()));
! if (!IS_TOUCH_SUPPORTED) {
if (newHVal > hsb.getMax()) {
newHVal = hsb.getMax();
}
else if (newHVal < hsb.getMin()) {
newHVal = hsb.getMin();
--- 790,800 ----
if (Math.abs(deltaX) > PAN_THRESHOLD) {
if (isReverseNodeOrientation()) {
deltaX = -deltaX;
}
double newHVal = (ohvalue + deltaX / (nodeWidth - viewRect.getWidth()) * (hsb.getMax() - hsb.getMin()));
! if (!Properties.IS_TOUCH_SUPPORTED) {
if (newHVal > hsb.getMax()) {
newHVal = hsb.getMax();
}
else if (newHVal < hsb.getMin()) {
newHVal = hsb.getMin();
*** 422,432 ****
** we only drag if not all of the content is visible.
*/
if (vsb.getVisibleAmount() > 0.0 && vsb.getVisibleAmount() < vsb.getMax()) {
if (Math.abs(deltaY) > PAN_THRESHOLD) {
double newVVal = (ovvalue + deltaY / (nodeHeight - viewRect.getHeight()) * (vsb.getMax() - vsb.getMin()));
! if (!IS_TOUCH_SUPPORTED) {
if (newVVal > vsb.getMax()) {
newVVal = vsb.getMax();
}
else if (newVVal < vsb.getMin()) {
newVVal = vsb.getMin();
--- 810,820 ----
** we only drag if not all of the content is visible.
*/
if (vsb.getVisibleAmount() > 0.0 && vsb.getVisibleAmount() < vsb.getMax()) {
if (Math.abs(deltaY) > PAN_THRESHOLD) {
double newVVal = (ovvalue + deltaY / (nodeHeight - viewRect.getHeight()) * (vsb.getMax() - vsb.getMin()));
! if (!Properties.IS_TOUCH_SUPPORTED) {
if (newVVal > vsb.getMax()) {
newVVal = vsb.getMax();
}
else if (newVVal < vsb.getMin()) {
newVVal = vsb.getMin();
*** 487,497 ****
* allows for us to prioritise handling (and consuming) the event
* internally, before it is made available to users listening to events
* on the control. This is consistent with the VirtualFlow-based controls.
*/
viewRect.addEventHandler(ScrollEvent.SCROLL, event -> {
! if (IS_TOUCH_SUPPORTED) {
startSBReleasedAnimation();
}
/*
** if we're completely visible then do nothing....
** we only consume an event that we've used.
--- 875,885 ----
* allows for us to prioritise handling (and consuming) the event
* internally, before it is made available to users listening to events
* on the control. This is consistent with the VirtualFlow-based controls.
*/
viewRect.addEventHandler(ScrollEvent.SCROLL, event -> {
! if (Properties.IS_TOUCH_SUPPORTED) {
startSBReleasedAnimation();
}
/*
** if we're completely visible then do nothing....
** we only consume an event that we've used.
*** 504,514 ****
}
else {
vPixelValue = 0.0;
}
double newValue = vsb.getValue()+(-event.getDeltaY())*vPixelValue;
! if (!IS_TOUCH_SUPPORTED) {
if ((event.getDeltaY() > 0.0 && vsb.getValue() > vsb.getMin()) ||
(event.getDeltaY() < 0.0 && vsb.getValue() < vsb.getMax())) {
vsb.setValue(newValue);
event.consume();
}
--- 892,902 ----
}
else {
vPixelValue = 0.0;
}
double newValue = vsb.getValue()+(-event.getDeltaY())*vPixelValue;
! if (!Properties.IS_TOUCH_SUPPORTED) {
if ((event.getDeltaY() > 0.0 && vsb.getValue() > vsb.getMin()) ||
(event.getDeltaY() < 0.0 && vsb.getValue() < vsb.getMax())) {
vsb.setValue(newValue);
event.consume();
}
*** 537,547 ****
else {
hPixelValue = 0.0;
}
double newValue = hsb.getValue()+(-event.getDeltaX())*hPixelValue;
! if (!IS_TOUCH_SUPPORTED) {
if ((event.getDeltaX() > 0.0 && hsb.getValue() > hsb.getMin()) ||
(event.getDeltaX() < 0.0 && hsb.getValue() < hsb.getMax())) {
hsb.setValue(newValue);
event.consume();
}
--- 925,935 ----
else {
hPixelValue = 0.0;
}
double newValue = hsb.getValue()+(-event.getDeltaX())*hPixelValue;
! if (!Properties.IS_TOUCH_SUPPORTED) {
if ((event.getDeltaX() > 0.0 && hsb.getValue() > hsb.getMin()) ||
(event.getDeltaX() < 0.0 && hsb.getValue() < hsb.getMax())) {
hsb.setValue(newValue);
event.consume();
}
*** 574,778 ****
});
getSkinnable().addEventHandler(TouchEvent.TOUCH_RELEASED, e -> {
touchDetected = false;
e.consume();
! });
!
! // ScrollPanes do not block all MouseEvents by default, unlike most other UI Controls.
! consumeMouseEvents(false);
!
! // update skin initial state to match control (see RT-35554)
! hsb.setValue(control.getHvalue());
! vsb.setValue(control.getVvalue());
! }
!
!
! @Override protected void handleControlPropertyChanged(String p) {
! super.handleControlPropertyChanged(p);
! if ("NODE".equals(p)) {
! if (scrollNode != getSkinnable().getContent()) {
! if (scrollNode != null) {
! scrollNode.layoutBoundsProperty().removeListener(nodeListener);
! scrollNode.layoutBoundsProperty().removeListener(boundsChangeListener);
! viewContent.getChildren().remove(scrollNode);
! }
! scrollNode = getSkinnable().getContent();
! if (scrollNode != null) {
! nodeWidth = snapSize(scrollNode.getLayoutBounds().getWidth());
! nodeHeight = snapSize(scrollNode.getLayoutBounds().getHeight());
! viewContent.getChildren().setAll(scrollNode);
! scrollNode.layoutBoundsProperty().addListener(nodeListener);
! scrollNode.layoutBoundsProperty().addListener(boundsChangeListener);
! }
! }
! getSkinnable().requestLayout();
! } else if ("FIT_TO_WIDTH".equals(p) || "FIT_TO_HEIGHT".equals(p)) {
! getSkinnable().requestLayout();
! viewRect.requestLayout();
! } else if ("HBAR_POLICY".equals(p) || "VBAR_POLICY".equals(p)) {
! // change might affect pref size, so requestLayout on control
! getSkinnable().requestLayout();
! } else if ("HVALUE".equals(p)) {
! hsb.setValue(getSkinnable().getHvalue());
! } else if ("HMAX".equals(p)) {
! hsb.setMax(getSkinnable().getHmax());
! } else if ("HMIN".equals(p)) {
! hsb.setMin(getSkinnable().getHmin());
! } else if ("VVALUE".equals(p)) {
! vsb.setValue(getSkinnable().getVvalue());
! } else if ("VMAX".equals(p)) {
! vsb.setMax(getSkinnable().getVmax());
! } else if ("VMIN".equals(p)) {
! vsb.setMin(getSkinnable().getVmin());
! } else if ("VIEWPORT_SIZE_HINT".equals(p)) {
! // change affects pref size, so requestLayout on control
! getSkinnable().requestLayout();
! }
! }
!
! void scrollBoundsIntoView(Bounds b) {
! double dx = 0.0;
! double dy = 0.0;
! if (b.getMaxX() > contentWidth) {
! dx = b.getMinX() - snappedLeftInset();
! }
! if (b.getMinX() < snappedLeftInset()) {
! dx = b.getMaxX() - contentWidth - snappedLeftInset();
! }
! if (b.getMaxY() > snappedTopInset() + contentHeight) {
! dy = b.getMinY() - snappedTopInset();
! }
! if (b.getMinY() < snappedTopInset()) {
! dy = b.getMaxY() - contentHeight - snappedTopInset();
! }
! // We want to move contentPanel's layoutX,Y by (dx,dy).
! // But to do this we have to set the scrollbars' values appropriately.
!
! if (dx != 0) {
! double sdx = dx * (hsb.getMax() - hsb.getMin()) / (nodeWidth - contentWidth);
! // Adjust back for some amount so that the Node border is not too close to view border
! sdx += -1 * Math.signum(sdx) * hsb.getUnitIncrement() / 5; // This accounts to 2% of view width
! hsb.setValue(hsb.getValue() + sdx);
! getSkinnable().requestLayout();
! }
! if (dy != 0) {
! double sdy = dy * (vsb.getMax() - vsb.getMin()) / (nodeHeight - contentHeight);
! // Adjust back for some amount so that the Node border is not too close to view border
! sdy += -1 * Math.signum(sdy) * vsb.getUnitIncrement() / 5; // This accounts to 2% of view height
! vsb.setValue(vsb.getValue() + sdy);
! getSkinnable().requestLayout();
! }
!
! }
!
! /*
! ** auto-scroll so node is within (0,0),(contentWidth,contentHeight)
! */
! @Override public void onTraverse(Node n, Bounds b) {
! scrollBoundsIntoView(b);
! }
!
! public void hsbIncrement() {
! if (hsb != null) hsb.increment();
! }
! public void hsbDecrement() {
! if (hsb != null) hsb.decrement();
! }
!
! // TODO: add page increment and decrement
! public void hsbPageIncrement() {
! if (hsb != null) hsb.increment();
! }
! // TODO: add page increment and decrement
! public void hsbPageDecrement() {
! if (hsb != null) hsb.decrement();
! }
!
! public void vsbIncrement() {
! if (vsb != null) vsb.increment();
! }
! public void vsbDecrement() {
! if (vsb != null) vsb.decrement();
! }
!
! // TODO: add page increment and decrement
! public void vsbPageIncrement() {
! if (vsb != null) vsb.increment();
! }
! // TODO: add page increment and decrement
! public void vsbPageDecrement() {
! if (vsb != null) vsb.decrement();
! }
!
! /***************************************************************************
! * *
! * Layout *
! * *
! **************************************************************************/
!
! @Override protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
! final ScrollPane sp = getSkinnable();
!
! double vsbWidth = computeVsbSizeHint(sp);
! double minWidth = vsbWidth + snappedLeftInset() + snappedRightInset();
!
! if (sp.getPrefViewportWidth() > 0) {
! return (sp.getPrefViewportWidth() + minWidth);
! }
! else if (sp.getContent() != null) {
! return (sp.getContent().prefWidth(height) + minWidth);
! }
! else {
! return Math.max(minWidth, DEFAULT_PREF_SIZE);
! }
! }
! @Override protected double computePrefHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {
! final ScrollPane sp = getSkinnable();
! double hsbHeight = computeHsbSizeHint(sp);
! double minHeight = hsbHeight + snappedTopInset() + snappedBottomInset();
! if (sp.getPrefViewportHeight() > 0) {
! return (sp.getPrefViewportHeight() + minHeight);
}
! else if (sp.getContent() != null) {
! return (sp.getContent().prefHeight(width) + minHeight);
}
! else {
! return Math.max(minHeight, DEFAULT_PREF_SIZE);
}
}
! @Override protected double computeMinWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
! final ScrollPane sp = getSkinnable();
!
! double vsbWidth = computeVsbSizeHint(sp);
! double minWidth = vsbWidth + snappedLeftInset() + snappedRightInset();
!
! if (sp.getMinViewportWidth() > 0) {
! return (sp.getMinViewportWidth() + minWidth);
! } else {
! double w = corner.minWidth(-1);
! return (w > 0) ? (3 * w) : (DEFAULT_MIN_SIZE);
}
!
}
- @Override protected double computeMinHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {
- final ScrollPane sp = getSkinnable();
-
- double hsbHeight = computeHsbSizeHint(sp);
- double minHeight = hsbHeight + snappedTopInset() + snappedBottomInset();
-
- if (sp.getMinViewportHeight() > 0) {
- return (sp.getMinViewportHeight() + minHeight);
- } else {
- double h = corner.minHeight(-1);
- return (h > 0) ? (3 * h) : (DEFAULT_MIN_SIZE);
- }
}
/**
* Computes the size that should be reserved for horizontal scrollbar in size hints (min/pref height)
*/
--- 962,1014 ----
});
getSkinnable().addEventHandler(TouchEvent.TOUCH_RELEASED, e -> {
touchDetected = false;
e.consume();
! });
! // ScrollPanes do not block all MouseEvents by default, unlike most other UI Controls.
! consumeMouseEvents(false);
! // update skin initial state to match control (see RT-35554)
! hsb.setValue(control.getHvalue());
! vsb.setValue(control.getVvalue());
! }
! void scrollBoundsIntoView(Bounds b) {
! double dx = 0.0;
! double dy = 0.0;
! if (b.getMaxX() > contentWidth) {
! dx = b.getMinX() - snappedLeftInset();
}
! if (b.getMinX() < snappedLeftInset()) {
! dx = b.getMaxX() - contentWidth - snappedLeftInset();
}
! if (b.getMaxY() > snappedTopInset() + contentHeight) {
! dy = b.getMinY() - snappedTopInset();
}
+ if (b.getMinY() < snappedTopInset()) {
+ dy = b.getMaxY() - contentHeight - snappedTopInset();
}
+ // We want to move contentPanel's layoutX,Y by (dx,dy).
+ // But to do this we have to set the scrollbars' values appropriately.
! if (dx != 0) {
! double sdx = dx * (hsb.getMax() - hsb.getMin()) / (nodeWidth - contentWidth);
! // Adjust back for some amount so that the Node border is not too close to view border
! sdx += -1 * Math.signum(sdx) * hsb.getUnitIncrement() / 5; // This accounts to 2% of view width
! hsb.setValue(hsb.getValue() + sdx);
! getSkinnable().requestLayout();
}
! if (dy != 0) {
! double sdy = dy * (vsb.getMax() - vsb.getMin()) / (nodeHeight - contentHeight);
! // Adjust back for some amount so that the Node border is not too close to view border
! sdy += -1 * Math.signum(sdy) * vsb.getUnitIncrement() / 5; // This accounts to 2% of view height
! vsb.setValue(vsb.getValue() + sdy);
! getSkinnable().requestLayout();
}
}
/**
* Computes the size that should be reserved for horizontal scrollbar in size hints (min/pref height)
*/
*** 792,927 ****
|| sp.getMinViewportWidth() > 0)))
? vsb.prefWidth(ScrollBar.USE_COMPUTED_SIZE)
: 0;
}
- @Override protected void layoutChildren(final double x, final double y,
- final double w, final double h) {
- final ScrollPane control = getSkinnable();
- final Insets padding = control.getPadding();
- final double rightPadding = snapSize(padding.getRight());
- final double leftPadding = snapSize(padding.getLeft());
- final double topPadding = snapSize(padding.getTop());
- final double bottomPadding = snapSize(padding.getBottom());
-
- vsb.setMin(control.getVmin());
- vsb.setMax(control.getVmax());
-
- //should only do this on css setup
- hsb.setMin(control.getHmin());
- hsb.setMax(control.getHmax());
-
- contentWidth = w;
- contentHeight = h;
-
- /*
- ** we want the scrollbars to go right to the border
- */
- double hsbWidth = 0;
- double vsbHeight = 0;
-
- computeScrollNodeSize(contentWidth, contentHeight);
- computeScrollBarSize();
-
- for (int i = 0; i < 2; ++i) {
- vsbvis = determineVerticalSBVisible();
- hsbvis = determineHorizontalSBVisible();
-
- if (vsbvis && !IS_TOUCH_SUPPORTED) {
- contentWidth = w - vsbWidth;
- }
- hsbWidth = w + leftPadding + rightPadding - (vsbvis ? vsbWidth : 0);
- if (hsbvis && !IS_TOUCH_SUPPORTED) {
- contentHeight = h - hsbHeight;
- }
- vsbHeight = h + topPadding + bottomPadding - (hsbvis ? hsbHeight : 0);
- }
-
-
- if (scrollNode != null && scrollNode.isResizable()) {
- // maybe adjust size now that scrollbars may take up space
- if (vsbvis && hsbvis) {
- // adjust just once to accommodate
- computeScrollNodeSize(contentWidth, contentHeight);
-
- } else if (hsbvis && !vsbvis) {
- computeScrollNodeSize(contentWidth, contentHeight);
- vsbvis = determineVerticalSBVisible();
- if (vsbvis) {
- // now both are visible
- contentWidth -= vsbWidth;
- hsbWidth -= vsbWidth;
- computeScrollNodeSize(contentWidth, contentHeight);
- }
- } else if (vsbvis && !hsbvis) {
- computeScrollNodeSize(contentWidth, contentHeight);
- hsbvis = determineHorizontalSBVisible();
- if (hsbvis) {
- // now both are visible
- contentHeight -= hsbHeight;
- vsbHeight -= hsbHeight;
- computeScrollNodeSize(contentWidth, contentHeight);
- }
- }
- }
-
- // figure out the content area that is to be filled
- double cx = snappedLeftInset() - leftPadding;
- double cy = snappedTopInset() - topPadding;
-
- vsb.setVisible(vsbvis);
- if (vsbvis) {
- /*
- ** round up position of ScrollBar, round down it's size.
- **
- ** Positioning the ScrollBar
- ** The Padding should go between the content and the edge,
- ** otherwise changes in padding move the ScrollBar, and could
- ** in extreme cases size the ScrollBar to become unusable.
- ** The -1, +1 plus one bit :
- ** If padding in => 1 then we allow one pixel to appear as the
- ** outside border of the Scrollbar, and the rest on the inside.
- ** If padding is < 1 then we just stick to the edge.
- */
- vsb.resizeRelocate(snappedLeftInset() + w - vsbWidth + (rightPadding < 1 ? 0 : rightPadding - 1) ,
- cy, vsbWidth, vsbHeight);
- }
- updateVerticalSB();
-
- hsb.setVisible(hsbvis);
- if (hsbvis) {
- /*
- ** round up position of ScrollBar, round down it's size.
- **
- ** Positioning the ScrollBar
- ** The Padding should go between the content and the edge,
- ** otherwise changes in padding move the ScrollBar, and could
- ** in extreme cases size the ScrollBar to become unusable.
- ** The -1, +1 plus one bit :
- ** If padding in => 1 then we allow one pixel to appear as the
- ** outside border of the Scrollbar, and the rest on the inside.
- ** If padding is < 1 then we just stick to the edge.
- */
- hsb.resizeRelocate(cx, snappedTopInset() + h - hsbHeight + (bottomPadding < 1 ? 0 : bottomPadding - 1),
- hsbWidth, hsbHeight);
- }
- updateHorizontalSB();
-
- viewRect.resizeRelocate(snappedLeftInset(), snappedTopInset(), snapSize(contentWidth), snapSize(contentHeight));
- resetClip();
-
- if (vsbvis && hsbvis) {
- corner.setVisible(true);
- double cornerWidth = vsbWidth;
- double cornerHeight = hsbHeight;
- corner.resizeRelocate(snapPosition(vsb.getLayoutX()), snapPosition(hsb.getLayoutY()), snapSize(cornerWidth), snapSize(cornerHeight));
- } else {
- corner.setVisible(false);
- }
- control.setViewportBounds(new BoundingBox(snapPosition(viewContent.getLayoutX()), snapPosition(viewContent.getLayoutY()), snapSize(contentWidth), snapSize(contentHeight)));
- }
-
private void computeScrollNodeSize(double contentWidth, double contentHeight) {
if (scrollNode != null) {
if (scrollNode.isResizable()) {
ScrollPane control = getSkinnable();
Orientation bias = scrollNode.getContentBias();
--- 1028,1037 ----
*** 959,969 ****
}
private boolean determineHorizontalSBVisible() {
final ScrollPane sp = getSkinnable();
! if (IS_TOUCH_SUPPORTED) {
return (tempVisibility && (nodeWidth > contentWidth));
}
else {
// RT-17395: ScrollBarPolicy might be null. If so, treat it as "AS_NEEDED", which is the default
ScrollBarPolicy hbarPolicy = sp.getHbarPolicy();
--- 1069,1079 ----
}
private boolean determineHorizontalSBVisible() {
final ScrollPane sp = getSkinnable();
! if (Properties.IS_TOUCH_SUPPORTED) {
return (tempVisibility && (nodeWidth > contentWidth));
}
else {
// RT-17395: ScrollBarPolicy might be null. If so, treat it as "AS_NEEDED", which is the default
ScrollBarPolicy hbarPolicy = sp.getHbarPolicy();
*** 975,985 ****
}
private boolean determineVerticalSBVisible() {
final ScrollPane sp = getSkinnable();
! if (IS_TOUCH_SUPPORTED) {
return (tempVisibility && (nodeHeight > contentHeight));
}
else {
// RT-17395: ScrollBarPolicy might be null. If so, treat it as "AS_NEEDED", which is the default
ScrollBarPolicy vbarPolicy = sp.getVbarPolicy();
--- 1085,1095 ----
}
private boolean determineVerticalSBVisible() {
final ScrollPane sp = getSkinnable();
! if (Properties.IS_TOUCH_SUPPORTED) {
return (tempVisibility && (nodeHeight > contentHeight));
}
else {
// RT-17395: ScrollBarPolicy might be null. If so, treat it as "AS_NEEDED", which is the default
ScrollBarPolicy vbarPolicy = sp.getVbarPolicy();
*** 992,1012 ****
private void computeScrollBarSize() {
vsbWidth = snapSize(vsb.prefWidth(-1));
if (vsbWidth == 0) {
// println("*** WARNING ScrollPaneSkin: can't get scroll bar width, using {DEFAULT_SB_BREADTH}");
! if (IS_TOUCH_SUPPORTED) {
vsbWidth = DEFAULT_EMBEDDED_SB_BREADTH;
}
else {
vsbWidth = DEFAULT_SB_BREADTH;
}
}
hsbHeight = snapSize(hsb.prefHeight(-1));
if (hsbHeight == 0) {
// println("*** WARNING ScrollPaneSkin: can't get scroll bar height, using {DEFAULT_SB_BREADTH}");
! if (IS_TOUCH_SUPPORTED) {
hsbHeight = DEFAULT_EMBEDDED_SB_BREADTH;
}
else {
hsbHeight = DEFAULT_SB_BREADTH;
}
--- 1102,1122 ----
private void computeScrollBarSize() {
vsbWidth = snapSize(vsb.prefWidth(-1));
if (vsbWidth == 0) {
// println("*** WARNING ScrollPaneSkin: can't get scroll bar width, using {DEFAULT_SB_BREADTH}");
! if (Properties.IS_TOUCH_SUPPORTED) {
vsbWidth = DEFAULT_EMBEDDED_SB_BREADTH;
}
else {
vsbWidth = DEFAULT_SB_BREADTH;
}
}
hsbHeight = snapSize(hsb.prefHeight(-1));
if (hsbHeight == 0) {
// println("*** WARNING ScrollPaneSkin: can't get scroll bar height, using {DEFAULT_SB_BREADTH}");
! if (Properties.IS_TOUCH_SUPPORTED) {
hsbHeight = DEFAULT_EMBEDDED_SB_BREADTH;
}
else {
hsbHeight = DEFAULT_SB_BREADTH;
}
*** 1081,1102 ****
private void resetClip() {
clipRect.setWidth(snapSize(contentWidth));
clipRect.setHeight(snapSize(contentHeight));
}
! Timeline sbTouchTimeline;
! KeyFrame sbTouchKF1;
! KeyFrame sbTouchKF2;
! Timeline contentsToViewTimeline;
! KeyFrame contentsToViewKF1;
! KeyFrame contentsToViewKF2;
! KeyFrame contentsToViewKF3;
!
! private boolean tempVisibility;
!
!
! protected void startSBReleasedAnimation() {
if (sbTouchTimeline == null) {
/*
** timeline to leave the scrollbars visible for a short
** while after a scroll/drag
*/
--- 1191,1201 ----
private void resetClip() {
clipRect.setWidth(snapSize(contentWidth));
clipRect.setHeight(snapSize(contentHeight));
}
! private void startSBReleasedAnimation() {
if (sbTouchTimeline == null) {
/*
** timeline to leave the scrollbars visible for a short
** while after a scroll/drag
*/
*** 1115,1127 ****
sbTouchTimeline.getKeyFrames().addAll(sbTouchKF1, sbTouchKF2);
}
sbTouchTimeline.playFromStart();
}
!
!
! protected void startContentsToViewport() {
double newPosX = posX;
double newPosY = posY;
setContentPosX(posX);
setContentPosY(posY);
--- 1214,1224 ----
sbTouchTimeline.getKeyFrames().addAll(sbTouchKF1, sbTouchKF2);
}
sbTouchTimeline.playFromStart();
}
! private void startContentsToViewport() {
double newPosX = posX;
double newPosY = posY;
setContentPosX(posX);
setContentPosY(posY);
*** 1139,1149 ****
}
else if (posX < getSkinnable().getHmin()) {
newPosX = getSkinnable().getHmin();
}
! if (!IS_TOUCH_SUPPORTED) {
startSBReleasedAnimation();
}
/*
** timeline to return the contents of the scrollpane to the viewport
--- 1236,1246 ----
}
else if (posX < getSkinnable().getHmin()) {
newPosX = getSkinnable().getHmin();
}
! if (!Properties.IS_TOUCH_SUPPORTED) {
startSBReleasedAnimation();
}
/*
** timeline to return the contents of the scrollpane to the viewport
*** 1171,1236 ****
*/
contentsToViewKF3 = new KeyFrame(Duration.millis(1500));
contentsToViewTimeline.getKeyFrames().addAll(contentsToViewKF1, contentsToViewKF2, contentsToViewKF3);
contentsToViewTimeline.playFromStart();
}
-
-
- private DoubleProperty contentPosX;
- private void setContentPosX(double value) { contentPosXProperty().set(value); }
- private double getContentPosX() { return contentPosX == null ? 0.0 : contentPosX.get(); }
- private DoubleProperty contentPosXProperty() {
- if (contentPosX == null) {
- contentPosX = new DoublePropertyBase() {
- @Override protected void invalidated() {
- hsb.setValue(getContentPosX());
- getSkinnable().requestLayout();
- }
-
- @Override
- public Object getBean() {
- return ScrollPaneSkin.this;
- }
-
- @Override
- public String getName() {
- return "contentPosX";
- }
- };
- }
- return contentPosX;
- }
-
- private DoubleProperty contentPosY;
- private void setContentPosY(double value) { contentPosYProperty().set(value); }
- private double getContentPosY() { return contentPosY == null ? 0.0 : contentPosY.get(); }
- private DoubleProperty contentPosYProperty() {
- if (contentPosY == null) {
- contentPosY = new DoublePropertyBase() {
- @Override protected void invalidated() {
- vsb.setValue(getContentPosY());
- getSkinnable().requestLayout();
- }
-
- @Override
- public Object getBean() {
- return ScrollPaneSkin.this;
- }
-
- @Override
- public String getName() {
- return "contentPosY";
- }
- };
- }
- return contentPosY;
- }
-
- @Override
- protected Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) {
- switch (attribute) {
- case VERTICAL_SCROLLBAR: return vsb;
- case HORIZONTAL_SCROLLBAR: return hsb;
- default: return super.queryAccessibleAttribute(attribute, parameters);
- }
- }
}
--- 1268,1273 ----