TabbedPane: support specifying tab insets via client property

This commit is contained in:
Karl Tauber
2020-10-21 01:14:26 +02:00
parent 9bc656a5c5
commit 6d38e44f91
4 changed files with 119 additions and 19 deletions

View File

@@ -254,6 +254,15 @@ public interface FlatClientProperties
*/ */
String TABBED_PANE_TAB_HEIGHT = "JTabbedPane.tabHeight"; String TABBED_PANE_TAB_HEIGHT = "JTabbedPane.tabHeight";
/**
* Specifies the insets of a tab.
* <p>
* <strong>Component</strong> {@link javax.swing.JTabbedPane}
* or tab content components (see {@link javax.swing.JTabbedPane#setComponentAt(int, java.awt.Component)})<br>
* <strong>Value type</strong> {@link java.awt.Insets}
*/
String TABBED_PANE_TAB_INSETS = "JTabbedPane.tabInsets";
/** /**
* Specifies whether tabs are closable. * Specifies whether tabs are closable.
* If set to {@code true} on a tabbed pane component, all tabs in that tabbed pane are closable. * If set to {@code true} on a tabbed pane component, all tabs in that tabbed pane are closable.

View File

@@ -529,6 +529,14 @@ public class FlatTabbedPaneUI
return Math.max( tabHeight, super.calculateTabHeight( tabPlacement, tabIndex, fontHeight ) - 2 /* was added by superclass */ ); return Math.max( tabHeight, super.calculateTabHeight( tabPlacement, tabIndex, fontHeight ) - 2 /* was added by superclass */ );
} }
@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 @Override
protected Insets getTabAreaInsets( int tabPlacement ) { protected Insets getTabAreaInsets( int tabPlacement ) {
Insets currentTabAreaInsets = super.getTabAreaInsets( tabPlacement ); Insets currentTabAreaInsets = super.getTabAreaInsets( tabPlacement );
@@ -1503,6 +1511,8 @@ public class FlatTabbedPaneUI
PropertyChangeListener propertyChangeDelegate; PropertyChangeListener propertyChangeDelegate;
ChangeListener changeDelegate; ChangeListener changeDelegate;
private final PropertyChangeListener contentListener = this::contentPropertyChange;
private int pressedTabIndex = -1; private int pressedTabIndex = -1;
void installListeners() { void installListeners() {
@@ -1512,7 +1522,7 @@ public class FlatTabbedPaneUI
for( Component c : tabPane.getComponents() ) { for( Component c : tabPane.getComponents() ) {
if( !(c instanceof UIResource) ) 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() ) { for( Component c : tabPane.getComponents() ) {
if( !(c instanceof UIResource) ) if( !(c instanceof UIResource) )
c.removePropertyChangeListener( TABBED_PANE_TAB_CLOSABLE, this ); c.removePropertyChangeListener( contentListener );
} }
} }
@@ -1604,21 +1614,19 @@ public class FlatTabbedPaneUI
@Override @Override
public void propertyChange( PropertyChangeEvent e ) { public void propertyChange( PropertyChangeEvent e ) {
// invoke delegate listener // invoke delegate listener
if( e.getSource() instanceof JTabbedPane ) { switch( e.getPropertyName() ) {
switch( e.getPropertyName() ) { case "tabPlacement":
case "tabPlacement": case "opaque":
case "opaque": case "background":
case "background": case "indexForTabComponent":
case "indexForTabComponent": runWithOriginalLayoutManager( () -> {
runWithOriginalLayoutManager( () -> {
propertyChangeDelegate.propertyChange( e );
} );
break;
default:
propertyChangeDelegate.propertyChange( e ); propertyChangeDelegate.propertyChange( e );
break; } );
} break;
default:
propertyChangeDelegate.propertyChange( e );
break;
} }
// handle event // handle event
@@ -1636,6 +1644,7 @@ public class FlatTabbedPaneUI
case TABBED_PANE_SHOW_CONTENT_SEPARATOR: case TABBED_PANE_SHOW_CONTENT_SEPARATOR:
case TABBED_PANE_HAS_FULL_BORDER: case TABBED_PANE_HAS_FULL_BORDER:
case TABBED_PANE_TAB_HEIGHT: case TABBED_PANE_TAB_HEIGHT:
case TABBED_PANE_TAB_INSETS:
case TABBED_PANE_HIDDEN_TABS_NAVIGATION: case TABBED_PANE_HIDDEN_TABS_NAVIGATION:
case TABBED_PANE_TAB_CLOSABLE: case TABBED_PANE_TAB_CLOSABLE:
tabPane.revalidate(); tabPane.revalidate();
@@ -1671,6 +1680,16 @@ public class FlatTabbedPaneUI
ensureSelectedTabIsVisible(); 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 ---- //---- interface ComponentListener ----
@Override @Override
@@ -1689,14 +1708,14 @@ public class FlatTabbedPaneUI
public void componentAdded( ContainerEvent e ) { public void componentAdded( ContainerEvent e ) {
Component c = e.getChild(); Component c = e.getChild();
if( !(c instanceof UIResource) ) if( !(c instanceof UIResource) )
c.addPropertyChangeListener( TABBED_PANE_TAB_CLOSABLE, this ); c.addPropertyChangeListener( contentListener );
} }
@Override @Override
public void componentRemoved( ContainerEvent e ) { public void componentRemoved( ContainerEvent e ) {
Component c = e.getChild(); Component c = e.getChild();
if( !(c instanceof UIResource) ) if( !(c instanceof UIResource) )
c.removePropertyChangeListener( TABBED_PANE_TAB_CLOSABLE, this ); c.removePropertyChangeListener( contentListener );
} }
} }

View File

@@ -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() { private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JPanel panel9 = new JPanel(); JPanel panel9 = new JPanel();
@@ -337,6 +357,9 @@ public class FlatContainerTest
trailingComponentCheckBox = new JCheckBox(); trailingComponentCheckBox = new JCheckBox();
tabsClosableCheckBox = new JCheckBox(); tabsClosableCheckBox = new JCheckBox();
secondTabClosableCheckBox = new TriStateCheckBox(); secondTabClosableCheckBox = new TriStateCheckBox();
smallerTabHeightCheckBox = new JCheckBox();
smallerInsetsCheckBox = new JCheckBox();
secondTabWiderCheckBox = new JCheckBox();
CellConstraints cc = new CellConstraints(); CellConstraints cc = new CellConstraints();
//======== this ======== //======== this ========
@@ -451,6 +474,7 @@ public class FlatContainerTest
"[center]" + "[center]" +
"[]" + "[]" +
"[]" + "[]" +
"[]" +
"[]")); "[]"));
//---- moreTabsCheckBox ---- //---- moreTabsCheckBox ----
@@ -559,6 +583,21 @@ public class FlatContainerTest
secondTabClosableCheckBox.setText("Second Tab closable"); secondTabClosableCheckBox.setText("Second Tab closable");
secondTabClosableCheckBox.addActionListener(e -> secondTabClosableChanged()); secondTabClosableCheckBox.addActionListener(e -> secondTabClosableChanged());
panel14.add(secondTabClosableCheckBox, "cell 3 3"); 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)); panel9.add(panel14, cc.xywh(1, 11, 3, 1));
} }
@@ -588,6 +627,9 @@ public class FlatContainerTest
private JCheckBox trailingComponentCheckBox; private JCheckBox trailingComponentCheckBox;
private JCheckBox tabsClosableCheckBox; private JCheckBox tabsClosableCheckBox;
private TriStateCheckBox secondTabClosableCheckBox; private TriStateCheckBox secondTabClosableCheckBox;
private JCheckBox smallerTabHeightCheckBox;
private JCheckBox smallerInsetsCheckBox;
private JCheckBox secondTabWiderCheckBox;
// JFormDesigner - End of variables declaration //GEN-END:variables // JFormDesigner - End of variables declaration //GEN-END:variables
//---- class Tab1Panel ---------------------------------------------------- //---- class Tab1Panel ----------------------------------------------------

View File

@@ -132,7 +132,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "insets 0,hidemode 3" "$layoutConstraints": "insets 0,hidemode 3"
"$columnConstraints": "[][fill][][][fill]" "$columnConstraints": "[][fill][][][fill]"
"$rowConstraints": "[center][][][]" "$rowConstraints": "[center][][][][]"
} ) { } ) {
name: "panel14" name: "panel14"
"opaque": false "opaque": false
@@ -347,6 +347,36 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 3" "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 ) { }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridY": 11 "gridY": 11
"gridWidth": 3 "gridWidth": 3