mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-13 15:27:16 -06:00
TabbedPane: support adding custom components to left and right sides of tabs area if scroll backward/foreward buttons are used (issue #40)
this also fixes some minor layout issues when using tabAreaInsets and arrow buttons
This commit is contained in:
@@ -120,6 +120,8 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault TabbedPane.hiddenTabsNavigation String moreTabsButton (default) or arrowButtons
|
* @uiDefault TabbedPane.hiddenTabsNavigation String moreTabsButton (default) or arrowButtons
|
||||||
* @uiDefault ScrollPane.smoothScrolling boolean
|
* @uiDefault ScrollPane.smoothScrolling boolean
|
||||||
*
|
*
|
||||||
|
* @uiDefault TabbedPane.moreTabsButtonToolTipText String
|
||||||
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatTabbedPaneUI
|
public class FlatTabbedPaneUI
|
||||||
@@ -149,7 +151,7 @@ public class FlatTabbedPaneUI
|
|||||||
protected boolean tabSeparatorsFullHeight;
|
protected boolean tabSeparatorsFullHeight;
|
||||||
protected boolean hasFullBorder;
|
protected boolean hasFullBorder;
|
||||||
|
|
||||||
protected int hiddenTabsNavigation = MORE_TABS_BUTTON;
|
private String hiddenTabsNavigationStr;
|
||||||
|
|
||||||
protected String moreTabsButtonToolTipText;
|
protected String moreTabsButtonToolTipText;
|
||||||
|
|
||||||
@@ -207,6 +209,7 @@ public class FlatTabbedPaneUI
|
|||||||
showTabSeparators = UIManager.getBoolean( "TabbedPane.showTabSeparators" );
|
showTabSeparators = UIManager.getBoolean( "TabbedPane.showTabSeparators" );
|
||||||
tabSeparatorsFullHeight = UIManager.getBoolean( "TabbedPane.tabSeparatorsFullHeight" );
|
tabSeparatorsFullHeight = UIManager.getBoolean( "TabbedPane.tabSeparatorsFullHeight" );
|
||||||
hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" );
|
hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" );
|
||||||
|
hiddenTabsNavigationStr = UIManager.getString( "TabbedPane.hiddenTabsNavigation" );
|
||||||
|
|
||||||
Locale l = tabPane.getLocale();
|
Locale l = tabPane.getLocale();
|
||||||
moreTabsButtonToolTipText = UIManager.getString( "TabbedPane.moreTabsButtonToolTipText", l );
|
moreTabsButtonToolTipText = UIManager.getString( "TabbedPane.moreTabsButtonToolTipText", l );
|
||||||
@@ -285,16 +288,8 @@ public class FlatTabbedPaneUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void installHiddenTabsNavigation() {
|
protected void installHiddenTabsNavigation() {
|
||||||
// initialize here because used in installHiddenTabsNavigation() before installDefaults() was invoked
|
if( !isScrollTabLayout() || tabViewport == null )
|
||||||
String hiddenTabsNavigationStr = (String) tabPane.getClientProperty( TABBED_PANE_HIDDEN_TABS_NAVIGATION );
|
return;
|
||||||
if( hiddenTabsNavigationStr == null )
|
|
||||||
hiddenTabsNavigationStr = UIManager.getString( "TabbedPane.hiddenTabsNavigation" );
|
|
||||||
hiddenTabsNavigation = parseHiddenTabsNavigation( hiddenTabsNavigationStr );
|
|
||||||
|
|
||||||
if( hiddenTabsNavigation != MORE_TABS_BUTTON ||
|
|
||||||
!isScrollTabLayout() ||
|
|
||||||
tabViewport == null )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// At this point, BasicTabbedPaneUI already has installed
|
// At this point, BasicTabbedPaneUI already has installed
|
||||||
// TabbedPaneScrollLayout (in super.createLayoutManager()) and
|
// TabbedPaneScrollLayout (in super.createLayoutManager()) and
|
||||||
@@ -550,10 +545,9 @@ public class FlatTabbedPaneUI
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// clip title if "more tabs" button is used
|
// clip title if our layout manager is used
|
||||||
// (normally this is done by invoker, but fails in this case)
|
// (normally this is done by invoker, but fails in this case)
|
||||||
if( hiddenTabsNavigation == MORE_TABS_BUTTON &&
|
if( tabViewport != null &&
|
||||||
tabViewport != null &&
|
|
||||||
(tabPlacement == TOP || tabPlacement == BOTTOM) )
|
(tabPlacement == TOP || tabPlacement == BOTTOM) )
|
||||||
{
|
{
|
||||||
Rectangle viewRect = tabViewport.getViewRect();
|
Rectangle viewRect = tabViewport.getViewRect();
|
||||||
@@ -831,6 +825,13 @@ public class FlatTabbedPaneUI
|
|||||||
return UIManager.getBoolean( "ScrollPane.smoothScrolling" );
|
return UIManager.getBoolean( "ScrollPane.smoothScrolling" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected int getHiddenTabsNavigation() {
|
||||||
|
String hiddenTabsNavigationStr = (String) tabPane.getClientProperty( TABBED_PANE_HIDDEN_TABS_NAVIGATION );
|
||||||
|
if( hiddenTabsNavigationStr == null )
|
||||||
|
hiddenTabsNavigationStr = this.hiddenTabsNavigationStr;
|
||||||
|
return parseHiddenTabsNavigation( hiddenTabsNavigationStr );
|
||||||
|
}
|
||||||
|
|
||||||
protected static int parseHiddenTabsNavigation( String str ) {
|
protected static int parseHiddenTabsNavigation( String str ) {
|
||||||
if( str == null )
|
if( str == null )
|
||||||
return MORE_TABS_BUTTON;
|
return MORE_TABS_BUTTON;
|
||||||
@@ -1051,12 +1052,10 @@ public class FlatTabbedPaneUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dimension getPreferredSize() {
|
protected void fireActionPerformed( ActionEvent event ) {
|
||||||
Dimension size = super.getPreferredSize();
|
runWithOriginalLayoutManager( () -> {
|
||||||
boolean horizontal = (direction == WEST || direction == EAST);
|
super.fireActionPerformed( event );
|
||||||
return new Dimension(
|
} );
|
||||||
horizontal ? size.width : Math.max( size.width, maxTabWidth ),
|
|
||||||
horizontal ? Math.max( size.height, maxTabHeight ) : size.height );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1386,13 +1385,8 @@ public class FlatTabbedPaneUI
|
|||||||
case TABBED_PANE_SHOW_CONTENT_SEPARATOR:
|
case TABBED_PANE_SHOW_CONTENT_SEPARATOR:
|
||||||
case TABBED_PANE_HAS_FULL_BORDER:
|
case TABBED_PANE_HAS_FULL_BORDER:
|
||||||
case TABBED_PANE_TAB_HEIGHT:
|
case TABBED_PANE_TAB_HEIGHT:
|
||||||
tabPane.revalidate();
|
|
||||||
tabPane.repaint();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TABBED_PANE_HIDDEN_TABS_NAVIGATION:
|
case TABBED_PANE_HIDDEN_TABS_NAVIGATION:
|
||||||
uninstallHiddenTabsNavigation();
|
tabPane.revalidate();
|
||||||
installHiddenTabsNavigation();
|
|
||||||
tabPane.repaint();
|
tabPane.repaint();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1516,20 +1510,34 @@ public class FlatTabbedPaneUI
|
|||||||
delegate.layoutContainer( parent );
|
delegate.layoutContainer( parent );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// hide scroll buttons
|
boolean useMoreButton = (getHiddenTabsNavigation() == MORE_TABS_BUTTON);
|
||||||
|
|
||||||
|
// find backward/forward scroll buttons
|
||||||
|
JButton backwardButton = null;
|
||||||
|
JButton forwardButton = null;
|
||||||
for( Component c : tabPane.getComponents() ) {
|
for( Component c : tabPane.getComponents() ) {
|
||||||
if( c instanceof FlatScrollableTabButton && c.isVisible() )
|
if( c instanceof FlatScrollableTabButton ) {
|
||||||
c.setVisible( false );
|
int direction = ((FlatScrollableTabButton)c).getDirection();
|
||||||
|
if( direction == WEST || direction == NORTH )
|
||||||
|
backwardButton = (JButton) c;
|
||||||
|
else if( direction == EAST || direction == SOUTH )
|
||||||
|
forwardButton = (JButton) c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( !useMoreButton && (backwardButton == null || forwardButton == null) )
|
||||||
|
return; // should never occur
|
||||||
|
|
||||||
Rectangle bounds = tabPane.getBounds();
|
Rectangle bounds = tabPane.getBounds();
|
||||||
Insets insets = tabPane.getInsets();
|
Insets insets = tabPane.getInsets();
|
||||||
int tabPlacement = tabPane.getTabPlacement();
|
int tabPlacement = tabPane.getTabPlacement();
|
||||||
Insets tabAreaInsets = getTabAreaInsets( tabPlacement );
|
Insets tabAreaInsets = getTabAreaInsets( tabPlacement );
|
||||||
Rectangle lastRect = rects[rects.length - 1];
|
Rectangle lastRect = rects[rects.length - 1];
|
||||||
Dimension moreButtonSize = moreTabsButton.getPreferredSize();
|
Dimension moreButtonSize = useMoreButton ? moreTabsButton.getPreferredSize() : null;
|
||||||
|
Dimension backwardButtonSize = useMoreButton ? null : backwardButton.getPreferredSize();
|
||||||
|
Dimension forwardButtonSize = useMoreButton ? null : forwardButton.getPreferredSize();
|
||||||
boolean leftToRight = tabPane.getComponentOrientation().isLeftToRight();
|
boolean leftToRight = tabPane.getComponentOrientation().isLeftToRight();
|
||||||
boolean moreTabsButtonVisible = false;
|
boolean buttonsVisible = false;
|
||||||
|
|
||||||
// TabbedPaneScrollLayout adds tabAreaInsets to tab coordinates,
|
// TabbedPaneScrollLayout adds tabAreaInsets to tab coordinates,
|
||||||
// but we use it to position the viewport
|
// but we use it to position the viewport
|
||||||
@@ -1582,18 +1590,24 @@ public class FlatTabbedPaneUI
|
|||||||
int txi = tx + tabAreaInsets.left;
|
int txi = tx + tabAreaInsets.left;
|
||||||
int twi = tw - tabAreaInsets.left - tabAreaInsets.right;
|
int twi = tw - tabAreaInsets.left - tabAreaInsets.right;
|
||||||
|
|
||||||
// layout viewport and "more tabs" button
|
// layout viewport and buttons
|
||||||
int viewportWidth = twi;
|
int viewportWidth = twi;
|
||||||
int tabsWidth = leftToRight
|
int tabsWidth = leftToRight
|
||||||
? (lastRect.x + lastRect.width)
|
? (lastRect.x + lastRect.width)
|
||||||
: (rects[0].x + rects[0].width - lastRect.x);
|
: (rects[0].x + rects[0].width - lastRect.x);
|
||||||
if( viewportWidth < tabsWidth ) {
|
if( viewportWidth < tabsWidth ) {
|
||||||
// need "more tabs" button
|
// need buttons
|
||||||
viewportWidth = Math.max( viewportWidth - moreButtonSize.width, 0 );
|
buttonsVisible = true;
|
||||||
|
int buttonsWidth = useMoreButton ? moreButtonSize.width : (backwardButtonSize.width + forwardButtonSize.width);
|
||||||
|
viewportWidth = Math.max( viewportWidth - buttonsWidth, 0 );
|
||||||
|
|
||||||
moreTabsButton.setBounds( leftToRight ? (txi + twi - moreButtonSize.width) : txi, tyi, moreButtonSize.width, th );
|
if( useMoreButton )
|
||||||
tabViewport.setBounds( leftToRight ? txi : (txi + moreButtonSize.width), tyi, viewportWidth, th );
|
moreTabsButton.setBounds( leftToRight ? (txi + twi - buttonsWidth) : txi, tyi, moreButtonSize.width, th );
|
||||||
moreTabsButtonVisible = true;
|
else {
|
||||||
|
backwardButton.setBounds( leftToRight ? (txi + twi - buttonsWidth) : txi, tyi, backwardButtonSize.width, th );
|
||||||
|
forwardButton.setBounds( leftToRight ? (txi + twi - forwardButtonSize.width) : (txi + backwardButtonSize.width), tyi, forwardButtonSize.width, th );
|
||||||
|
}
|
||||||
|
tabViewport.setBounds( leftToRight ? txi : (txi + buttonsWidth), tyi, viewportWidth, th );
|
||||||
} else
|
} else
|
||||||
tabViewport.setBounds( txi, tyi, viewportWidth, th );
|
tabViewport.setBounds( txi, tyi, viewportWidth, th );
|
||||||
|
|
||||||
@@ -1637,21 +1651,29 @@ public class FlatTabbedPaneUI
|
|||||||
int tyi = ty + tabAreaInsets.top;
|
int tyi = ty + tabAreaInsets.top;
|
||||||
int thi = th - tabAreaInsets.top - tabAreaInsets.bottom;
|
int thi = th - tabAreaInsets.top - tabAreaInsets.bottom;
|
||||||
|
|
||||||
// layout viewport and "more tabs" button
|
// layout viewport and buttons
|
||||||
int viewportHeight = thi;
|
int viewportHeight = thi;
|
||||||
int tabsHeight = lastRect.y + lastRect.height;
|
int tabsHeight = lastRect.y + lastRect.height;
|
||||||
if( viewportHeight < tabsHeight ) {
|
if( viewportHeight < tabsHeight ) {
|
||||||
// need "more tabs" button
|
// need buttons
|
||||||
viewportHeight = Math.max( viewportHeight - moreButtonSize.height, 0 );
|
buttonsVisible = true;
|
||||||
|
int buttonsHeight = useMoreButton ? moreButtonSize.height : (backwardButtonSize.height + forwardButtonSize.height);
|
||||||
|
viewportHeight = Math.max( viewportHeight - buttonsHeight, 0 );
|
||||||
|
|
||||||
moreTabsButton.setBounds( txi, tyi + thi - moreButtonSize.height, tw, moreButtonSize.height );
|
if( useMoreButton )
|
||||||
moreTabsButtonVisible = true;
|
moreTabsButton.setBounds( txi, tyi + thi - buttonsHeight, tw, moreButtonSize.height );
|
||||||
|
else {
|
||||||
|
backwardButton.setBounds( txi, tyi + thi - buttonsHeight, tw, backwardButtonSize.height );
|
||||||
|
forwardButton.setBounds( txi, tyi + thi - forwardButtonSize.height, tw, forwardButtonSize.height );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tabViewport.setBounds( txi, tyi, tw, viewportHeight );
|
tabViewport.setBounds( txi, tyi, tw, viewportHeight );
|
||||||
}
|
}
|
||||||
|
|
||||||
// show/hide "more tabs" button
|
// show/hide buttons
|
||||||
moreTabsButton.setVisible( moreTabsButtonVisible );
|
moreTabsButton.setVisible( useMoreButton && buttonsVisible );
|
||||||
|
backwardButton.setVisible( !useMoreButton && buttonsVisible );
|
||||||
|
forwardButton.setVisible( !useMoreButton && buttonsVisible );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void shiftTabs( int sx, int sy ) {
|
private void shiftTabs( int sx, int sy ) {
|
||||||
|
|||||||
Reference in New Issue
Block a user