TabbedPane: make sure that tab stays hover highlighted when mouse is moved to custom tab component that handles mouse events (e.g. a close button)

refactored PropertyChangeListener to class Handler
This commit is contained in:
Karl Tauber
2020-10-09 10:19:17 +02:00
parent 5b0c96cd6d
commit eddb9eee46

View File

@@ -130,6 +130,8 @@ public class FlatTabbedPaneUI
protected JViewport tabViewport;
protected FlatWheelTabScroller wheelTabScroller;
private Handler handler;
public static ComponentUI createUI( JComponent c ) {
return new FlatTabbedPaneUI();
}
@@ -220,6 +222,8 @@ public class FlatTabbedPaneUI
protected void installListeners() {
super.installListeners();
tabPane.addMouseListener( getHandler() );
if( tabViewport != null && (wheelTabScroller = createWheelTabScroller()) != null ) {
// ideally we would add the mouse listeners to the viewport, but then the
// mouse listener of the tabbed pane would not receive events while
@@ -234,6 +238,11 @@ public class FlatTabbedPaneUI
protected void uninstallListeners() {
super.uninstallListeners();
if( handler != null ) {
tabPane.removeMouseListener( handler );
handler = null;
}
if( wheelTabScroller != null ) {
wheelTabScroller.uninstall();
@@ -244,28 +253,21 @@ public class FlatTabbedPaneUI
}
}
private Handler getHandler() {
if( handler == null )
handler = new Handler();
return handler;
}
protected FlatWheelTabScroller createWheelTabScroller() {
return new FlatWheelTabScroller();
}
@Override
protected PropertyChangeListener createPropertyChangeListener() {
return new BasicTabbedPaneUI.PropertyChangeHandler() {
@Override
public void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
switch( e.getPropertyName() ) {
case TABBED_PANE_SHOW_TAB_SEPARATORS:
case TABBED_PANE_SHOW_CONTENT_SEPARATOR:
case TABBED_PANE_HAS_FULL_BORDER:
case TABBED_PANE_TAB_HEIGHT:
tabPane.revalidate();
tabPane.repaint();
break;
}
}
};
Handler handler = getHandler();
handler.propertyChangeDelegate = super.createPropertyChangeListener();
return handler;
}
@Override
@@ -273,6 +275,10 @@ public class FlatTabbedPaneUI
return new FlatScrollableTabButton( direction );
}
protected void setRolloverTab( int x, int y ) {
setRolloverTab( tabForCoordinate( tabPane, x, y ) );
}
@Override
protected void setRolloverTab( int index ) {
int oldIndex = getRolloverTab();
@@ -701,7 +707,7 @@ public class FlatTabbedPaneUI
// do not use animation if disabled
if( !Animator.useAnimation() ) {
tabViewport.setViewPosition( viewPosition );
updateHover( lastMouseX, lastMouseY );
setRolloverTab( lastMouseX, lastMouseY );
return;
}
@@ -730,7 +736,7 @@ public class FlatTabbedPaneUI
startViewPosition = targetViewPosition = null;
if( tabPane != null )
updateHover( lastMouseX, lastMouseY );
setRolloverTab( lastMouseX, lastMouseY );
} );
animator.setResolution( resolution );
@@ -757,17 +763,13 @@ public class FlatTabbedPaneUI
@Override
public void mousePressed( MouseEvent e ) {
// for the case that the tab was only partly visible before the user clicked it
updateHover( e.getX(), e.getY() );
setRolloverTab( e.getX(), e.getY() );
}
protected boolean isInViewport( int x, int y ) {
return (tabViewport != null && tabViewport.getBounds().contains( x, y ) );
}
protected void updateHover( int x, int y ) {
setRolloverTab( tabForCoordinate( tabPane, x, y ) );
}
protected void checkViewportExited( int x, int y ) {
lastMouseX = x;
lastMouseY = y;
@@ -811,4 +813,36 @@ public class FlatTabbedPaneUI
}
}
}
//---- class Handler ------------------------------------------------------
private class Handler
extends MouseAdapter
implements PropertyChangeListener
{
PropertyChangeListener propertyChangeDelegate;
@Override
public void mouseExited( MouseEvent e ) {
// this event occurs also if mouse is moved to a custom tab component
// that handles mouse events (e.g. a close button)
// --> make sure that the tab stays highlighted
setRolloverTab( e.getX(), e.getY() );
}
@Override
public void propertyChange( PropertyChangeEvent e ) {
propertyChangeDelegate.propertyChange( e );
switch( e.getPropertyName() ) {
case TABBED_PANE_SHOW_TAB_SEPARATORS:
case TABBED_PANE_SHOW_CONTENT_SEPARATOR:
case TABBED_PANE_HAS_FULL_BORDER:
case TABBED_PANE_TAB_HEIGHT:
tabPane.revalidate();
tabPane.repaint();
break;
}
}
}
}