diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java index 0c7c31a2..1ce48b33 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -254,6 +254,15 @@ public interface FlatClientProperties */ String TABBED_PANE_TAB_HEIGHT = "JTabbedPane.tabHeight"; + /** + * Specifies the insets of a tab. + *
+ * Component {@link javax.swing.JTabbedPane}
+ * or tab content components (see {@link javax.swing.JTabbedPane#setComponentAt(int, java.awt.Component)})
+ * Value type {@link java.awt.Insets}
+ */
+ String TABBED_PANE_TAB_INSETS = "JTabbedPane.tabInsets";
+
/**
* Specifies whether tabs are closable.
* If set to {@code true} on a tabbed pane component, all tabs in that tabbed pane are closable.
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java
index 7536883c..ec86fcd7 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java
@@ -529,6 +529,14 @@ public class FlatTabbedPaneUI
return Math.max( tabHeight, super.calculateTabHeight( tabPlacement, tabIndex, fontHeight ) - 2 /* was added by superclass */ );
}
+ @Override
+ protected Insets getTabInsets( int tabPlacement, int tabIndex ) {
+ Object value = getTabClientProperty( tabIndex, TABBED_PANE_TAB_INSETS );
+ return (value instanceof Insets)
+ ? scale( (Insets) value )
+ : super.getTabInsets( tabPlacement, tabIndex );
+ }
+
@Override
protected Insets getTabAreaInsets( int tabPlacement ) {
Insets currentTabAreaInsets = super.getTabAreaInsets( tabPlacement );
@@ -1503,6 +1511,8 @@ public class FlatTabbedPaneUI
PropertyChangeListener propertyChangeDelegate;
ChangeListener changeDelegate;
+ private final PropertyChangeListener contentListener = this::contentPropertyChange;
+
private int pressedTabIndex = -1;
void installListeners() {
@@ -1512,7 +1522,7 @@ public class FlatTabbedPaneUI
for( Component c : tabPane.getComponents() ) {
if( !(c instanceof UIResource) )
- c.addPropertyChangeListener( TABBED_PANE_TAB_CLOSABLE, this );
+ c.addPropertyChangeListener( contentListener );
}
}
@@ -1523,7 +1533,7 @@ public class FlatTabbedPaneUI
for( Component c : tabPane.getComponents() ) {
if( !(c instanceof UIResource) )
- c.removePropertyChangeListener( TABBED_PANE_TAB_CLOSABLE, this );
+ c.removePropertyChangeListener( contentListener );
}
}
@@ -1604,21 +1614,19 @@ public class FlatTabbedPaneUI
@Override
public void propertyChange( PropertyChangeEvent e ) {
// invoke delegate listener
- if( e.getSource() instanceof JTabbedPane ) {
- switch( e.getPropertyName() ) {
- case "tabPlacement":
- case "opaque":
- case "background":
- case "indexForTabComponent":
- runWithOriginalLayoutManager( () -> {
- propertyChangeDelegate.propertyChange( e );
- } );
- break;
-
- default:
+ switch( e.getPropertyName() ) {
+ case "tabPlacement":
+ case "opaque":
+ case "background":
+ case "indexForTabComponent":
+ runWithOriginalLayoutManager( () -> {
propertyChangeDelegate.propertyChange( e );
- break;
- }
+ } );
+ break;
+
+ default:
+ propertyChangeDelegate.propertyChange( e );
+ break;
}
// handle event
@@ -1636,6 +1644,7 @@ public class FlatTabbedPaneUI
case TABBED_PANE_SHOW_CONTENT_SEPARATOR:
case TABBED_PANE_HAS_FULL_BORDER:
case TABBED_PANE_TAB_HEIGHT:
+ case TABBED_PANE_TAB_INSETS:
case TABBED_PANE_HIDDEN_TABS_NAVIGATION:
case TABBED_PANE_TAB_CLOSABLE:
tabPane.revalidate();
@@ -1671,6 +1680,16 @@ public class FlatTabbedPaneUI
ensureSelectedTabIsVisible();
}
+ protected void contentPropertyChange( PropertyChangeEvent e ) {
+ switch( e.getPropertyName() ) {
+ case TABBED_PANE_TAB_INSETS:
+ case TABBED_PANE_TAB_CLOSABLE:
+ tabPane.revalidate();
+ tabPane.repaint();
+ break;
+ }
+ }
+
//---- interface ComponentListener ----
@Override
@@ -1689,14 +1708,14 @@ public class FlatTabbedPaneUI
public void componentAdded( ContainerEvent e ) {
Component c = e.getChild();
if( !(c instanceof UIResource) )
- c.addPropertyChangeListener( TABBED_PANE_TAB_CLOSABLE, this );
+ c.addPropertyChangeListener( contentListener );
}
@Override
public void componentRemoved( ContainerEvent e ) {
Component c = e.getChild();
if( !(c instanceof UIResource) )
- c.removePropertyChangeListener( TABBED_PANE_TAB_CLOSABLE, this );
+ c.removePropertyChangeListener( contentListener );
}
}
diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.java
index b6da5b97..6326e004 100644
--- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.java
+++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.java
@@ -299,6 +299,26 @@ public class FlatContainerTest
}
}
+ private void smallerTabHeightChanged() {
+ Integer tabHeight = smallerTabHeightCheckBox.isSelected() ? 20 : null;
+ putTabbedPanesClientProperty( TABBED_PANE_TAB_HEIGHT, tabHeight );
+ }
+
+ private void smallerInsetsChanged() {
+ Insets insets = smallerInsetsCheckBox.isSelected() ? new Insets( 2, 2, 2, 2 ) : null;
+ putTabbedPanesClientProperty( TABBED_PANE_TAB_INSETS, insets );
+ }
+
+ private void secondTabWiderChanged() {
+ Insets insets = secondTabWiderCheckBox.isSelected() ? new Insets( 4, 20, 4, 20 ) : null;
+
+ JTabbedPane[] tabbedPanes = new JTabbedPane[] { tabbedPane1, tabbedPane2, tabbedPane3, tabbedPane4 };
+ for( JTabbedPane tabbedPane : tabbedPanes ) {
+ Component c = tabbedPane.getComponentAt( 1 );
+ ((JComponent)c).putClientProperty( TABBED_PANE_TAB_INSETS, insets );
+ }
+ }
+
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JPanel panel9 = new JPanel();
@@ -337,6 +357,9 @@ public class FlatContainerTest
trailingComponentCheckBox = new JCheckBox();
tabsClosableCheckBox = new JCheckBox();
secondTabClosableCheckBox = new TriStateCheckBox();
+ smallerTabHeightCheckBox = new JCheckBox();
+ smallerInsetsCheckBox = new JCheckBox();
+ secondTabWiderCheckBox = new JCheckBox();
CellConstraints cc = new CellConstraints();
//======== this ========
@@ -451,6 +474,7 @@ public class FlatContainerTest
"[center]" +
"[]" +
"[]" +
+ "[]" +
"[]"));
//---- moreTabsCheckBox ----
@@ -559,6 +583,21 @@ public class FlatContainerTest
secondTabClosableCheckBox.setText("Second Tab closable");
secondTabClosableCheckBox.addActionListener(e -> secondTabClosableChanged());
panel14.add(secondTabClosableCheckBox, "cell 3 3");
+
+ //---- smallerTabHeightCheckBox ----
+ smallerTabHeightCheckBox.setText("Smaller tab height");
+ smallerTabHeightCheckBox.addActionListener(e -> smallerTabHeightChanged());
+ panel14.add(smallerTabHeightCheckBox, "cell 0 4 2 1");
+
+ //---- smallerInsetsCheckBox ----
+ smallerInsetsCheckBox.setText("Smaller insets");
+ smallerInsetsCheckBox.addActionListener(e -> smallerInsetsChanged());
+ panel14.add(smallerInsetsCheckBox, "cell 2 4");
+
+ //---- secondTabWiderCheckBox ----
+ secondTabWiderCheckBox.setText("Second Tab wider");
+ secondTabWiderCheckBox.addActionListener(e -> secondTabWiderChanged());
+ panel14.add(secondTabWiderCheckBox, "cell 3 4");
}
panel9.add(panel14, cc.xywh(1, 11, 3, 1));
}
@@ -588,6 +627,9 @@ public class FlatContainerTest
private JCheckBox trailingComponentCheckBox;
private JCheckBox tabsClosableCheckBox;
private TriStateCheckBox secondTabClosableCheckBox;
+ private JCheckBox smallerTabHeightCheckBox;
+ private JCheckBox smallerInsetsCheckBox;
+ private JCheckBox secondTabWiderCheckBox;
// JFormDesigner - End of variables declaration //GEN-END:variables
//---- class Tab1Panel ----------------------------------------------------
diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.jfd
index 9e64f1f6..e6c45887 100644
--- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.jfd
+++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatContainerTest.jfd
@@ -132,7 +132,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[][fill][][][fill]"
- "$rowConstraints": "[center][][][]"
+ "$rowConstraints": "[center][][][][]"
} ) {
name: "panel14"
"opaque": false
@@ -347,6 +347,36 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 3"
} )
+ add( new FormComponent( "javax.swing.JCheckBox" ) {
+ name: "smallerTabHeightCheckBox"
+ "text": "Smaller tab height"
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "smallerTabHeightChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 4 2 1"
+ } )
+ add( new FormComponent( "javax.swing.JCheckBox" ) {
+ name: "smallerInsetsCheckBox"
+ "text": "Smaller insets"
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "smallerInsetsChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 2 4"
+ } )
+ add( new FormComponent( "javax.swing.JCheckBox" ) {
+ name: "secondTabWiderCheckBox"
+ "text": "Second Tab wider"
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "secondTabWiderChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 3 4"
+ } )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridY": 11
"gridWidth": 3