From bffac60bf834c2f7b3158337c35a628b10edec84 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Thu, 25 Mar 2021 18:49:16 +0100 Subject: [PATCH 01/13] JIDE: JideTabbedPane: - support selected tab background - support tab separators --- .../jideoss/ui/FlatJideTabbedPaneUI.java | 62 ++++++++++++++++--- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java index 37424aad..1e611eb3 100644 --- a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java +++ b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java @@ -17,6 +17,7 @@ package com.formdev.flatlaf.jideoss.ui; import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER; +import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_SHOW_TAB_SEPARATORS; import static com.formdev.flatlaf.FlatClientProperties.clientPropertyBoolean; import static com.formdev.flatlaf.util.UIScale.scale; import java.awt.Color; @@ -36,8 +37,8 @@ import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; -import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.ui.FlatUIUtils; +import com.formdev.flatlaf.util.UIScale; import com.jidesoft.plaf.LookAndFeelFactory; import com.jidesoft.plaf.UIDefaultsLookup; import com.jidesoft.plaf.basic.BasicJideTabbedPaneUI; @@ -51,15 +52,19 @@ import com.jidesoft.swing.JideTabbedPane; public class FlatJideTabbedPaneUI extends BasicJideTabbedPaneUI { + protected Color selectedBackground; protected Color underlineColor; protected Color disabledUnderlineColor; protected Color hoverColor; protected Color focusColor; + protected Color tabSeparatorColor; protected Color contentAreaColor; protected int tabHeight; protected int tabSelectionHeight; protected int contentSeparatorHeight; + protected boolean showTabSeparators; + protected boolean tabSeparatorsFullHeight; protected boolean hasFullBorder; protected boolean tabsOverlapBorder; @@ -79,15 +84,19 @@ public class FlatJideTabbedPaneUI _background = UIDefaultsLookup.getColor( "JideTabbedPane.background" ); + selectedBackground = UIManager.getColor( "TabbedPane.selectedBackground" ); underlineColor = UIManager.getColor( "TabbedPane.underlineColor" ); disabledUnderlineColor = UIManager.getColor( "TabbedPane.disabledUnderlineColor" ); hoverColor = UIManager.getColor( "TabbedPane.hoverColor" ); focusColor = UIManager.getColor( "TabbedPane.focusColor" ); + tabSeparatorColor = UIManager.getColor( "TabbedPane.tabSeparatorColor" ); contentAreaColor = UIManager.getColor( "TabbedPane.contentAreaColor" ); tabHeight = UIManager.getInt( "TabbedPane.tabHeight" ); tabSelectionHeight = UIManager.getInt( "TabbedPane.tabSelectionHeight" ); contentSeparatorHeight = UIManager.getInt( "TabbedPane.contentSeparatorHeight" ); + showTabSeparators = UIManager.getBoolean( "TabbedPane.showTabSeparators" ); + tabSeparatorsFullHeight = UIManager.getBoolean( "TabbedPane.tabSeparatorsFullHeight" ); hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" ); tabsOverlapBorder = UIManager.getBoolean( "TabbedPane.tabsOverlapBorder" ); @@ -101,10 +110,12 @@ public class FlatJideTabbedPaneUI protected void uninstallDefaults() { super.uninstallDefaults(); + selectedBackground = null; underlineColor = null; disabledUnderlineColor = null; hoverColor = null; focusColor = null; + tabSeparatorColor = null; contentAreaColor = null; } @@ -114,13 +125,17 @@ public class FlatJideTabbedPaneUI return e -> { superListener.propertyChange( e ); - String propertyName = e.getPropertyName(); - if( JideTabbedPane.PROPERTY_SELECTED_INDEX.equals( propertyName ) ) { - repaintTab( (Integer) e.getOldValue() ); - repaintTab( (Integer) e.getNewValue() ); - } else if( FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER.equals( propertyName ) ) { - _tabPane.revalidate(); - _tabPane.repaint(); + switch( e.getPropertyName() ) { + case JideTabbedPane.PROPERTY_SELECTED_INDEX: + repaintTab( (Integer) e.getOldValue() ); + repaintTab( (Integer) e.getNewValue() ); + break; + + case TABBED_PANE_SHOW_TAB_SEPARATORS: + case TABBED_PANE_HAS_FULL_BORDER: + _tabPane.revalidate(); + _tabPane.repaint(); + break; } }; } @@ -226,7 +241,9 @@ public class FlatJideTabbedPaneUI ? hoverColor : (enabled && isSelected && FlatUIUtils.isPermanentFocusOwner( _tabPane ) ? focusColor - : _tabPane.getBackgroundAt( tabIndex )) ); + : (selectedBackground != null && enabled && isSelected + ? selectedBackground + : _tabPane.getBackgroundAt( tabIndex ))) ); g.fillRect( x, y, w, h ); } @@ -243,10 +260,32 @@ public class FlatJideTabbedPaneUI protected void paintTabBorder( Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected ) { + // paint tab separators + if( clientPropertyBoolean( _tabPane, TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators ) && + !isLastInRun( tabIndex ) ) + paintTabSeparator( g, tabPlacement, x, y, w, h ); + if( isSelected ) paintTabSelection( g, tabPlacement, x, y, w, h ); } + protected void paintTabSeparator( Graphics g, int tabPlacement, int x, int y, int w, int h ) { + float sepWidth = UIScale.scale( 1f ); + float offset = tabSeparatorsFullHeight ? 0 : UIScale.scale( 5f ); + + g.setColor( (tabSeparatorColor != null) ? tabSeparatorColor : contentAreaColor ); + if( tabPlacement == LEFT || tabPlacement == RIGHT ) { + // paint tab separator at bottom side + ((Graphics2D)g).fill( new Rectangle2D.Float( x + offset, y + h - sepWidth, w - (offset * 2), sepWidth ) ); + } else if( _tabPane.getComponentOrientation().isLeftToRight() ) { + // paint tab separator at right side + ((Graphics2D)g).fill( new Rectangle2D.Float( x + w - sepWidth, y + offset, sepWidth, h - (offset * 2) ) ); + } else { + // paint tab separator at left side + ((Graphics2D)g).fill( new Rectangle2D.Float( x, y + offset, sepWidth, h - (offset * 2) ) ); + } + } + protected void paintTabSelection( Graphics g, int tabPlacement, int x, int y, int w, int h ) { // increase clip bounds in scroll-tab-layout to paint over the separator line Rectangle clipBounds = scrollableTabLayoutEnabled() ? g.getClipBounds() : null; @@ -386,4 +425,9 @@ public class FlatJideTabbedPaneUI Rectangle iconRect, Rectangle textRect, boolean isSelected ) { } + + private boolean isLastInRun( int tabIndex ) { + int run = getRunForTab( _tabPane.getTabCount(), tabIndex ); + return lastTabInRun( _tabPane.getTabCount(), run ) == tabIndex; + } } From c8f74781704f6baa6b442eafafefb8d4ec6f53d2 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 27 Mar 2021 11:02:33 +0100 Subject: [PATCH 02/13] JIDE: JideTabbedPane: - use `FlatTabbedPaneCloseIcon` for tab close buttons - scale close buttons - fix close buttons location --- .../jideoss/ui/FlatJideTabbedPaneUI.java | 148 +++++++++++++++++- .../flatlaf/jideoss/FlatLaf.properties | 3 + .../uidefaults/FlatDarkLaf_1.8.0_202.txt | 2 + .../uidefaults/FlatLightLaf_1.8.0_202.txt | 2 + .../uidefaults/FlatTestLaf_1.8.0_202.txt | 2 + .../uidefaults/JIDE-FlatDarkLaf_1.8.0_202.txt | 2 - .../JIDE-FlatLightLaf_1.8.0_202.txt | 2 - .../flatlaf/themeeditor/FlatLafUIKeys.txt | 2 + 8 files changed, 158 insertions(+), 5 deletions(-) diff --git a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java index 1e611eb3..6bd37a37 100644 --- a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java +++ b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java @@ -21,12 +21,15 @@ import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_SHOW_TAB_SEPA import static com.formdev.flatlaf.FlatClientProperties.clientPropertyBoolean; import static com.formdev.flatlaf.util.UIScale.scale; import java.awt.Color; +import java.awt.Component; +import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; +import java.awt.LayoutManager; import java.awt.Rectangle; import java.awt.Shape; import java.awt.event.MouseListener; @@ -34,15 +37,19 @@ import java.awt.event.MouseMotionListener; import java.awt.geom.Path2D; import java.awt.geom.Rectangle2D; import java.beans.PropertyChangeListener; +import javax.swing.Icon; +import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; +import com.formdev.flatlaf.icons.FlatTabbedPaneCloseIcon; import com.formdev.flatlaf.ui.FlatUIUtils; import com.formdev.flatlaf.util.UIScale; import com.jidesoft.plaf.LookAndFeelFactory; import com.jidesoft.plaf.UIDefaultsLookup; import com.jidesoft.plaf.basic.BasicJideTabbedPaneUI; import com.jidesoft.swing.JideTabbedPane; +import com.jidesoft.swing.JideTabbedPane.NoFocusButton; /** * Provides the Flat LaF UI delegate for {@link com.jidesoft.swing.JideTabbedPane}. @@ -68,6 +75,11 @@ public class FlatJideTabbedPaneUI protected boolean hasFullBorder; protected boolean tabsOverlapBorder; + protected Icon closeIcon; + + protected int closeButtonLeftMarginUnscaled; + protected int closeButtonRightMarginUnscaled; + private Object[] oldRenderingHints; public static ComponentUI createUI( JComponent c ) { @@ -100,6 +112,11 @@ public class FlatJideTabbedPaneUI hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" ); tabsOverlapBorder = UIManager.getBoolean( "TabbedPane.tabsOverlapBorder" ); + closeIcon = new FlatJideTabCloseIcon(); + + closeButtonLeftMarginUnscaled = _closeButtonLeftMargin; + closeButtonRightMarginUnscaled = _closeButtonRightMargin; + // scale _textIconGap = scale( _textIconGap ); tabHeight = scale( tabHeight ); @@ -117,6 +134,7 @@ public class FlatJideTabbedPaneUI focusColor = null; tabSeparatorColor = null; contentAreaColor = null; + closeIcon = null; } @Override @@ -159,14 +177,23 @@ public class FlatJideTabbedPaneUI return new RolloverMouseMotionHandler(); } + @Override + protected LayoutManager createLayoutManager() { + return (_tabPane.getTabLayoutPolicy() == JideTabbedPane.SCROLL_TAB_LAYOUT) + ? new FlatJideTabbedPaneScrollLayout() + : super.createLayoutManager(); + } + @Override protected int calculateTabHeight( int tabPlacement, int tabIndex, FontMetrics metrics ) { + updateCloseButtonMargins(); return Math.max( tabHeight, super.calculateTabHeight( tabPlacement, tabIndex, metrics ) ); } @Override protected int calculateTabWidth( int tabPlacement, int tabIndex, FontMetrics metrics ) { - return Math.max( tabHeight, super.calculateTabWidth( tabPlacement, tabIndex, metrics ) ); + updateCloseButtonMargins(); + return Math.max( tabHeight, super.calculateTabWidth( tabPlacement, tabIndex, metrics ) - 3 ); } @Override @@ -189,6 +216,26 @@ public class FlatJideTabbedPaneUI return JideTabbedPane.SHAPE_BOX; } + @Override + protected int getLeftMargin() { + return 0; + } + + @Override + protected int getTabGap() { + return 0; + } + + @Override + protected int getLayoutSize() { + return 0; + } + + @Override + protected int getTabRightPadding() { + return 0; + } + /** * The content border insets are used to create a separator between tabs and content. * If client property JTabbedPane.hasFullBorder is true, then the content border insets @@ -430,4 +477,103 @@ public class FlatJideTabbedPaneUI int run = getRunForTab( _tabPane.getTabCount(), tabIndex ); return lastTabInRun( _tabPane.getTabCount(), run ) == tabIndex; } + + @Override + public void ensureCloseButtonCreated() { + super.ensureCloseButtonCreated(); + + if( _closeButtons == null ) + return; + + // make sure that close buttons use our icon and do not fill background + for( JButton closeButton : _closeButtons ) { + if( closeButton.getIcon() != closeIcon ) + closeButton.setIcon( closeIcon ); + if( closeButton.isContentAreaFilled() ) + closeButton.setContentAreaFilled( false ); + } + } + + protected void updateCloseButtonMargins() { + // scale close button margins + _closeButtonLeftMargin = scale( closeButtonLeftMarginUnscaled ); + _closeButtonRightMargin = scale( closeButtonRightMarginUnscaled ); + + // since close button size is hardcoded to 16x16 in NoFocusButton.getPreferredSize(), + // add difference between scaled and unscaled close button size to margins + int offset = (closeIcon.getIconWidth() - 16) / 2; + _closeButtonLeftMargin += offset; + _closeButtonRightMargin += offset; + } + + //---- class FlatJideTabbedPaneScrollLayout ------------------------------- + + protected class FlatJideTabbedPaneScrollLayout + extends TabbedPaneScrollLayout + { + @Override + public void layoutContainer( Container parent ) { + updateCloseButtonMargins(); + + super.layoutContainer( parent ); + + updateCloseButtons(); + } + + private void updateCloseButtons() { + if( !scrollableTabLayoutEnabled() || !isShowCloseButton() || !isShowCloseButtonOnTab() ) + return; + + for( int i = 0; i < _closeButtons.length; i++ ) { + JButton closeButton = _closeButtons[i]; + if( closeButton.getWidth() == 0 || closeButton.getHeight() == 0 ) + continue; // not visible + + closeButton.setBounds( getTabCloseBounds( i ) ); + } + } + + private Rectangle getTabCloseBounds( int tabIndex ) { + int iconWidth = closeIcon.getIconWidth(); + int iconHeight = closeIcon.getIconHeight(); + Rectangle tabRect = _rects[tabIndex]; + Insets tabInsets = getTabInsets( _tabPane.getTabPlacement(), tabIndex ); + + // use one-third of right/left tab insets as gap between tab text and close button + if( _tabPane.getTabPlacement() == JideTabbedPane.TOP || _tabPane.getTabPlacement() == JideTabbedPane.BOTTOM ) { + return new Rectangle( + _tabPane.getComponentOrientation().isLeftToRight() + ? (tabRect.x + tabRect.width - (tabInsets.right / 3 * 2) - iconWidth) + : (tabRect.x + (tabInsets.left / 3 * 2)), + tabRect.y + (tabRect.height - iconHeight) / 2, + iconWidth, + iconHeight ); + } else { + return new Rectangle( + tabRect.x + (tabRect.width - iconWidth) / 2, + tabRect.y + tabRect.height - (tabInsets.bottom / 3 * 2) - iconHeight, + iconWidth, + iconHeight ); + } + } + } + + //---- class FlatJideTabAreaArrowIcon ------------------------------------- + + protected class FlatJideTabCloseIcon + extends FlatTabbedPaneCloseIcon + { + @Override + public void paintIcon( Component c, Graphics g, int x, int y ) { + NoFocusButton button = (NoFocusButton) c; + + if( _tabPane.isShowCloseButtonOnMouseOver() && !button.isMouseOver() ) { + Object property = _tabPane.getClientProperty( "JideTabbedPane.mouseOverTabIndex" ); + if( property instanceof Integer && button.getIndex() >= 0 && (Integer) property != button.getIndex() ) + return; + } + + super.paintIcon( c, g, x, y ); + } + } } diff --git a/flatlaf-jide-oss/src/main/resources/com/formdev/flatlaf/jideoss/FlatLaf.properties b/flatlaf-jide-oss/src/main/resources/com/formdev/flatlaf/jideoss/FlatLaf.properties index be03720a..a4c48098 100644 --- a/flatlaf-jide-oss/src/main/resources/com/formdev/flatlaf/jideoss/FlatLaf.properties +++ b/flatlaf-jide-oss/src/main/resources/com/formdev/flatlaf/jideoss/FlatLaf.properties @@ -81,3 +81,6 @@ JideTabbedPane.tabAreaInsets = $TabbedPane.tabAreaInsets JideTabbedPane.contentBorderInsets = 0,0,0,0 JideTabbedPane.tabRunOverlay = $TabbedPane.tabRunOverlay JideTabbedPane.shadow = $TabbedPane.shadow + +JideTabbedPane.closeButtonLeftMargin = 0 +JideTabbedPane.closeButtonRightMargin = 0 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 317d0fa9..a383c63e 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0_202.txt @@ -489,6 +489,8 @@ JideSplitButtonUI com.formdev.flatlaf.jideoss.ui.FlatJideSplitButto #---- JideTabbedPane ---- JideTabbedPane.background #3c3f41 javax.swing.plaf.ColorUIResource [UI] +JideTabbedPane.closeButtonLeftMargin 0 +JideTabbedPane.closeButtonRightMargin 0 JideTabbedPane.contentBorderInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] JideTabbedPane.foreground #bbbbbb javax.swing.plaf.ColorUIResource [UI] JideTabbedPane.shadow #3c3f41 javax.swing.plaf.ColorUIResource [UI] 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 899ee0ae..6f41d1e7 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0_202.txt @@ -494,6 +494,8 @@ JideSplitButtonUI com.formdev.flatlaf.jideoss.ui.FlatJideSplitButto #---- JideTabbedPane ---- JideTabbedPane.background #f2f2f2 javax.swing.plaf.ColorUIResource [UI] +JideTabbedPane.closeButtonLeftMargin 0 +JideTabbedPane.closeButtonRightMargin 0 JideTabbedPane.contentBorderInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] JideTabbedPane.foreground #000000 javax.swing.plaf.ColorUIResource [UI] JideTabbedPane.shadow #f2f2f2 javax.swing.plaf.ColorUIResource [UI] 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 7fa30e96..152930fa 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt @@ -485,6 +485,8 @@ JideSplitButtonUI com.formdev.flatlaf.jideoss.ui.FlatJideSplitButto #---- JideTabbedPane ---- JideTabbedPane.background #ccffcc javax.swing.plaf.ColorUIResource [UI] +JideTabbedPane.closeButtonLeftMargin 0 +JideTabbedPane.closeButtonRightMargin 0 JideTabbedPane.contentBorderInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] JideTabbedPane.foreground #ff0000 javax.swing.plaf.ColorUIResource [UI] JideTabbedPane.shadow #ccffcc javax.swing.plaf.ColorUIResource [UI] diff --git a/flatlaf-testing/dumps/uidefaults/JIDE-FlatDarkLaf_1.8.0_202.txt b/flatlaf-testing/dumps/uidefaults/JIDE-FlatDarkLaf_1.8.0_202.txt index c6a60a4f..9c228198 100644 --- a/flatlaf-testing/dumps/uidefaults/JIDE-FlatDarkLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/JIDE-FlatDarkLaf_1.8.0_202.txt @@ -108,12 +108,10 @@ + JideTabbedPane.buttonMargin 5 + JideTabbedPane.buttonSize 18 + JideTabbedPane.closeButtonAlignment 11 -+ JideTabbedPane.closeButtonLeftMargin 2 + JideTabbedPane.closeButtonMargin 2 + JideTabbedPane.closeButtonMarginHorizonal 3 + JideTabbedPane.closeButtonMarginSize 6 + JideTabbedPane.closeButtonMarginVertical 3 -+ JideTabbedPane.closeButtonRightMargin 2 + JideTabbedPane.compressedStyleCloseButtonMarginHorizontal 0 + JideTabbedPane.compressedStyleCloseButtonMarginVertical 0 + JideTabbedPane.compressedStyleIconMargin 12 diff --git a/flatlaf-testing/dumps/uidefaults/JIDE-FlatLightLaf_1.8.0_202.txt b/flatlaf-testing/dumps/uidefaults/JIDE-FlatLightLaf_1.8.0_202.txt index 24f9de05..57f4bb8f 100644 --- a/flatlaf-testing/dumps/uidefaults/JIDE-FlatLightLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/JIDE-FlatLightLaf_1.8.0_202.txt @@ -108,12 +108,10 @@ + JideTabbedPane.buttonMargin 5 + JideTabbedPane.buttonSize 18 + JideTabbedPane.closeButtonAlignment 11 -+ JideTabbedPane.closeButtonLeftMargin 2 + JideTabbedPane.closeButtonMargin 2 + JideTabbedPane.closeButtonMarginHorizonal 3 + JideTabbedPane.closeButtonMarginSize 6 + JideTabbedPane.closeButtonMarginVertical 3 -+ JideTabbedPane.closeButtonRightMargin 2 + JideTabbedPane.compressedStyleCloseButtonMarginHorizontal 0 + JideTabbedPane.compressedStyleCloseButtonMarginVertical 0 + JideTabbedPane.compressedStyleIconMargin 12 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 bf51c220..4cafd761 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 @@ -343,6 +343,8 @@ JideSplitButton.selectionForeground JideSplitButton.textIconGap JideSplitButtonUI JideTabbedPane.background +JideTabbedPane.closeButtonLeftMargin +JideTabbedPane.closeButtonRightMargin JideTabbedPane.contentBorderInsets JideTabbedPane.foreground JideTabbedPane.shadow From 923cc51f3e5bf829431bc3b3047c0f3485857d6f Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 27 Mar 2021 12:18:06 +0100 Subject: [PATCH 03/13] JIDE: JideTabbedPane: FlatJideOssContainerTest updated (based on FlatContainerTest) --- .../jideoss/ui/FlatJideTabbedPaneUI.java | 2 + .../jideoss/FlatJideOssContainerTest.java | 797 ++++++++++++++---- .../jideoss/FlatJideOssContainerTest.jfd | 447 +++++++--- 3 files changed, 982 insertions(+), 264 deletions(-) diff --git a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java index 6bd37a37..b2c93a11 100644 --- a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java +++ b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java @@ -149,6 +149,8 @@ public class FlatJideTabbedPaneUI repaintTab( (Integer) e.getNewValue() ); break; + case JideTabbedPane.PROPERTY_TAB_AREA_INSETS: + case JideTabbedPane.PROPERTY_TAB_INSETS: case TABBED_PANE_SHOW_TAB_SEPARATORS: case TABBED_PANE_HAS_FULL_BORDER: _tabPane.revalidate(); diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java index 97d6e9cd..a8cbd3a4 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java @@ -16,12 +16,15 @@ package com.formdev.flatlaf.testing.jideoss; -import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER; import java.awt.*; import javax.swing.*; import javax.swing.border.*; +import com.formdev.flatlaf.FlatClientProperties; +import com.formdev.flatlaf.FlatLaf; +import com.formdev.flatlaf.icons.FlatInternalFrameCloseIcon; import com.formdev.flatlaf.testing.*; import com.formdev.flatlaf.testing.FlatTestFrame; +import com.formdev.flatlaf.util.ScaledImageIcon; import com.jgoodies.forms.layout.*; import com.jidesoft.swing.*; import net.miginfocom.swing.*; @@ -35,49 +38,335 @@ public class FlatJideOssContainerTest public static void main( String[] args ) { SwingUtilities.invokeLater( () -> { FlatTestFrame frame = FlatTestFrame.create( args, "FlatJideOssContainerTest" ); + frame.useApplyComponentOrientation = true; frame.showFrame( FlatJideOssContainerTest::new ); } ); } FlatJideOssContainerTest() { initComponents(); + + tabPlacementField.init( TabPlacement.class, true ); + tabAlignmentField.init( JideTabAlignment.class, false ); + tabResizeModeField.init( JideTabResizeMode.class, true ); + + tabCountChanged(); + + tabsClosableCheckBox.setSelected( true ); + tabsClosableChanged(); + + tabScrollCheckBox.setSelected( true ); + tabScrollChanged(); } private void tabScrollChanged() { + // JideTabbedPane supports tab closing only in scroll layout + // --> turn of if necessary to avoid exceptions in BasicJideTabbedPaneUI + tabsClosableChanged(); + int tabLayoutPolicy = tabScrollCheckBox.isSelected() ? JTabbedPane.SCROLL_TAB_LAYOUT : JTabbedPane.WRAP_TAB_LAYOUT; - tabbedPane1.setTabLayoutPolicy( tabLayoutPolicy ); - tabbedPane2.setTabLayoutPolicy( tabLayoutPolicy ); - tabbedPane3.setTabLayoutPolicy( tabLayoutPolicy ); - tabbedPane4.setTabLayoutPolicy( tabLayoutPolicy ); + for( JTabbedPane tabbedPane : allTabbedPanes ) + tabbedPane.setTabLayoutPolicy( tabLayoutPolicy ); + + int tabCount = (Integer) tabCountSpinner.getValue(); + if( tabLayoutPolicy == JTabbedPane.SCROLL_TAB_LAYOUT && tabCount == 4 ) + tabCountSpinner.setValue( 8 ); + else if( tabLayoutPolicy == JTabbedPane.WRAP_TAB_LAYOUT && tabCount == 8 ) + tabCountSpinner.setValue( 4 ); + } + + private void showTabSeparatorsChanged() { + Boolean showTabSeparators = showTabSeparatorsCheckBox.isSelected() ? true : null; + putTabbedPanesClientProperty( FlatClientProperties.TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators ); + } + + private void hideTabAreaWithOneTabChanged() { + boolean hideTabAreaWithOneTab = hideTabAreaWithOneTabCheckBox.isSelected(); + for( JideTabbedPane tabbedPane : allTabbedPanes ) + tabbedPane.setHideOneTab( hideTabAreaWithOneTab ); } private void hasFullBorderChanged() { Boolean hasFullBorder = hasFullBorderCheckBox.isSelected() ? true : null; - tabbedPane1.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder ); - tabbedPane2.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder ); - tabbedPane3.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder ); - tabbedPane4.putClientProperty( TABBED_PANE_HAS_FULL_BORDER, hasFullBorder ); + putTabbedPanesClientProperty( FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER, hasFullBorder ); } - private void moreTabsChanged() { - boolean moreTabs = moreTabsCheckBox.isSelected(); - addRemoveMoreTabs( tabbedPane1, moreTabs ); - addRemoveMoreTabs( tabbedPane2, moreTabs ); - addRemoveMoreTabs( tabbedPane3, moreTabs ); - addRemoveMoreTabs( tabbedPane4, moreTabs ); + private void putTabbedPanesClientProperty( String key, Object value ) { + for( JTabbedPane tabbedPane : allTabbedPanes ) + tabbedPane.putClientProperty( key, value ); } - private void addRemoveMoreTabs( JTabbedPane tabbedPane, boolean add ) { - if( add ) { - tabbedPane.addTab( "Tab 4", new JLabel( "tab 4" ) ); - tabbedPane.addTab( "Tab 5", new JLabel( "tab 5" ) ); - } else { - int tabCount = tabbedPane.getTabCount(); - if( tabCount > 3 ) { - for( int i = 0; i < 2; i++ ) - tabbedPane.removeTabAt( tabbedPane.getTabCount() - 1 ); - } + private void tabCountChanged() { + for( JideTabbedPane tabbedPane : allTabbedPanes ) + tabCountChanged( tabbedPane ); + } + + private void tabCountChanged( JideTabbedPane tabbedPane ) { + int oldTabCount = tabbedPane.getTabCount(); + int newTabCount = (Integer) tabCountSpinner.getValue(); + + if( newTabCount > oldTabCount ) { + for( int i = oldTabCount + 1; i <= newTabCount; i++ ) + addTab( tabbedPane ); + } else if( newTabCount < oldTabCount ) { + while( tabbedPane.getTabCount() > newTabCount ) + tabbedPane.removeTabAt( tabbedPane.getTabCount() - 1 ); } + + customTabsChanged( tabbedPane ); + tabBackForegroundChanged( tabbedPane ); + setTabIcons( tabbedPane ); + } + + private void addTab( JideTabbedPane tabbedPane ) { + switch( tabbedPane.getTabCount() ) { + case 0: + tabbedPane.addTab( "Tab 1", null, new Panel1(), "First tab." ); + break; + + case 1: + JComponent tab2 = new Panel2(); + tab2.setBorder( new LineBorder( Color.magenta ) ); + tabbedPane.addTab( "Second Tab", null, tab2, "This is the second tab." ); + break; + + case 2: + tabbedPane.addTab( "Disabled", createTab( "tab content 3" ) ); + tabbedPane.setEnabledAt( 2, false ); + tabbedPane.setToolTipTextAt( 2, "Disabled tab." ); + break; + + case 3: + tabbedPane.addTab( "Tab 4", new JLabel( "non-opaque content", SwingConstants.CENTER ) ); + break; + + default: + int index = tabbedPane.getTabCount() + 1; + tabbedPane.addTab( "Tab " + index, createTab( "tab content " + index ) ); + break; + } + } + + private JComponent createTab( String text ) { + JLabel label = new JLabel( text ); + label.setHorizontalAlignment( SwingConstants.CENTER ); + + JPanel tab = new JPanel( new BorderLayout() ); + tab.add( label, BorderLayout.CENTER ); + return tab; + } + + private void tabIconsChanged() { + for( JTabbedPane tabbedPane : allTabbedPanes ) + setTabIcons( tabbedPane ); + + tabIconSizeSpinner.setEnabled( tabIconsCheckBox.isSelected() ); + } + + private void setTabIcons( JTabbedPane tabbedPane ) { + boolean showTabIcons = tabIconsCheckBox.isSelected(); + Object iconSize = tabIconSizeSpinner.getValue(); + + Icon icon = null; + Icon disabledIcon = null; + if( showTabIcons ) { + ImageIcon imageIcon = new ImageIcon( getClass().getResource( "/com/formdev/flatlaf/testing/test" + iconSize + ".png" ) ); + icon = new ScaledImageIcon( imageIcon ); + disabledIcon = UIManager.getLookAndFeel().getDisabledIcon( tabbedPane, imageIcon ); + if( disabledIcon instanceof ImageIcon ) + disabledIcon = new ScaledImageIcon( (ImageIcon) disabledIcon ); + } + + int tabCount = tabbedPane.getTabCount(); + for( int i = 0; i < tabCount; i++ ) { + tabbedPane.setIconAt( i, icon ); + tabbedPane.setDisabledIconAt( i, disabledIcon ); + } + } + + private void customBorderChanged() { + Border border = customBorderCheckBox.isSelected() + ? new MatteBorder( 10, 20, 25, 35, Color.green ) + : null; + + for( JTabbedPane tabbedPane : allTabbedPanes ) + tabbedPane.setBorder( border ); + } + + private void customTabsChanged() { + for( JTabbedPane tabbedPane : allTabbedPanes ) + customTabsChanged( tabbedPane ); + } + + private void customTabsChanged( JTabbedPane tabbedPane ) { + boolean customTabs = customTabsCheckBox.isSelected(); + int tabCount = tabbedPane.getTabCount(); + if( tabCount > 1 ) + tabbedPane.setTabComponentAt( 1, customTabs ? new JButton( tabbedPane.getTitleAt( 1 ) ) : null ); + if( tabCount > 3 ) + tabbedPane.setTabComponentAt( 3, customTabs ? createCustomTab( tabbedPane.getTitleAt( 3 ) ) : null ); + if( tabCount > 5 ) + tabbedPane.setTabComponentAt( 5, customTabs ? new JCheckBox( tabbedPane.getTitleAt( 5 ) ) : null ); + } + + private Component createCustomTab( String tabTitle ) { + JButton closeButton; + if( UIManager.getLookAndFeel() instanceof FlatLaf ) { + closeButton = new JButton( new FlatInternalFrameCloseIcon() ); + closeButton.setContentAreaFilled( false ); + closeButton.setBorder( null ); + } else + closeButton = new JButton( "x" ); + + JPanel tab = new JPanel( new BorderLayout( 5, 0 ) ); + tab.setOpaque( false ); + tab.add( closeButton, BorderLayout.EAST ); + tab.add( new JLabel( tabTitle ), BorderLayout.CENTER ); + return tab; + } + + private void htmlTabsChanged() { + for( JTabbedPane tabbedPane : allTabbedPanes ) + htmlTabsChanged( tabbedPane ); + } + + private void htmlTabsChanged( JTabbedPane tabbedPane ) { + boolean html = htmlTabsCheckBox.isSelected(); + boolean multiLine = multiLineTabsCheckBox.isSelected(); + String s = multiLine + ? "Bold Tab
Second Line " + : (html ? "Bold Tab " : "Tab "); + int tabCount = tabbedPane.getTabCount(); + if( tabCount > 0 ) + tabbedPane.setTitleAt( 0, s + "1" ); + if( tabCount > 3 ) + tabbedPane.setTitleAt( 3, s + "4" ); + } + + private void tabPlacementChanged() { + TabPlacement value = tabPlacementField.getSelectedValue(); + int tabPlacement = (value != null) ? value.value : -1; + + tabbedPane1.setTabPlacement( (tabPlacement >= 0) ? tabPlacement : SwingConstants.TOP ); + tabbedPane2.setTabPlacement( (tabPlacement >= 0) ? tabPlacement : SwingConstants.BOTTOM ); + tabbedPane3.setTabPlacement( (tabPlacement >= 0) ? tabPlacement : SwingConstants.LEFT ); + tabbedPane4.setTabPlacement( (tabPlacement >= 0) ? tabPlacement : SwingConstants.RIGHT ); + } + + private void tabAlignmentChanged() { + JideTabAlignment value = tabAlignmentField.getSelectedValue(); + for( JideTabbedPane tabbedPane : allTabbedPanes ) + tabbedPane.setTabAlignment( value.value ); + } + + private void tabResizeModeChanged() { + JideTabResizeMode value = tabResizeModeField.getSelectedValue(); + int resizeMode = (value != null) ? value.value : JideTabbedPane.RESIZE_MODE_DEFAULT; + for( JideTabbedPane tabbedPane : allTabbedPanes ) + tabbedPane.setTabResizeMode( resizeMode ); + } + + private void tabBackForegroundChanged() { + for( JTabbedPane tabbedPane : allTabbedPanes ) + tabBackForegroundChanged( tabbedPane ); + } + + private void tabBackForegroundChanged( JTabbedPane tabbedPane ) { + boolean enabled = tabBackForegroundCheckBox.isSelected(); + int tabCount = tabbedPane.getTabCount(); + if( tabCount > 0 ) + tabbedPane.setBackgroundAt( 0, enabled ? Color.red : null ); + if( tabCount > 1 ) + tabbedPane.setForegroundAt( 1, enabled ? Color.red : null ); + } + + private void leadingComponentChanged() { + leadingTrailingComponentChanged( leadingComponentCheckBox.isSelected(), true, "L", 4 ); + } + + private void trailingComponentChanged() { + leadingTrailingComponentChanged( trailingComponentCheckBox.isSelected(), false, "Trailing", 12 ); + } + + private void leadingTrailingComponentChanged( boolean enabled, boolean leading, String text, int gap ) { + for( JideTabbedPane tabbedPane : allTabbedPanes ) { + JComponent c = null; + if( enabled ) { + c = new JLabel( text ); + c.setOpaque( true ); + c.setBackground( leading ? Color.cyan : Color.orange ); + c.setBorder( new EmptyBorder( gap, gap, gap, gap ) ); + } + if( leading ) + tabbedPane.setTabLeadingComponent( c ); + else + tabbedPane.setTabTrailingComponent( c ); + } + } + + private void tabsClosableChanged() { + boolean closable = tabsClosableCheckBox.isSelected() && tabScrollCheckBox.isSelected(); + for( JideTabbedPane tabbedPane : allTabbedPanes ) { + tabbedPane.setShowCloseButton( closable ); + tabbedPane.setShowCloseButtonOnTab( closable ); + } + } + + private void secondTabClosableChanged() { + boolean closable = secondTabClosableCheckBox.isSelected(); + + for( JideTabbedPane tabbedPane : allTabbedPanes ) { + if( tabbedPane.getTabCount() > 1 ) + tabbedPane.setTabClosableAt( 1, closable ); + } + } + + private void showCloseButtonOnSelectedTabChanged() { + boolean onSelected = showCloseButtonOnSelectedTabCheckBox.isSelected(); + + for( JideTabbedPane tabbedPane : allTabbedPanes ) { + tabbedPane.setShowCloseButtonOnSelectedTab( onSelected ); + tabbedPane.revalidate(); + tabbedPane.repaint(); + } + } + + private void showCloseButtonOnMouseOverChanged() { + boolean onMouseOver = showCloseButtonOnMouseOverCheckBox.isSelected(); + + for( JideTabbedPane tabbedPane : allTabbedPanes ) { + tabbedPane.setShowCloseButtonOnMouseOver( onMouseOver ); + tabbedPane.revalidate(); + tabbedPane.repaint(); + } + } + + private void tabAreaInsetsChanged() { + Insets insets = tabAreaInsetsCheckBox.isSelected() ? new Insets( 5, 5, 10, 10 ) : null; + for( JideTabbedPane tabbedPane : allTabbedPanes ) + tabbedPane.setTabAreaInsets( insets ); + } + + private void smallerInsetsChanged() { + Insets insets = smallerInsetsCheckBox.isSelected() + ? new Insets( 2, 2, 2, 2 ) + : UIManager.getInsets( "JideTabbedPane.tabInsets" ); + for( JideTabbedPane tabbedPane : allTabbedPanes ) + tabbedPane.setTabInsets( insets ); + } + + private void boldActiveTabChanged() { + boolean boldActiveTab = boldActiveTabCheckBox.isSelected(); + + for( JideTabbedPane tabbedPane : allTabbedPanes ) + tabbedPane.setBoldActiveTab( boldActiveTab ); + } + + private void showTabButtonsChanged() { + boolean showTabButtons = showTabButtonsCheckBox.isSelected(); + + for( JideTabbedPane tabbedPane : allTabbedPanes ) + tabbedPane.setShowTabButtons( showTabButtons ); } private void initComponents() { @@ -85,29 +374,39 @@ public class FlatJideOssContainerTest JPanel panel9 = new JPanel(); JLabel tabbedPaneLabel = new JLabel(); tabbedPane1 = new JideTabbedPane(); - JPanel panel1 = new JPanel(); - JLabel label1 = new JLabel(); - JPanel panel2 = new JPanel(); - JLabel label2 = new JLabel(); tabbedPane3 = new JideTabbedPane(); - JPanel panel5 = new JPanel(); - JLabel label5 = new JLabel(); - JPanel panel6 = new JPanel(); - JLabel label6 = new JLabel(); tabbedPane2 = new JideTabbedPane(); - JPanel panel3 = new JPanel(); - JLabel label3 = new JLabel(); - JPanel panel4 = new JPanel(); - JLabel label4 = new JLabel(); tabbedPane4 = new JideTabbedPane(); - JPanel panel7 = new JPanel(); - JLabel label7 = new JLabel(); - JPanel panel8 = new JPanel(); - JLabel label8 = new JLabel(); - JPanel panel14 = new JPanel(); - moreTabsCheckBox = new JCheckBox(); + FlatTestFrame.NoRightToLeftPanel tabbedPaneControlPanel = new FlatTestFrame.NoRightToLeftPanel(); tabScrollCheckBox = new JCheckBox(); + JLabel tabCountLabel = new JLabel(); + tabCountSpinner = new JSpinner(); + customTabsCheckBox = new JCheckBox(); + htmlTabsCheckBox = new JCheckBox(); + multiLineTabsCheckBox = new JCheckBox(); + tabBackForegroundCheckBox = new JCheckBox(); + tabIconsCheckBox = new JCheckBox(); + tabIconSizeSpinner = new JSpinner(); + tabsClosableCheckBox = new JCheckBox(); + showCloseButtonOnSelectedTabCheckBox = new JCheckBox(); + JLabel tabPlacementLabel = new JLabel(); + tabPlacementField = new FlatTestEnumComboBox<>(); + secondTabClosableCheckBox = new JCheckBox(); + showCloseButtonOnMouseOverCheckBox = new JCheckBox(); + JLabel tabAreaAlignmentLabel = new JLabel(); + tabAlignmentField = new FlatTestEnumComboBox<>(); + JLabel tabResizeModeLabel = new JLabel(); + tabResizeModeField = new FlatTestEnumComboBox<>(); + leadingComponentCheckBox = new JCheckBox(); + customBorderCheckBox = new JCheckBox(); + tabAreaInsetsCheckBox = new JCheckBox(); + trailingComponentCheckBox = new JCheckBox(); hasFullBorderCheckBox = new JCheckBox(); + boldActiveTabCheckBox = new JCheckBox(); + showTabButtonsCheckBox = new JCheckBox(); + smallerInsetsCheckBox = new JCheckBox(); + showTabSeparatorsCheckBox = new JCheckBox(); + hideTabAreaWithOneTabCheckBox = new JCheckBox(); CellConstraints cc = new CellConstraints(); //======== this ======== @@ -122,156 +421,201 @@ public class FlatJideOssContainerTest { panel9.setOpaque(false); panel9.setLayout(new FormLayout( - "70dlu:grow, $lcgap, 70dlu:grow", - "pref, 2*($lgap, fill:70dlu:grow), $lgap, pref")); + "70dlu:grow, $ugap, 70dlu:grow", + "pref, $lgap, fill:80dlu:grow, $ugap, fill:80dlu:grow, $pgap, pref")); //---- tabbedPaneLabel ---- tabbedPaneLabel.setText("JideTabbedPane:"); panel9.add(tabbedPaneLabel, cc.xy(1, 1)); - - //======== tabbedPane1 ======== - { - - //======== panel1 ======== - { - panel1.setLayout(new FlowLayout()); - - //---- label1 ---- - label1.setText("TOP"); - panel1.add(label1); - } - tabbedPane1.addTab("Tab 1", panel1); - - //======== panel2 ======== - { - panel2.setBorder(new LineBorder(Color.magenta)); - panel2.setLayout(new FlowLayout()); - } - tabbedPane1.addTab("Tab 2", panel2); - - //---- label2 ---- - label2.setText("text"); - tabbedPane1.addTab("Tab 3", label2); - } panel9.add(tabbedPane1, cc.xy(1, 3)); //======== tabbedPane3 ======== { tabbedPane3.setTabPlacement(SwingConstants.LEFT); - - //======== panel5 ======== - { - panel5.setLayout(new FlowLayout()); - - //---- label5 ---- - label5.setText("LEFT"); - panel5.add(label5); - } - tabbedPane3.addTab("Tab 1", panel5); - - //======== panel6 ======== - { - panel6.setBorder(new LineBorder(Color.magenta)); - panel6.setLayout(new FlowLayout()); - } - tabbedPane3.addTab("Tab 2", panel6); - - //---- label6 ---- - label6.setText("text"); - tabbedPane3.addTab("Tab 3", label6); } panel9.add(tabbedPane3, cc.xy(3, 3)); //======== tabbedPane2 ======== { tabbedPane2.setTabPlacement(SwingConstants.BOTTOM); - - //======== panel3 ======== - { - panel3.setLayout(new FlowLayout()); - - //---- label3 ---- - label3.setText("BOTTOM"); - panel3.add(label3); - } - tabbedPane2.addTab("Tab 1", panel3); - - //======== panel4 ======== - { - panel4.setBorder(new LineBorder(Color.magenta)); - panel4.setLayout(new FlowLayout()); - } - tabbedPane2.addTab("Tab 2", panel4); - tabbedPane2.setEnabledAt(1, false); - - //---- label4 ---- - label4.setText("text"); - tabbedPane2.addTab("Tab 3", label4); } panel9.add(tabbedPane2, cc.xy(1, 5)); //======== tabbedPane4 ======== { tabbedPane4.setTabPlacement(SwingConstants.RIGHT); - - //======== panel7 ======== - { - panel7.setLayout(new FlowLayout()); - - //---- label7 ---- - label7.setText("RIGHT"); - panel7.add(label7); - } - tabbedPane4.addTab("Tab 1", panel7); - - //======== panel8 ======== - { - panel8.setBorder(new LineBorder(Color.magenta)); - panel8.setLayout(new FlowLayout()); - } - tabbedPane4.addTab("Tab 2", panel8); - - //---- label8 ---- - label8.setText("text"); - tabbedPane4.addTab("Tab 3", label8); } panel9.add(tabbedPane4, cc.xy(3, 5)); - //======== panel14 ======== + //======== tabbedPaneControlPanel ======== { - panel14.setOpaque(false); - panel14.setLayout(new MigLayout( + tabbedPaneControlPanel.setOpaque(false); + tabbedPaneControlPanel.setLayout(new MigLayout( "insets 0,hidemode 3", // columns "[]" + - "[]" + + "[fill]" + "[]", // rows - "[center]")); - - //---- moreTabsCheckBox ---- - moreTabsCheckBox.setText("more tabs"); - moreTabsCheckBox.setMnemonic('M'); - moreTabsCheckBox.addActionListener(e -> moreTabsChanged()); - panel14.add(moreTabsCheckBox, "cell 0 0"); + "[center]" + + "[]" + + "[]" + + "[]" + + "[]" + + "[]para" + + "[]" + + "[]para" + + "[]" + + "[]" + + "[]")); //---- tabScrollCheckBox ---- - tabScrollCheckBox.setText("tabLayoutPolicy = SCROLL"); + tabScrollCheckBox.setText("Use scroll layout"); tabScrollCheckBox.setMnemonic('S'); - tabScrollCheckBox.setSelected(true); tabScrollCheckBox.addActionListener(e -> tabScrollChanged()); - panel14.add(tabScrollCheckBox, "cell 1 0,alignx left,growx 0"); + tabbedPaneControlPanel.add(tabScrollCheckBox, "cell 0 0,alignx left,growx 0"); + + //---- tabCountLabel ---- + tabCountLabel.setText("Tab count:"); + tabbedPaneControlPanel.add(tabCountLabel, "cell 1 0"); + + //---- tabCountSpinner ---- + tabCountSpinner.setModel(new SpinnerNumberModel(4, 0, null, 1)); + tabCountSpinner.addChangeListener(e -> tabCountChanged()); + tabbedPaneControlPanel.add(tabCountSpinner, "cell 1 0"); + + //---- customTabsCheckBox ---- + customTabsCheckBox.setText("Custom tabs"); + customTabsCheckBox.addActionListener(e -> customTabsChanged()); + tabbedPaneControlPanel.add(customTabsCheckBox, "cell 2 0"); + + //---- htmlTabsCheckBox ---- + htmlTabsCheckBox.setText("HTML"); + htmlTabsCheckBox.addActionListener(e -> htmlTabsChanged()); + tabbedPaneControlPanel.add(htmlTabsCheckBox, "cell 2 0"); + + //---- multiLineTabsCheckBox ---- + multiLineTabsCheckBox.setText("multi-line"); + multiLineTabsCheckBox.addActionListener(e -> htmlTabsChanged()); + tabbedPaneControlPanel.add(multiLineTabsCheckBox, "cell 2 0"); + + //---- tabBackForegroundCheckBox ---- + tabBackForegroundCheckBox.setText("Tab back/foreground"); + tabBackForegroundCheckBox.addActionListener(e -> tabBackForegroundChanged()); + tabbedPaneControlPanel.add(tabBackForegroundCheckBox, "cell 2 1"); + + //---- tabIconsCheckBox ---- + tabIconsCheckBox.setText("Tab icons"); + tabIconsCheckBox.addActionListener(e -> tabIconsChanged()); + tabbedPaneControlPanel.add(tabIconsCheckBox, "cell 2 2"); + + //---- tabIconSizeSpinner ---- + tabIconSizeSpinner.setModel(new SpinnerListModel(new String[] {"16", "24", "32", "48", "64"})); + tabIconSizeSpinner.setEnabled(false); + tabIconSizeSpinner.addChangeListener(e -> tabIconsChanged()); + tabbedPaneControlPanel.add(tabIconSizeSpinner, "cell 2 2"); + + //---- tabsClosableCheckBox ---- + tabsClosableCheckBox.setText("Tabs closable"); + tabsClosableCheckBox.addActionListener(e -> tabsClosableChanged()); + tabbedPaneControlPanel.add(tabsClosableCheckBox, "cell 2 3"); + + //---- showCloseButtonOnSelectedTabCheckBox ---- + showCloseButtonOnSelectedTabCheckBox.setText("show on selected"); + showCloseButtonOnSelectedTabCheckBox.addActionListener(e -> showCloseButtonOnSelectedTabChanged()); + tabbedPaneControlPanel.add(showCloseButtonOnSelectedTabCheckBox, "cell 2 3"); + + //---- tabPlacementLabel ---- + tabPlacementLabel.setText("Tab placement:"); + tabbedPaneControlPanel.add(tabPlacementLabel, "cell 0 4"); + + //---- tabPlacementField ---- + tabPlacementField.addActionListener(e -> tabPlacementChanged()); + tabbedPaneControlPanel.add(tabPlacementField, "cell 1 4"); + + //---- secondTabClosableCheckBox ---- + secondTabClosableCheckBox.setText("Second Tab closable"); + secondTabClosableCheckBox.setSelected(true); + secondTabClosableCheckBox.addActionListener(e -> secondTabClosableChanged()); + tabbedPaneControlPanel.add(secondTabClosableCheckBox, "cell 2 4"); + + //---- showCloseButtonOnMouseOverCheckBox ---- + showCloseButtonOnMouseOverCheckBox.setText("show on hover"); + showCloseButtonOnMouseOverCheckBox.addActionListener(e -> showCloseButtonOnMouseOverChanged()); + tabbedPaneControlPanel.add(showCloseButtonOnMouseOverCheckBox, "cell 2 4"); + + //---- tabAreaAlignmentLabel ---- + tabAreaAlignmentLabel.setText("Tab alignment:"); + tabbedPaneControlPanel.add(tabAreaAlignmentLabel, "cell 0 5"); + + //---- tabAlignmentField ---- + tabAlignmentField.addActionListener(e -> tabAlignmentChanged()); + tabbedPaneControlPanel.add(tabAlignmentField, "cell 1 5"); + + //---- tabResizeModeLabel ---- + tabResizeModeLabel.setText("Tab resize mode:"); + tabbedPaneControlPanel.add(tabResizeModeLabel, "cell 2 5"); + + //---- tabResizeModeField ---- + tabResizeModeField.addActionListener(e -> tabResizeModeChanged()); + tabbedPaneControlPanel.add(tabResizeModeField, "cell 2 5"); + + //---- leadingComponentCheckBox ---- + leadingComponentCheckBox.setText("Leading component"); + leadingComponentCheckBox.addActionListener(e -> leadingComponentChanged()); + tabbedPaneControlPanel.add(leadingComponentCheckBox, "cell 0 6"); + + //---- customBorderCheckBox ---- + customBorderCheckBox.setText("Custom border"); + customBorderCheckBox.addActionListener(e -> customBorderChanged()); + tabbedPaneControlPanel.add(customBorderCheckBox, "cell 1 6"); + + //---- tabAreaInsetsCheckBox ---- + tabAreaInsetsCheckBox.setText("Tab area insets (5,5,10,10)"); + tabAreaInsetsCheckBox.addActionListener(e -> tabAreaInsetsChanged()); + tabbedPaneControlPanel.add(tabAreaInsetsCheckBox, "cell 2 6"); + + //---- trailingComponentCheckBox ---- + trailingComponentCheckBox.setText("Trailing component"); + trailingComponentCheckBox.addActionListener(e -> trailingComponentChanged()); + tabbedPaneControlPanel.add(trailingComponentCheckBox, "cell 0 7"); //---- hasFullBorderCheckBox ---- - hasFullBorderCheckBox.setText("JTabbedPane.hasFullBorder"); - hasFullBorderCheckBox.setMnemonic('F'); + hasFullBorderCheckBox.setText("Show content border"); hasFullBorderCheckBox.addActionListener(e -> hasFullBorderChanged()); - panel14.add(hasFullBorderCheckBox, "cell 2 0,alignx left,growx 0"); + tabbedPaneControlPanel.add(hasFullBorderCheckBox, "cell 1 7,alignx left,growx 0"); + + //---- boldActiveTabCheckBox ---- + boldActiveTabCheckBox.setText("Bold active tab"); + boldActiveTabCheckBox.addActionListener(e -> boldActiveTabChanged()); + tabbedPaneControlPanel.add(boldActiveTabCheckBox, "cell 0 8"); + + //---- showTabButtonsCheckBox ---- + showTabButtonsCheckBox.setText("Show tab buttons always"); + showTabButtonsCheckBox.addActionListener(e -> showTabButtonsChanged()); + tabbedPaneControlPanel.add(showTabButtonsCheckBox, "cell 1 8"); + + //---- smallerInsetsCheckBox ---- + smallerInsetsCheckBox.setText("Smaller tab insets (2,2,2,2)"); + smallerInsetsCheckBox.addActionListener(e -> smallerInsetsChanged()); + tabbedPaneControlPanel.add(smallerInsetsCheckBox, "cell 2 8"); + + //---- showTabSeparatorsCheckBox ---- + showTabSeparatorsCheckBox.setText("Show tab separators"); + showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged()); + tabbedPaneControlPanel.add(showTabSeparatorsCheckBox, "cell 1 9"); + + //---- hideTabAreaWithOneTabCheckBox ---- + hideTabAreaWithOneTabCheckBox.setText("Hide tab area with one tab"); + hideTabAreaWithOneTabCheckBox.addActionListener(e -> hideTabAreaWithOneTabChanged()); + tabbedPaneControlPanel.add(hideTabAreaWithOneTabCheckBox, "cell 1 10"); } - panel9.add(panel14, cc.xywh(1, 7, 3, 1)); + panel9.add(tabbedPaneControlPanel, cc.xywh(1, 7, 3, 1)); } add(panel9, "cell 0 0"); // JFormDesigner - End of component initialization //GEN-END:initComponents + + allTabbedPanes = new JideTabbedPane[] { tabbedPane1, tabbedPane2, tabbedPane3, tabbedPane4 }; } // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables @@ -279,8 +623,155 @@ public class FlatJideOssContainerTest private JideTabbedPane tabbedPane3; private JideTabbedPane tabbedPane2; private JideTabbedPane tabbedPane4; - private JCheckBox moreTabsCheckBox; private JCheckBox tabScrollCheckBox; + private JSpinner tabCountSpinner; + private JCheckBox customTabsCheckBox; + private JCheckBox htmlTabsCheckBox; + private JCheckBox multiLineTabsCheckBox; + private JCheckBox tabBackForegroundCheckBox; + private JCheckBox tabIconsCheckBox; + private JSpinner tabIconSizeSpinner; + private JCheckBox tabsClosableCheckBox; + private JCheckBox showCloseButtonOnSelectedTabCheckBox; + private FlatTestEnumComboBox tabPlacementField; + private JCheckBox secondTabClosableCheckBox; + private JCheckBox showCloseButtonOnMouseOverCheckBox; + private FlatTestEnumComboBox tabAlignmentField; + private FlatTestEnumComboBox tabResizeModeField; + private JCheckBox leadingComponentCheckBox; + private JCheckBox customBorderCheckBox; + private JCheckBox tabAreaInsetsCheckBox; + private JCheckBox trailingComponentCheckBox; private JCheckBox hasFullBorderCheckBox; + private JCheckBox boldActiveTabCheckBox; + private JCheckBox showTabButtonsCheckBox; + private JCheckBox smallerInsetsCheckBox; + private JCheckBox showTabSeparatorsCheckBox; + private JCheckBox hideTabAreaWithOneTabCheckBox; // JFormDesigner - End of variables declaration //GEN-END:variables + + private JideTabbedPane[] allTabbedPanes; + + //---- enum TabPlacement -------------------------------------------------- + + enum TabPlacement { + top( SwingConstants.TOP ), + bottom( SwingConstants.BOTTOM ), + left( SwingConstants.LEFT ), + right( SwingConstants.RIGHT ); + + public final int value; + + TabPlacement( int value ) { + this.value = value; + } + }; + + //---- enum JideTabAlignment ---------------------------------------------- + + enum JideTabAlignment { + leading( SwingConstants.LEADING ), + center( SwingConstants.CENTER ); + + public final int value; + + JideTabAlignment( int value ) { + this.value = value; + } + }; + + //---- enum JideTabResizeMode --------------------------------------------- + + enum JideTabResizeMode { + none( JideTabbedPane.RESIZE_MODE_NONE ), + fit( JideTabbedPane.RESIZE_MODE_FIT ), + fixed( JideTabbedPane.RESIZE_MODE_FIXED ), + compressed( JideTabbedPane.RESIZE_MODE_COMPRESSED ); + + public final int value; + + JideTabResizeMode( int value ) { + this.value = value; + } + }; + + //---- class Tab1Panel ---------------------------------------------------- + + private static class Panel1 + extends JPanel + { + private Panel1() { + initComponents(); + } + + private void initComponents() { + // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents + JLabel label1 = new JLabel(); + JTextField textField4 = new JTextField(); + JButton button3 = new JButton(); + + //======== this ======== + setLayout(new MigLayout( + "hidemode 3,align center center", + // columns + "[fill]" + + "[fill]" + + "[fill]", + // rows + "[fill]")); + + //---- label1 ---- + label1.setText("text"); + add(label1, "cell 0 0"); + + //---- textField4 ---- + textField4.setText("some text"); + add(textField4, "cell 1 0"); + + //---- button3 ---- + button3.setText("..."); + add(button3, "cell 2 0"); + // JFormDesigner - End of component initialization //GEN-END:initComponents + } + + // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables + // JFormDesigner - End of variables declaration //GEN-END:variables + } + + //---- class Tab2Panel ---------------------------------------------------- + + private static class Panel2 + extends JPanel + { + private Panel2() { + initComponents(); + } + + private void initComponents() { + // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents + JTextField textField5 = new JTextField(); + JButton button4 = new JButton(); + + //======== this ======== + setLayout(new MigLayout( + "insets 0,hidemode 3,align center center", + // columns + "[fill]" + + "[fill]", + // rows + "[fill]")); + + //---- textField5 ---- + textField5.setText("more text"); + add(textField5, "cell 0 0"); + + //---- button4 ---- + button4.setText("..."); + add(button4, "cell 1 0"); + // JFormDesigner - End of component initialization //GEN-END:initComponents + } + + // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables + // JFormDesigner - End of variables declaration //GEN-END:variables + } } diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd index 7b73a58a..680e3e72 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd @@ -13,8 +13,8 @@ new FormModel { } ) { name: "this" add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class com.jgoodies.forms.layout.FormLayout ) { - "$columnSpecs": "70dlu:grow, labelcompgap, 70dlu:grow" - "$rowSpecs": "pref, linegap, fill:70dlu:grow, linegap, fill:70dlu:grow, linegap, pref" + "$columnSpecs": "70dlu:grow, unrelgap, 70dlu:grow" + "$rowSpecs": "pref, linegap, fill:80dlu:grow, unrelgap, fill:80dlu:grow, pargap, pref" } ) { name: "panel9" "opaque": false @@ -29,27 +29,6 @@ new FormModel { auxiliary() { "JavaCodeGenerator.variableLocal": false } - add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { - name: "panel1" - add( new FormComponent( "javax.swing.JLabel" ) { - name: "label1" - "text": "TOP" - } ) - }, new FormLayoutConstraints( null ) { - "title": "Tab 1" - } ) - add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { - name: "panel2" - "border": &LineBorder0 new javax.swing.border.LineBorder( sfield java.awt.Color magenta, 1, false ) - }, new FormLayoutConstraints( null ) { - "title": "Tab 2" - } ) - add( new FormComponent( "javax.swing.JLabel" ) { - name: "label2" - "text": "text" - }, new FormLayoutConstraints( null ) { - "title": "Tab 3" - } ) }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { "gridX": 1 "gridY": 3 @@ -60,30 +39,9 @@ new FormModel { auxiliary() { "JavaCodeGenerator.variableLocal": false } - add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { - name: "panel5" - add( new FormComponent( "javax.swing.JLabel" ) { - name: "label5" - "text": "LEFT" - } ) - }, new FormLayoutConstraints( null ) { - "title": "Tab 1" - } ) - add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { - name: "panel6" - "border": #LineBorder0 - }, new FormLayoutConstraints( null ) { - "title": "Tab 2" - } ) - add( new FormComponent( "javax.swing.JLabel" ) { - name: "label6" - "text": "text" - }, new FormLayoutConstraints( null ) { - "title": "Tab 3" - } ) }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { - "gridX": 3 "gridY": 3 + "gridX": 3 } ) add( new FormContainer( "com.jidesoft.swing.JideTabbedPane", new FormLayoutManager( class javax.swing.JTabbedPane ) ) { name: "tabbedPane2" @@ -91,28 +49,6 @@ new FormModel { auxiliary() { "JavaCodeGenerator.variableLocal": false } - add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { - name: "panel3" - add( new FormComponent( "javax.swing.JLabel" ) { - name: "label3" - "text": "BOTTOM" - } ) - }, new FormLayoutConstraints( null ) { - "title": "Tab 1" - } ) - add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { - name: "panel4" - "border": #LineBorder0 - }, new FormLayoutConstraints( null ) { - "title": "Tab 2" - "enabled": false - } ) - add( new FormComponent( "javax.swing.JLabel" ) { - name: "label4" - "text": "text" - }, new FormLayoutConstraints( null ) { - "title": "Tab 3" - } ) }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { "gridY": 5 } ) @@ -122,71 +58,304 @@ new FormModel { auxiliary() { "JavaCodeGenerator.variableLocal": false } - add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { - name: "panel7" - add( new FormComponent( "javax.swing.JLabel" ) { - name: "label7" - "text": "RIGHT" - } ) - }, new FormLayoutConstraints( null ) { - "title": "Tab 1" - } ) - add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) { - name: "panel8" - "border": #LineBorder0 - }, new FormLayoutConstraints( null ) { - "title": "Tab 2" - } ) - add( new FormComponent( "javax.swing.JLabel" ) { - name: "label8" - "text": "text" - }, new FormLayoutConstraints( null ) { - "title": "Tab 3" - } ) }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { - "gridX": 3 "gridY": 5 + "gridX": 3 } ) - add( new FormContainer( "javax.swing.JPanel", 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" - "$columnConstraints": "[][][]" - "$rowConstraints": "[center]" + "$columnConstraints": "[][fill][]" + "$rowConstraints": "[center][][][][][]para[][]para[][][]" } ) { - name: "panel14" + name: "tabbedPaneControlPanel" "opaque": false - add( new FormComponent( "javax.swing.JCheckBox" ) { - name: "moreTabsCheckBox" - "text": "more tabs" - "mnemonic": 77 - auxiliary() { - "JavaCodeGenerator.variableLocal": false - } - addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "moreTabsChanged", false ) ) - }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 0" - } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "tabScrollCheckBox" - "text": "tabLayoutPolicy = SCROLL" + "text": "Use scroll layout" "mnemonic": 83 - "selected": true auxiliary() { "JavaCodeGenerator.variableLocal": false } addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabScrollChanged", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 0,alignx left,growx 0" + "value": "cell 0 0,alignx left,growx 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tabCountLabel" + "text": "Tab count:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0" + } ) + add( new FormComponent( "javax.swing.JSpinner" ) { + name: "tabCountSpinner" + "model": new javax.swing.SpinnerNumberModel { + minimum: 0 + value: 4 + } + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "tabCountChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "customTabsCheckBox" + "text": "Custom tabs" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "customTabsChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "htmlTabsCheckBox" + "text": "HTML" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "htmlTabsChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "multiLineTabsCheckBox" + "text": "multi-line" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "htmlTabsChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "tabBackForegroundCheckBox" + "text": "Tab back/foreground" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabBackForegroundChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 1" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "tabIconsCheckBox" + "text": "Tab icons" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabIconsChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 2" + } ) + add( new FormComponent( "javax.swing.JSpinner" ) { + name: "tabIconSizeSpinner" + "model": new javax.swing.SpinnerListModel { + list: new java.util.ArrayList { + add( "16" ) + add( "24" ) + add( "32" ) + add( "48" ) + add( "64" ) + } + } + "enabled": false + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "tabIconsChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 2" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "tabsClosableCheckBox" + "text": "Tabs closable" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabsClosableChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 3" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "showCloseButtonOnSelectedTabCheckBox" + "text": "show on selected" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showCloseButtonOnSelectedTabChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 3" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tabPlacementLabel" + "text": "Tab placement:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 4" + } ) + add( new FormComponent( "com.formdev.flatlaf.testing.FlatTestEnumComboBox" ) { + name: "tabPlacementField" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + "JavaCodeGenerator.typeParameters": "TabPlacement" + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabPlacementChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 4" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "secondTabClosableCheckBox" + "text": "Second Tab closable" + "selected": true + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "secondTabClosableChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 4" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "showCloseButtonOnMouseOverCheckBox" + "text": "show on hover" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showCloseButtonOnMouseOverChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 4" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tabAreaAlignmentLabel" + "text": "Tab alignment:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 5" + } ) + add( new FormComponent( "com.formdev.flatlaf.testing.FlatTestEnumComboBox" ) { + name: "tabAlignmentField" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + "JavaCodeGenerator.typeParameters": "JideTabAlignment" + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabAlignmentChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 5" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tabResizeModeLabel" + "text": "Tab resize mode:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 5" + } ) + add( new FormComponent( "com.formdev.flatlaf.testing.FlatTestEnumComboBox" ) { + name: "tabResizeModeField" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + "JavaCodeGenerator.typeParameters": "JideTabResizeMode" + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabResizeModeChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 5" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "leadingComponentCheckBox" + "text": "Leading component" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "leadingComponentChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 6" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "customBorderCheckBox" + "text": "Custom border" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "customBorderChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 6" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "tabAreaInsetsCheckBox" + "text": "Tab area insets (5,5,10,10)" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabAreaInsetsChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 6" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "trailingComponentCheckBox" + "text": "Trailing component" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "trailingComponentChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 7" } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "hasFullBorderCheckBox" - "text": "JTabbedPane.hasFullBorder" - "mnemonic": 70 + "text": "Show content border" auxiliary() { "JavaCodeGenerator.variableLocal": false } addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hasFullBorderChanged", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 0,alignx left,growx 0" + "value": "cell 1 7,alignx left,growx 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "boldActiveTabCheckBox" + "text": "Bold active tab" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "boldActiveTabChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 8" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "showTabButtonsCheckBox" + "text": "Show tab buttons always" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTabButtonsChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 8" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "smallerInsetsCheckBox" + "text": "Smaller tab insets (2,2,2,2)" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "smallerInsetsChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 8" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "showTabSeparatorsCheckBox" + "text": "Show tab separators" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTabSeparatorsChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 9" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "hideTabAreaWithOneTabCheckBox" + "text": "Hide tab area with one tab" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "hideTabAreaWithOneTabChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 10" } ) }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) { "gridY": 7 @@ -197,7 +366,63 @@ new FormModel { } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 ) - "size": new java.awt.Dimension( 500, 500 ) + "size": new java.awt.Dimension( 695, 655 ) + } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$layoutConstraints": "hidemode 3,align center center" + "$columnConstraints": "[fill][fill][fill]" + "$rowConstraints": "[fill]" + } ) { + name: "panel1" + auxiliary() { + "JavaCodeGenerator.className": "Panel1" + } + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label1" + "text": "text" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + add( new FormComponent( "javax.swing.JTextField" ) { + name: "textField4" + "text": "some text" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0" + } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "button3" + "text": "..." + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 0" + } ) + }, new FormLayoutConstraints( null ) { + "location": new java.awt.Point( 0, 710 ) + "size": new java.awt.Dimension( 291, 118 ) + } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$layoutConstraints": "insets 0,hidemode 3,align center center" + "$columnConstraints": "[fill][fill]" + "$rowConstraints": "[fill]" + } ) { + name: "panel2" + auxiliary() { + "JavaCodeGenerator.className": "Panel2" + } + add( new FormComponent( "javax.swing.JTextField" ) { + name: "textField5" + "text": "more text" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "button4" + "text": "..." + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0" + } ) + }, new FormLayoutConstraints( null ) { + "location": new java.awt.Point( 340, 710 ) + "size": new java.awt.Dimension( 291, 118 ) } ) } } From 2a00de11f18212ee878f833e77aa94a1628ed642 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 27 Mar 2021 14:28:21 +0100 Subject: [PATCH 04/13] JIDE: JideTabbedPane: fixed tab icon and title locations in vertical tabs --- .../jideoss/ui/FlatJideTabbedPaneUI.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java index b2c93a11..3b6f63e8 100644 --- a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java +++ b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java @@ -475,6 +475,33 @@ public class FlatJideTabbedPaneUI { } + @Override + protected void layoutLabel( int tabPlacement, FontMetrics metrics, int tabIndex, String title, Icon icon, + Rectangle tabRect, Rectangle iconRect, Rectangle textRect, boolean isSelected ) + { + if( tabPlacement == LEFT || tabPlacement == RIGHT ) { + Rectangle tabRect2 = new Rectangle( 0, 0, tabRect.height, tabRect.width ); + Rectangle iconRect2 = new Rectangle(); + Rectangle textRect2 = new Rectangle(); + + super.layoutLabel( TOP, metrics, tabIndex, title, icon, tabRect2, iconRect2, textRect2, isSelected ); + + textRect.x = tabRect.x + textRect2.y; + textRect.y = tabRect.y + textRect2.x; + textRect.width = textRect2.height; + textRect.height = textRect2.width; + + if( tabPlacement == LEFT ) + textRect.y += metrics.getHeight() / 2; + + iconRect.x = tabRect.x + iconRect2.y; + iconRect.y = tabRect.y + iconRect2.x; + iconRect.width = iconRect2.height; + iconRect.height = iconRect2.width; + } else + super.layoutLabel( tabPlacement, metrics, tabIndex, title, icon, tabRect, iconRect, textRect, isSelected ); + } + private boolean isLastInRun( int tabIndex ) { int run = getRunForTab( _tabPane.getTabCount(), tabIndex ); return lastTabInRun( _tabPane.getTabCount(), run ) == tabIndex; From d7b0754327dec3acc4fcd7475c726cec9cd47ed3 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 27 Mar 2021 17:03:49 +0100 Subject: [PATCH 05/13] JIDE: JideTabbedPane: tab layout fixes for compact resize mode --- .../jideoss/ui/FlatJideTabbedPaneUI.java | 23 +++++++++++++++++++ .../flatlaf/jideoss/FlatLaf.properties | 2 ++ .../uidefaults/FlatDarkLaf_1.8.0_202.txt | 2 ++ .../uidefaults/FlatLightLaf_1.8.0_202.txt | 2 ++ .../uidefaults/FlatTestLaf_1.8.0_202.txt | 2 ++ .../uidefaults/JIDE-FlatDarkLaf_1.8.0_202.txt | 2 -- .../JIDE-FlatLightLaf_1.8.0_202.txt | 2 -- .../flatlaf/themeeditor/FlatLafUIKeys.txt | 2 ++ 8 files changed, 33 insertions(+), 4 deletions(-) diff --git a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java index 3b6f63e8..14a94add 100644 --- a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java +++ b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java @@ -507,6 +507,29 @@ public class FlatJideTabbedPaneUI return lastTabInRun( _tabPane.getTabCount(), run ) == tabIndex; } + @Override + protected void ensureCurrentRects( int leftMargin, int tabCount ) { + int oldFitStyleBoundSize = _fitStyleBoundSize; + int oldFitStyleFirstTabMargin = _fitStyleFirstTabMargin; + int oldCompressedStyleNoIconRectSize = _compressedStyleNoIconRectSize; + int oldCompressedStyleIconMargin = _compressedStyleIconMargin; + int oldFixedStyleRectSize = _fixedStyleRectSize; + + _fitStyleBoundSize = scale( _fitStyleBoundSize ); + _fitStyleFirstTabMargin = scale( _fitStyleFirstTabMargin ); + _compressedStyleNoIconRectSize = scale( _compressedStyleNoIconRectSize ); + _compressedStyleIconMargin = scale( _compressedStyleIconMargin ); + _fixedStyleRectSize = scale( _fixedStyleRectSize ); + + super.ensureCurrentRects( leftMargin, tabCount ); + + _fitStyleBoundSize = oldFitStyleBoundSize; + _fitStyleFirstTabMargin = oldFitStyleFirstTabMargin; + _compressedStyleNoIconRectSize = oldCompressedStyleNoIconRectSize; + _compressedStyleIconMargin = oldCompressedStyleIconMargin; + _fixedStyleRectSize = oldFixedStyleRectSize; + } + @Override public void ensureCloseButtonCreated() { super.ensureCloseButtonCreated(); diff --git a/flatlaf-jide-oss/src/main/resources/com/formdev/flatlaf/jideoss/FlatLaf.properties b/flatlaf-jide-oss/src/main/resources/com/formdev/flatlaf/jideoss/FlatLaf.properties index a4c48098..f52999cd 100644 --- a/flatlaf-jide-oss/src/main/resources/com/formdev/flatlaf/jideoss/FlatLaf.properties +++ b/flatlaf-jide-oss/src/main/resources/com/formdev/flatlaf/jideoss/FlatLaf.properties @@ -84,3 +84,5 @@ JideTabbedPane.shadow = $TabbedPane.shadow JideTabbedPane.closeButtonLeftMargin = 0 JideTabbedPane.closeButtonRightMargin = 0 +JideTabbedPane.fitStyleBoundSize = {integer}0 +JideTabbedPane.fitStyleFirstTabMargin = 0 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 a383c63e..3a8e60ef 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0_202.txt @@ -492,6 +492,8 @@ JideTabbedPane.background #3c3f41 javax.swing.plaf.ColorUIResource [UI] JideTabbedPane.closeButtonLeftMargin 0 JideTabbedPane.closeButtonRightMargin 0 JideTabbedPane.contentBorderInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] +JideTabbedPane.fitStyleBoundSize 0 +JideTabbedPane.fitStyleFirstTabMargin 0 JideTabbedPane.foreground #bbbbbb javax.swing.plaf.ColorUIResource [UI] JideTabbedPane.shadow #3c3f41 javax.swing.plaf.ColorUIResource [UI] JideTabbedPane.tabAreaBackground #3c3f41 javax.swing.plaf.ColorUIResource [UI] 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 6f41d1e7..c2f80570 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0_202.txt @@ -497,6 +497,8 @@ JideTabbedPane.background #f2f2f2 javax.swing.plaf.ColorUIResource [UI] JideTabbedPane.closeButtonLeftMargin 0 JideTabbedPane.closeButtonRightMargin 0 JideTabbedPane.contentBorderInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] +JideTabbedPane.fitStyleBoundSize 0 +JideTabbedPane.fitStyleFirstTabMargin 0 JideTabbedPane.foreground #000000 javax.swing.plaf.ColorUIResource [UI] JideTabbedPane.shadow #f2f2f2 javax.swing.plaf.ColorUIResource [UI] JideTabbedPane.tabAreaBackground #f2f2f2 javax.swing.plaf.ColorUIResource [UI] 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 152930fa..42e64115 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt @@ -488,6 +488,8 @@ JideTabbedPane.background #ccffcc javax.swing.plaf.ColorUIResource [UI] JideTabbedPane.closeButtonLeftMargin 0 JideTabbedPane.closeButtonRightMargin 0 JideTabbedPane.contentBorderInsets 0,0,0,0 javax.swing.plaf.InsetsUIResource [UI] +JideTabbedPane.fitStyleBoundSize 0 +JideTabbedPane.fitStyleFirstTabMargin 0 JideTabbedPane.foreground #ff0000 javax.swing.plaf.ColorUIResource [UI] JideTabbedPane.shadow #ccffcc javax.swing.plaf.ColorUIResource [UI] JideTabbedPane.tabAreaBackground #ccffcc javax.swing.plaf.ColorUIResource [UI] diff --git a/flatlaf-testing/dumps/uidefaults/JIDE-FlatDarkLaf_1.8.0_202.txt b/flatlaf-testing/dumps/uidefaults/JIDE-FlatDarkLaf_1.8.0_202.txt index 9c228198..96cf9d80 100644 --- a/flatlaf-testing/dumps/uidefaults/JIDE-FlatDarkLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/JIDE-FlatDarkLaf_1.8.0_202.txt @@ -121,8 +121,6 @@ + JideTabbedPane.defaultTabBorderShadowColor #736d63 javax.swing.plaf.ColorUIResource [UI] + JideTabbedPane.defaultTabColorTheme 3 + JideTabbedPane.defaultTabShape 2 -+ JideTabbedPane.fitStyleBoundSize 8 -+ JideTabbedPane.fitStyleFirstTabMargin 4 + JideTabbedPane.fitStyleIconMinWidth 24 + JideTabbedPane.fitStyleTextMinWidth 16 + JideTabbedPane.fixedStyleRectSize 60 diff --git a/flatlaf-testing/dumps/uidefaults/JIDE-FlatLightLaf_1.8.0_202.txt b/flatlaf-testing/dumps/uidefaults/JIDE-FlatLightLaf_1.8.0_202.txt index 57f4bb8f..0aa742d0 100644 --- a/flatlaf-testing/dumps/uidefaults/JIDE-FlatLightLaf_1.8.0_202.txt +++ b/flatlaf-testing/dumps/uidefaults/JIDE-FlatLightLaf_1.8.0_202.txt @@ -121,8 +121,6 @@ + JideTabbedPane.defaultTabBorderShadowColor #736d63 javax.swing.plaf.ColorUIResource [UI] + JideTabbedPane.defaultTabColorTheme 3 + JideTabbedPane.defaultTabShape 2 -+ JideTabbedPane.fitStyleBoundSize 8 -+ JideTabbedPane.fitStyleFirstTabMargin 4 + JideTabbedPane.fitStyleIconMinWidth 24 + JideTabbedPane.fitStyleTextMinWidth 16 + JideTabbedPane.fixedStyleRectSize 60 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 4cafd761..f0d734c3 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 @@ -346,6 +346,8 @@ JideTabbedPane.background JideTabbedPane.closeButtonLeftMargin JideTabbedPane.closeButtonRightMargin JideTabbedPane.contentBorderInsets +JideTabbedPane.fitStyleBoundSize +JideTabbedPane.fitStyleFirstTabMargin JideTabbedPane.foreground JideTabbedPane.shadow JideTabbedPane.tabAreaBackground From 69f52c8abd7f14ad028f499b51a9c3ef30a097ad Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 27 Mar 2021 17:48:58 +0100 Subject: [PATCH 06/13] JIDE: JideTabbedPane: scale tab gripper --- .../flatlaf/jideoss/ui/FlatJidePainter.java | 18 ++++++++++++++++++ .../jideoss/ui/FlatJideTabbedPaneUI.java | 1 + .../jideoss/FlatJideOssContainerTest.java | 14 ++++++++++++++ .../jideoss/FlatJideOssContainerTest.jfd | 10 ++++++++++ 4 files changed, 43 insertions(+) diff --git a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJidePainter.java b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJidePainter.java index 56f8fb1e..9930c1e1 100644 --- a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJidePainter.java +++ b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJidePainter.java @@ -107,4 +107,22 @@ public class FlatJidePainter } else super.paintBackground( c, g, rect, borderColor, background, orientation ); } + + @Override + public void paintGripper( JComponent c, Graphics g, Rectangle rect, int orientation, int state ) { + float userScaleFactor = UIScale.getUserScaleFactor(); + if( userScaleFactor > 1 ) { + // scale gripper + Graphics2D g2 = (Graphics2D) g.create(); + try { + g2.translate( rect.x, rect.y ); + g2.scale( userScaleFactor, userScaleFactor ); + Rectangle rect2 = new Rectangle( 0, 0, UIScale.unscale( rect.width ), UIScale.unscale( rect.height ) ); + super.paintGripper( c, g2, rect2, orientation, state ); + } finally { + g2.dispose(); + } + } else + super.paintGripper( c, g, rect, orientation, state ); + } } diff --git a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java index 14a94add..02bba2a9 100644 --- a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java +++ b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java @@ -151,6 +151,7 @@ public class FlatJideTabbedPaneUI case JideTabbedPane.PROPERTY_TAB_AREA_INSETS: case JideTabbedPane.PROPERTY_TAB_INSETS: + case JideTabbedPane.GRIPPER_PROPERTY: case TABBED_PANE_SHOW_TAB_SEPARATORS: case TABBED_PANE_HAS_FULL_BORDER: _tabPane.revalidate(); diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java index a8cbd3a4..6b185cb1 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java @@ -369,6 +369,13 @@ public class FlatJideOssContainerTest tabbedPane.setShowTabButtons( showTabButtons ); } + private void showGripperChanged() { + boolean showGripper = showGripperCheckBox.isSelected(); + + for( JideTabbedPane tabbedPane : allTabbedPanes ) + tabbedPane.setShowGripper( showGripper ); + } + private void initComponents() { // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents JPanel panel9 = new JPanel(); @@ -405,6 +412,7 @@ public class FlatJideOssContainerTest boldActiveTabCheckBox = new JCheckBox(); showTabButtonsCheckBox = new JCheckBox(); smallerInsetsCheckBox = new JCheckBox(); + showGripperCheckBox = new JCheckBox(); showTabSeparatorsCheckBox = new JCheckBox(); hideTabAreaWithOneTabCheckBox = new JCheckBox(); CellConstraints cc = new CellConstraints(); @@ -600,6 +608,11 @@ public class FlatJideOssContainerTest smallerInsetsCheckBox.addActionListener(e -> smallerInsetsChanged()); tabbedPaneControlPanel.add(smallerInsetsCheckBox, "cell 2 8"); + //---- showGripperCheckBox ---- + showGripperCheckBox.setText("Show gripper"); + showGripperCheckBox.addActionListener(e -> showGripperChanged()); + tabbedPaneControlPanel.add(showGripperCheckBox, "cell 0 9"); + //---- showTabSeparatorsCheckBox ---- showTabSeparatorsCheckBox.setText("Show tab separators"); showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged()); @@ -646,6 +659,7 @@ public class FlatJideOssContainerTest private JCheckBox boldActiveTabCheckBox; private JCheckBox showTabButtonsCheckBox; private JCheckBox smallerInsetsCheckBox; + private JCheckBox showGripperCheckBox; private JCheckBox showTabSeparatorsCheckBox; private JCheckBox hideTabAreaWithOneTabCheckBox; // JFormDesigner - End of variables declaration //GEN-END:variables diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd index 680e3e72..d305280e 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd @@ -337,6 +337,16 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 2 8" } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "showGripperCheckBox" + "text": "Show gripper" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showGripperChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 9" + } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "showTabSeparatorsCheckBox" "text": "Show tab separators" From 8e49904f8dc799dd96495bf93fedafa1fc5e39e3 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 27 Mar 2021 18:22:10 +0100 Subject: [PATCH 07/13] JIDE: JideTabbedPane: fixed location of tab title editing box --- .../flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java | 7 +++++++ .../testing/jideoss/FlatJideOssContainerTest.java | 14 ++++++++++++++ .../testing/jideoss/FlatJideOssContainerTest.jfd | 10 ++++++++++ 3 files changed, 31 insertions(+) diff --git a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java index 02bba2a9..143171a6 100644 --- a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java +++ b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java @@ -503,6 +503,13 @@ public class FlatJideTabbedPaneUI super.layoutLabel( tabPlacement, metrics, tabIndex, title, icon, tabRect, iconRect, textRect, isSelected ); } + @Override + protected Rectangle getTabsTextBoundsAt( int tabIndex ) { + Rectangle rect = super.getTabsTextBoundsAt( tabIndex ); + rect.x += getTabInsets( _tabPane.getTabPlacement(), tabIndex ).left; + return rect; + } + private boolean isLastInRun( int tabIndex ) { int run = getRunForTab( _tabPane.getTabCount(), tabIndex ); return lastTabInRun( _tabPane.getTabCount(), run ) == tabIndex; diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java index 6b185cb1..5410316b 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java @@ -376,6 +376,13 @@ public class FlatJideOssContainerTest tabbedPane.setShowGripper( showGripper ); } + private void tabEditingAllowedChanged() { + boolean tabEditingAllowed = tabEditingAllowedCheckBox.isSelected(); + + for( JideTabbedPane tabbedPane : allTabbedPanes ) + tabbedPane.setTabEditingAllowed( tabEditingAllowed ); + } + private void initComponents() { // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents JPanel panel9 = new JPanel(); @@ -414,6 +421,7 @@ public class FlatJideOssContainerTest smallerInsetsCheckBox = new JCheckBox(); showGripperCheckBox = new JCheckBox(); showTabSeparatorsCheckBox = new JCheckBox(); + tabEditingAllowedCheckBox = new JCheckBox(); hideTabAreaWithOneTabCheckBox = new JCheckBox(); CellConstraints cc = new CellConstraints(); @@ -618,6 +626,11 @@ public class FlatJideOssContainerTest showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged()); tabbedPaneControlPanel.add(showTabSeparatorsCheckBox, "cell 1 9"); + //---- tabEditingAllowedCheckBox ---- + tabEditingAllowedCheckBox.setText("Tab editing allowed"); + tabEditingAllowedCheckBox.addActionListener(e -> tabEditingAllowedChanged()); + tabbedPaneControlPanel.add(tabEditingAllowedCheckBox, "cell 0 10"); + //---- hideTabAreaWithOneTabCheckBox ---- hideTabAreaWithOneTabCheckBox.setText("Hide tab area with one tab"); hideTabAreaWithOneTabCheckBox.addActionListener(e -> hideTabAreaWithOneTabChanged()); @@ -661,6 +674,7 @@ public class FlatJideOssContainerTest private JCheckBox smallerInsetsCheckBox; private JCheckBox showGripperCheckBox; private JCheckBox showTabSeparatorsCheckBox; + private JCheckBox tabEditingAllowedCheckBox; private JCheckBox hideTabAreaWithOneTabCheckBox; // JFormDesigner - End of variables declaration //GEN-END:variables diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd index d305280e..8fe97eaf 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd @@ -357,6 +357,16 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 9" } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "tabEditingAllowedCheckBox" + "text": "Tab editing allowed" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabEditingAllowedChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 10" + } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "hideTabAreaWithOneTabCheckBox" "text": "Hide tab area with one tab" From 6e990a7e31a20a3602598f211bc021c038d17a0d Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 27 Mar 2021 18:46:37 +0100 Subject: [PATCH 08/13] JIDE: JideTabbedPane: fixed hover background of close button on selected tab --- .../com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java index 143171a6..e063439f 100644 --- a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java +++ b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java @@ -584,12 +584,15 @@ public class FlatJideTabbedPaneUI if( !scrollableTabLayoutEnabled() || !isShowCloseButton() || !isShowCloseButtonOnTab() ) return; + Color background = _tabPane.getBackground(); + for( int i = 0; i < _closeButtons.length; i++ ) { JButton closeButton = _closeButtons[i]; if( closeButton.getWidth() == 0 || closeButton.getHeight() == 0 ) continue; // not visible closeButton.setBounds( getTabCloseBounds( i ) ); + closeButton.setBackground( background ); } } From 98a3c4b0f574def0769896a64bfe181b43681900 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 27 Mar 2021 19:19:17 +0100 Subject: [PATCH 09/13] JIDE: JideTabbedPane: fixed disabled tab text, which was unreadable in dark themes --- .../jideoss/ui/FlatJideTabbedPaneUI.java | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java index e063439f..c1e0e20b 100644 --- a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java +++ b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java @@ -44,6 +44,7 @@ import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import com.formdev.flatlaf.icons.FlatTabbedPaneCloseIcon; import com.formdev.flatlaf.ui.FlatUIUtils; +import com.formdev.flatlaf.util.Graphics2DProxy; import com.formdev.flatlaf.util.UIScale; import com.jidesoft.plaf.LookAndFeelFactory; import com.jidesoft.plaf.UIDefaultsLookup; @@ -59,6 +60,7 @@ import com.jidesoft.swing.JideTabbedPane.NoFocusButton; public class FlatJideTabbedPaneUI extends BasicJideTabbedPaneUI { + protected Color disabledForeground; protected Color selectedBackground; protected Color underlineColor; protected Color disabledUnderlineColor; @@ -96,6 +98,7 @@ public class FlatJideTabbedPaneUI _background = UIDefaultsLookup.getColor( "JideTabbedPane.background" ); + disabledForeground = UIManager.getColor( "TabbedPane.disabledForeground" ); selectedBackground = UIManager.getColor( "TabbedPane.selectedBackground" ); underlineColor = UIManager.getColor( "TabbedPane.underlineColor" ); disabledUnderlineColor = UIManager.getColor( "TabbedPane.disabledUnderlineColor" ); @@ -127,6 +130,7 @@ public class FlatJideTabbedPaneUI protected void uninstallDefaults() { super.uninstallDefaults(); + disabledForeground = null; selectedBackground = null; underlineColor = null; disabledUnderlineColor = null; @@ -301,8 +305,38 @@ public class FlatJideTabbedPaneUI protected void paintText( Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected ) { + if( !_tabPane.isEnabled() || !_tabPane.isEnabledAt( tabIndex ) ) { + // super method paints disabled text twice with different colors + // and one pixel offset to simulate disabled text + // --> draw only once with disabledForeground + class DisabledTextGraphics extends Graphics2DProxy { + private int count; + + public DisabledTextGraphics( Graphics delegate ) { + super( (Graphics2D) delegate ); + } + + @Override + public Graphics create() { + return new DisabledTextGraphics( super.create() ); + } + + @Override + public void drawString( String str, int x, int y ) { + count++; + if( (count % 2) != 1 ) + return; + + setColor( disabledForeground ); + super.drawString( str, x, y ); + } + } + g = new DisabledTextGraphics( g ); + } + + Graphics g2 = g; FlatUIUtils.runWithoutRenderingHints( g, oldRenderingHints, () -> { - super.paintText( g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected ); + super.paintText( g2, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected ); } ); } From 1f8eaf4a6444f84d287a66d9945e3f1a2e4bba16 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Tue, 13 Apr 2021 10:51:04 +0200 Subject: [PATCH 10/13] JIDE: JideTabbedPane: fixed scroll and list buttons --- .../jideoss/ui/FlatJideTabbedPaneUI.java | 228 +++++++++++++++++- .../jideoss/FlatJideOssContainerTest.java | 7 +- 2 files changed, 232 insertions(+), 3 deletions(-) diff --git a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java index c1e0e20b..e499297e 100644 --- a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java +++ b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java @@ -60,6 +60,7 @@ import com.jidesoft.swing.JideTabbedPane.NoFocusButton; public class FlatJideTabbedPaneUI extends BasicJideTabbedPaneUI { + protected Color foreground; protected Color disabledForeground; protected Color selectedBackground; protected Color underlineColor; @@ -78,6 +79,13 @@ public class FlatJideTabbedPaneUI protected boolean tabsOverlapBorder; protected Icon closeIcon; + protected Icon arrowIcon; + + protected String arrowType; + protected Insets buttonInsets; + protected int buttonArc; + protected Color buttonHoverBackground; + protected Color buttonPressedBackground; protected int closeButtonLeftMarginUnscaled; protected int closeButtonRightMarginUnscaled; @@ -98,6 +106,7 @@ public class FlatJideTabbedPaneUI _background = UIDefaultsLookup.getColor( "JideTabbedPane.background" ); + foreground = UIManager.getColor( "TabbedPane.foreground" ); disabledForeground = UIManager.getColor( "TabbedPane.disabledForeground" ); selectedBackground = UIManager.getColor( "TabbedPane.selectedBackground" ); underlineColor = UIManager.getColor( "TabbedPane.underlineColor" ); @@ -115,7 +124,11 @@ public class FlatJideTabbedPaneUI hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" ); tabsOverlapBorder = UIManager.getBoolean( "TabbedPane.tabsOverlapBorder" ); - closeIcon = new FlatJideTabCloseIcon(); + arrowType = UIManager.getString( "TabbedPane.arrowType" ); + buttonInsets = UIManager.getInsets( "TabbedPane.buttonInsets" ); + buttonArc = UIManager.getInt( "TabbedPane.buttonArc" ); + buttonHoverBackground = UIManager.getColor( "TabbedPane.buttonHoverBackground" ); + buttonPressedBackground = UIManager.getColor( "TabbedPane.buttonPressedBackground" ); closeButtonLeftMarginUnscaled = _closeButtonLeftMargin; closeButtonRightMarginUnscaled = _closeButtonRightMargin; @@ -130,6 +143,7 @@ public class FlatJideTabbedPaneUI protected void uninstallDefaults() { super.uninstallDefaults(); + foreground = null; disabledForeground = null; selectedBackground = null; underlineColor = null; @@ -138,7 +152,35 @@ public class FlatJideTabbedPaneUI focusColor = null; tabSeparatorColor = null; contentAreaColor = null; + + buttonHoverBackground = null; + buttonPressedBackground = null; + } + + @Override + protected void installComponents() { + super.installComponents(); + + closeIcon = new FlatJideTabCloseIcon(); + arrowIcon = new FlatJideTabAreaArrowIcon(); + + if( _tabScroller != null ) { + _tabScroller.scrollForwardButton.setIcon( arrowIcon ); + _tabScroller.scrollBackwardButton.setIcon( arrowIcon ); + _tabScroller.listButton.setIcon( arrowIcon ); + + _tabScroller.scrollForwardButton.setContentAreaFilled( false ); + _tabScroller.scrollBackwardButton.setContentAreaFilled( false ); + _tabScroller.listButton.setContentAreaFilled( false ); + } + } + + @Override + protected void uninstallComponents() { + super.uninstallComponents(); + closeIcon = null; + arrowIcon = null; } @Override @@ -549,6 +591,15 @@ public class FlatJideTabbedPaneUI return lastTabInRun( _tabPane.getTabCount(), run ) == tabIndex; } + private boolean isLeftToRight() { + return _tabPane.getComponentOrientation().isLeftToRight(); + } + + private boolean isHorizontalTabPlacement() { + int tabPlacement = _tabPane.getTabPlacement(); + return tabPlacement == TOP || tabPlacement == BOTTOM; + } + @Override protected void ensureCurrentRects( int leftMargin, int tabCount ) { int oldFitStyleBoundSize = _fitStyleBoundSize; @@ -612,6 +663,7 @@ public class FlatJideTabbedPaneUI super.layoutContainer( parent ); updateCloseButtons(); + updateArrowButtons(); } private void updateCloseButtons() { @@ -653,9 +705,101 @@ public class FlatJideTabbedPaneUI iconHeight ); } } + + private void updateArrowButtons() { + if( !scrollableTabLayoutEnabled() ) + return; + + Insets insets = _tabPane.getInsets(); + int tabPlacement = _tabPane.getTabPlacement(); + Insets tabAreaInsets = getTabAreaInsets( tabPlacement ); + Dimension tsize = isTabTrailingComponentVisible() ? _tabTrailingComponent.getSize() : new Dimension(); + + if( tabPlacement == TOP || tabPlacement == BOTTOM ) { + // for BOTTOM tab placement, _maxTabHeight is not correct if having tall leading/trailing component + int maxTabHeight = (tabPlacement == BOTTOM) + ? calculateMaxTabHeight( tabPlacement ) + : _maxTabHeight; + + // button bounds + boolean leftToRight = isLeftToRight(); + int x = leftToRight + ? _tabPane.getWidth() - insets.right - tsize.width + : insets.left + tsize.width; + int y = _tabScroller.viewport.getY(); + int h = maxTabHeight; + if( tabPlacement == TOP ) { + // if leading or trailing component is taller than tab area then + // _tabScroller.viewport has same height as leading/trailing component + // but tabs are painted smaller + y += (_tabScroller.viewport.getHeight() - h - tabAreaInsets.bottom); + } else + y += tabAreaInsets.top; + + // layout buttons + x = layoutButtonHorizontal( _tabScroller.listButton, 24, x, y, h, leftToRight ); + x = layoutButtonHorizontal( _tabScroller.scrollForwardButton, 16, x, y, h, leftToRight ); + x = layoutButtonHorizontal( _tabScroller.scrollBackwardButton, 16, x, y, h, leftToRight ); + + // layout tab area + Rectangle r = _tabScroller.viewport.getBounds(); + if( leftToRight ) + _tabScroller.viewport.setSize( x - r.x, r.height ); + else + _tabScroller.viewport.setBounds( x, r.y, r.width - (x - r.x), r.height ); + + } else { // LEFT and RIGHT tab placement + // for RIGHT tab placement, _maxTabWidth is not correct if having wide leading/trailing component + int maxTabWidth = (tabPlacement == RIGHT) + ? calculateMaxTabWidth( tabPlacement ) + : _maxTabWidth; + + // button bounds + int x = _tabScroller.viewport.getX(); + int y = _tabPane.getHeight() - insets.bottom - tsize.height; + int w = maxTabWidth; + if( tabPlacement == LEFT ) { + // if leading or trailing component is wider than tab area then + // _tabScroller.viewport has same width as leading/trailing component + // but tabs are painted smaller + x += (_tabScroller.viewport.getWidth() - w - tabAreaInsets.right); + } else + x += tabAreaInsets.left; + + // layout buttons + y = layoutButtonVertical( _tabScroller.listButton, 24, x, y, w ); + y = layoutButtonVertical( _tabScroller.scrollForwardButton, 16, x, y, w ); + y = layoutButtonVertical( _tabScroller.scrollBackwardButton, 16, x, y, w ); + + // layout tab area + Rectangle r = _tabScroller.viewport.getBounds(); + _tabScroller.viewport.setSize( r.width, y - r.y ); + } + } + + private int layoutButtonHorizontal( JButton button, int wu, int x, int y, int h, boolean leftToRight ) { + if( button.isVisible() ) { + int w = scale( wu ); + if( leftToRight ) + x -= w; + button.setBounds( x, y, w, h ); + if( !leftToRight ) + x += w; + } + return x; + } + + private int layoutButtonVertical( JButton button, int hu, int x, int y, int w ) { + if( button.isVisible() ) { + int h = scale( hu ); + y -= h; + button.setBounds( x, y, w, h ); + } + return y; + } } - //---- class FlatJideTabAreaArrowIcon ------------------------------------- + //---- class FlatJideTabCloseIcon ----------------------------------------- protected class FlatJideTabCloseIcon extends FlatTabbedPaneCloseIcon @@ -673,4 +817,84 @@ public class FlatJideTabbedPaneUI super.paintIcon( c, g, x, y ); } } + + //---- class FlatJideTabAreaArrowIcon ------------------------------------- + + protected class FlatJideTabAreaArrowIcon + implements Icon + { + @Override + public void paintIcon( Component c, Graphics g, int x, int y ) { + NoFocusButton button = (NoFocusButton) c; + + Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g ); + + // paint hover or pressed background + if( button.isEnabled() ) { + Color background = (buttonPressedBackground != null && button.isMousePressed()) + ? buttonPressedBackground + : (buttonHoverBackground != null && button.isMouseOver() + ? buttonHoverBackground + : null); + + if( background != null ) { + // rotate button insets + Insets insets = new Insets( 0, 0, 0, 0 ); + rotateInsets( buttonInsets, insets, _tabPane.getTabPlacement() ); + + // fill background + g.setColor( FlatUIUtils.deriveColor( background, _tabPane.getBackground() ) ); + FlatUIUtils.paintComponentBackground( (Graphics2D) g, + insets.left, insets.top, + button.getWidth() - insets.left - insets.right, + button.getHeight() - insets.top - insets.bottom, + 0, scale( (float) buttonArc ) ); + } + } + + // arrow direction + int direction = -1; + switch( button.getType() ) { + case JideTabbedPane.BUTTON_WEST: + direction = isHorizontalTabPlacement() + ? (isLeftToRight() ? WEST : EAST) + : NORTH; + break; + + case JideTabbedPane.BUTTON_EAST: + direction = isHorizontalTabPlacement() + ? (isLeftToRight() ? EAST : WEST) + : SOUTH; + break; + + case JideTabbedPane.BUTTON_LIST: + switch( _tabPane.getTabPlacement() ) { + default: + case TOP: direction = SOUTH; break; + case BOTTOM: direction = NORTH; break; + case LEFT: direction = EAST; break; + case RIGHT: direction = WEST; break; + } + break; + } + + // paint arrow + g.setColor( button.isEnabled() ? foreground : disabledForeground ); + FlatUIUtils.paintArrow( (Graphics2D) g, + 0, 0, button.getWidth(), button.getHeight(), + direction, FlatUIUtils.isChevron( arrowType ), 10, 0, 0 ); + + FlatUIUtils.resetRenderingHints( g, oldRenderingHints ); + } + + @Override + public int getIconWidth() { + return scale( 16 ); + } + + @Override + public int getIconHeight() { + return scale( 16 ); + } + } } diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java index 5410316b..42c4471e 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java @@ -296,6 +296,8 @@ public class FlatJideOssContainerTest c.setOpaque( true ); c.setBackground( leading ? Color.cyan : Color.orange ); c.setBorder( new EmptyBorder( gap, gap, gap, gap ) ); + if( leading && (tabbedPane.getTabPlacement() == SwingConstants.TOP || tabbedPane.getTabPlacement() == SwingConstants.BOTTOM) ) + c.setPreferredSize( new Dimension( 20, 80 ) ); } if( leading ) tabbedPane.setTabLeadingComponent( c ); @@ -343,8 +345,11 @@ public class FlatJideOssContainerTest private void tabAreaInsetsChanged() { Insets insets = tabAreaInsetsCheckBox.isSelected() ? new Insets( 5, 5, 10, 10 ) : null; - for( JideTabbedPane tabbedPane : allTabbedPanes ) + for( JideTabbedPane tabbedPane : allTabbedPanes ) { tabbedPane.setTabAreaInsets( insets ); + tabbedPane.revalidate(); + tabbedPane.repaint(); + } } private void smallerInsetsChanged() { From 2e7637f27442348e28a518e77177ba0f09d606f0 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Tue, 13 Apr 2021 11:25:42 +0200 Subject: [PATCH 11/13] JIDE: JideTabbedPane: fixed close button in tab area --- .../jideoss/ui/FlatJideTabbedPaneUI.java | 4 ++++ .../jideoss/FlatJideOssContainerTest.java | 19 ++++++++++++++++++- .../jideoss/FlatJideOssContainerTest.jfd | 13 ++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java index e499297e..7c2af75e 100644 --- a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java +++ b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java @@ -168,10 +168,12 @@ public class FlatJideTabbedPaneUI _tabScroller.scrollForwardButton.setIcon( arrowIcon ); _tabScroller.scrollBackwardButton.setIcon( arrowIcon ); _tabScroller.listButton.setIcon( arrowIcon ); + _tabScroller.closeButton.setIcon( closeIcon ); _tabScroller.scrollForwardButton.setContentAreaFilled( false ); _tabScroller.scrollBackwardButton.setContentAreaFilled( false ); _tabScroller.listButton.setContentAreaFilled( false ); + _tabScroller.closeButton.setContentAreaFilled( false ); } } @@ -737,6 +739,7 @@ public class FlatJideTabbedPaneUI y += tabAreaInsets.top; // layout buttons + x = layoutButtonHorizontal( _tabScroller.closeButton, 16, x, y, h, leftToRight ); x = layoutButtonHorizontal( _tabScroller.listButton, 24, x, y, h, leftToRight ); x = layoutButtonHorizontal( _tabScroller.scrollForwardButton, 16, x, y, h, leftToRight ); x = layoutButtonHorizontal( _tabScroller.scrollBackwardButton, 16, x, y, h, leftToRight ); @@ -767,6 +770,7 @@ public class FlatJideTabbedPaneUI x += tabAreaInsets.left; // layout buttons + y = layoutButtonVertical( _tabScroller.closeButton, 16, x, y, w ); y = layoutButtonVertical( _tabScroller.listButton, 24, x, y, w ); y = layoutButtonVertical( _tabScroller.scrollForwardButton, 16, x, y, w ); y = layoutButtonVertical( _tabScroller.scrollBackwardButton, 16, x, y, w ); diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java index 42c4471e..d7b82879 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java @@ -308,9 +308,11 @@ public class FlatJideOssContainerTest private void tabsClosableChanged() { boolean closable = tabsClosableCheckBox.isSelected() && tabScrollCheckBox.isSelected(); + boolean onTab = showCloseButtonOnTabCheckBox.isSelected(); + for( JideTabbedPane tabbedPane : allTabbedPanes ) { tabbedPane.setShowCloseButton( closable ); - tabbedPane.setShowCloseButtonOnTab( closable ); + tabbedPane.setShowCloseButtonOnTab( onTab ); } } @@ -323,6 +325,13 @@ public class FlatJideOssContainerTest } } + private void showCloseButtonOnTabChanged() { + boolean onTab = showCloseButtonOnTabCheckBox.isSelected(); + + for( JideTabbedPane tabbedPane : allTabbedPanes ) + tabbedPane.setShowCloseButtonOnTab( onTab ); + } + private void showCloseButtonOnSelectedTabChanged() { boolean onSelected = showCloseButtonOnSelectedTabCheckBox.isSelected(); @@ -407,6 +416,7 @@ public class FlatJideOssContainerTest tabIconsCheckBox = new JCheckBox(); tabIconSizeSpinner = new JSpinner(); tabsClosableCheckBox = new JCheckBox(); + showCloseButtonOnTabCheckBox = new JCheckBox(); showCloseButtonOnSelectedTabCheckBox = new JCheckBox(); JLabel tabPlacementLabel = new JLabel(); tabPlacementField = new FlatTestEnumComboBox<>(); @@ -541,6 +551,12 @@ public class FlatJideOssContainerTest tabsClosableCheckBox.addActionListener(e -> tabsClosableChanged()); tabbedPaneControlPanel.add(tabsClosableCheckBox, "cell 2 3"); + //---- showCloseButtonOnTabCheckBox ---- + showCloseButtonOnTabCheckBox.setText("on tab"); + showCloseButtonOnTabCheckBox.setSelected(true); + showCloseButtonOnTabCheckBox.addActionListener(e -> showCloseButtonOnTabChanged()); + tabbedPaneControlPanel.add(showCloseButtonOnTabCheckBox, "cell 2 3"); + //---- showCloseButtonOnSelectedTabCheckBox ---- showCloseButtonOnSelectedTabCheckBox.setText("show on selected"); showCloseButtonOnSelectedTabCheckBox.addActionListener(e -> showCloseButtonOnSelectedTabChanged()); @@ -663,6 +679,7 @@ public class FlatJideOssContainerTest private JCheckBox tabIconsCheckBox; private JSpinner tabIconSizeSpinner; private JCheckBox tabsClosableCheckBox; + private JCheckBox showCloseButtonOnTabCheckBox; private JCheckBox showCloseButtonOnSelectedTabCheckBox; private FlatTestEnumComboBox tabPlacementField; private JCheckBox secondTabClosableCheckBox; diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd index 8fe97eaf..7f2b7fac 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd @@ -1,4 +1,4 @@ -JFDML JFormDesigner: "7.0.3.1.342" Java: "15" encoding: "UTF-8" +JFDML JFormDesigner: "7.0.3.1.342" Java: "16" encoding: "UTF-8" new FormModel { contentType: "form/swing" @@ -178,6 +178,17 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 2 3" } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "showCloseButtonOnTabCheckBox" + "text": "on tab" + "selected": true + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showCloseButtonOnTabChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 3" + } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "showCloseButtonOnSelectedTabCheckBox" "text": "show on selected" From 992349da8c86cc0b8aa7e8ebadbbea6938f4b241 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Tue, 13 Apr 2021 12:06:28 +0200 Subject: [PATCH 12/13] JIDE: JideTabbedPane: fixed close button in tab area, which was visible even if shown on tabs (regression in previous commit) --- .../flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java | 8 +++++--- .../testing/jideoss/FlatJideOssContainerTest.java | 13 +++---------- .../testing/jideoss/FlatJideOssContainerTest.jfd | 2 +- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java index 7c2af75e..d88e36d0 100644 --- a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java +++ b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java @@ -709,7 +709,7 @@ public class FlatJideTabbedPaneUI } private void updateArrowButtons() { - if( !scrollableTabLayoutEnabled() ) + if( !scrollableTabLayoutEnabled() || !_tabPane.isTabShown() ) return; Insets insets = _tabPane.getInsets(); @@ -739,7 +739,8 @@ public class FlatJideTabbedPaneUI y += tabAreaInsets.top; // layout buttons - x = layoutButtonHorizontal( _tabScroller.closeButton, 16, x, y, h, leftToRight ); + if( !isShowCloseButtonOnTab() ) + x = layoutButtonHorizontal( _tabScroller.closeButton, 16, x, y, h, leftToRight ); x = layoutButtonHorizontal( _tabScroller.listButton, 24, x, y, h, leftToRight ); x = layoutButtonHorizontal( _tabScroller.scrollForwardButton, 16, x, y, h, leftToRight ); x = layoutButtonHorizontal( _tabScroller.scrollBackwardButton, 16, x, y, h, leftToRight ); @@ -770,7 +771,8 @@ public class FlatJideTabbedPaneUI x += tabAreaInsets.left; // layout buttons - y = layoutButtonVertical( _tabScroller.closeButton, 16, x, y, w ); + if( !isShowCloseButtonOnTab() ) + y = layoutButtonVertical( _tabScroller.closeButton, 16, x, y, w ); y = layoutButtonVertical( _tabScroller.listButton, 24, x, y, w ); y = layoutButtonVertical( _tabScroller.scrollForwardButton, 16, x, y, w ); y = layoutButtonVertical( _tabScroller.scrollBackwardButton, 16, x, y, w ); diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java index d7b82879..e444071b 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.java @@ -308,11 +308,11 @@ public class FlatJideOssContainerTest private void tabsClosableChanged() { boolean closable = tabsClosableCheckBox.isSelected() && tabScrollCheckBox.isSelected(); - boolean onTab = showCloseButtonOnTabCheckBox.isSelected(); + boolean onTab = closable && showCloseButtonOnTabCheckBox.isSelected(); for( JideTabbedPane tabbedPane : allTabbedPanes ) { - tabbedPane.setShowCloseButton( closable ); tabbedPane.setShowCloseButtonOnTab( onTab ); + tabbedPane.setShowCloseButton( closable ); } } @@ -325,13 +325,6 @@ public class FlatJideOssContainerTest } } - private void showCloseButtonOnTabChanged() { - boolean onTab = showCloseButtonOnTabCheckBox.isSelected(); - - for( JideTabbedPane tabbedPane : allTabbedPanes ) - tabbedPane.setShowCloseButtonOnTab( onTab ); - } - private void showCloseButtonOnSelectedTabChanged() { boolean onSelected = showCloseButtonOnSelectedTabCheckBox.isSelected(); @@ -554,7 +547,7 @@ public class FlatJideOssContainerTest //---- showCloseButtonOnTabCheckBox ---- showCloseButtonOnTabCheckBox.setText("on tab"); showCloseButtonOnTabCheckBox.setSelected(true); - showCloseButtonOnTabCheckBox.addActionListener(e -> showCloseButtonOnTabChanged()); + showCloseButtonOnTabCheckBox.addActionListener(e -> tabsClosableChanged()); tabbedPaneControlPanel.add(showCloseButtonOnTabCheckBox, "cell 2 3"); //---- showCloseButtonOnSelectedTabCheckBox ---- diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd index 7f2b7fac..4454c5b7 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/jideoss/FlatJideOssContainerTest.jfd @@ -185,7 +185,7 @@ new FormModel { auxiliary() { "JavaCodeGenerator.variableLocal": false } - addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showCloseButtonOnTabChanged", false ) ) + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabsClosableChanged", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 2 3" } ) From cb11d98bf7a538ad5acf9a0d33267ce741d8c0bc Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Tue, 13 Apr 2021 12:20:11 +0200 Subject: [PATCH 13/13] JIDE: JideTabbedPane: hide tab selection and tab area separator for `tabbedPane.setHideOneTab(true)` if tabbed pane contains only one tab --- .../com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java index d88e36d0..f11de429 100644 --- a/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java +++ b/flatlaf-jide-oss/src/main/java/com/formdev/flatlaf/jideoss/ui/FlatJideTabbedPaneUI.java @@ -415,6 +415,9 @@ public class FlatJideTabbedPaneUI } protected void paintTabSelection( Graphics g, int tabPlacement, int x, int y, int w, int h ) { + if( !_tabPane.isTabShown() ) + return; + // increase clip bounds in scroll-tab-layout to paint over the separator line Rectangle clipBounds = scrollableTabLayoutEnabled() ? g.getClipBounds() : null; if( clipBounds != null ) { @@ -480,7 +483,7 @@ public class FlatJideTabbedPaneUI */ @Override protected void paintContentBorder( Graphics g, int tabPlacement, int selectedIndex ) { - if( _tabPane.getTabCount() <= 0 ) + if( !_tabPane.isTabShown() ) return; Insets insets = _tabPane.getInsets();