TabbedPane: support adding custom components to left and right sides of tabs area if wrap layout is used (issue #40)

This commit is contained in:
Karl Tauber
2020-10-17 18:17:45 +02:00
parent c34ce389a4
commit 3818790ced

View File

@@ -274,6 +274,8 @@ public class FlatTabbedPaneUI
} }
installHiddenTabsNavigation(); installHiddenTabsNavigation();
installLeadingComponent();
installTrailingComponent();
} }
@Override @Override
@@ -281,6 +283,8 @@ public class FlatTabbedPaneUI
// uninstall hidden tabs navigation before invoking super.uninstallComponents() for // uninstall hidden tabs navigation before invoking super.uninstallComponents() for
// correct uninstallation of BasicTabbedPaneUI tab scroller support // correct uninstallation of BasicTabbedPaneUI tab scroller support
uninstallHiddenTabsNavigation(); uninstallHiddenTabsNavigation();
uninstallLeadingComponent();
uninstallTrailingComponent();
super.uninstallComponents(); super.uninstallComponents();
@@ -302,9 +306,6 @@ public class FlatTabbedPaneUI
// create and add "more tabs" button // create and add "more tabs" button
moreTabsButton = createMoreTabsButton(); moreTabsButton = createMoreTabsButton();
tabPane.add( moreTabsButton ); tabPane.add( moreTabsButton );
installLeadingComponent();
installTrailingComponent();
} }
protected void uninstallHiddenTabsNavigation() { protected void uninstallHiddenTabsNavigation() {
@@ -317,9 +318,6 @@ public class FlatTabbedPaneUI
tabPane.remove( moreTabsButton ); tabPane.remove( moreTabsButton );
moreTabsButton = null; moreTabsButton = null;
} }
uninstallLeadingComponent();
uninstallTrailingComponent();
} }
protected void installLeadingComponent() { protected void installLeadingComponent() {
@@ -415,6 +413,14 @@ public class FlatTabbedPaneUI
return handler; return handler;
} }
@Override
protected LayoutManager createLayoutManager() {
if( tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT )
return new FlatTabbedPaneLayout();
return super.createLayoutManager();
}
protected LayoutManager createScrollLayoutManager( TabbedPaneLayout delegate ) { protected LayoutManager createScrollLayoutManager( TabbedPaneLayout delegate ) {
return new FlatTabbedPaneScrollLayout( delegate ); return new FlatTabbedPaneScrollLayout( delegate );
} }
@@ -480,6 +486,24 @@ public class FlatTabbedPaneUI
// Giving it large values clips painting of the cropped edge and makes it invisible. // Giving it large values clips painting of the cropped edge and makes it invisible.
currentTabAreaInsets.top = currentTabAreaInsets.left = -10000; currentTabAreaInsets.top = currentTabAreaInsets.left = -10000;
// increase insets for wrap layout if using leading/trailing components
if( tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT ) {
if( leadingComponent != null ) {
Dimension leadingSize = leadingComponent.getPreferredSize();
if( isHorizontalTabPlacement() )
insets.left += leadingSize.width;
else
insets.top += leadingSize.height;
}
if( trailingComponent != null ) {
Dimension trailingSize = trailingComponent.getPreferredSize();
if( isHorizontalTabPlacement() )
insets.right += trailingSize.width;
else
insets.bottom += trailingSize.height;
}
}
return insets; return insets;
} }
@@ -874,6 +898,22 @@ public class FlatTabbedPaneUI
((JComponent)tabViewport.getView()).scrollRectToVisible( (Rectangle) rects[selectedIndex].clone() ); ((JComponent)tabViewport.getView()).scrollRectToVisible( (Rectangle) rects[selectedIndex].clone() );
} }
private void shiftTabs( int sx, int sy ) {
if( sx == 0 && sy == 0 )
return;
for( int i = 0; i < rects.length; i++ ) {
// fix x location in rects
rects[i].x += sx;
rects[i].y += sy;
// fix tab component location
Component c = tabPane.getTabComponentAt( i );
if( c != null )
c.setLocation( c.getX() + sx, c.getY() + sy );
}
}
//---- class ContainerUIResource ------------------------------------------ //---- class ContainerUIResource ------------------------------------------
private class ContainerUIResource private class ContainerUIResource
@@ -1432,6 +1472,84 @@ public class FlatTabbedPaneUI
@Override public void componentHidden( ComponentEvent e ) {} @Override public void componentHidden( ComponentEvent e ) {}
} }
//---- class FlatTabbedPaneLayout -----------------------------------------
protected class FlatTabbedPaneLayout
extends TabbedPaneLayout
{
@Override
public void layoutContainer( Container parent ) {
super.layoutContainer( parent );
Rectangle bounds = tabPane.getBounds();
Insets insets = tabPane.getInsets();
int tabPlacement = tabPane.getTabPlacement();
Insets tabAreaInsets = getTabAreaInsets( tabPlacement );
boolean leftToRight = tabPane.getComponentOrientation().isLeftToRight();
// layout leading and trailing components in tab area
if( tabPlacement == TOP || tabPlacement == BOTTOM ) {
// tab area bounds
int tx = insets.left;
int ty = (tabPlacement == TOP)
? insets.top
: (bounds.height - insets.bottom - maxTabHeight - tabAreaInsets.top - tabAreaInsets.bottom);
int tw = bounds.width - insets.left - insets.right;
int th = maxTabHeight;
int tyi = ty + tabAreaInsets.top;
// layout left component
Container leftComponent = leftToRight ? leadingComponent : trailingComponent;
if( leftComponent != null ) {
int leftWidth = leftComponent.getPreferredSize().width;
leftComponent.setBounds( tx, tyi, leftWidth, th );
// reduce tab area bounds
tx += leftWidth;
tw -= leftWidth;
}
// layout right component
Container rightComponent = leftToRight ? trailingComponent : leadingComponent;
if( rightComponent != null ) {
int rightWidth = rightComponent.getPreferredSize().width;
rightComponent.setBounds( tx + tw - rightWidth, tyi, rightWidth, th );
}
// fix x-locations of tabs in right-to-left component orientation
if( !leftToRight )
shiftTabs( insets.left + tabAreaInsets.right, 0 );
} else { // LEFT, RIGHT
// tab area bounds
int tx = (tabPlacement == LEFT)
? insets.left
: (bounds.width - insets.right - maxTabWidth - tabAreaInsets.left - tabAreaInsets.right);
int ty = insets.top;
int tw = maxTabWidth;
int th = bounds.height - insets.top - insets.bottom;
int txi = tx + tabAreaInsets.left;
// layout top component
if( leadingComponent != null ) {
int topHeight = leadingComponent.getPreferredSize().height;
leadingComponent.setBounds( txi, ty, tw, topHeight );
// reduce tab area bounds
ty += topHeight;
th -= topHeight;
}
// layout bottom component
if( trailingComponent != null ) {
int bottomHeight = trailingComponent.getPreferredSize().height;
trailingComponent.setBounds( txi, ty + th - bottomHeight, tw, bottomHeight );
}
}
}
}
//---- class FlatTabbedPaneScrollLayout ----------------------------------- //---- class FlatTabbedPaneScrollLayout -----------------------------------
/** /**
@@ -1539,22 +1657,22 @@ public class FlatTabbedPaneUI
// layout left component // layout left component
Container leftComponent = leftToRight ? leadingComponent : trailingComponent; Container leftComponent = leftToRight ? leadingComponent : trailingComponent;
if( leftComponent != null ) { if( leftComponent != null ) {
Dimension leftSize = leftComponent.getPreferredSize(); int leftWidth = leftComponent.getPreferredSize().width;
leftComponent.setBounds( tx, tyi, leftSize.width, th ); leftComponent.setBounds( tx, tyi, leftWidth, th );
// reduce tab area bounds // reduce tab area bounds
tx += leftSize.width; tx += leftWidth;
tw -= leftSize.width; tw -= leftWidth;
} }
// layout right component // layout right component
Container rightComponent = leftToRight ? trailingComponent : leadingComponent; Container rightComponent = leftToRight ? trailingComponent : leadingComponent;
if( rightComponent != null ) { if( rightComponent != null ) {
Dimension rightSize = rightComponent.getPreferredSize(); int rightWidth = rightComponent.getPreferredSize().width;
rightComponent.setBounds( tx + tw - rightSize.width, tyi, rightSize.width, th ); rightComponent.setBounds( tx + tw - rightWidth, tyi, rightWidth, th );
// reduce tab area bounds // reduce tab area bounds
tw -= rightSize.width; tw -= rightWidth;
} }
int txi = tx + tabAreaInsets.left; int txi = tx + tabAreaInsets.left;
@@ -1601,21 +1719,21 @@ public class FlatTabbedPaneUI
// layout top component // layout top component
if( leadingComponent != null ) { if( leadingComponent != null ) {
Dimension topSize = leadingComponent.getPreferredSize(); int topHeight = leadingComponent.getPreferredSize().height;
leadingComponent.setBounds( txi, ty, tw, topSize.height ); leadingComponent.setBounds( txi, ty, tw, topHeight );
// reduce tab area bounds // reduce tab area bounds
ty += topSize.height; ty += topHeight;
th -= topSize.height; th -= topHeight;
} }
// layout bottom component // layout bottom component
if( trailingComponent != null ) { if( trailingComponent != null ) {
Dimension bottomSize = trailingComponent.getPreferredSize(); int bottomHeight = trailingComponent.getPreferredSize().height;
trailingComponent.setBounds( txi, ty + th - bottomSize.height, tw, bottomSize.height ); trailingComponent.setBounds( txi, ty + th - bottomHeight, tw, bottomHeight );
// reduce tab area bounds // reduce tab area bounds
th -= bottomSize.height; th -= bottomHeight;
} }
int tyi = ty + tabAreaInsets.top; int tyi = ty + tabAreaInsets.top;
@@ -1645,21 +1763,5 @@ public class FlatTabbedPaneUI
backwardButton.setVisible( !useMoreButton && buttonsVisible ); backwardButton.setVisible( !useMoreButton && buttonsVisible );
forwardButton.setVisible( !useMoreButton && buttonsVisible ); forwardButton.setVisible( !useMoreButton && buttonsVisible );
} }
private void shiftTabs( int sx, int sy ) {
if( sx == 0 && sy == 0 )
return;
for( int i = 0; i < rects.length; i++ ) {
// fix x location in rects
rects[i].x += sx;
rects[i].y += sy;
// fix tab component location
Component c = tabPane.getTabComponentAt( i );
if( c != null )
c.setLocation( c.getX() + sx, c.getY() + sy );
}
}
} }
} }