diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d911aec..386d74fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,9 @@ FlatLaf Change Log - TabbedPane: Support alignment of tab area. (set client property `JTabbedPane.tabAreaAlignment` to `"leading"`, `"trailing"`, `"center"` or `"fill"`) (PR #199) +- TabbedPane: Support horizontal alignment of tab title and icon. (set client + property `JTabbedPane.tabAlignment` to `SwingConstants.LEADING`, + `SwingConstants.TRAILING` or `SwingConstants.CENTER`) - TabbedPane: Support equal and compact tab width modes. (set client property `JTabbedPane.tabWidthMode` to `"preferred"`, `"equal"` or `"compact"`) (PR #199) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java index 2cbf1ab4..693d2097 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -33,8 +33,12 @@ public interface FlatClientProperties *

* Components {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}
* Value type {@link java.lang.String}
- * Allowed Values {@link #BUTTON_TYPE_SQUARE}, {@link #BUTTON_TYPE_ROUND_RECT}, - * {@link #BUTTON_TYPE_TAB}, {@link #BUTTON_TYPE_HELP} and {@link BUTTON_TYPE_TOOLBAR_BUTTON} + * Allowed Values + * {@link #BUTTON_TYPE_SQUARE}, + * {@link #BUTTON_TYPE_ROUND_RECT}, + * {@link #BUTTON_TYPE_TAB}, + * {@link #BUTTON_TYPE_HELP} or + * {@link BUTTON_TYPE_TOOLBAR_BUTTON} */ String BUTTON_TYPE = "JButton.buttonType"; @@ -134,9 +138,12 @@ public interface FlatClientProperties * {@link javax.swing.JScrollPane}, {@link javax.swing.JSpinner}, * {@link javax.swing.JTextField} and {@link javax.swing.JToggleButton}
* Value type {@link java.lang.String} or {@link java.awt.Color} or {@link java.awt.Color}[2]
- * Allowed Values {@link #OUTLINE_ERROR}, {@link #OUTLINE_WARNING}, - * any color (type {@link java.awt.Color}) or an array of two colors (type {@link java.awt.Color}[2]) - * where the first color is for focused state and the second for unfocused state + * Allowed Values + * {@link #OUTLINE_ERROR}, + * {@link #OUTLINE_WARNING}, + * any color (type {@link java.awt.Color}) or + * an array of two colors (type {@link java.awt.Color}[2]) where the first color + * is for focused state and the second for unfocused state */ String OUTLINE = "JComponent.outline"; @@ -316,6 +323,8 @@ public interface FlatClientProperties * Component {@link javax.swing.JTabbedPane} * or tab content components (see {@link javax.swing.JTabbedPane#setComponentAt(int, java.awt.Component)})
* Value type {@link java.lang.String} + * + * @see #TABBED_PANE_TAB_CLOSABLE */ String TABBED_PANE_TAB_CLOSE_TOOLTIPTEXT = "JTabbedPane.tabCloseToolTipText"; @@ -384,48 +393,74 @@ public interface FlatClientProperties * Specifies the alignment of the tab area. *

* Component {@link javax.swing.JTabbedPane}
- * Value type {@link java.lang.String}
- * Allowed Values {@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} + * Value type {@link java.lang.Integer} or {@link java.lang.String}
+ * Allowed Values + * {@link SwingConstants#LEADING} (default) + * {@link SwingConstants#TRAILING}, + * {@link SwingConstants#CENTER}, + * {@link #TABBED_PANE_ALIGN_LEADING} (default), + * {@link #TABBED_PANE_ALIGN_TRAILING}, + * {@link #TABBED_PANE_ALIGN_CENTER} or + * {@link #TABBED_PANE_ALIGN_FILL} */ String TABBED_PANE_TAB_AREA_ALIGNMENT = "JTabbedPane.tabAreaAlignment"; /** - * Align the tab area to the leading edge. - * - * @see #TABBED_PANE_TAB_AREA_ALIGNMENT + * Specifies the horizontal alignment of the tab title and icon. + *

+ * Component {@link javax.swing.JTabbedPane} + * or tab content components (see {@link javax.swing.JTabbedPane#setComponentAt(int, java.awt.Component)})
+ * Value type {@link java.lang.Integer} or {@link java.lang.String}
+ * Allowed Values + * {@link SwingConstants#LEADING}, + * {@link SwingConstants#TRAILING}, + * {@link SwingConstants#CENTER} (default), + * {@link #TABBED_PANE_ALIGN_LEADING}, + * {@link #TABBED_PANE_ALIGN_TRAILING} or + * {@link #TABBED_PANE_ALIGN_CENTER} (default) */ - String TABBED_PANE_TAB_AREA_ALIGN_LEADING = "leading"; + String TABBED_PANE_TAB_ALIGNMENT = "JTabbedPane.tabAlignment"; /** - * Align the tab area to the trailing edge. + * Align to the leading edge. * * @see #TABBED_PANE_TAB_AREA_ALIGNMENT + * @see #TABBED_PANE_TAB_ALIGNMENT */ - String TABBED_PANE_TAB_AREA_ALIGN_TRAILING = "trailing"; + String TABBED_PANE_ALIGN_LEADING = "leading"; /** - * Align the tab area to center. + * Align to the trailing edge. * * @see #TABBED_PANE_TAB_AREA_ALIGNMENT + * @see #TABBED_PANE_TAB_ALIGNMENT */ - String TABBED_PANE_TAB_AREA_ALIGN_CENTER = "center"; + String TABBED_PANE_ALIGN_TRAILING = "trailing"; /** - * Stretch tabs to fill all available space. + * Align to center. + * + * @see #TABBED_PANE_TAB_AREA_ALIGNMENT + * @see #TABBED_PANE_TAB_ALIGNMENT + */ + String TABBED_PANE_ALIGN_CENTER = "center"; + + /** + * Stretch to fill all available space. * * @see #TABBED_PANE_TAB_AREA_ALIGNMENT */ - String TABBED_PANE_TAB_AREA_ALIGN_FILL = "fill"; + String TABBED_PANE_ALIGN_FILL = "fill"; /** * Specifies how the tabs should be sized. *

* Component {@link javax.swing.JTabbedPane}
* Value type {@link java.lang.String}
- * Allowed Values {@link #TABBED_PANE_TAB_WIDTH_MODE_PREFERRED} (default), - * {@link #TABBED_PANE_TAB_WIDTH_MODE_EQUAL} or {@link #TABBED_PANE_TAB_WIDTH_MODE_COMPACT} + * Allowed Values + * {@link #TABBED_PANE_TAB_WIDTH_MODE_PREFERRED} (default), + * {@link #TABBED_PANE_TAB_WIDTH_MODE_EQUAL} or + * {@link #TABBED_PANE_TAB_WIDTH_MODE_COMPACT} */ String TABBED_PANE_TAB_WIDTH_MODE = "JTabbedPane.tabWidthMode"; @@ -456,9 +491,11 @@ public interface FlatClientProperties *

* Component {@link javax.swing.JTabbedPane}
* Value type {@link java.lang.Integer}
- * Allowed Values {@link SwingConstants#LEADING} (default), - * {@link SwingConstants#TRAILING}, {@link SwingConstants#TOP} - * or {@link SwingConstants#BOTTOM} + * Allowed Values + * {@link SwingConstants#LEADING} (default), + * {@link SwingConstants#TRAILING}, + * {@link SwingConstants#TOP} or + * {@link SwingConstants#BOTTOM} */ String TABBED_PANE_TAB_ICON_PLACEMENT = "JTabbedPane.tabIconPlacement"; @@ -495,9 +532,10 @@ public interface FlatClientProperties *

* Component {@link javax.swing.JTextField} (and subclasses)
* Value type {@link java.lang.String}
- * Allowed Values {@link #SELECT_ALL_ON_FOCUS_POLICY_NEVER}, - * {@link #SELECT_ALL_ON_FOCUS_POLICY_ONCE} (default) or - * {@link #SELECT_ALL_ON_FOCUS_POLICY_ALWAYS} + * Allowed Values + * {@link #SELECT_ALL_ON_FOCUS_POLICY_NEVER}, + * {@link #SELECT_ALL_ON_FOCUS_POLICY_ONCE} (default) or + * {@link #SELECT_ALL_ON_FOCUS_POLICY_ALWAYS} */ String SELECT_ALL_ON_FOCUS_POLICY = "JTextField.selectAllOnFocusPolicy"; diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java index 0e02555b..c0b32dfa 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java @@ -128,6 +128,7 @@ import com.formdev.flatlaf.util.UIScale; * @uiDefault TabbedPane.hasFullBorder boolean * @uiDefault TabbedPane.hiddenTabsNavigation String moreTabsButton (default) or arrowButtons * @uiDefault TabbedPane.tabAreaAlignment String leading (default), center, trailing or fill + * @uiDefault TabbedPane.tabAlignment String leading, center (default) or trailing * @uiDefault TabbedPane.tabWidthMode String preferred (default), equal or compact * @uiDefault ScrollPane.smoothScrolling boolean * @uiDefault TabbedPane.closeIcon Icon @@ -144,10 +145,7 @@ public class FlatTabbedPaneUI 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; + protected static final int FILL = 100; protected static final int WIDTH_MODE_PREFERRED = 0; protected static final int WIDTH_MODE_EQUAL = 1; @@ -178,7 +176,8 @@ public class FlatTabbedPaneUI protected boolean tabsOpaque = true; private String hiddenTabsNavigationStr; - private String tabAreaAlignmentStr; + protected int tabAreaAlignment; + protected int tabAlignment; private String tabWidthModeStr; protected Icon closeIcon; @@ -246,7 +245,8 @@ public class FlatTabbedPaneUI hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" ); tabsOpaque = UIManager.getBoolean( "TabbedPane.tabsOpaque" ); hiddenTabsNavigationStr = UIManager.getString( "TabbedPane.hiddenTabsNavigation" ); - tabAreaAlignmentStr = UIManager.getString( "TabbedPane.tabAreaAlignment" ); + tabAreaAlignment = parseAlignment( UIManager.getString( "TabbedPane.tabAreaAlignment" ), LEADING ); + tabAlignment = parseAlignment( UIManager.getString( "TabbedPane.tabAlignment" ), CENTER ); tabWidthModeStr = UIManager.getString( "TabbedPane.tabWidthMode" ); closeIcon = UIManager.getIcon( "TabbedPane.closeIcon" ); @@ -1003,11 +1003,12 @@ public class FlatTabbedPaneUI } // icon placement - int iconPlacement = clientPropertyInt( tabPane, TABBED_PANE_TAB_ICON_PLACEMENT, LEADING ); - int verticalTextPosition = CENTER; - int horizontalTextPosition = TRAILING; - switch( iconPlacement ) { - case TRAILING: horizontalTextPosition = LEADING; break; + int verticalTextPosition; + int horizontalTextPosition; + switch( clientPropertyInt( tabPane, TABBED_PANE_TAB_ICON_PLACEMENT, LEADING ) ) { + default: + case LEADING: verticalTextPosition = CENTER; horizontalTextPosition = TRAILING; break; + case TRAILING: verticalTextPosition = CENTER; horizontalTextPosition = LEADING; break; case TOP: verticalTextPosition = BOTTOM; horizontalTextPosition = CENTER; break; case BOTTOM: verticalTextPosition = TOP; horizontalTextPosition = CENTER; break; } @@ -1023,7 +1024,7 @@ public class FlatTabbedPaneUI // layout label String clippedTitle = SwingUtilities.layoutCompoundLabel( tabPane, metrics, title, icon, - CENTER, CENTER, verticalTextPosition, horizontalTextPosition, + CENTER, getTabAlignment( tabIndex ), verticalTextPosition, horizontalTextPosition, tabRect, iconRect, textRect, scale( textIconGapUnscaled ) ); // remove temporary client property @@ -1164,10 +1165,23 @@ public class FlatTabbedPaneUI } protected int getTabAreaAlignment() { - String str = (String) tabPane.getClientProperty( TABBED_PANE_TAB_AREA_ALIGNMENT ); - if( str == null ) - str = tabAreaAlignmentStr; - return parseTabAreaAlignment( str ); + Object value = tabPane.getClientProperty( TABBED_PANE_TAB_AREA_ALIGNMENT ); + if( value instanceof Integer ) + return (Integer) value; + + return (value instanceof String) + ? parseAlignment( (String) value, LEADING ) + : tabAreaAlignment; + } + + protected int getTabAlignment( int tabIndex ) { + Object value = getTabClientProperty( tabIndex, TABBED_PANE_TAB_ALIGNMENT ); + if( value instanceof Integer ) + return (Integer) value; + + return (value instanceof String) + ? parseAlignment( (String) value, CENTER ) + : tabAlignment; } protected int getTabWidthMode() { @@ -1188,16 +1202,16 @@ public class FlatTabbedPaneUI } } - protected static int parseTabAreaAlignment( String str ) { + protected static int parseAlignment( String str, int defaultValue ) { if( str == null ) - return ALIGN_LEADING; + return defaultValue; 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; + case TABBED_PANE_ALIGN_LEADING: return LEADING; + case TABBED_PANE_ALIGN_TRAILING: return TRAILING; + case TABBED_PANE_ALIGN_CENTER: return CENTER; + case TABBED_PANE_ALIGN_FILL: return FILL; + default: return defaultValue; } } @@ -1972,6 +1986,7 @@ public class FlatTabbedPaneUI case TABBED_PANE_TAB_AREA_INSETS: case TABBED_PANE_HIDDEN_TABS_NAVIGATION: case TABBED_PANE_TAB_AREA_ALIGNMENT: + case TABBED_PANE_TAB_ALIGNMENT: case TABBED_PANE_TAB_WIDTH_MODE: case TABBED_PANE_TAB_ICON_PLACEMENT: case TABBED_PANE_TAB_CLOSABLE: @@ -2013,6 +2028,7 @@ public class FlatTabbedPaneUI case TABBED_PANE_MINIMUM_TAB_WIDTH: case TABBED_PANE_MAXIMUM_TAB_WIDTH: case TABBED_PANE_TAB_INSETS: + case TABBED_PANE_TAB_ALIGNMENT: case TABBED_PANE_TAB_CLOSABLE: tabPane.revalidate(); tabPane.repaint(); @@ -2161,22 +2177,22 @@ public class FlatTabbedPaneUI int diff = availWidth - totalTabWidth; switch( tabAreaAlignment ) { - case ALIGN_LEADING: + case LEADING: trailingWidth += diff; break; - case ALIGN_TRAILING: + case TRAILING: shiftTabs( leftToRight ? diff : -diff, 0 ); leadingWidth += diff; break; - case ALIGN_CENTER: + case CENTER: shiftTabs( (leftToRight ? diff : -diff) / 2, 0 ); leadingWidth += diff / 2; trailingWidth += diff - (diff / 2); break; - case ALIGN_FILL: + case FILL: stretchTabsWidth( diff, leftToRight ); break; } @@ -2220,22 +2236,22 @@ public class FlatTabbedPaneUI int diff = availHeight - totalTabHeight; switch( tabAreaAlignment ) { - case ALIGN_LEADING: + case LEADING: bottomHeight += diff; break; - case ALIGN_TRAILING: + case TRAILING: shiftTabs( 0, diff ); topHeight += diff; break; - case ALIGN_CENTER: + case CENTER: shiftTabs( 0, (diff) / 2 ); topHeight += diff / 2; bottomHeight += diff - (diff / 2); break; - case ALIGN_FILL: + case FILL: stretchTabsHeight( diff ); break; } @@ -2405,20 +2421,20 @@ public class FlatTabbedPaneUI if( totalTabWidth < availWidth && rects.length > 0 ) { int diff = availWidth - totalTabWidth; switch( tabAreaAlignment ) { - case ALIGN_LEADING: + case LEADING: trailingWidth += diff; break; - case ALIGN_TRAILING: + case TRAILING: leadingWidth += diff; break; - case ALIGN_CENTER: + case CENTER: leadingWidth += diff / 2; trailingWidth += diff - (diff / 2); break; - case ALIGN_FILL: + case FILL: stretchTabsWidth( diff, leftToRight ); totalTabWidth = rectsTotalWidth( leftToRight ); break; @@ -2492,20 +2508,20 @@ public class FlatTabbedPaneUI if( totalTabHeight < availHeight && rects.length > 0 ) { int diff = availHeight - totalTabHeight; switch( tabAreaAlignment ) { - case ALIGN_LEADING: + case LEADING: bottomHeight += diff; break; - case ALIGN_TRAILING: + case TRAILING: topHeight += diff; break; - case ALIGN_CENTER: + case CENTER: topHeight += diff / 2; bottomHeight += diff - (diff / 2); break; - case ALIGN_FILL: + case FILL: stretchTabsHeight( diff ); totalTabHeight = rectsTotalHeight(); break; diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties index 8a184861..8399a523 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -552,6 +552,7 @@ TabbedPane.shadow=@background TabbedPane.contentBorderInsets=null TabbedPane.hiddenTabsNavigation=moreTabsButton TabbedPane.tabAreaAlignment=leading +TabbedPane.tabAlignment=center TabbedPane.closeIcon=com.formdev.flatlaf.icons.FlatTabbedPaneCloseIcon TabbedPane.closeSize=16,16 diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/TabsPanel.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/TabsPanel.java index 5e4bed57..128b1ebb 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/TabsPanel.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/TabsPanel.java @@ -53,10 +53,15 @@ class TabsPanel initTabIconPlacement( iconLeadingTabbedPane, SwingConstants.LEADING ); initTabIconPlacement( iconTrailingTabbedPane, SwingConstants.TRAILING ); - initTabAreaAlignment( alignLeadingTabbedPane, TABBED_PANE_TAB_AREA_ALIGN_LEADING ); - initTabAreaAlignment( alignCenterTabbedPane, TABBED_PANE_TAB_AREA_ALIGN_CENTER ); - initTabAreaAlignment( alignTrailingTabbedPane, TABBED_PANE_TAB_AREA_ALIGN_TRAILING ); - initTabAreaAlignment( alignFillTabbedPane, TABBED_PANE_TAB_AREA_ALIGN_FILL ); + initTabAreaAlignment( alignLeadingTabbedPane, TABBED_PANE_ALIGN_LEADING ); + initTabAreaAlignment( alignCenterTabbedPane, TABBED_PANE_ALIGN_CENTER ); + initTabAreaAlignment( alignTrailingTabbedPane, TABBED_PANE_ALIGN_TRAILING ); + initTabAreaAlignment( alignFillTabbedPane, TABBED_PANE_ALIGN_FILL ); + + initTabAlignment( tabAlignLeadingTabbedPane, SwingConstants.LEADING ); + initTabAlignment( tabAlignCenterTabbedPane, SwingConstants.CENTER ); + initTabAlignment( tabAlignTrailingTabbedPane, SwingConstants.TRAILING ); + initTabAlignment( tabAlignVerticalTabbedPane, SwingConstants.TRAILING ); initTabWidthMode( widthPreferredTabbedPane, TABBED_PANE_TAB_WIDTH_MODE_PREFERRED ); initTabWidthMode( widthEqualTabbedPane, TABBED_PANE_TAB_WIDTH_MODE_EQUAL ); @@ -223,7 +228,7 @@ class TabsPanel int iconSize = topOrBottom ? 24 : 16; tabbedPane.putClientProperty( TABBED_PANE_TAB_ICON_PLACEMENT, iconPlacement ); if( topOrBottom ) { - tabbedPane.putClientProperty( TABBED_PANE_TAB_AREA_ALIGNMENT, TABBED_PANE_TAB_AREA_ALIGN_FILL ); + tabbedPane.putClientProperty( TABBED_PANE_TAB_AREA_ALIGNMENT, TABBED_PANE_ALIGN_FILL ); tabbedPane.putClientProperty( TABBED_PANE_TAB_WIDTH_MODE, TABBED_PANE_TAB_WIDTH_MODE_EQUAL ); } tabbedPane.addTab( "Search", new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/search.svg", iconSize, iconSize ), null ); @@ -238,6 +243,18 @@ class TabsPanel tabbedPane.addTab( "Recents", null ); } + private void initTabAlignment( JTabbedPane tabbedPane, int tabAlignment ) { + boolean vertical = (tabbedPane.getTabPlacement() == JTabbedPane.LEFT || tabbedPane.getTabPlacement() == JTabbedPane.RIGHT); + tabbedPane.putClientProperty( TABBED_PANE_TAB_ALIGNMENT, tabAlignment ); + if( !vertical ) + tabbedPane.putClientProperty( TABBED_PANE_MINIMUM_TAB_WIDTH, 80 ); + tabbedPane.addTab( "A", null ); + if( vertical ) { + tabbedPane.addTab( "Search", null ); + tabbedPane.addTab( "Recents", null ); + } + } + private void initTabWidthMode( JTabbedPane tabbedPane, String tabWidthMode ) { tabbedPane.putClientProperty( TABBED_PANE_TAB_WIDTH_MODE, tabWidthMode ); if( tabWidthMode.equals( TABBED_PANE_TAB_WIDTH_MODE_COMPACT ) ) { @@ -337,6 +354,14 @@ class TabsPanel JLabel minMaxTabWidthLabel = new JLabel(); minimumTabWidthTabbedPane = new JTabbedPane(); maximumTabWidthTabbedPane = new JTabbedPane(); + JLabel tabAlignmentLabel = new JLabel(); + panel5 = new JPanel(); + JLabel tabAlignmentNoteLabel = new JLabel(); + JLabel tabAlignmentNoteLabel2 = new JLabel(); + tabAlignLeadingTabbedPane = new JTabbedPane(); + tabAlignVerticalTabbedPane = new JTabbedPane(); + tabAlignCenterTabbedPane = new JTabbedPane(); + tabAlignTrailingTabbedPane = new JTabbedPane(); JPanel panel4 = new JPanel(); showTabSeparatorsCheckBox = new JCheckBox(); @@ -681,6 +706,8 @@ class TabsPanel "[]para" + "[]" + "[]" + + "[]para" + + "[]0" + "[]")); //---- tabWidthModeLabel ---- @@ -731,6 +758,67 @@ class TabsPanel maximumTabWidthTabbedPane.setName("maximumTabWidthTabbedPane"); } panel3.add(maximumTabWidthTabbedPane, "cell 0 7"); + + //---- tabAlignmentLabel ---- + tabAlignmentLabel.setText("Tab title alignment"); + tabAlignmentLabel.setFont(tabAlignmentLabel.getFont().deriveFont(tabAlignmentLabel.getFont().getSize() + 4f)); + tabAlignmentLabel.setName("tabAlignmentLabel"); + panel3.add(tabAlignmentLabel, "cell 0 8"); + + //======== panel5 ======== + { + panel5.setName("panel5"); + panel5.setLayout(new MigLayout( + "insets 0,hidemode 3", + // columns + "[grow,fill]para" + + "[fill]", + // rows + "[]" + + "[]" + + "[]" + + "[]")); + + //---- tabAlignmentNoteLabel ---- + tabAlignmentNoteLabel.setText("(leading/center/trailing)"); + tabAlignmentNoteLabel.setEnabled(false); + tabAlignmentNoteLabel.setFont(tabAlignmentNoteLabel.getFont().deriveFont(tabAlignmentNoteLabel.getFont().getSize() - 2f)); + tabAlignmentNoteLabel.setName("tabAlignmentNoteLabel"); + panel5.add(tabAlignmentNoteLabel, "cell 0 0"); + + //---- tabAlignmentNoteLabel2 ---- + tabAlignmentNoteLabel2.setText("(trailing)"); + tabAlignmentNoteLabel2.setEnabled(false); + tabAlignmentNoteLabel2.setFont(tabAlignmentNoteLabel2.getFont().deriveFont(tabAlignmentNoteLabel2.getFont().getSize() - 2f)); + tabAlignmentNoteLabel2.setName("tabAlignmentNoteLabel2"); + panel5.add(tabAlignmentNoteLabel2, "cell 1 0,alignx right,growx 0"); + + //======== tabAlignLeadingTabbedPane ======== + { + tabAlignLeadingTabbedPane.setName("tabAlignLeadingTabbedPane"); + } + panel5.add(tabAlignLeadingTabbedPane, "cell 0 1"); + + //======== tabAlignVerticalTabbedPane ======== + { + tabAlignVerticalTabbedPane.setTabPlacement(SwingConstants.LEFT); + tabAlignVerticalTabbedPane.setName("tabAlignVerticalTabbedPane"); + } + panel5.add(tabAlignVerticalTabbedPane, "cell 1 1 1 3,growy"); + + //======== tabAlignCenterTabbedPane ======== + { + tabAlignCenterTabbedPane.setName("tabAlignCenterTabbedPane"); + } + panel5.add(tabAlignCenterTabbedPane, "cell 0 2"); + + //======== tabAlignTrailingTabbedPane ======== + { + tabAlignTrailingTabbedPane.setName("tabAlignTrailingTabbedPane"); + } + panel5.add(tabAlignTrailingTabbedPane, "cell 0 3"); + } + panel3.add(panel5, "cell 0 9"); } add(panel3, "cell 2 0"); @@ -759,16 +847,16 @@ class TabsPanel tabPlacementButtonGroup.add(leftPlacementButton); tabPlacementButtonGroup.add(rightPlacementButton); - //---- buttonGroup2 ---- - ButtonGroup buttonGroup2 = new ButtonGroup(); - buttonGroup2.add(scrollTabLayoutButton); - buttonGroup2.add(wrapTabLayoutButton); + //---- tabLayoutButtonGroup ---- + ButtonGroup tabLayoutButtonGroup = new ButtonGroup(); + tabLayoutButtonGroup.add(scrollTabLayoutButton); + tabLayoutButtonGroup.add(wrapTabLayoutButton); - //---- buttonGroup1 ---- - ButtonGroup buttonGroup1 = new ButtonGroup(); - buttonGroup1.add(squareCloseButton); - buttonGroup1.add(circleCloseButton); - buttonGroup1.add(redCrossCloseButton); + //---- closableTabsButtonGroup ---- + ButtonGroup closableTabsButtonGroup = new ButtonGroup(); + closableTabsButtonGroup.add(squareCloseButton); + closableTabsButtonGroup.add(circleCloseButton); + closableTabsButtonGroup.add(redCrossCloseButton); // JFormDesigner - End of component initialization //GEN-END:initComponents } @@ -810,6 +898,11 @@ class TabsPanel private JTabbedPane widthCompactTabbedPane; private JTabbedPane minimumTabWidthTabbedPane; private JTabbedPane maximumTabWidthTabbedPane; + private JPanel panel5; + private JTabbedPane tabAlignLeadingTabbedPane; + private JTabbedPane tabAlignVerticalTabbedPane; + private JTabbedPane tabAlignCenterTabbedPane; + private JTabbedPane tabAlignTrailingTabbedPane; private JCheckBox showTabSeparatorsCheckBox; // JFormDesigner - End of variables declaration //GEN-END:variables } diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/TabsPanel.jfd b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/TabsPanel.jfd index 57394cd2..e14e73ef 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/TabsPanel.jfd +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/TabsPanel.jfd @@ -102,7 +102,7 @@ new FormModel { add( new FormComponent( "javax.swing.JToggleButton" ) { name: "scrollTabLayoutButton" "text": "scroll" - "$buttonGroup": new FormReference( "buttonGroup2" ) + "$buttonGroup": new FormReference( "tabLayoutButtonGroup" ) "font": &SwingDerivedFont2 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false ) "selected": true addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabLayoutChanged", false ) ) @@ -110,7 +110,7 @@ new FormModel { add( new FormComponent( "javax.swing.JToggleButton" ) { name: "wrapTabLayoutButton" "text": "wrap" - "$buttonGroup": new FormReference( "buttonGroup2" ) + "$buttonGroup": new FormReference( "tabLayoutButtonGroup" ) "font": #SwingDerivedFont2 addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabLayoutChanged", false ) ) } ) @@ -161,7 +161,7 @@ new FormModel { name: "squareCloseButton" "text": "square" "font": &SwingDerivedFont4 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false ) - "$buttonGroup": new FormReference( "buttonGroup1" ) + "$buttonGroup": new FormReference( "closableTabsButtonGroup" ) "selected": true addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "closeButtonStyleChanged", false ) ) } ) @@ -169,14 +169,14 @@ new FormModel { name: "circleCloseButton" "text": "circle" "font": #SwingDerivedFont4 - "$buttonGroup": new FormReference( "buttonGroup1" ) + "$buttonGroup": new FormReference( "closableTabsButtonGroup" ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "closeButtonStyleChanged", false ) ) } ) add( new FormComponent( "javax.swing.JToggleButton" ) { name: "redCrossCloseButton" "text": "red cross" "font": #SwingDerivedFont4 - "$buttonGroup": new FormReference( "buttonGroup1" ) + "$buttonGroup": new FormReference( "closableTabsButtonGroup" ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "closeButtonStyleChanged", false ) ) } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { @@ -290,7 +290,7 @@ new FormModel { name: "tabAreaAlignmentNoteLabel" "text": "(leading/center/trailing/fill)" "enabled": false - "font": new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false ) + "font": &SwingDerivedFont7 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false ) auxiliary() { "JavaCodeGenerator.variableLocal": true } @@ -323,7 +323,7 @@ new FormModel { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "insets 0,hidemode 3" "$columnConstraints": "[grow,fill]" - "$rowConstraints": "[]0[][][][]para[][][]" + "$rowConstraints": "[]0[][][][]para[][][]para[]0[]" } ) { name: "panel3" auxiliary() { @@ -385,6 +385,68 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 7" } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tabAlignmentLabel" + "text": "Tab title alignment" + "font": #SwingDerivedFont6 + auxiliary() { + "JavaCodeGenerator.variableLocal": true + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 8" + } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$columnConstraints": "[grow,fill]para[fill]" + "$rowConstraints": "[][][][]" + "$layoutConstraints": "insets 0,hidemode 3" + } ) { + name: "panel5" + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tabAlignmentNoteLabel" + "text": "(leading/center/trailing)" + "enabled": false + "font": #SwingDerivedFont7 + auxiliary() { + "JavaCodeGenerator.variableLocal": true + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tabAlignmentNoteLabel2" + "text": "(trailing)" + "enabled": false + "font": #SwingDerivedFont7 + auxiliary() { + "JavaCodeGenerator.variableLocal": true + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0,alignx right,growx 0" + } ) + add( new FormContainer( "javax.swing.JTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) { + name: "tabAlignLeadingTabbedPane" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 1" + } ) + add( new FormContainer( "javax.swing.JTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) { + name: "tabAlignVerticalTabbedPane" + "tabPlacement": 2 + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 1 1 3,growy" + } ) + add( new FormContainer( "javax.swing.JTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) { + name: "tabAlignCenterTabbedPane" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 2" + } ) + add( new FormContainer( "javax.swing.JTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) { + name: "tabAlignTrailingTabbedPane" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 3" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 9" + } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 2 0" } ) @@ -412,22 +474,22 @@ new FormModel { } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 ) - "size": new java.awt.Dimension( 925, 825 ) + "size": new java.awt.Dimension( 1075, 860 ) } ) add( new FormNonVisual( "javax.swing.ButtonGroup" ) { name: "tabPlacementButtonGroup" }, new FormLayoutConstraints( null ) { - "location": new java.awt.Point( 10, 1240 ) + "location": new java.awt.Point( 5, 915 ) } ) add( new FormNonVisual( "javax.swing.ButtonGroup" ) { - name: "buttonGroup1" + name: "closableTabsButtonGroup" }, new FormLayoutConstraints( null ) { - "location": new java.awt.Point( 0, 1292 ) + "location": new java.awt.Point( 5, 970 ) } ) add( new FormNonVisual( "javax.swing.ButtonGroup" ) { - name: "buttonGroup2" + name: "tabLayoutButtonGroup" }, new FormLayoutConstraints( null ) { - "location": new java.awt.Point( 0, 1344 ) + "location": new java.awt.Point( 5, 1020 ) } ) } } diff --git a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0_202.txt b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0_202.txt index 5ef5e6a6..b0f78b4b 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0_202.txt @@ -937,6 +937,7 @@ TabbedPane.selectedTabPadInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI TabbedPane.selectionFollowsFocus true TabbedPane.shadow #3c3f41 javax.swing.plaf.ColorUIResource [UI] TabbedPane.showTabSeparators false +TabbedPane.tabAlignment center TabbedPane.tabAreaAlignment leading TabbedPane.tabAreaInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] TabbedPane.tabHeight 32 diff --git a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0_202.txt b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0_202.txt index cb2585b2..29154cb4 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0_202.txt @@ -942,6 +942,7 @@ TabbedPane.selectedTabPadInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI TabbedPane.selectionFollowsFocus true TabbedPane.shadow #f2f2f2 javax.swing.plaf.ColorUIResource [UI] TabbedPane.showTabSeparators false +TabbedPane.tabAlignment center TabbedPane.tabAreaAlignment leading TabbedPane.tabAreaInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] TabbedPane.tabHeight 32 diff --git a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt index 1c29e8dd..c95430f0 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt @@ -932,6 +932,7 @@ TabbedPane.selectedTabPadInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI TabbedPane.selectionFollowsFocus true TabbedPane.shadow #ccffcc javax.swing.plaf.ColorUIResource [UI] TabbedPane.showTabSeparators false +TabbedPane.tabAlignment center TabbedPane.tabAreaAlignment leading TabbedPane.tabAreaInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] TabbedPane.tabHeight 32 diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.java index fed8ad65..dd98255c 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.java @@ -276,6 +276,17 @@ public class FlatContainerTest putTabbedPanesClientProperty( TABBED_PANE_TAB_AREA_ALIGNMENT, value ); } + private void tabAlignmentChanged() { + String value = (String) tabAlignmentField.getSelectedItem(); + Integer tabAlignment = null; + switch( value ) { + case "center": tabAlignment = SwingConstants.CENTER; break; + case "leading": tabAlignment = SwingConstants.LEADING; break; + case "trailing": tabAlignment = SwingConstants.TRAILING; break; + } + putTabbedPanesClientProperty( TABBED_PANE_TAB_ALIGNMENT, tabAlignment ); + } + private void tabWidthModeChanged() { String value = (String) tabWidthModeField.getSelectedItem(); if( "default".equals( value ) ) @@ -416,6 +427,7 @@ public class FlatContainerTest iconPlacementField = new JComboBox<>(); JLabel tabAreaAlignmentLabel = new JLabel(); tabAreaAlignmentField = new JComboBox<>(); + tabAlignmentField = new JComboBox<>(); JLabel tabWidthModeLabel = new JLabel(); tabWidthModeField = new JComboBox<>(); tabsClosableCheckBox = new JCheckBox(); @@ -637,7 +649,7 @@ public class FlatContainerTest tabbedPaneControlPanel.add(iconPlacementField, "cell 2 2"); //---- tabAreaAlignmentLabel ---- - tabAreaAlignmentLabel.setText("Tab area alignment:"); + tabAreaAlignmentLabel.setText("Tab area/title alignment:"); tabbedPaneControlPanel.add(tabAreaAlignmentLabel, "cell 0 3"); //---- tabAreaAlignmentField ---- @@ -651,6 +663,16 @@ public class FlatContainerTest tabAreaAlignmentField.addActionListener(e -> tabAreaAlignmentChanged()); tabbedPaneControlPanel.add(tabAreaAlignmentField, "cell 1 3"); + //---- tabAlignmentField ---- + tabAlignmentField.setModel(new DefaultComboBoxModel<>(new String[] { + "default", + "leading", + "trailing", + "center" + })); + tabAlignmentField.addActionListener(e -> tabAlignmentChanged()); + tabbedPaneControlPanel.add(tabAlignmentField, "cell 1 3"); + //---- tabWidthModeLabel ---- tabWidthModeLabel.setText("Tab width mode:"); tabbedPaneControlPanel.add(tabWidthModeLabel, "cell 2 3"); @@ -760,6 +782,7 @@ public class FlatContainerTest private JSpinner tabIconSizeSpinner; private JComboBox iconPlacementField; private JComboBox tabAreaAlignmentField; + private JComboBox tabAlignmentField; private JComboBox tabWidthModeField; private JCheckBox tabsClosableCheckBox; private JCheckBox customBorderCheckBox; diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.jfd index 2fb4ea68..2c8acf3c 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.jfd @@ -300,7 +300,7 @@ new FormModel { } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "tabAreaAlignmentLabel" - "text": "Tab area alignment:" + "text": "Tab area/title alignment:" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 3" } ) @@ -322,6 +322,23 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 3" } ) + add( new FormComponent( "javax.swing.JComboBox" ) { + name: "tabAlignmentField" + "model": new javax.swing.DefaultComboBoxModel { + selectedItem: "default" + addElement( "default" ) + addElement( "leading" ) + addElement( "trailing" ) + addElement( "center" ) + } + auxiliary() { + "JavaCodeGenerator.variableLocal": false + "JavaCodeGenerator.typeParameters": "String" + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabAlignmentChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 3" + } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "tabWidthModeLabel" "text": "Tab width mode:" diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt index 52c3803d..1e5d9edb 100644 --- a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt +++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt @@ -667,6 +667,7 @@ TabbedPane.selectedTabPadInsets TabbedPane.selectionFollowsFocus TabbedPane.shadow TabbedPane.showTabSeparators +TabbedPane.tabAlignment TabbedPane.tabAreaAlignment TabbedPane.tabAreaInsets TabbedPane.tabHeight