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 JViewport tabViewport;
protected FlatWheelTabScroller wheelTabScroller; protected FlatWheelTabScroller wheelTabScroller;
private Handler handler;
public static ComponentUI createUI( JComponent c ) { public static ComponentUI createUI( JComponent c ) {
return new FlatTabbedPaneUI(); return new FlatTabbedPaneUI();
} }
@@ -220,6 +222,8 @@ public class FlatTabbedPaneUI
protected void installListeners() { protected void installListeners() {
super.installListeners(); super.installListeners();
tabPane.addMouseListener( getHandler() );
if( tabViewport != null && (wheelTabScroller = createWheelTabScroller()) != null ) { if( tabViewport != null && (wheelTabScroller = createWheelTabScroller()) != null ) {
// ideally we would add the mouse listeners to the viewport, but then the // ideally we would add the mouse listeners to the viewport, but then the
// mouse listener of the tabbed pane would not receive events while // mouse listener of the tabbed pane would not receive events while
@@ -234,6 +238,11 @@ public class FlatTabbedPaneUI
protected void uninstallListeners() { protected void uninstallListeners() {
super.uninstallListeners(); super.uninstallListeners();
if( handler != null ) {
tabPane.removeMouseListener( handler );
handler = null;
}
if( wheelTabScroller != null ) { if( wheelTabScroller != null ) {
wheelTabScroller.uninstall(); wheelTabScroller.uninstall();
@@ -244,28 +253,21 @@ public class FlatTabbedPaneUI
} }
} }
private Handler getHandler() {
if( handler == null )
handler = new Handler();
return handler;
}
protected FlatWheelTabScroller createWheelTabScroller() { protected FlatWheelTabScroller createWheelTabScroller() {
return new FlatWheelTabScroller(); return new FlatWheelTabScroller();
} }
@Override @Override
protected PropertyChangeListener createPropertyChangeListener() { protected PropertyChangeListener createPropertyChangeListener() {
return new BasicTabbedPaneUI.PropertyChangeHandler() { Handler handler = getHandler();
@Override handler.propertyChangeDelegate = super.createPropertyChangeListener();
public void propertyChange( PropertyChangeEvent e ) { return handler;
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;
}
}
};
} }
@Override @Override
@@ -273,6 +275,10 @@ public class FlatTabbedPaneUI
return new FlatScrollableTabButton( direction ); return new FlatScrollableTabButton( direction );
} }
protected void setRolloverTab( int x, int y ) {
setRolloverTab( tabForCoordinate( tabPane, x, y ) );
}
@Override @Override
protected void setRolloverTab( int index ) { protected void setRolloverTab( int index ) {
int oldIndex = getRolloverTab(); int oldIndex = getRolloverTab();
@@ -701,7 +707,7 @@ public class FlatTabbedPaneUI
// do not use animation if disabled // do not use animation if disabled
if( !Animator.useAnimation() ) { if( !Animator.useAnimation() ) {
tabViewport.setViewPosition( viewPosition ); tabViewport.setViewPosition( viewPosition );
updateHover( lastMouseX, lastMouseY ); setRolloverTab( lastMouseX, lastMouseY );
return; return;
} }
@@ -730,7 +736,7 @@ public class FlatTabbedPaneUI
startViewPosition = targetViewPosition = null; startViewPosition = targetViewPosition = null;
if( tabPane != null ) if( tabPane != null )
updateHover( lastMouseX, lastMouseY ); setRolloverTab( lastMouseX, lastMouseY );
} ); } );
animator.setResolution( resolution ); animator.setResolution( resolution );
@@ -757,17 +763,13 @@ public class FlatTabbedPaneUI
@Override @Override
public void mousePressed( MouseEvent e ) { public void mousePressed( MouseEvent e ) {
// for the case that the tab was only partly visible before the user clicked it // 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 ) { protected boolean isInViewport( int x, int y ) {
return (tabViewport != null && tabViewport.getBounds().contains( x, 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 ) { protected void checkViewportExited( int x, int y ) {
lastMouseX = x; lastMouseX = x;
lastMouseY = y; 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;
}
}
}
} }