TabbedPane: support alignment of tab area (leading, trailing, center or fill)

This commit is contained in:
Karl Tauber
2020-10-29 16:11:30 +01:00
parent 71b1e07ba6
commit 0374c65159
10 changed files with 453 additions and 196 deletions

View File

@@ -21,6 +21,9 @@ FlatLaf Change Log
- TabbedPane: Support closable tabs. (PR #193; issues #31 and #40) - TabbedPane: Support closable tabs. (PR #193; issues #31 and #40)
- TabbedPane: Support minimum or maximum tab widths. (set client property - TabbedPane: Support minimum or maximum tab widths. (set client property
`JTabbedPane.minimumTabWidth` or `JTabbedPane.maximumTabWidth` to an integer) `JTabbedPane.minimumTabWidth` or `JTabbedPane.maximumTabWidth` to an integer)
- TabbedPane: Support alignment of tab area. (set client property
`JTabbedPane.tabAreaAlignment` to `"leading"`, `"trailing"`, `"center"` or
`"fill"`)
- Support painting separator line between window title and content (use UI value - Support painting separator line between window title and content (use UI value
`TitlePane.borderColor`). (issue #184) `TitlePane.borderColor`). (issue #184)
- Extras: `FlatSVGIcon` now allows specifying icon width and height in - Extras: `FlatSVGIcon` now allows specifying icon width and height in

View File

@@ -371,6 +371,45 @@ public interface FlatClientProperties
*/ */
String TABBED_PANE_HIDDEN_TABS_NAVIGATION_ARROW_BUTTONS = "arrowButtons"; String TABBED_PANE_HIDDEN_TABS_NAVIGATION_ARROW_BUTTONS = "arrowButtons";
/**
* Specifies the alignment of the tab area.
* <p>
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
* <strong>Value type</strong> {@link java.lang.String}
* <strong>Allowed Values</strong> {@link #TABBED_PANE_TAB_AREA_ALIGN_LEADING} (default),
* {@link #TABBED_PANE_TAB_AREA_ALIGN_TRAILING}, {@link #TABBED_PANE_TAB_AREA_ALIGN_CENTER}
* or {@link #TABBED_PANE_TAB_AREA_ALIGN_FILL}
*/
String TABBED_PANE_TAB_AREA_ALIGNMENT = "JTabbedPane.tabAreaAlignment";
/**
* Align the tab area to the leading edge.
*
* @see #TABBED_PANE_TAB_AREA_ALIGNMENT
*/
String TABBED_PANE_TAB_AREA_ALIGN_LEADING = "leading";
/**
* Align the tab area to the trailing edge.
*
* @see #TABBED_PANE_TAB_AREA_ALIGNMENT
*/
String TABBED_PANE_TAB_AREA_ALIGN_TRAILING = "trailing";
/**
* Align the tab area to center.
*
* @see #TABBED_PANE_TAB_AREA_ALIGNMENT
*/
String TABBED_PANE_TAB_AREA_ALIGN_CENTER = "center";
/**
* Stretch tabs to fill all available space.
*
* @see #TABBED_PANE_TAB_AREA_ALIGNMENT
*/
String TABBED_PANE_TAB_AREA_ALIGN_FILL = "fill";
/** /**
* Specifies a component that will be placed at the leading edge of the tabs area. * Specifies a component that will be placed at the leading edge of the tabs area.
* <p> * <p>

View File

@@ -127,6 +127,7 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault TabbedPane.tabSeparatorsFullHeight boolean * @uiDefault TabbedPane.tabSeparatorsFullHeight boolean
* @uiDefault TabbedPane.hasFullBorder boolean * @uiDefault TabbedPane.hasFullBorder boolean
* @uiDefault TabbedPane.hiddenTabsNavigation String moreTabsButton (default) or arrowButtons * @uiDefault TabbedPane.hiddenTabsNavigation String moreTabsButton (default) or arrowButtons
* @uiDefault TabbedPane.tabAreaAlignment String leading (default), center, trailing or fill
* @uiDefault ScrollPane.smoothScrolling boolean * @uiDefault ScrollPane.smoothScrolling boolean
* @uiDefault TabbedPane.closeIcon Icon * @uiDefault TabbedPane.closeIcon Icon
* *
@@ -141,6 +142,12 @@ public class FlatTabbedPaneUI
protected static final int MORE_TABS_BUTTON = 0; protected static final int MORE_TABS_BUTTON = 0;
protected static final int ARROW_BUTTONS = 1; protected static final int ARROW_BUTTONS = 1;
// tab area alignment
protected static final int ALIGN_LEADING = 0;
protected static final int ALIGN_TRAILING = 1;
protected static final int ALIGN_CENTER = 2;
protected static final int ALIGN_FILL = 3;
private static Set<KeyStroke> focusForwardTraversalKeys; private static Set<KeyStroke> focusForwardTraversalKeys;
private static Set<KeyStroke> focusBackwardTraversalKeys; private static Set<KeyStroke> focusBackwardTraversalKeys;
@@ -166,6 +173,7 @@ public class FlatTabbedPaneUI
protected boolean tabsOpaque = true; protected boolean tabsOpaque = true;
private String hiddenTabsNavigationStr; private String hiddenTabsNavigationStr;
private String tabAreaAlignmentStr;
protected Icon closeIcon; protected Icon closeIcon;
protected String moreTabsButtonToolTipText; protected String moreTabsButtonToolTipText;
@@ -232,6 +240,7 @@ public class FlatTabbedPaneUI
hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" ); hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" );
tabsOpaque = UIManager.getBoolean( "TabbedPane.tabsOpaque" ); tabsOpaque = UIManager.getBoolean( "TabbedPane.tabsOpaque" );
hiddenTabsNavigationStr = UIManager.getString( "TabbedPane.hiddenTabsNavigation" ); hiddenTabsNavigationStr = UIManager.getString( "TabbedPane.hiddenTabsNavigation" );
tabAreaAlignmentStr = UIManager.getString( "TabbedPane.tabAreaAlignment" );
closeIcon = UIManager.getIcon( "TabbedPane.closeIcon" ); closeIcon = UIManager.getIcon( "TabbedPane.closeIcon" );
Locale l = tabPane.getLocale(); Locale l = tabPane.getLocale();
@@ -548,24 +557,6 @@ public class FlatTabbedPaneUI
return Math.max( tabHeight, super.calculateTabHeight( tabPlacement, tabIndex, fontHeight ) - 2 /* was added by superclass */ ); return Math.max( tabHeight, super.calculateTabHeight( tabPlacement, tabIndex, fontHeight ) - 2 /* was added by superclass */ );
} }
protected int calculateMaxExtrasWidth() {
int width = 0;
if( leadingComponent != null )
width = Math.max( width, leadingComponent.getPreferredSize().width );
if( trailingComponent != null )
width = Math.max( width, trailingComponent.getPreferredSize().width );
return width;
}
protected int calculateMaxExtrasHeight() {
int height = 0;
if( leadingComponent != null )
height = Math.max( height, leadingComponent.getPreferredSize().height );
if( trailingComponent != null )
height = Math.max( height, trailingComponent.getPreferredSize().height );
return height;
}
@Override @Override
protected Insets getTabInsets( int tabPlacement, int tabIndex ) { protected Insets getTabInsets( int tabPlacement, int tabIndex ) {
Object value = getTabClientProperty( tabIndex, TABBED_PANE_TAB_INSETS ); Object value = getTabClientProperty( tabIndex, TABBED_PANE_TAB_INSETS );
@@ -579,8 +570,7 @@ public class FlatTabbedPaneUI
return new Insets( 0, 0, 0, 0 ); return new Insets( 0, 0, 0, 0 );
} }
@Override protected Insets getRealTabAreaInsets( int tabPlacement ) {
protected Insets getTabAreaInsets( int tabPlacement ) {
Insets currentTabAreaInsets = super.getTabAreaInsets( tabPlacement ); Insets currentTabAreaInsets = super.getTabAreaInsets( tabPlacement );
Insets insets = (Insets) currentTabAreaInsets.clone(); Insets insets = (Insets) currentTabAreaInsets.clone();
@@ -594,21 +584,21 @@ public class FlatTabbedPaneUI
// scale insets (before adding leading/trailing component sizes) // scale insets (before adding leading/trailing component sizes)
insets = scale( insets ); insets = scale( insets );
return insets;
}
@Override
protected Insets getTabAreaInsets( int tabPlacement ) {
Insets insets = getRealTabAreaInsets( tabPlacement );
// increase insets for wrap layout if using leading/trailing components // increase insets for wrap layout if using leading/trailing components
if( tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT ) { if( tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT ) {
if( leadingComponent != null ) { if( isHorizontalTabPlacement() ) {
Dimension leadingSize = leadingComponent.getPreferredSize(); insets.left += getLeadingPreferredWidth();
if( isHorizontalTabPlacement() ) insets.right += getTrailingPreferredWidth();
insets.left += leadingSize.width; } else {
else insets.top += getLeadingPreferredHeight();
insets.top += leadingSize.height; insets.bottom += getTrailingPreferredHeight();
}
if( trailingComponent != null ) {
Dimension trailingSize = trailingComponent.getPreferredSize();
if( isHorizontalTabPlacement() )
insets.right += trailingSize.width;
else
insets.bottom += trailingSize.height;
} }
} }
@@ -1101,10 +1091,17 @@ public class FlatTabbedPaneUI
} }
protected int getHiddenTabsNavigation() { protected int getHiddenTabsNavigation() {
String hiddenTabsNavigationStr = (String) tabPane.getClientProperty( TABBED_PANE_HIDDEN_TABS_NAVIGATION ); String str = (String) tabPane.getClientProperty( TABBED_PANE_HIDDEN_TABS_NAVIGATION );
if( hiddenTabsNavigationStr == null ) if( str == null )
hiddenTabsNavigationStr = this.hiddenTabsNavigationStr; str = hiddenTabsNavigationStr;
return parseHiddenTabsNavigation( hiddenTabsNavigationStr ); return parseHiddenTabsNavigation( str );
}
protected int getTabAreaAlignment() {
String str = (String) tabPane.getClientProperty( TABBED_PANE_TAB_AREA_ALIGNMENT );
if( str == null )
str = tabAreaAlignmentStr;
return parseTabAreaAlignment( str );
} }
protected static int parseHiddenTabsNavigation( String str ) { protected static int parseHiddenTabsNavigation( String str ) {
@@ -1113,8 +1110,21 @@ public class FlatTabbedPaneUI
switch( str ) { switch( str ) {
default: default:
case "moreTabsButton": return MORE_TABS_BUTTON; case TABBED_PANE_HIDDEN_TABS_NAVIGATION_MORE_TABS_BUTTON: return MORE_TABS_BUTTON;
case "arrowButtons": return ARROW_BUTTONS; case TABBED_PANE_HIDDEN_TABS_NAVIGATION_ARROW_BUTTONS: return ARROW_BUTTONS;
}
}
protected static int parseTabAreaAlignment( String str ) {
if( str == null )
return ALIGN_LEADING;
switch( str ) {
default:
case TABBED_PANE_TAB_AREA_ALIGN_LEADING: return ALIGN_LEADING;
case TABBED_PANE_TAB_AREA_ALIGN_TRAILING: return ALIGN_TRAILING;
case TABBED_PANE_TAB_AREA_ALIGN_CENTER: return ALIGN_CENTER;
case TABBED_PANE_TAB_AREA_ALIGN_FILL: return ALIGN_FILL;
} }
} }
@@ -1149,6 +1159,22 @@ public class FlatTabbedPaneUI
((JComponent)tabViewport.getView()).scrollRectToVisible( (Rectangle) rects[selectedIndex].clone() ); ((JComponent)tabViewport.getView()).scrollRectToVisible( (Rectangle) rects[selectedIndex].clone() );
} }
private int getLeadingPreferredWidth() {
return (leadingComponent != null) ? leadingComponent.getPreferredSize().width : 0;
}
private int getLeadingPreferredHeight() {
return (leadingComponent != null) ? leadingComponent.getPreferredSize().height : 0;
}
private int getTrailingPreferredWidth() {
return (trailingComponent != null) ? trailingComponent.getPreferredSize().width : 0;
}
private int getTrailingPreferredHeight() {
return (trailingComponent != null) ? trailingComponent.getPreferredSize().height : 0;
}
private void shiftTabs( int sx, int sy ) { private void shiftTabs( int sx, int sy ) {
if( sx == 0 && sy == 0 ) if( sx == 0 && sy == 0 )
return; return;
@@ -1165,6 +1191,64 @@ public class FlatTabbedPaneUI
} }
} }
private void stretchTabsWidth( int sw, boolean leftToRight ) {
int rsw = sw / rects.length;
int x = rects[0].x - (leftToRight ? 0 : rsw);
for( int i = 0; i < rects.length; i++ ) {
// fix tab component location
Component c = tabPane.getTabComponentAt( i );
if( c != null )
c.setLocation( x + (c.getX() - rects[i].x) + (rsw / 2), c.getY() );
// fix x location and width in rects
rects[i].x = x;
rects[i].width += rsw;
if( leftToRight )
x += rects[i].width;
else if( i + 1 < rects.length )
x = rects[i].x - rects[i+1].width - rsw;
}
// fix width of last tab
int diff = sw - (rsw * rects.length);
rects[rects.length-1].width += diff;
if( !leftToRight )
rects[rects.length-1].x -= diff;
}
private void stretchTabsHeight( int sh ) {
int rsh = sh / rects.length;
int y = rects[0].y;
for( int i = 0; i < rects.length; i++ ) {
// fix tab component location
Component c = tabPane.getTabComponentAt( i );
if( c != null )
c.setLocation( c.getX(), y + (c.getY() - rects[i].y) + (rsh / 2) );
// fix y location and height in rects
rects[i].y = y;
rects[i].height += rsh;
y += rects[i].height;
}
// fix height of last tab
rects[rects.length-1].height += (sh - (rsh * rects.length));
}
private int rectsTotalWidth( boolean leftToRight ) {
int last = rects.length - 1;
return leftToRight
? (rects[last].x + rects[last].width) - rects[0].x
: (rects[0].x + rects[0].width) - rects[last].x;
}
private int rectsTotalHeight() {
int last = rects.length - 1;
return (rects[last].y + rects[last].height) - rects[0].y;
}
//---- class TabCloseButton ----------------------------------------------- //---- class TabCloseButton -----------------------------------------------
private class TabCloseButton private class TabCloseButton
@@ -1796,6 +1880,7 @@ public class FlatTabbedPaneUI
case TABBED_PANE_TAB_HEIGHT: case TABBED_PANE_TAB_HEIGHT:
case TABBED_PANE_TAB_INSETS: case TABBED_PANE_TAB_INSETS:
case TABBED_PANE_HIDDEN_TABS_NAVIGATION: case TABBED_PANE_HIDDEN_TABS_NAVIGATION:
case TABBED_PANE_TAB_AREA_ALIGNMENT:
case TABBED_PANE_TAB_CLOSABLE: case TABBED_PANE_TAB_CLOSABLE:
tabPane.revalidate(); tabPane.revalidate();
tabPane.repaint(); tabPane.repaint();
@@ -1883,19 +1968,22 @@ public class FlatTabbedPaneUI
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 ); int tabAreaAlignment = getTabAreaAlignment();
Insets tabAreaInsets = getRealTabAreaInsets( tabPlacement );
boolean leftToRight = isLeftToRight(); boolean leftToRight = isLeftToRight();
// layout leading and trailing components in tab area // layout leading and trailing components in tab area
if( tabPlacement == TOP || tabPlacement == BOTTOM ) { if( tabPlacement == TOP || tabPlacement == BOTTOM ) {
// fix x-locations of tabs in right-to-left component orientation // fix x-locations of tabs in right-to-left component orientation
if( !leftToRight ) if( !leftToRight )
shiftTabs( insets.left + tabAreaInsets.right, 0 ); shiftTabs( insets.left + tabAreaInsets.right + getTrailingPreferredWidth(), 0 );
// tab area height (maxTabHeight is zero if tab count is zero) // tab area height (maxTabHeight is zero if tab count is zero)
int tabAreaHeight = (maxTabHeight > 0) int tabAreaHeight = (maxTabHeight > 0)
? maxTabHeight ? maxTabHeight
: Math.max( calculateMaxExtrasHeight(), scale( clientPropertyInt( tabPane, TABBED_PANE_TAB_HEIGHT, tabHeight ) ) ); : Math.max(
Math.max( getLeadingPreferredHeight(), getTrailingPreferredHeight() ),
scale( clientPropertyInt( tabPane, TABBED_PANE_TAB_HEIGHT, tabHeight ) ) );
// tab area bounds // tab area bounds
int tx = insets.left; int tx = insets.left;
@@ -1905,38 +1993,56 @@ public class FlatTabbedPaneUI
int tw = bounds.width - insets.left - insets.right; int tw = bounds.width - insets.left - insets.right;
int th = tabAreaHeight; int th = tabAreaHeight;
int leadingWidth = getLeadingPreferredWidth();
int trailingWidth = getTrailingPreferredWidth();
// apply tab area alignment
if( runCount == 1 && rects.length > 0 ) {
int availWidth = tw - leadingWidth - trailingWidth - tabAreaInsets.left - tabAreaInsets.right;
int totalTabWidth = rectsTotalWidth( leftToRight );
int diff = availWidth - totalTabWidth;
switch( tabAreaAlignment ) {
case ALIGN_LEADING:
trailingWidth += diff;
break;
case ALIGN_TRAILING:
shiftTabs( leftToRight ? diff : -diff, 0 );
leadingWidth += diff;
break;
case ALIGN_CENTER:
shiftTabs( (leftToRight ? diff : -diff) / 2, 0 );
leadingWidth += diff / 2;
trailingWidth += diff - (diff / 2);
break;
case ALIGN_FILL:
stretchTabsWidth( diff, leftToRight );
break;
}
} else if( rects.length == 0 )
trailingWidth = tw - leadingWidth;
// layout left component // layout left component
Container leftComponent = leftToRight ? leadingComponent : trailingComponent; Container leftComponent = leftToRight ? leadingComponent : trailingComponent;
if( leftComponent != null ) { if( leftComponent != null ) {
// trailing component fills all available horizontal space int leftWidth = leftToRight ? leadingWidth : trailingWidth;
int leftWidth = leftToRight
? leftComponent.getPreferredSize().width
: (rects.length > 0
? rects[rects.length-1].x - tx
- (tabAreaInsets.right - trailingComponent.getPreferredSize().width)
: tw - (leadingComponent != null ? leadingComponent.getPreferredSize().width : 0));
leftComponent.setBounds( tx, ty, leftWidth, th ); leftComponent.setBounds( tx, ty, leftWidth, th );
// reduce tab area bounds
tx += leftWidth;
tw -= leftWidth;
} }
// layout right component // layout right component
Container rightComponent = leftToRight ? trailingComponent : leadingComponent; Container rightComponent = leftToRight ? trailingComponent : leadingComponent;
if( rightComponent != null ) { if( rightComponent != null ) {
// trailing component fills all available horizontal space int rightWidth = leftToRight ? trailingWidth : leadingWidth;
int rightWidth = !leftToRight
? rightComponent.getPreferredSize().width
: (rects.length > 0
? tx + tw - (rects[rects.length-1].x + rects[rects.length-1].width)
- (tabAreaInsets.right - trailingComponent.getPreferredSize().width)
: tw);
rightComponent.setBounds( tx + tw - rightWidth, ty, rightWidth, th ); rightComponent.setBounds( tx + tw - rightWidth, ty, rightWidth, th );
} }
} else { // LEFT and RIGHT tab placement } else { // LEFT and RIGHT tab placement
// tab area width (maxTabWidth is zero if tab count is zero) // tab area width (maxTabWidth is zero if tab count is zero)
int tabAreaWidth = (maxTabWidth > 0) ? maxTabWidth : calculateMaxExtrasWidth(); int tabAreaWidth = (maxTabWidth > 0)
? maxTabWidth
: Math.max( getLeadingPreferredWidth(), getTrailingPreferredWidth() );
// tab area bounds // tab area bounds
int tx = (tabPlacement == LEFT) int tx = (tabPlacement == LEFT)
@@ -1946,25 +2052,45 @@ public class FlatTabbedPaneUI
int tw = tabAreaWidth; int tw = tabAreaWidth;
int th = bounds.height - insets.top - insets.bottom; int th = bounds.height - insets.top - insets.bottom;
int topHeight = getLeadingPreferredHeight();
int bottomHeight = getTrailingPreferredHeight();
// apply tab area alignment
if( runCount == 1 && rects.length > 0 ) {
int availHeight = th - topHeight - bottomHeight - tabAreaInsets.top - tabAreaInsets.bottom;
int totalTabHeight = rectsTotalHeight();
int diff = availHeight - totalTabHeight;
switch( tabAreaAlignment ) {
case ALIGN_LEADING:
bottomHeight += diff;
break;
case ALIGN_TRAILING:
shiftTabs( 0, diff );
topHeight += diff;
break;
case ALIGN_CENTER:
shiftTabs( 0, (diff) / 2 );
topHeight += diff / 2;
bottomHeight += diff - (diff / 2);
break;
case ALIGN_FILL:
stretchTabsHeight( diff );
break;
}
} else if( rects.length == 0 )
bottomHeight = th - topHeight;
// layout top component // layout top component
if( leadingComponent != null ) { if( leadingComponent != null )
int topHeight = leadingComponent.getPreferredSize().height;
leadingComponent.setBounds( tx, ty, tw, topHeight ); leadingComponent.setBounds( tx, ty, tw, topHeight );
// reduce tab area bounds
ty += topHeight;
th -= topHeight;
}
// layout bottom component // layout bottom component
if( trailingComponent != null ) { if( trailingComponent != null )
// trailing component fills all available vertical space
int bottomHeight = (rects.length > 0)
? ty + th - (rects[rects.length-1].y + rects[rects.length-1].height)
- (tabAreaInsets.bottom - trailingComponent.getPreferredSize().height)
: th;
trailingComponent.setBounds( tx, ty + th - bottomHeight, tw, bottomHeight ); trailingComponent.setBounds( tx, ty + th - bottomHeight, tw, bottomHeight );
}
} }
} }
} }
@@ -2045,7 +2171,8 @@ public class FlatTabbedPaneUI
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 ); int tabAreaAlignment = getTabAreaAlignment();
Insets tabAreaInsets = getRealTabAreaInsets( tabPlacement );
Dimension moreButtonSize = useMoreButton ? moreTabsButton.getPreferredSize() : null; Dimension moreButtonSize = useMoreButton ? moreTabsButton.getPreferredSize() : null;
Dimension backwardButtonSize = useMoreButton ? null : backwardButton.getPreferredSize(); Dimension backwardButtonSize = useMoreButton ? null : backwardButton.getPreferredSize();
Dimension forwardButtonSize = useMoreButton ? null : forwardButton.getPreferredSize(); Dimension forwardButtonSize = useMoreButton ? null : forwardButton.getPreferredSize();
@@ -2071,7 +2198,9 @@ public class FlatTabbedPaneUI
// tab area height (maxTabHeight is zero if tab count is zero) // tab area height (maxTabHeight is zero if tab count is zero)
int tabAreaHeight = (maxTabHeight > 0) int tabAreaHeight = (maxTabHeight > 0)
? maxTabHeight ? maxTabHeight
: Math.max( calculateMaxExtrasHeight(), scale( clientPropertyInt( tabPane, TABBED_PANE_TAB_HEIGHT, tabHeight ) ) ); : Math.max(
Math.max( getLeadingPreferredHeight(), getTrailingPreferredHeight() ),
scale( clientPropertyInt( tabPane, TABBED_PANE_TAB_HEIGHT, tabHeight ) ) );
// tab area bounds // tab area bounds
int tx = insets.left; int tx = insets.left;
@@ -2081,54 +2210,56 @@ public class FlatTabbedPaneUI
int tw = bounds.width - insets.left - insets.right; int tw = bounds.width - insets.left - insets.right;
int th = tabAreaHeight; int th = tabAreaHeight;
int leadingWidth = getLeadingPreferredWidth();
int trailingWidth = getTrailingPreferredWidth();
int availWidth = tw - leadingWidth - trailingWidth - tabAreaInsets.left - tabAreaInsets.right;
int totalTabWidth = (rects.length > 0) ? rectsTotalWidth( leftToRight ) : 0;
// apply tab area alignment
if( totalTabWidth < availWidth && rects.length > 0 ) {
int diff = availWidth - totalTabWidth;
switch( tabAreaAlignment ) {
case ALIGN_LEADING:
trailingWidth += diff;
break;
case ALIGN_TRAILING:
leadingWidth += diff;
break;
case ALIGN_CENTER:
leadingWidth += diff / 2;
trailingWidth += diff - (diff / 2);
break;
case ALIGN_FILL:
stretchTabsWidth( diff, leftToRight );
totalTabWidth = rectsTotalWidth( leftToRight );
break;
}
} else if( rects.length == 0 )
trailingWidth = tw - leadingWidth;
// layout left component // layout left component
Container leftComponent = leftToRight ? leadingComponent : trailingComponent; Container leftComponent = leftToRight ? leadingComponent : trailingComponent;
if( leftComponent != null ) { int leftWidth = leftToRight ? leadingWidth : trailingWidth;
int leftWidth = leftComponent.getPreferredSize().width; if( leftComponent != null )
if( !leftToRight ) {
// trailing component fills all available horizontal space
int leadingWidth = (leadingComponent != null) ? leadingComponent.getPreferredSize().width : 0;
leftWidth = Math.max( leftWidth, (rects.length > 0)
? tw - leadingWidth - (rects[0].x + rects[0].width - rects[rects.length-1].x)
- (tabAreaInsets.left + tabAreaInsets.right)
: tw - leadingWidth );
}
leftComponent.setBounds( tx, ty, leftWidth, th ); leftComponent.setBounds( tx, ty, leftWidth, th );
// reduce tab area bounds
tx += leftWidth;
tw -= leftWidth;
}
// layout right component // layout right component
Container rightComponent = leftToRight ? trailingComponent : leadingComponent; Container rightComponent = leftToRight ? trailingComponent : leadingComponent;
if( rightComponent != null ) { int rightWidth = leftToRight ? trailingWidth : leadingWidth;
int rightWidth = rightComponent.getPreferredSize().width; if( rightComponent != null )
if( leftToRight ) {
// trailing component fills all available horizontal space
rightWidth = Math.max( rightWidth, (rects.length > 0)
? tw - (rects[rects.length-1].x + rects[rects.length-1].width)
- (tabAreaInsets.left + tabAreaInsets.right)
: tw );
}
rightComponent.setBounds( tx + tw - rightWidth, ty, rightWidth, th ); rightComponent.setBounds( tx + tw - rightWidth, ty, rightWidth, th );
// reduce tab area bounds
tw -= rightWidth;
}
// layout tab viewport and buttons // layout tab viewport and buttons
if( rects.length > 0 ) { if( rects.length > 0 ) {
int txi = tx + (leftToRight ? tabAreaInsets.left : tabAreaInsets.right); int txi = tx + leftWidth + (leftToRight ? tabAreaInsets.left : tabAreaInsets.right);
int twi = tw - tabAreaInsets.left - tabAreaInsets.right; int twi = tw - leftWidth - rightWidth - tabAreaInsets.left - tabAreaInsets.right;
// layout viewport and buttons // layout viewport and buttons
int viewportWidth = twi; int viewportWidth = twi;
Rectangle lastRect = rects[rects.length - 1]; if( viewportWidth < totalTabWidth ) {
int tabsWidth = leftToRight
? (lastRect.x + lastRect.width)
: (rects[0].x + rects[0].width - lastRect.x);
if( viewportWidth < tabsWidth ) {
// need buttons // need buttons
buttonsVisible = true; buttonsVisible = true;
int buttonsWidth = useMoreButton ? moreButtonSize.width : (backwardButtonSize.width + forwardButtonSize.width); int buttonsWidth = useMoreButton ? moreButtonSize.width : (backwardButtonSize.width + forwardButtonSize.width);
@@ -2154,7 +2285,9 @@ public class FlatTabbedPaneUI
} }
} else { // LEFT and RIGHT tab placement } else { // LEFT and RIGHT tab placement
// tab area width (maxTabWidth is zero if tab count is zero) // tab area width (maxTabWidth is zero if tab count is zero)
int tabAreaWidth = (maxTabWidth > 0) ? maxTabWidth : calculateMaxExtrasWidth(); int tabAreaWidth = (maxTabWidth > 0)
? maxTabWidth
: Math.max( getLeadingPreferredWidth(), getTrailingPreferredWidth() );
// tab area bounds // tab area bounds
int tx = (tabPlacement == LEFT) int tx = (tabPlacement == LEFT)
@@ -2164,40 +2297,52 @@ public class FlatTabbedPaneUI
int tw = tabAreaWidth; int tw = tabAreaWidth;
int th = bounds.height - insets.top - insets.bottom; int th = bounds.height - insets.top - insets.bottom;
int topHeight = getLeadingPreferredHeight();
int bottomHeight = getTrailingPreferredHeight();
int availHeight = th - topHeight - bottomHeight - tabAreaInsets.top - tabAreaInsets.bottom;
int totalTabHeight = (rects.length > 0) ? rectsTotalHeight() : 0;
// apply tab area alignment
if( totalTabHeight < availHeight && rects.length > 0 ) {
int diff = availHeight - totalTabHeight;
switch( tabAreaAlignment ) {
case ALIGN_LEADING:
bottomHeight += diff;
break;
case ALIGN_TRAILING:
topHeight += diff;
break;
case ALIGN_CENTER:
topHeight += diff / 2;
bottomHeight += diff - (diff / 2);
break;
case ALIGN_FILL:
stretchTabsHeight( diff );
totalTabHeight = rectsTotalHeight();
break;
}
} else if( rects.length == 0 )
bottomHeight = th - topHeight;
// layout top component // layout top component
if( leadingComponent != null ) { if( leadingComponent != null )
int topHeight = leadingComponent.getPreferredSize().height;
leadingComponent.setBounds( tx, ty, tw, topHeight ); leadingComponent.setBounds( tx, ty, tw, topHeight );
// reduce tab area bounds
ty += topHeight;
th -= topHeight;
}
// layout bottom component // layout bottom component
if( trailingComponent != null ) { if( trailingComponent != null )
int bottomHeight = trailingComponent.getPreferredSize().height;
// trailing component fills all available vertical space
bottomHeight = Math.max( bottomHeight, (rects.length > 0)
? th - (rects[rects.length-1].y + rects[rects.length-1].height)
- (tabAreaInsets.top + tabAreaInsets.bottom)
: th );
trailingComponent.setBounds( tx, ty + th - bottomHeight, tw, bottomHeight ); trailingComponent.setBounds( tx, ty + th - bottomHeight, tw, bottomHeight );
// reduce tab area bounds
th -= bottomHeight;
}
// layout tab viewport and buttons // layout tab viewport and buttons
if( rects.length > 0 ) { if( rects.length > 0 ) {
int tyi = ty + tabAreaInsets.top; int tyi = ty + topHeight + tabAreaInsets.top;
int thi = th - tabAreaInsets.top - tabAreaInsets.bottom; int thi = th - topHeight - bottomHeight - tabAreaInsets.top - tabAreaInsets.bottom;
// layout viewport and buttons // layout viewport and buttons
int viewportHeight = thi; int viewportHeight = thi;
Rectangle lastRect = rects[rects.length - 1]; if( viewportHeight < totalTabHeight ) {
int tabsHeight = lastRect.y + lastRect.height;
if( viewportHeight < tabsHeight ) {
// need buttons // need buttons
buttonsVisible = true; buttonsVisible = true;
int buttonsHeight = useMoreButton ? moreButtonSize.height : (backwardButtonSize.height + forwardButtonSize.height); int buttonsHeight = useMoreButton ? moreButtonSize.height : (backwardButtonSize.height + forwardButtonSize.height);

View File

@@ -551,6 +551,7 @@ TabbedPane.disabledForeground=@disabledText
TabbedPane.shadow=@background TabbedPane.shadow=@background
TabbedPane.contentBorderInsets=null TabbedPane.contentBorderInsets=null
TabbedPane.hiddenTabsNavigation=moreTabsButton TabbedPane.hiddenTabsNavigation=moreTabsButton
TabbedPane.tabAreaAlignment=leading
TabbedPane.closeIcon=com.formdev.flatlaf.icons.FlatTabbedPaneCloseIcon TabbedPane.closeIcon=com.formdev.flatlaf.icons.FlatTabbedPaneCloseIcon
TabbedPane.closeSize=16,16 TabbedPane.closeSize=16,16

View File

@@ -937,6 +937,7 @@ TabbedPane.selectedTabPadInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI
TabbedPane.selectionFollowsFocus true TabbedPane.selectionFollowsFocus true
TabbedPane.shadow #3c3f41 javax.swing.plaf.ColorUIResource [UI] TabbedPane.shadow #3c3f41 javax.swing.plaf.ColorUIResource [UI]
TabbedPane.showTabSeparators false TabbedPane.showTabSeparators false
TabbedPane.tabAreaAlignment leading
TabbedPane.tabAreaInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] TabbedPane.tabAreaInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI]
TabbedPane.tabHeight 32 TabbedPane.tabHeight 32
TabbedPane.tabInsets 4,12,4,12 javax.swing.plaf.InsetsUIResource [UI] TabbedPane.tabInsets 4,12,4,12 javax.swing.plaf.InsetsUIResource [UI]

View File

@@ -942,6 +942,7 @@ TabbedPane.selectedTabPadInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI
TabbedPane.selectionFollowsFocus true TabbedPane.selectionFollowsFocus true
TabbedPane.shadow #f2f2f2 javax.swing.plaf.ColorUIResource [UI] TabbedPane.shadow #f2f2f2 javax.swing.plaf.ColorUIResource [UI]
TabbedPane.showTabSeparators false TabbedPane.showTabSeparators false
TabbedPane.tabAreaAlignment leading
TabbedPane.tabAreaInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] TabbedPane.tabAreaInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI]
TabbedPane.tabHeight 32 TabbedPane.tabHeight 32
TabbedPane.tabInsets 4,12,4,12 javax.swing.plaf.InsetsUIResource [UI] TabbedPane.tabInsets 4,12,4,12 javax.swing.plaf.InsetsUIResource [UI]

View File

@@ -932,6 +932,7 @@ TabbedPane.selectedTabPadInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI
TabbedPane.selectionFollowsFocus true TabbedPane.selectionFollowsFocus true
TabbedPane.shadow #ccffcc javax.swing.plaf.ColorUIResource [UI] TabbedPane.shadow #ccffcc javax.swing.plaf.ColorUIResource [UI]
TabbedPane.showTabSeparators false TabbedPane.showTabSeparators false
TabbedPane.tabAreaAlignment leading
TabbedPane.tabAreaInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] TabbedPane.tabAreaInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI]
TabbedPane.tabHeight 32 TabbedPane.tabHeight 32
TabbedPane.tabInsets 4,12,4,12 javax.swing.plaf.InsetsUIResource [UI] TabbedPane.tabInsets 4,12,4,12 javax.swing.plaf.InsetsUIResource [UI]

View File

@@ -112,6 +112,8 @@ public class FlatContainerTest
} }
customTabsChanged( tabbedPane ); customTabsChanged( tabbedPane );
tabBackForegroundChanged( tabbedPane );
setTabIcons( tabbedPane );
} }
private void addTab( JTabbedPane tabbedPane ) { private void addTab( JTabbedPane tabbedPane ) {
@@ -154,24 +156,26 @@ public class FlatContainerTest
} }
private void tabIconsChanged() { private void tabIconsChanged() {
boolean showTabIcons = tabIconsCheckBox.isSelected(); setTabIcons( tabbedPane1 );
setTabIcons( tabbedPane2 );
setTabIcons( tabbedPane3 );
setTabIcons( tabbedPane4 );
setTabIcons( tabbedPane1, showTabIcons ); tabIconSizeSpinner.setEnabled( tabIconsCheckBox.isSelected() );
setTabIcons( tabbedPane2, showTabIcons );
setTabIcons( tabbedPane3, showTabIcons );
setTabIcons( tabbedPane4, showTabIcons );
tabIconSizeSpinner.setEnabled( showTabIcons );
} }
private void setTabIcons( JTabbedPane tabbedPane, boolean showTabIcons ) { private void setTabIcons( JTabbedPane tabbedPane ) {
boolean showTabIcons = tabIconsCheckBox.isSelected();
Object iconSize = tabIconSizeSpinner.getValue(); Object iconSize = tabIconSizeSpinner.getValue();
Icon icon = showTabIcons Icon icon = showTabIcons
? new ScaledImageIcon( new ImageIcon( getClass().getResource( "/com/formdev/flatlaf/testing/test" + iconSize + ".png" ) ) ) ? new ScaledImageIcon( new ImageIcon( getClass().getResource( "/com/formdev/flatlaf/testing/test" + iconSize + ".png" ) ) )
: null; : null;
tabbedPane.setIconAt( 0, icon ); int tabCount = tabbedPane.getTabCount();
tabbedPane.setIconAt( 1, icon ); if( tabCount > 0 )
tabbedPane.setIconAt( 0, icon );
if( tabCount > 1 )
tabbedPane.setIconAt( 1, icon );
} }
private void customBorderChanged() { private void customBorderChanged() {
@@ -195,11 +199,11 @@ public class FlatContainerTest
private void customTabsChanged( JTabbedPane tabbedPane ) { private void customTabsChanged( JTabbedPane tabbedPane ) {
boolean customTabs = customTabsCheckBox.isSelected(); boolean customTabs = customTabsCheckBox.isSelected();
int tabCount = tabbedPane.getTabCount(); int tabCount = tabbedPane.getTabCount();
if( tabCount >= 2 ) if( tabCount > 1 )
tabbedPane.setTabComponentAt( 1, customTabs ? new JButton( tabbedPane.getTitleAt( 1 ) ) : null ); tabbedPane.setTabComponentAt( 1, customTabs ? new JButton( tabbedPane.getTitleAt( 1 ) ) : null );
if( tabCount >= 4 ) if( tabCount > 3 )
tabbedPane.setTabComponentAt( 3, customTabs ? createCustomTab( tabbedPane.getTitleAt( 3 ) ) : null ); tabbedPane.setTabComponentAt( 3, customTabs ? createCustomTab( tabbedPane.getTitleAt( 3 ) ) : null );
if( tabCount >= 6 ) if( tabCount > 5 )
tabbedPane.setTabComponentAt( 5, customTabs ? new JCheckBox( tabbedPane.getTitleAt( 5 ) ) : null ); tabbedPane.setTabComponentAt( 5, customTabs ? new JCheckBox( tabbedPane.getTitleAt( 5 ) ) : null );
} }
@@ -235,19 +239,33 @@ public class FlatContainerTest
} }
private void hiddenTabsNavigationChanged() { private void hiddenTabsNavigationChanged() {
String value = null; String value = (String) hiddenTabsNavigationField.getSelectedItem();
switch( (String) hiddenTabsNavigationField.getSelectedItem() ) { if( "default".equals( value ) )
case "moreTabsButton": value = TABBED_PANE_HIDDEN_TABS_NAVIGATION_MORE_TABS_BUTTON; break; value = null;
case "arrowButtons": value = TABBED_PANE_HIDDEN_TABS_NAVIGATION_ARROW_BUTTONS; break;
}
putTabbedPanesClientProperty( TABBED_PANE_HIDDEN_TABS_NAVIGATION, value ); putTabbedPanesClientProperty( TABBED_PANE_HIDDEN_TABS_NAVIGATION, value );
} }
private void tabAreaAlignmentChanged() {
String value = (String) tabAreaAlignmentField.getSelectedItem();
if( "default".equals( value ) )
value = null;
putTabbedPanesClientProperty( TABBED_PANE_TAB_AREA_ALIGNMENT, value );
}
private void tabBackForegroundChanged() { private void tabBackForegroundChanged() {
tabBackForegroundChanged( tabbedPane1 );
tabBackForegroundChanged( tabbedPane2 );
tabBackForegroundChanged( tabbedPane3 );
tabBackForegroundChanged( tabbedPane4 );
}
private void tabBackForegroundChanged( JTabbedPane tabbedPane ) {
boolean enabled = tabBackForegroundCheckBox.isSelected(); boolean enabled = tabBackForegroundCheckBox.isSelected();
tabbedPane1.setBackgroundAt( 0, enabled ? Color.red : null ); int tabCount = tabbedPane.getTabCount();
tabbedPane1.setForegroundAt( 1, enabled ? Color.red : null ); if( tabCount > 0 )
tabbedPane.setBackgroundAt( 0, enabled ? Color.red : null );
if( tabCount > 1 )
tabbedPane.setForegroundAt( 1, enabled ? Color.red : null );
} }
private void leadingComponentChanged() { private void leadingComponentChanged() {
@@ -293,13 +311,15 @@ public class FlatContainerTest
JTabbedPane[] tabbedPanes = new JTabbedPane[] { tabbedPane1, tabbedPane2, tabbedPane3, tabbedPane4 }; JTabbedPane[] tabbedPanes = new JTabbedPane[] { tabbedPane1, tabbedPane2, tabbedPane3, tabbedPane4 };
for( JTabbedPane tabbedPane : tabbedPanes ) { for( JTabbedPane tabbedPane : tabbedPanes ) {
Component c = tabbedPane.getComponentAt( 1 ); if( tabbedPane.getTabCount() > 1 ) {
((JComponent)c).putClientProperty( TABBED_PANE_TAB_CLOSABLE, value ); Component c = tabbedPane.getComponentAt( 1 );
((JComponent)c).putClientProperty( TABBED_PANE_TAB_CLOSABLE, value );
}
} }
} }
private void tabAreaInsetsChanged() { private void tabAreaInsetsChanged() {
UIManager.put( "TabbedPane.tabAreaInsets", tabAreaInsetsCheckBox.isSelected() ? new Insets( 10, 10, 25, 25 ) : null ); UIManager.put( "TabbedPane.tabAreaInsets", tabAreaInsetsCheckBox.isSelected() ? new Insets( 5, 5, 10, 10 ) : null );
FlatLaf.updateUI(); FlatLaf.updateUI();
} }
@@ -318,8 +338,10 @@ public class FlatContainerTest
JTabbedPane[] tabbedPanes = new JTabbedPane[] { tabbedPane1, tabbedPane2, tabbedPane3, tabbedPane4 }; JTabbedPane[] tabbedPanes = new JTabbedPane[] { tabbedPane1, tabbedPane2, tabbedPane3, tabbedPane4 };
for( JTabbedPane tabbedPane : tabbedPanes ) { for( JTabbedPane tabbedPane : tabbedPanes ) {
Component c = tabbedPane.getComponentAt( 1 ); if( tabbedPane.getTabCount() > 1 ) {
((JComponent)c).putClientProperty( TABBED_PANE_TAB_INSETS, insets ); Component c = tabbedPane.getComponentAt( 1 );
((JComponent)c).putClientProperty( TABBED_PANE_TAB_INSETS, insets );
}
} }
} }
@@ -363,6 +385,8 @@ public class FlatContainerTest
tabPlacementField = new JComboBox<>(); tabPlacementField = new JComboBox<>();
tabIconsCheckBox = new JCheckBox(); tabIconsCheckBox = new JCheckBox();
tabIconSizeSpinner = new JSpinner(); tabIconSizeSpinner = new JSpinner();
JLabel tabAreaAlignmentLabel = new JLabel();
tabAreaAlignmentField = new JComboBox<>();
tabsClosableCheckBox = new JCheckBox(); tabsClosableCheckBox = new JCheckBox();
customBorderCheckBox = new JCheckBox(); customBorderCheckBox = new JCheckBox();
tabAreaInsetsCheckBox = new JCheckBox(); tabAreaInsetsCheckBox = new JCheckBox();
@@ -488,6 +512,7 @@ public class FlatContainerTest
// rows // rows
"[center]" + "[center]" +
"[]" + "[]" +
"[]" +
"[]para" + "[]para" +
"[]" + "[]" +
"[]para" + "[]para" +
@@ -560,75 +585,90 @@ public class FlatContainerTest
tabIconSizeSpinner.addChangeListener(e -> tabIconsChanged()); tabIconSizeSpinner.addChangeListener(e -> tabIconsChanged());
tabbedPaneControlPanel.add(tabIconSizeSpinner, "cell 2 2"); tabbedPaneControlPanel.add(tabIconSizeSpinner, "cell 2 2");
//---- tabAreaAlignmentLabel ----
tabAreaAlignmentLabel.setText("Tab area alignment:");
tabbedPaneControlPanel.add(tabAreaAlignmentLabel, "cell 0 3");
//---- tabAreaAlignmentField ----
tabAreaAlignmentField.setModel(new DefaultComboBoxModel<>(new String[] {
"default",
"leading",
"trailing",
"center",
"fill"
}));
tabAreaAlignmentField.addActionListener(e -> tabAreaAlignmentChanged());
tabbedPaneControlPanel.add(tabAreaAlignmentField, "cell 1 3");
//---- tabsClosableCheckBox ---- //---- tabsClosableCheckBox ----
tabsClosableCheckBox.setText("Tabs closable"); tabsClosableCheckBox.setText("Tabs closable");
tabsClosableCheckBox.addActionListener(e -> tabsClosableChanged()); tabsClosableCheckBox.addActionListener(e -> tabsClosableChanged());
tabbedPaneControlPanel.add(tabsClosableCheckBox, "cell 0 3"); tabbedPaneControlPanel.add(tabsClosableCheckBox, "cell 0 4");
//---- customBorderCheckBox ---- //---- customBorderCheckBox ----
customBorderCheckBox.setText("Custom border"); customBorderCheckBox.setText("Custom border");
customBorderCheckBox.addActionListener(e -> customBorderChanged()); customBorderCheckBox.addActionListener(e -> customBorderChanged());
tabbedPaneControlPanel.add(customBorderCheckBox, "cell 1 3"); tabbedPaneControlPanel.add(customBorderCheckBox, "cell 1 4");
//---- tabAreaInsetsCheckBox ---- //---- tabAreaInsetsCheckBox ----
tabAreaInsetsCheckBox.setText("Tab area insets (10,10,25,25)"); tabAreaInsetsCheckBox.setText("Tab area insets (5,5,10,10)");
tabAreaInsetsCheckBox.addActionListener(e -> tabAreaInsetsChanged()); tabAreaInsetsCheckBox.addActionListener(e -> tabAreaInsetsChanged());
tabbedPaneControlPanel.add(tabAreaInsetsCheckBox, "cell 2 3"); tabbedPaneControlPanel.add(tabAreaInsetsCheckBox, "cell 2 4");
//---- secondTabClosableCheckBox ---- //---- secondTabClosableCheckBox ----
secondTabClosableCheckBox.setText("Second Tab closable"); secondTabClosableCheckBox.setText("Second Tab closable");
secondTabClosableCheckBox.addActionListener(e -> secondTabClosableChanged()); secondTabClosableCheckBox.addActionListener(e -> secondTabClosableChanged());
tabbedPaneControlPanel.add(secondTabClosableCheckBox, "cell 0 4"); tabbedPaneControlPanel.add(secondTabClosableCheckBox, "cell 0 5");
//---- hasFullBorderCheckBox ---- //---- hasFullBorderCheckBox ----
hasFullBorderCheckBox.setText("Show content border"); hasFullBorderCheckBox.setText("Show content border");
hasFullBorderCheckBox.addActionListener(e -> hasFullBorderChanged()); hasFullBorderCheckBox.addActionListener(e -> hasFullBorderChanged());
tabbedPaneControlPanel.add(hasFullBorderCheckBox, "cell 1 4,alignx left,growx 0"); tabbedPaneControlPanel.add(hasFullBorderCheckBox, "cell 1 5,alignx left,growx 0");
//---- smallerTabHeightCheckBox ---- //---- smallerTabHeightCheckBox ----
smallerTabHeightCheckBox.setText("Smaller tab height (26)"); smallerTabHeightCheckBox.setText("Smaller tab height (26)");
smallerTabHeightCheckBox.addActionListener(e -> smallerTabHeightChanged()); smallerTabHeightCheckBox.addActionListener(e -> smallerTabHeightChanged());
tabbedPaneControlPanel.add(smallerTabHeightCheckBox, "cell 2 4"); tabbedPaneControlPanel.add(smallerTabHeightCheckBox, "cell 2 5");
//---- leadingComponentCheckBox ---- //---- leadingComponentCheckBox ----
leadingComponentCheckBox.setText("Leading component"); leadingComponentCheckBox.setText("Leading component");
leadingComponentCheckBox.addActionListener(e -> leadingComponentChanged()); leadingComponentCheckBox.addActionListener(e -> leadingComponentChanged());
tabbedPaneControlPanel.add(leadingComponentCheckBox, "cell 0 5"); tabbedPaneControlPanel.add(leadingComponentCheckBox, "cell 0 6");
//---- hideContentSeparatorCheckBox ---- //---- hideContentSeparatorCheckBox ----
hideContentSeparatorCheckBox.setText("Hide content separator"); hideContentSeparatorCheckBox.setText("Hide content separator");
hideContentSeparatorCheckBox.addActionListener(e -> hideContentSeparatorChanged()); hideContentSeparatorCheckBox.addActionListener(e -> hideContentSeparatorChanged());
tabbedPaneControlPanel.add(hideContentSeparatorCheckBox, "cell 1 5"); tabbedPaneControlPanel.add(hideContentSeparatorCheckBox, "cell 1 6");
//---- smallerInsetsCheckBox ---- //---- smallerInsetsCheckBox ----
smallerInsetsCheckBox.setText("Smaller tab insets (2,2,2,2)"); smallerInsetsCheckBox.setText("Smaller tab insets (2,2,2,2)");
smallerInsetsCheckBox.addActionListener(e -> smallerInsetsChanged()); smallerInsetsCheckBox.addActionListener(e -> smallerInsetsChanged());
tabbedPaneControlPanel.add(smallerInsetsCheckBox, "cell 2 5"); tabbedPaneControlPanel.add(smallerInsetsCheckBox, "cell 2 6");
//---- trailingComponentCheckBox ---- //---- trailingComponentCheckBox ----
trailingComponentCheckBox.setText("Trailing component"); trailingComponentCheckBox.setText("Trailing component");
trailingComponentCheckBox.addActionListener(e -> trailingComponentChanged()); trailingComponentCheckBox.addActionListener(e -> trailingComponentChanged());
tabbedPaneControlPanel.add(trailingComponentCheckBox, "cell 0 6"); tabbedPaneControlPanel.add(trailingComponentCheckBox, "cell 0 7");
//---- showTabSeparatorsCheckBox ---- //---- showTabSeparatorsCheckBox ----
showTabSeparatorsCheckBox.setText("Show tab separators"); showTabSeparatorsCheckBox.setText("Show tab separators");
showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged()); showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged());
tabbedPaneControlPanel.add(showTabSeparatorsCheckBox, "cell 1 6"); tabbedPaneControlPanel.add(showTabSeparatorsCheckBox, "cell 1 7");
//---- secondTabWiderCheckBox ---- //---- secondTabWiderCheckBox ----
secondTabWiderCheckBox.setText("Second Tab insets wider (4,20,4,20)"); secondTabWiderCheckBox.setText("Second Tab insets wider (4,20,4,20)");
secondTabWiderCheckBox.addActionListener(e -> secondTabWiderChanged()); secondTabWiderCheckBox.addActionListener(e -> secondTabWiderChanged());
tabbedPaneControlPanel.add(secondTabWiderCheckBox, "cell 2 6"); tabbedPaneControlPanel.add(secondTabWiderCheckBox, "cell 2 7");
//---- minimumTabWidthCheckBox ---- //---- minimumTabWidthCheckBox ----
minimumTabWidthCheckBox.setText("Minimum tab width (100)"); minimumTabWidthCheckBox.setText("Minimum tab width (100)");
minimumTabWidthCheckBox.addActionListener(e -> minimumTabWidthChanged()); minimumTabWidthCheckBox.addActionListener(e -> minimumTabWidthChanged());
tabbedPaneControlPanel.add(minimumTabWidthCheckBox, "cell 2 7"); tabbedPaneControlPanel.add(minimumTabWidthCheckBox, "cell 2 8");
//---- maximumTabWidthCheckBox ---- //---- maximumTabWidthCheckBox ----
maximumTabWidthCheckBox.setText("Maximum tab width (60)"); maximumTabWidthCheckBox.setText("Maximum tab width (60)");
maximumTabWidthCheckBox.addActionListener(e -> maximumTabWidthChanged()); maximumTabWidthCheckBox.addActionListener(e -> maximumTabWidthChanged());
tabbedPaneControlPanel.add(maximumTabWidthCheckBox, "cell 2 8"); tabbedPaneControlPanel.add(maximumTabWidthCheckBox, "cell 2 9");
} }
panel9.add(tabbedPaneControlPanel, cc.xywh(1, 11, 3, 1)); panel9.add(tabbedPaneControlPanel, cc.xywh(1, 11, 3, 1));
} }
@@ -649,6 +689,7 @@ public class FlatContainerTest
private JComboBox<String> tabPlacementField; private JComboBox<String> tabPlacementField;
private JCheckBox tabIconsCheckBox; private JCheckBox tabIconsCheckBox;
private JSpinner tabIconSizeSpinner; private JSpinner tabIconSizeSpinner;
private JComboBox<String> tabAreaAlignmentField;
private JCheckBox tabsClosableCheckBox; private JCheckBox tabsClosableCheckBox;
private JCheckBox customBorderCheckBox; private JCheckBox customBorderCheckBox;
private JCheckBox tabAreaInsetsCheckBox; private JCheckBox tabAreaInsetsCheckBox;

View File

@@ -132,7 +132,7 @@ new FormModel {
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestFrame$NoRightToLeftPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestFrame$NoRightToLeftPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3" "$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[][fill][]" "$columnConstraints": "[][fill][]"
"$rowConstraints": "[center][][]para[][]para[][]para[][]" "$rowConstraints": "[center][][][]para[][]para[][]para[][]"
} ) { } ) {
name: "tabbedPaneControlPanel" name: "tabbedPaneControlPanel"
"opaque": false "opaque": false
@@ -261,6 +261,30 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 2" "value": "cell 2 2"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "tabAreaAlignmentLabel"
"text": "Tab area alignment:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3"
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "tabAreaAlignmentField"
"model": new javax.swing.DefaultComboBoxModel {
selectedItem: "default"
addElement( "default" )
addElement( "leading" )
addElement( "trailing" )
addElement( "center" )
addElement( "fill" )
}
auxiliary() {
"JavaCodeGenerator.variableLocal": false
"JavaCodeGenerator.typeParameters": "String"
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabAreaAlignmentChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "tabsClosableCheckBox" name: "tabsClosableCheckBox"
"text": "Tabs closable" "text": "Tabs closable"
@@ -269,7 +293,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabsClosableChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabsClosableChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3" "value": "cell 0 4"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "customBorderCheckBox" name: "customBorderCheckBox"
@@ -279,17 +303,17 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "customBorderChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "customBorderChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3" "value": "cell 1 4"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "tabAreaInsetsCheckBox" name: "tabAreaInsetsCheckBox"
"text": "Tab area insets (10,10,25,25)" "text": "Tab area insets (5,5,10,10)"
auxiliary() { auxiliary() {
"JavaCodeGenerator.variableLocal": false "JavaCodeGenerator.variableLocal": false
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabAreaInsetsChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabAreaInsetsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 3" "value": "cell 2 4"
} ) } )
add( new FormComponent( "com.formdev.flatlaf.extras.TriStateCheckBox" ) { add( new FormComponent( "com.formdev.flatlaf.extras.TriStateCheckBox" ) {
name: "secondTabClosableCheckBox" name: "secondTabClosableCheckBox"
@@ -299,7 +323,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "secondTabClosableChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "secondTabClosableChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4" "value": "cell 0 5"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "hasFullBorderCheckBox" name: "hasFullBorderCheckBox"
@@ -309,7 +333,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hasFullBorderChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hasFullBorderChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 4,alignx left,growx 0" "value": "cell 1 5,alignx left,growx 0"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "smallerTabHeightCheckBox" name: "smallerTabHeightCheckBox"
@@ -319,7 +343,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "smallerTabHeightChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "smallerTabHeightChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 4" "value": "cell 2 5"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "leadingComponentCheckBox" name: "leadingComponentCheckBox"
@@ -329,7 +353,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "leadingComponentChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "leadingComponentChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 5" "value": "cell 0 6"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "hideContentSeparatorCheckBox" name: "hideContentSeparatorCheckBox"
@@ -339,7 +363,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hideContentSeparatorChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hideContentSeparatorChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 5" "value": "cell 1 6"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "smallerInsetsCheckBox" name: "smallerInsetsCheckBox"
@@ -349,7 +373,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "smallerInsetsChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "smallerInsetsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 5" "value": "cell 2 6"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "trailingComponentCheckBox" name: "trailingComponentCheckBox"
@@ -359,7 +383,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "trailingComponentChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "trailingComponentChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 6" "value": "cell 0 7"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "showTabSeparatorsCheckBox" name: "showTabSeparatorsCheckBox"
@@ -369,7 +393,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTabSeparatorsChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTabSeparatorsChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 6" "value": "cell 1 7"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "secondTabWiderCheckBox" name: "secondTabWiderCheckBox"
@@ -379,7 +403,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "secondTabWiderChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "secondTabWiderChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 6" "value": "cell 2 7"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "minimumTabWidthCheckBox" name: "minimumTabWidthCheckBox"
@@ -389,7 +413,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "minimumTabWidthChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "minimumTabWidthChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 7" "value": "cell 2 8"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "maximumTabWidthCheckBox" name: "maximumTabWidthCheckBox"
@@ -399,7 +423,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "maximumTabWidthChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "maximumTabWidthChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 8" "value": "cell 2 9"
} ) } )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridY": 11 "gridY": 11
@@ -410,7 +434,7 @@ new FormModel {
} ) } )
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 ) "location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 810, 745 ) "size": new java.awt.Dimension( 810, 860 )
} ) } )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3,align center center" "$layoutConstraints": "hidemode 3,align center center"
@@ -440,7 +464,7 @@ new FormModel {
"value": "cell 2 0" "value": "cell 2 0"
} ) } )
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 790 ) "location": new java.awt.Point( 0, 890 )
"size": new java.awt.Dimension( 291, 118 ) "size": new java.awt.Dimension( 291, 118 )
} ) } )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
@@ -465,7 +489,7 @@ new FormModel {
"value": "cell 1 0" "value": "cell 1 0"
} ) } )
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 340, 790 ) "location": new java.awt.Point( 340, 890 )
"size": new java.awt.Dimension( 291, 118 ) "size": new java.awt.Dimension( 291, 118 )
} ) } )
} }

View File

@@ -667,6 +667,7 @@ TabbedPane.selectedTabPadInsets
TabbedPane.selectionFollowsFocus TabbedPane.selectionFollowsFocus
TabbedPane.shadow TabbedPane.shadow
TabbedPane.showTabSeparators TabbedPane.showTabSeparators
TabbedPane.tabAreaAlignment
TabbedPane.tabAreaInsets TabbedPane.tabAreaInsets
TabbedPane.tabHeight TabbedPane.tabHeight
TabbedPane.tabInsets TabbedPane.tabInsets