Skip to content

Commit 5805bf8

Browse files
Michael StraußJohan Vos
authored andcommitted
8276313: ScrollPane scroll delta incorrectly depends on content height
Reviewed-by: kcr, aghaisas, jvos
1 parent d3fbb51 commit 5805bf8

File tree

2 files changed

+62
-20
lines changed

2 files changed

+62
-20
lines changed

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

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -891,13 +891,8 @@ else if (newVVal < vsb.getMin()) {
891891
*/
892892
if (vsb.getVisibleAmount() < vsb.getMax()) {
893893
double vRange = getSkinnable().getVmax()-getSkinnable().getVmin();
894-
double vPixelValue;
895-
if (nodeHeight > 0.0) {
896-
vPixelValue = vRange / nodeHeight;
897-
}
898-
else {
899-
vPixelValue = 0.0;
900-
}
894+
double hDelta = nodeHeight - contentHeight;
895+
double vPixelValue = hDelta > 0.0 ? vRange / hDelta : 0.0;
901896
double newValue = vsb.getValue()+(-event.getDeltaY())*vPixelValue;
902897
if (!Properties.IS_TOUCH_SUPPORTED) {
903898
if ((event.getDeltaY() > 0.0 && vsb.getValue() > vsb.getMin()) ||
@@ -923,14 +918,8 @@ else if (newVVal < vsb.getMin()) {
923918

924919
if (hsb.getVisibleAmount() < hsb.getMax()) {
925920
double hRange = getSkinnable().getHmax()-getSkinnable().getHmin();
926-
double hPixelValue;
927-
if (nodeWidth > 0.0) {
928-
hPixelValue = hRange / nodeWidth;
929-
}
930-
else {
931-
hPixelValue = 0.0;
932-
}
933-
921+
double wDelta = nodeWidth - contentWidth;
922+
double hPixelValue = wDelta > 0.0 ? hRange / wDelta : 0.0;
934923
double newValue = hsb.getValue()+(-event.getDeltaX())*hPixelValue;
935924
if (!Properties.IS_TOUCH_SUPPORTED) {
936925
if ((event.getDeltaX() > 0.0 && hsb.getValue() > hsb.getMin()) ||
@@ -998,14 +987,16 @@ void scrollBoundsIntoView(Bounds b) {
998987
// But to do this we have to set the scrollbars' values appropriately.
999988

1000989
if (dx != 0) {
1001-
double sdx = dx * (hsb.getMax() - hsb.getMin()) / (nodeWidth - contentWidth);
990+
double wd = nodeWidth - contentWidth;
991+
double sdx = wd > 0.0 ? dx * (hsb.getMax() - hsb.getMin()) / wd : 0;
1002992
// Adjust back for some amount so that the Node border is not too close to view border
1003993
sdx += -1 * Math.signum(sdx) * hsb.getUnitIncrement() / 5; // This accounts to 2% of view width
1004994
hsb.setValue(hsb.getValue() + sdx);
1005995
getSkinnable().requestLayout();
1006996
}
1007997
if (dy != 0) {
1008-
double sdy = dy * (vsb.getMax() - vsb.getMin()) / (nodeHeight - contentHeight);
998+
double hd = nodeHeight - contentHeight;
999+
double sdy = hd > 0.0 ? dy * (vsb.getMax() - vsb.getMin()) / hd : 0.0;
10091000
// Adjust back for some amount so that the Node border is not too close to view border
10101001
sdy += -1 * Math.signum(sdy) * vsb.getUnitIncrement() / 5; // This accounts to 2% of view height
10111002
vsb.setValue(vsb.getValue() + sdy);
@@ -1179,15 +1170,17 @@ private void updateVerticalSB() {
11791170
private double updatePosX() {
11801171
final ScrollPane sp = getSkinnable();
11811172
double x = isReverseNodeOrientation() ? (hsb.getMax() - (posX - hsb.getMin())) : posX;
1182-
double minX = Math.min((- x / (hsb.getMax() - hsb.getMin()) * (nodeWidth - contentWidth)), 0);
1173+
double hsbRange = hsb.getMax() - hsb.getMin();
1174+
double minX = hsbRange > 0 ? Math.min(-x / hsbRange * (nodeWidth - contentWidth), 0) : 0;
11831175
viewContent.setLayoutX(snapPositionX(minX));
11841176
if (!sp.hvalueProperty().isBound()) sp.setHvalue(Utils.clamp(sp.getHmin(), posX, sp.getHmax()));
11851177
return posX;
11861178
}
11871179

11881180
private double updatePosY() {
11891181
final ScrollPane sp = getSkinnable();
1190-
double minY = Math.min((- posY / (vsb.getMax() - vsb.getMin()) * (nodeHeight - contentHeight)), 0);
1182+
double vsbRange = vsb.getMax() - vsb.getMin();
1183+
double minY = vsbRange > 0 ? Math.min(-posY / vsbRange * (nodeHeight - contentHeight), 0) : 0;
11911184
viewContent.setLayoutY(snapPositionY(minY));
11921185
if (!sp.vvalueProperty().isBound()) sp.setVvalue(Utils.clamp(sp.getVmin(), posY, sp.getVmax()));
11931186
return posY;

modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/ScrollPaneSkinTest.java

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -745,7 +745,56 @@ public void growW() {
745745
assertTrue(scrollPaneInner.getHvalue() > 0.0);
746746
}
747747

748+
@Test
749+
public void testScrollDeltaIsIndependentOfScrollPaneHeight() {
750+
var content = new Rectangle();
751+
content.setHeight(200);
752+
content.setWidth(100);
748753

754+
var scrollPane = new ScrollPane();
755+
scrollPane.setSkin(new ScrollPaneSkinMock(scrollPane));
756+
scrollPane.setContent(content);
757+
scrollPane.setPrefWidth(100);
758+
scrollPane.setPrefHeight(100);
759+
760+
Stage stage = new Stage();
761+
stage.setScene(new Scene(new Group(scrollPane), 500, 500));
762+
stage.show();
763+
764+
Event.fireEvent(content, new ScrollEvent(
765+
ScrollEvent.SCROLL,
766+
50, 50,
767+
50, 50,
768+
false, false, false, false, true, false,
769+
0.0, -10.0, 0.0, -10.0,
770+
ScrollEvent.HorizontalTextScrollUnits.NONE, 0.0,
771+
ScrollEvent.VerticalTextScrollUnits.NONE, 0.0,
772+
0, null));
773+
774+
double firstY = content.getLocalToSceneTransform().transform(0, 0).getY();
775+
scrollPane.setPrefHeight(150);
776+
scrollPane.setVvalue(0);
777+
778+
stage.close();
779+
stage = new Stage();
780+
stage.setScene(new Scene(new Group(scrollPane), 500, 500));
781+
stage.show();
782+
783+
Event.fireEvent(content, new ScrollEvent(
784+
ScrollEvent.SCROLL,
785+
50, 50,
786+
50, 50,
787+
false, false, false, false, true, false,
788+
0.0, -10.0, 0.0, -10.0,
789+
ScrollEvent.HorizontalTextScrollUnits.NONE, 0.0,
790+
ScrollEvent.VerticalTextScrollUnits.NONE, 0.0,
791+
0, null));
792+
793+
double secondY = content.getLocalToSceneTransform().transform(0, 0).getY();
794+
stage.close();
795+
796+
assertEquals(firstY, secondY, 0.001);
797+
}
749798

750799
public static final class ScrollPaneSkinMock extends ScrollPaneSkinShim {
751800
boolean propertyChanged = false;

0 commit comments

Comments
 (0)