Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smooth scrolling #150

Draft
wants to merge 30 commits into
base: main
Choose a base branch
from
Draft

Smooth scrolling #150

wants to merge 30 commits into from

Conversation

DevCharly
Copy link
Collaborator

@DevCharly DevCharly commented Aug 4, 2020

This PR adds smooth scrolling, as used in modern Web browsers, to FlatLaf. (issue #50)

Instead of simply painting scroll pane content at new view position, smooth scrolling animates the painting so that it looks like the content is "moving" to the new view position.

ssc2

Please try this with real world applications (on various platforms if possible) and give feedback. Thanks.

Current state:

  • rotating mouse wheel does smooth scrolling
  • clicking on scroll bar track (or arrows if visible) does smooth scrolling
  • pressing keys that scroll (e.g. PageUp, Home, etc) do smooth scrolling

Smooth scrolling is enabled by default.

Can be disabled for the whole application (at any time) with (e.g. via some Settings dialog):

UIManager.put( "ScrollPane.smoothScrolling", false );

Or via system property:

System.setProperty( "flatlaf.smoothScrolling", "false" );

Or at command line with:

-Dflatlaf.smoothScrolling=false

Can be disabled for single scroll panes (at any time) with:

myScrollPane.putClientProperty( "JScrollPane.smoothScrolling", false );

It is also possible to customize the animation by changing the duration of the scroll animation and the resolution (time between repaints). Both values are in milliseconds. E.g.

UIManager.put( "ScrollPane.smoothScrolling.duration", 500 );
UIManager.put( "ScrollPane.smoothScrolling.resolution", 20 );

Default duration is 200ms and default resolution is 10ms.

@grimlock81
Copy link

grimlock81 commented Aug 5, 2020

I've tested this on a 5000 row JTable (real world application) on Windows 10, haven't seen any issues wither either mouse scrolling or pressing on the scroll bar track.

However when holding down the arrows on the scroll bar (I have enabled them), 'smooth scrolling' looks jittery compared to non 'smooth scrolling'

With smooth scrolling

Without smooth scrolling (using 0.39)

@DevCharly
Copy link
Collaborator Author

@grimlock81 thx for your feedback.
Have to look at how to improve arrow button scrolling.
There are two timers involved (arrow button repeating and scroll animation), which do not play well together...

@DevCharly
Copy link
Collaborator Author

DevCharly commented Aug 12, 2020

Arrow button scrolling is now less jittery (but not perfect, I think).

Smooth scrolling with keyboard is now implemented.
Works for all keys that do any kind of scrolling.
It works perfect for non-repeating scrolling,
but for repeating block (page) scrolling (e.g. hold down PageUp key) the speed depends on the used view component:

  • JList and JTable same speed as with smooth scrolling disabled (plus 200 milliseconds for the scroll animation)
  • JTree, JTextArea, JTextPane about 2x slower with smooth scrolling enabled (fixed in commit 542e7d5)
  • JEditorPane about 2x - 3x slower (depending on number of wrapped lines) (fixed in commit 542e7d5)

This needs some improvements.

Repeating unit (line) scrolling (e.g. hold down Up key) works with same speed on all components and with smooth scrolling enabled or disabled.

Base automatically changed from master to main February 19, 2021 15:10
@Chrriis
Copy link
Contributor

Chrriis commented May 16, 2023

I am really interest in this feature. I am willing to play with it, test it on our intensive application and eventually experiment code changes if needed.
We are currently using the latest official version of FlatLaf. This PR is marked as having conflicts... Would it be possible to bring it up-to-date with all the changes so that I can experiment?

@Chrriis
Copy link
Contributor

Chrriis commented May 25, 2023

I experimented with this smooth-scrolling implementation. I first ported the few changes to the current code because the PR has some conflicts. The result of this port is FlatLaf-smooth-scrolling00.patch in the zip below (I only patched flatlaf-core).

I tested it on our real world app and found several problems (I am using Windows 10 with Java 17). I then created a self-contained test case (SmoothScrollingTest.java in the zip) to experiment with these problems.
I fixed some of these problems and created the improved FlatLaf-smooth-scrolling01.patch.

The root cause of the problems is that calls to JViewPort.setViewPosition() result in an immediate painting using blitting (meaning it is not handled later by the RepaintManager). So the adjustments that set the target value on the scroll bar before the timer kicks in result in a visible jump to an incorrect location. With my example and using the first patch, scrolling with the wheel when a selection is active makes the problem more visible. Another way is to use ctrl+up/down with a line that is selected and it is clear that the selection is sometimes painted at the wrong location.
I worked around most of the problems by changing (and then restoring) the blitting mode around the chunks that we know result in a call to JViewPort.setViewPosition() so that the blitting optimized repaint does not happen (but it will for the timed movements). This approach fixed mouse wheel, and I also added this pattern to fix keyboard navigation for trees. I haven't fixed table keyboard navigation because these are triggered by handlers declared in BasicTableUI and I am not sure how to wrap their call with the blitting mode swap.

Please let me know what you think, if you see the scrolling artifacts I am describing, and if you have some ideas to fix table artifacts with keyboard navigation.

Zip file: FlatLaf-smooth-scrolling.zip

@DevCharly
Copy link
Collaborator Author

This PR is marked as having conflicts... Would it be possible to bring it up-to-date with all the changes so that I can experiment?

Sure, I've rebased all commits in this PR to current main branch. Sorry for the delay.

... if you see the scrolling artifacts I am describing ...

Yes, I see the scrolling artifacts too.
And temporary disabling blitting mode seem indeed fix them.
Many thanks for that tip 👍 🥇
Have added parts of your code to this PR in commit 91e318f

Will have a closer look at your PR #683 next week...

@DevCharly DevCharly marked this pull request as draft June 5, 2023 23:05
…ing" to disable all animations or smooth scrolling via command line (without modifying the application)
…th Alt+S without moving focus to checkbox; removed unused tree model
- use ChangeListener instead of AdjustmentListener because this is invoked before all other scrollbar listeners (which may run 20-30ms) and avoids a delay in the line chart
- use System.nanoTime() instead of System.currentTimeMillis() for better precision
- paint vertical lines in chart at every 200ms (was 1sec)
- print elapsed time between scrollbar events
…h scrolling in case that scroll view does not implement Scrollable interface
…crolling when using mouse-wheel or scroll bar

(still occurs when scrolling by moving selection via keyboard)

many thanks to @Chrriis for the idea to temporary disable blitting mode on viewport
- added small vertical line to indicate data points in chart
- added split pane to allow changing height of components
- Alt+C clears chart without moving focus to "Clear" button
- separate chart lines for smooth and non-smooth scrolling
- added slider to horizontally scale chart
- improved chart legend
- record stack for points in chart and show in tooltip on hover
…g. hold down PageUp key) for Tree, TextArea, TextPane and EditorPane
@DevCharly
Copy link
Collaborator Author

The too slow repeating block (page) scrolling (e.g. hold down PageUp key) for Tree, TextArea, TextPane and EditorPane is fixed in commit 542e7d5

- fixed jittery repeating-scrolling with PageUp/Down keys when reaching the top/bottom/left/right of the viewport (see FlatScrollBarUI.setValueAnimated())
- temporary change viewport scroll mode only if it is JViewport.BLIT_SCROLL_MODE
- use JViewport.SIMPLE_SCROLL_MODE when temporary disabling blitting
@DevCharly
Copy link
Collaborator Author

Fixed jittery repeating-scrolling with PageUp/Down keys when reaching the top/bottom/left/right of the viewport in commit c529dcb.

Following screenshot shows the difference in the chart, which shows the scrollbar value.
The curve shows the animated change of the scroll bar value when holding down the PageDown key and scrolling from top to bottom. The "down-pikes" are the temporary scroll bar value changes made before animation starts/continues.

Before this change, there were significant gaps in the curve, which resulted in jittery scrolling.

grafik

- better list/tree/etc items for easier recognizing jittery scrolling
- sliders to modify animation duration and resolution
- slider to invoke `scrollRectToVisible()`
- option to show row header for table
- use viewport.viewPosition for chart (instead of scrollbar.value)
- highlight methods in stack of tooltip (e.g. JViewport.setViewPosition())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants