mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-12 23:07:15 -06:00
ScrollPane: smooth scrolling:
- scroll at least one pixel to avoid "hanging" - limit scroll increment to visible width/height - no longer use block increment because had width/height of view (IOW was too large and had no effect) (issue #27)
This commit is contained in:
@@ -14,12 +14,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Smooth scrolling code partly based on code from IntelliJ IDEA Community Edition,
|
|
||||||
* which is licensed under the Apache 2.0 license. Copyright 2000-2016 JetBrains s.r.o.
|
|
||||||
* See: https://github.com/JetBrains/intellij-community/blob/31e1b5a8e43219b9571951bab6457cfb3012e3ef/platform/platform-api/src/com/intellij/ui/components/SmoothScrollPane.java#L141-L185
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
@@ -138,8 +132,6 @@ public class FlatScrollPaneUI
|
|||||||
return UIManager.getBoolean( "ScrollPane.smoothScrolling" );
|
return UIManager.getBoolean( "ScrollPane.smoothScrolling" );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final double EPSILON = 1e-5d;
|
|
||||||
|
|
||||||
private void mouseWheelMovedSmooth( MouseWheelEvent e ) {
|
private void mouseWheelMovedSmooth( MouseWheelEvent e ) {
|
||||||
// return if there is no viewport
|
// return if there is no viewport
|
||||||
JViewport viewport = scrollpane.getViewport();
|
JViewport viewport = scrollpane.getViewport();
|
||||||
@@ -160,24 +152,22 @@ public class FlatScrollPaneUI
|
|||||||
// get precise wheel rotation
|
// get precise wheel rotation
|
||||||
double rotation = e.getPreciseWheelRotation();
|
double rotation = e.getPreciseWheelRotation();
|
||||||
|
|
||||||
// get unit and block increment
|
// get unit increment
|
||||||
int unitIncrement;
|
int unitIncrement;
|
||||||
int blockIncrement;
|
|
||||||
int orientation = scrollbar.getOrientation();
|
int orientation = scrollbar.getOrientation();
|
||||||
Component view = viewport.getView();
|
Component view = viewport.getView();
|
||||||
if( view instanceof Scrollable ) {
|
if( view instanceof Scrollable ) {
|
||||||
Scrollable scrollable = (Scrollable) view;
|
Scrollable scrollable = (Scrollable) view;
|
||||||
|
|
||||||
// Use (0, 0) view position to obtain constant unit increment of first item
|
// Use (0, 0) view position to obtain a constant unit increment of first item.
|
||||||
// (which might otherwise be variable on smaller-than-unit scrolling).
|
// Unit increment may be different for each item.
|
||||||
Rectangle visibleRect = new Rectangle( viewport.getViewSize() );
|
Rectangle visibleRect = new Rectangle( viewport.getViewSize() );
|
||||||
unitIncrement = scrollable.getScrollableUnitIncrement( visibleRect, orientation, 1 );
|
unitIncrement = scrollable.getScrollableUnitIncrement( visibleRect, orientation, 1 );
|
||||||
blockIncrement = scrollable.getScrollableBlockIncrement( visibleRect, orientation, 1 );
|
|
||||||
|
|
||||||
if( unitIncrement > 0 ) {
|
if( unitIncrement > 0 ) {
|
||||||
// For the case that the first item (e.g. in a list) is larger
|
// For the case that the first item (e.g. in a list) is larger
|
||||||
// than the other items, get the unit increment of the second item
|
// than the other items (e.g. themes list in FlatLaf Demo),
|
||||||
// and use the smaller one.
|
// get the unit increment of the second item and use the smaller one.
|
||||||
if( orientation == SwingConstants.VERTICAL ) {
|
if( orientation == SwingConstants.VERTICAL ) {
|
||||||
visibleRect.y += unitIncrement;
|
visibleRect.y += unitIncrement;
|
||||||
visibleRect.height -= unitIncrement;
|
visibleRect.height -= unitIncrement;
|
||||||
@@ -192,52 +182,58 @@ public class FlatScrollPaneUI
|
|||||||
} else {
|
} else {
|
||||||
int direction = rotation < 0 ? -1 : 1;
|
int direction = rotation < 0 ? -1 : 1;
|
||||||
unitIncrement = scrollbar.getUnitIncrement( direction );
|
unitIncrement = scrollbar.getUnitIncrement( direction );
|
||||||
blockIncrement = scrollbar.getBlockIncrement( direction );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// limit scroll amount (number of units to scroll) for small viewports
|
// get viewport width/height (the visible width/height)
|
||||||
// (e.g. vertical scrolling in file chooser)
|
|
||||||
int scrollAmount = e.getScrollAmount();
|
|
||||||
int viewportWH = (orientation == SwingConstants.VERTICAL)
|
int viewportWH = (orientation == SwingConstants.VERTICAL)
|
||||||
? viewport.getHeight()
|
? viewport.getHeight()
|
||||||
: viewport.getWidth();
|
: viewport.getWidth();
|
||||||
if( unitIncrement * scrollAmount > viewportWH )
|
|
||||||
scrollAmount = Math.max( viewportWH / unitIncrement, 1 );
|
// limit scroll increment to viewport width/height
|
||||||
|
// - if scroll amount is set to a large value in OS settings
|
||||||
|
// - for large unit increments in small viewports (e.g. horizontal scrolling in file chooser)
|
||||||
|
int scrollIncrement = Math.min( unitIncrement * e.getScrollAmount(), viewportWH );
|
||||||
|
|
||||||
// compute relative delta
|
// compute relative delta
|
||||||
double delta = rotation * scrollAmount * unitIncrement;
|
double delta = rotation * scrollIncrement;
|
||||||
boolean adjustDelta = Math.abs( rotation ) < (1.0 + EPSILON);
|
int idelta = (int) Math.round( delta );
|
||||||
double adjustedDelta = adjustDelta
|
|
||||||
? Math.max( -blockIncrement, Math.min( delta, blockIncrement ) )
|
// scroll at least one pixel to avoid "hanging"
|
||||||
: delta;
|
// - for "super-low-speed" scrolling (move fingers very slowly on trackpad)
|
||||||
|
// - if unit increment is very small (e.g. 1 if scroll view does not implement
|
||||||
|
// javax.swing.Scrollable interface)
|
||||||
|
if( idelta == 0 ) {
|
||||||
|
if( rotation > 0 )
|
||||||
|
idelta = 1;
|
||||||
|
else if( rotation < 0 )
|
||||||
|
idelta = -1;
|
||||||
|
}
|
||||||
|
|
||||||
// compute new value
|
// compute new value
|
||||||
int value = scrollbar.getValue();
|
int value = scrollbar.getValue();
|
||||||
double minDelta = scrollbar.getMinimum() - value;
|
int minValue = scrollbar.getMinimum();
|
||||||
double maxDelta = scrollbar.getMaximum() - scrollbar.getModel().getExtent() - value;
|
int maxValue = scrollbar.getMaximum() - scrollbar.getModel().getExtent();
|
||||||
double boundedDelta = Math.max( minDelta, Math.min( adjustedDelta, maxDelta ) );
|
int newValue = Math.max( minValue, Math.min( value + idelta, maxValue ) );
|
||||||
int newValue = value + (int) Math.round( boundedDelta );
|
|
||||||
|
|
||||||
// set new value
|
// set new value
|
||||||
if( newValue != value )
|
if( newValue != value )
|
||||||
scrollbar.setValue( newValue );
|
scrollbar.setValue( newValue );
|
||||||
|
|
||||||
/*debug
|
/*debug
|
||||||
System.out.println( String.format( "%4d %9f / %4d %4d / %12f %5s %12f / %4d %4d %4d / %12f %12f %12f / %4d",
|
System.out.println( String.format( "%s %4d %9f / %3d * %d = %3d [%3d] / %8.2f %5d / %4d --> %4d [%d, %d]",
|
||||||
|
(orientation == SwingConstants.VERTICAL) ? "V" : "H",
|
||||||
e.getWheelRotation(),
|
e.getWheelRotation(),
|
||||||
e.getPreciseWheelRotation(),
|
e.getPreciseWheelRotation(),
|
||||||
unitIncrement,
|
unitIncrement,
|
||||||
blockIncrement,
|
e.getScrollAmount(),
|
||||||
|
scrollIncrement,
|
||||||
|
viewportWH,
|
||||||
delta,
|
delta,
|
||||||
adjustDelta,
|
idelta,
|
||||||
adjustedDelta,
|
|
||||||
value,
|
value,
|
||||||
scrollbar.getMinimum(),
|
newValue,
|
||||||
scrollbar.getMaximum(),
|
minValue,
|
||||||
minDelta,
|
maxValue ) );
|
||||||
maxDelta,
|
|
||||||
boundedDelta,
|
|
||||||
newValue ) );
|
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user