TabbedPane: fixed scrolling tabs with touchpads and high-resolution mouse wheels

This commit is contained in:
Karl Tauber
2021-01-18 18:34:21 +01:00
parent 74f50ec992
commit 0b880aa335
2 changed files with 59 additions and 8 deletions

View File

@@ -40,6 +40,8 @@ FlatLaf Change Log
`tab`) now respect explicitly set background color. `tab`) now respect explicitly set background color.
- TabbedPane: Fixed `IndexOutOfBoundsException` when using tooltip text on close - TabbedPane: Fixed `IndexOutOfBoundsException` when using tooltip text on close
buttons and closing last/rightmost tab. (issue #235) buttons and closing last/rightmost tab. (issue #235)
- TabbedPane: Fixed scrolling tabs with touchpads and high-resolution mouse
wheels.
- Extras: Added missing export of package - Extras: Added missing export of package
`com.formdev.flatlaf.extras.components` to Java 9 module descriptor. `com.formdev.flatlaf.extras.components` to Java 9 module descriptor.
- JIDE Common Layer: - JIDE Common Layer:

View File

@@ -221,6 +221,8 @@ public class FlatTabbedPaneUI
private Container leadingComponent; private Container leadingComponent;
private Container trailingComponent; private Container trailingComponent;
private Dimension scrollBackwardButtonPrefSize;
private Handler handler; private Handler handler;
private boolean blockRollover; private boolean blockRollover;
private boolean rolloverTabClose; private boolean rolloverTabClose;
@@ -1870,33 +1872,78 @@ public class FlatTabbedPaneUI
lastMouseY = e.getY(); lastMouseY = e.getY();
double preciseWheelRotation = e.getPreciseWheelRotation(); double preciseWheelRotation = e.getPreciseWheelRotation();
boolean isPreciseWheel = (preciseWheelRotation != 0 && preciseWheelRotation != e.getWheelRotation());
int amount = (int) (maxTabHeight * preciseWheelRotation); int amount = (int) (maxTabHeight * preciseWheelRotation);
// scroll at least one pixel to avoid "hanging"
if( amount == 0 ) {
if( preciseWheelRotation > 0 )
amount = 1;
else if( preciseWheelRotation < 0 )
amount = -1;
}
// compute new view position // compute new view position
Point viewPosition = (targetViewPosition != null) Point viewPosition = (targetViewPosition != null)
? targetViewPosition ? targetViewPosition
: tabViewport.getViewPosition(); : tabViewport.getViewPosition();
Dimension viewSize = tabViewport.getViewSize(); Dimension viewSize = tabViewport.getViewSize();
boolean horizontal = isHorizontalTabPlacement();
int x = viewPosition.x; int x = viewPosition.x;
int y = viewPosition.y; int y = viewPosition.y;
int tabPlacement = tabPane.getTabPlacement(); if( horizontal )
if( tabPlacement == TOP || tabPlacement == BOTTOM ) {
x += isLeftToRight() ? amount : -amount; x += isLeftToRight() ? amount : -amount;
x = Math.min( Math.max( x, 0 ), viewSize.width - tabViewport.getWidth() ); else
} else {
y += amount; y += amount;
y = Math.min( Math.max( y, 0 ), viewSize.height - tabViewport.getHeight() );
// In case of having scroll buttons on both sides and hiding disabled buttons,
// the viewport is moved when the scroll backward button becomes visible
// or is hidden. For non-precise wheel scrolling (e.g. mouse wheel on Windows),
// this is no problem because the scroll amount is at least a tab-height.
// For precise wheel scrolling (e.g. touchpad on Mac), this is a problem
// because it is possible to scroll by a fraction of a tab-height.
if( isPreciseWheel &&
getScrollButtonsPlacement() == BOTH &&
getScrollButtonsPolicy() == AS_NEEDED_SINGLE &&
(isLeftToRight() || !horizontal) || // scroll buttons are hidden in right-to-left
scrollBackwardButtonPrefSize != null )
{
// special cases for scrolling with touchpad or high-resolution wheel:
// 1. if view is at 0/0 and scrolling right/down, then the scroll backward button
// becomes visible, which moves the viewport right/down by the width/height of
// the button --> add button width/height to new view position so that
// tabs seems to stay in place at screen
// 2. if scrolling left/up to the beginning, then the scroll backward button
// becomes hidden, which moves the viewport left/up by the width/height of
// the button --> set new view position to 0/0 so that
// tabs seems to stay in place at screen
if( horizontal ) {
//
if( viewPosition.x == 0 && x > 0 )
x += scrollBackwardButtonPrefSize.width;
else if( amount < 0 && x <= scrollBackwardButtonPrefSize.width )
x = 0;
} else {
if( viewPosition.y == 0 && y > 0 )
y += scrollBackwardButtonPrefSize.height;
else if( amount < 0 && y <= scrollBackwardButtonPrefSize.height )
y = 0;
}
} }
// limit new view position
if( horizontal )
x = Math.min( Math.max( x, 0 ), viewSize.width - tabViewport.getWidth() );
else
y = Math.min( Math.max( y, 0 ), viewSize.height - tabViewport.getHeight() );
// check whether view position has changed // check whether view position has changed
Point newViewPosition = new Point( x, y ); Point newViewPosition = new Point( x, y );
if( newViewPosition.equals( viewPosition ) ) if( newViewPosition.equals( viewPosition ) )
return; return;
// update view position // update view position
if( preciseWheelRotation != 0 && if( isPreciseWheel ) {
preciseWheelRotation != e.getWheelRotation() )
{
// do not use animation for precise scrolling (e.g. with trackpad) // do not use animation for precise scrolling (e.g. with trackpad)
// stop running animation (if any) // stop running animation (if any)
@@ -2896,6 +2943,8 @@ public class FlatTabbedPaneUI
moreTabsButton.setVisible( moreTabsButtonVisible ); moreTabsButton.setVisible( moreTabsButtonVisible );
backwardButton.setVisible( backwardButtonVisible ); backwardButton.setVisible( backwardButtonVisible );
forwardButton.setVisible( forwardButtonVisible ); forwardButton.setVisible( forwardButtonVisible );
scrollBackwardButtonPrefSize = backwardButton.getPreferredSize();
} }
} }
} }