mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 22:10:54 +03:00
ScrollBar: support smooth scrolling via keyboard
This commit is contained in:
@@ -477,6 +477,7 @@ public class FlatScrollBarUI
|
|||||||
if( useValueIsAdjusting )
|
if( useValueIsAdjusting )
|
||||||
scrollbar.setValueIsAdjusting( true );
|
scrollbar.setValueIsAdjusting( true );
|
||||||
|
|
||||||
|
// remember current scrollbar value so that we can start scroll animation from there
|
||||||
int oldValue = scrollbar.getValue();
|
int oldValue = scrollbar.getValue();
|
||||||
|
|
||||||
// if invoked while animation is running, calculation of new value
|
// if invoked while animation is running, calculation of new value
|
||||||
@@ -488,31 +489,51 @@ public class FlatScrollBarUI
|
|||||||
|
|
||||||
// do not use animation if started dragging thumb
|
// do not use animation if started dragging thumb
|
||||||
if( isDragging ) {
|
if( isDragging ) {
|
||||||
|
// do not clear valueIsAdjusting here
|
||||||
inRunAndSetValueAnimated = false;
|
inRunAndSetValueAnimated = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int newValue = scrollbar.getValue();
|
int newValue = scrollbar.getValue();
|
||||||
if( newValue != oldValue ) {
|
if( newValue != oldValue ) {
|
||||||
scrollbar.setValue( oldValue );
|
// start scroll animation if value has changed
|
||||||
|
setValueAnimated( oldValue, newValue );
|
||||||
setValueAnimated( newValue );
|
} else {
|
||||||
} else if( useValueIsAdjusting )
|
// clear valueIsAdjusting if value has not changed
|
||||||
|
if( useValueIsAdjusting )
|
||||||
scrollbar.setValueIsAdjusting( false );
|
scrollbar.setValueIsAdjusting( false );
|
||||||
|
}
|
||||||
|
|
||||||
inRunAndSetValueAnimated = false;
|
inRunAndSetValueAnimated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean inRunAndSetValueAnimated;
|
private boolean inRunAndSetValueAnimated;
|
||||||
private Animator animator;
|
private Animator animator;
|
||||||
|
private int startValue = Integer.MIN_VALUE;
|
||||||
private int targetValue = Integer.MIN_VALUE;
|
private int targetValue = Integer.MIN_VALUE;
|
||||||
private int delta;
|
|
||||||
private boolean useValueIsAdjusting = true;
|
private boolean useValueIsAdjusting = true;
|
||||||
|
|
||||||
public void setValueAnimated( int value ) {
|
public void setValueAnimated( int initialValue, int value ) {
|
||||||
|
// do some check if animation already running
|
||||||
|
if( animator != null && animator.isRunning() && targetValue != Integer.MIN_VALUE ) {
|
||||||
|
// ignore requests if animation still running and scroll direction is the same
|
||||||
|
// and new value is within currently running animation
|
||||||
|
// (this may occur when repeat-scrolling via keyboard)
|
||||||
|
if( value == targetValue ||
|
||||||
|
(value > startValue && value < targetValue) || // scroll down/right
|
||||||
|
(value < startValue && value > targetValue) ) // scroll up/left
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( useValueIsAdjusting )
|
if( useValueIsAdjusting )
|
||||||
scrollbar.setValueIsAdjusting( true );
|
scrollbar.setValueIsAdjusting( true );
|
||||||
|
|
||||||
|
// set scrollbar value to initial value
|
||||||
|
scrollbar.setValue( initialValue );
|
||||||
|
|
||||||
|
startValue = initialValue;
|
||||||
|
targetValue = value;
|
||||||
|
|
||||||
// create animator
|
// create animator
|
||||||
if( animator == null ) {
|
if( animator == null ) {
|
||||||
int duration = FlatUIUtils.getUIInt( "ScrollPane.smoothScrolling.duration", 200 );
|
int duration = FlatUIUtils.getUIInt( "ScrollPane.smoothScrolling.duration", 200 );
|
||||||
@@ -521,7 +542,7 @@ public class FlatScrollBarUI
|
|||||||
|
|
||||||
animator = new Animator( duration, fraction -> {
|
animator = new Animator( duration, fraction -> {
|
||||||
if( scrollbar == null || !scrollbar.isShowing() ) {
|
if( scrollbar == null || !scrollbar.isShowing() ) {
|
||||||
animator.cancel();
|
animator.stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,10 +551,11 @@ public class FlatScrollBarUI
|
|||||||
if( useValueIsAdjusting && !scrollbar.getValueIsAdjusting() )
|
if( useValueIsAdjusting && !scrollbar.getValueIsAdjusting() )
|
||||||
scrollbar.setValueIsAdjusting( true );
|
scrollbar.setValueIsAdjusting( true );
|
||||||
|
|
||||||
scrollbar.setValue( targetValue - delta + Math.round( delta * fraction ) );
|
scrollbar.setValue( startValue + Math.round( (targetValue - startValue) * fraction ) );
|
||||||
}, () -> {
|
}, () -> {
|
||||||
targetValue = Integer.MIN_VALUE;
|
startValue = targetValue = Integer.MIN_VALUE;
|
||||||
if( useValueIsAdjusting )
|
|
||||||
|
if( useValueIsAdjusting && scrollbar != null )
|
||||||
scrollbar.setValueIsAdjusting( false );
|
scrollbar.setValueIsAdjusting( false );
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -543,9 +565,7 @@ public class FlatScrollBarUI
|
|||||||
: new CubicBezierEasing( 0.5f, 0.5f, 0.5f, 1 ) );
|
: new CubicBezierEasing( 0.5f, 0.5f, 0.5f, 1 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
targetValue = value;
|
// restart animator
|
||||||
delta = targetValue - scrollbar.getValue();
|
|
||||||
|
|
||||||
animator.cancel();
|
animator.cancel();
|
||||||
animator.start();
|
animator.start();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -453,6 +453,49 @@ public class FlatScrollPaneUI
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void syncScrollPaneWithViewport() {
|
||||||
|
if( isSmoothScrollingEnabled() ) {
|
||||||
|
runAndSyncScrollBarValueAnimated( scrollpane.getVerticalScrollBar(), 0, () -> {
|
||||||
|
runAndSyncScrollBarValueAnimated( scrollpane.getHorizontalScrollBar(), 1, () -> {
|
||||||
|
super.syncScrollPaneWithViewport();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
} else
|
||||||
|
super.syncScrollPaneWithViewport();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runAndSyncScrollBarValueAnimated( JScrollBar sb, int i, Runnable r ) {
|
||||||
|
if( inRunAndSyncValueAnimated[i] || sb == null ) {
|
||||||
|
r.run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inRunAndSyncValueAnimated[i] = true;
|
||||||
|
|
||||||
|
int oldValue = sb.getValue();
|
||||||
|
int oldVisibleAmount = sb.getVisibleAmount();
|
||||||
|
int oldMinimum = sb.getMinimum();
|
||||||
|
int oldMaximum = sb.getMaximum();
|
||||||
|
|
||||||
|
r.run();
|
||||||
|
|
||||||
|
int newValue = sb.getValue();
|
||||||
|
|
||||||
|
if( newValue != oldValue &&
|
||||||
|
sb.getVisibleAmount() == oldVisibleAmount &&
|
||||||
|
sb.getMinimum() == oldMinimum &&
|
||||||
|
sb.getMaximum() == oldMaximum &&
|
||||||
|
sb.getUI() instanceof FlatScrollBarUI )
|
||||||
|
{
|
||||||
|
((FlatScrollBarUI)sb.getUI()).setValueAnimated( oldValue, newValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
inRunAndSyncValueAnimated[i] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final boolean[] inRunAndSyncValueAnimated = new boolean[2];
|
||||||
|
|
||||||
//---- class Handler ------------------------------------------------------
|
//---- class Handler ------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user