Substance look and feel - documentation
Author: substance.dev.java.net
Description: Substance look and feel
Keywords: java, look, feel, skins, plaf, swing, ui, pluggable, substance

# Substance API

View all API methods.

View all client properties.

API method | `public static void registerTabCloseChangeListener(JTabbedPane tabbedPane, BaseTabCloseListener tabCloseListener)`
Description | Registers the specified listener on tab-close events on the specified tabbed pane. Parameters: `tabbedPane` - If `null`, the tab close listener is registered globally (for all tabbed panes). `tabCloseListener` - Listener to register.
See also | registerTabCloseChangeListener(BaseTabCloseListener) API. unregisterTabCloseChangeListener(BaseTabCloseListener) API. unregisterTabCloseChangeListener(JTabbedPane, BaseTabCloseListener) API.
Sample code | The following example registers a tab close listener on the specific tabbed pane. The listener listens on single tab close events: `import java.awt.BorderLayout; import java.awt.Component; import javax.swing.*; import org.jvnet.substance.SubstanceLookAndFeel; import org.jvnet.substance.api.tabbed.TabCloseListener; import org.jvnet.substance.skin.BusinessBlackSteelSkin; import test.Check; /** * Test application that shows the use of the * {@link SubstanceLookAndFeel#registerTabCloseChangeListener(JTabbedPane, org.jvnet.substance.tabbed.BaseTabCloseListener)} * API with registering a tab close listener that listens on single tab closing * on a specific tabbed pane. * * @author Kirill Grouchnikov * @see SubstanceLookAndFeel#registerTabCloseChangeListener(JTabbedPane, * org.jvnet.substance.tabbed.BaseTabCloseListener) */ public class RegisterTabCloseChangeListener_SpecificSingle extends JFrame { /** * Creates the main frame for <code>this</code> sample. */ public RegisterTabCloseChangeListener_SpecificSingle() { super("Register tab close listener"); this.setLayout(new BorderLayout()); final JTabbedPane jtp = new JTabbedPane(); jtp.addTab("tab1", Check.getIcon("flag_sweden"), new JPanel()); jtp.addTab("tab2", Check.getIcon("flag_mexico"), new JPanel()); jtp.addTab("tab3", Check.getIcon("flag_hong_kong"), new JPanel()); jtp.putClientProperty( SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_PROPERTY, Boolean.TRUE); // register tab close listener on the specific tabbed pane. SubstanceLookAndFeel.registerTabCloseChangeListener(jtp, new TabCloseListener() { public void tabClosing(JTabbedPane tabbedPane, Component tabComponent) { System.out.println("Tab " + tabbedPane.getTitleAt(tabbedPane .indexOfComponent(tabComponent)) + " closing"); } public void tabClosed(JTabbedPane tabbedPane, Component tabComponent) { System.out.println("Tab closed"); } }); this.add(jtp, BorderLayout.CENTER); this.setSize(400, 200); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } /** * The main method for <code>this</code> sample. The arguments are ignored. * * @param args * Ignored. */ public static void main(String[] args) { JFrame.setDefaultLookAndFeelDecorated(true); SwingUtilities.invokeLater(new Runnable() { public void run() { SubstanceLookAndFeel.setSkin(new BusinessBlackSteelSkin()); new RegisterTabCloseChangeListener_SpecificSingle() .setVisible(true); } }); } }` Running the example above and clicking the close button of the third tab produce the following output: `
    Tab tab3 closing
    Tab closed
` The following example registers a tab close listener on the specific tabbed pane. The listener listens on single tab close events and vetoes them: `import java.awt.BorderLayout; import java.awt.Component; import javax.swing.*; import org.jvnet.substance.SubstanceLookAndFeel; import org.jvnet.substance.api.tabbed.VetoableTabCloseListener; import org.jvnet.substance.skin.BusinessBlackSteelSkin; import test.Check; /** * Test application that shows the use of the * {@link SubstanceLookAndFeel#registerTabCloseChangeListener(JTabbedPane, org.jvnet.substance.tabbed.BaseTabCloseListener)} * API with registering a vetoable tab close listener that listens on single tab * closing on a specific tabbed pane. * * @author Kirill Grouchnikov * @see SubstanceLookAndFeel#registerTabCloseChangeListener(JTabbedPane, * org.jvnet.substance.tabbed.BaseTabCloseListener) */ public class RegisterTabCloseChangeListener_SpecificSingleVetoable extends JFrame { /** * Creates the main frame for <code>this</code> sample. */ public RegisterTabCloseChangeListener_SpecificSingleVetoable() { super("Register tab close listener"); this.setLayout(new BorderLayout()); final JTabbedPane jtp = new JTabbedPane(); jtp.addTab("tab1", Check.getIcon("flag_sweden"), new JPanel()); jtp.addTab("tab2", Check.getIcon("flag_mexico"), new JPanel()); jtp.addTab("tab3", Check.getIcon("flag_hong_kong"), new JPanel()); jtp.putClientProperty( SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_PROPERTY, Boolean.TRUE); // register tab close listener on the specific tabbed pane. SubstanceLookAndFeel.registerTabCloseChangeListener(jtp, new VetoableTabCloseListener() { public void tabClosing(JTabbedPane tabbedPane, Component tabComponent) { System.out.println("Tab " + tabbedPane.getTitleAt(tabbedPane .indexOfComponent(tabComponent)) + " closing"); } public void tabClosed(JTabbedPane tabbedPane, Component tabComponent) { System.out.println("Tab closed"); } public boolean vetoTabClosing(JTabbedPane tabbedPane, Component tabComponent) { return (JOptionPane .showConfirmDialog( RegisterTabCloseChangeListener_SpecificSingleVetoable.this, "Are you sure you want to close " + tabbedPane .getTitleAt(tabbedPane .indexOfComponent(tabComponent)) + "?") != JOptionPane.YES_OPTION); } }); this.add(jtp, BorderLayout.CENTER); this.setSize(400, 200); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } /** * The main method for <code>this</code> sample. The arguments are ignored. * * @param args * Ignored. */ public static void main(String[] args) { JFrame.setDefaultLookAndFeelDecorated(true); JDialog.setDefaultLookAndFeelDecorated(true); SwingUtilities.invokeLater(new Runnable() { public void run() { SubstanceLookAndFeel.setSkin(new BusinessBlackSteelSkin()); new RegisterTabCloseChangeListener_SpecificSingleVetoable() .setVisible(true); } }); } }` Running the example above and clicking the close button of the third tab shows the following dialog: Clicking "No" or "Cancel" dismisses the dialog and vetoes the tab closing. Pressing "Yes" dismisses the dialog, closes the tab and produces the following output: `
    Tab tab3 closing
    Tab closed
` The following example registers a tab close listener on the specific tabbed pane. The listener listens on multiple tab close events: `import java.awt.BorderLayout; import java.awt.Component; import java.awt.event.MouseEvent; import java.util.Set; import javax.swing.*; import org.jvnet.substance.SubstanceLookAndFeel; import org.jvnet.substance.api.SubstanceConstants.TabCloseKind; import org.jvnet.substance.api.tabbed.MultipleTabCloseListener; import org.jvnet.substance.api.tabbed.TabCloseCallback; import org.jvnet.substance.skin.BusinessBlackSteelSkin; import test.Check; /** * Test application that shows the use of the * {@link SubstanceLookAndFeel#registerTabCloseChangeListener(JTabbedPane, org.jvnet.substance.tabbed.BaseTabCloseListener)} * API with registering a tab close listener that listens on multiple tab * closing on a specific tabbed pane. * * @author Kirill Grouchnikov * @see SubstanceLookAndFeel#registerTabCloseChangeListener(JTabbedPane, * org.jvnet.substance.tabbed.BaseTabCloseListener) */ public class RegisterTabCloseChangeListener_SpecificMultiple extends JFrame { /** * Creates the main frame for <code>this</code> sample. */ public RegisterTabCloseChangeListener_SpecificMultiple() { super("Register tab close listener"); this.setLayout(new BorderLayout()); final JTabbedPane jtp = new JTabbedPane(); jtp.addTab("tab1", Check.getIcon("flag_sweden"), new JPanel()); jtp.addTab("tab2", Check.getIcon("flag_mexico"), new JPanel()); jtp.addTab("tab3", Check.getIcon("flag_hong_kong"), new JPanel()); jtp.putClientProperty( SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_PROPERTY, Boolean.TRUE); // create a custom implementation of TabCloseCallback interface. TabCloseCallback closeCallback = new TabCloseCallback() { public TabCloseKind onAreaClick(JTabbedPane tabbedPane, int tabIndex, MouseEvent mouseEvent) { if (mouseEvent.getButton() != MouseEvent.BUTTON3) return TabCloseKind.NONE; if (mouseEvent.isShiftDown()) { return TabCloseKind.ALL; } return TabCloseKind.THIS; } public TabCloseKind onCloseButtonClick(JTabbedPane tabbedPane, int tabIndex, MouseEvent mouseEvent) { if (mouseEvent.isAltDown()) { return TabCloseKind.ALL_BUT_THIS; } if (mouseEvent.isShiftDown()) { return TabCloseKind.ALL; } return TabCloseKind.THIS; } public String getAreaTooltip(JTabbedPane tabbedPane, int tabIndex) { return null; } public String getCloseButtonTooltip(JTabbedPane tabbedPane, int tabIndex) { StringBuffer result = new StringBuffer(); result.append("<html><body>"); result.append("Mouse click closes <b>" + tabbedPane.getTitleAt(tabIndex) + "</b> tab"); result .append("<br><b>Alt</b>-Mouse click closes all tabs but <b>" + tabbedPane.getTitleAt(tabIndex) + "</b> tab"); result.append("<br><b>Shift</b>-Mouse click closes all tabs"); result.append("</body></html>"); return result.toString(); } }; // register the callback on the tabbed pane jtp.putClientProperty(SubstanceLookAndFeel.TABBED_PANE_CLOSE_CALLBACK, closeCallback); // register tab close listener on the specific tabbed pane. SubstanceLookAndFeel.registerTabCloseChangeListener(jtp, new MultipleTabCloseListener() { public void tabsClosing(JTabbedPane tabbedPane, Set<Component> tabComponents) { StringBuffer sb = new StringBuffer("Tab (s)"); String sep = " ["; for (Component comp : tabComponents) { sb.append(sep); sep = ", "; sb.append(tabbedPane.getTitleAt(tabbedPane .indexOfComponent(comp))); } sb.append("] closing"); System.out.println(sb.toString()); } public void tabsClosed(JTabbedPane tabbedPane, Set<Component> tabComponents) { System.out.println(tabComponents.size() + " tab(s) closed"); } }); this.add(jtp, BorderLayout.CENTER); this.setSize(400, 200); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } /** * The main method for <code>this</code> sample. The arguments are ignored. * * @param args * Ignored. */ public static void main(String[] args) { JFrame.setDefaultLookAndFeelDecorated(true); SwingUtilities.invokeLater(new Runnable() { public void run() { SubstanceLookAndFeel.setSkin(new BusinessBlackSteelSkin()); new RegisterTabCloseChangeListener_SpecificMultiple() .setVisible(true); } }); } }` Running the example above and Alt-clicking the close button of the third tab produce the following output: `
    Tab (s) [tab1, tab2] closing
    2 tab(s) closed
` The following example registers a tab close listener on the specific tabbed pane. The listener listens on multiple tab close events and vetoes them: `import java.awt.BorderLayout; import java.awt.Component; import java.awt.event.MouseEvent; import java.util.Set; import javax.swing.*; import org.jvnet.substance.SubstanceLookAndFeel; import org.jvnet.substance.api.SubstanceConstants.TabCloseKind; import org.jvnet.substance.api.tabbed.TabCloseCallback; import org.jvnet.substance.api.tabbed.VetoableMultipleTabCloseListener; import org.jvnet.substance.skin.BusinessBlackSteelSkin; import test.Check; /** * Test application that shows the use of the * {@link SubstanceLookAndFeel#registerTabCloseChangeListener(JTabbedPane, org.jvnet.substance.tabbed.BaseTabCloseListener)} * API with registering a vetoable tab close listener that listens on multiple * tab closing on a specific tabbed pane. * * @author Kirill Grouchnikov * @see SubstanceLookAndFeel#registerTabCloseChangeListener(JTabbedPane, * org.jvnet.substance.tabbed.BaseTabCloseListener) */ public class RegisterTabCloseChangeListener_SpecificMultipleVetoable extends JFrame { /** * Creates the main frame for <code>this</code> sample. */ public RegisterTabCloseChangeListener_SpecificMultipleVetoable() { super("Register tab close listener"); this.setLayout(new BorderLayout()); final JTabbedPane jtp = new JTabbedPane(); jtp.addTab("tab1", Check.getIcon("flag_sweden"), new JPanel()); jtp.addTab("tab2", Check.getIcon("flag_mexico"), new JPanel()); jtp.addTab("tab3", Check.getIcon("flag_hong_kong"), new JPanel()); jtp.putClientProperty( SubstanceLookAndFeel.TABBED_PANE_CLOSE_BUTTONS_PROPERTY, Boolean.TRUE); // create a custom implementation of TabCloseCallback interface. TabCloseCallback closeCallback = new TabCloseCallback() { public TabCloseKind onAreaClick(JTabbedPane tabbedPane, int tabIndex, MouseEvent mouseEvent) { if (mouseEvent.getButton() != MouseEvent.BUTTON3) return TabCloseKind.NONE; if (mouseEvent.isShiftDown()) { return TabCloseKind.ALL; } return TabCloseKind.THIS; } public TabCloseKind onCloseButtonClick(JTabbedPane tabbedPane, int tabIndex, MouseEvent mouseEvent) { if (mouseEvent.isAltDown()) { return TabCloseKind.ALL_BUT_THIS; } if (mouseEvent.isShiftDown()) { return TabCloseKind.ALL; } return TabCloseKind.THIS; } public String getAreaTooltip(JTabbedPane tabbedPane, int tabIndex) { return null; } public String getCloseButtonTooltip(JTabbedPane tabbedPane, int tabIndex) { StringBuffer result = new StringBuffer(); result.append("<html><body>"); result.append("Mouse click closes <b>" + tabbedPane.getTitleAt(tabIndex) + "</b> tab"); result .append("<br><b>Alt</b>-Mouse click closes all tabs but <b>" + tabbedPane.getTitleAt(tabIndex) + "</b> tab"); result.append("<br><b>Shift</b>-Mouse click closes all tabs"); result.append("</body></html>"); return result.toString(); } }; // register the callback on the tabbed pane jtp.putClientProperty(SubstanceLookAndFeel.TABBED_PANE_CLOSE_CALLBACK, closeCallback); // register tab close listener on the specific tabbed pane. SubstanceLookAndFeel.registerTabCloseChangeListener(jtp, new VetoableMultipleTabCloseListener() { public void tabsClosing(JTabbedPane tabbedPane, Set<Component> tabComponents) { StringBuffer sb = new StringBuffer("Tab (s)"); String sep = " ["; for (Component comp : tabComponents) { sb.append(sep); sep = ", "; sb.append(tabbedPane.getTitleAt(tabbedPane .indexOfComponent(comp))); } sb.append("] closing"); System.out.println(sb.toString()); } public void tabsClosed(JTabbedPane tabbedPane, Set<Component> tabComponents) { System.out.println(tabComponents.size() + " tab(s) closed"); } public boolean vetoTabsClosing(JTabbedPane tabbedPane, Set<Component> tabComponents) { StringBuffer sb = new StringBuffer(""); String sep = "["; for (Component comp : tabComponents) { sb.append(sep); sep = ", "; sb.append(tabbedPane.getTitleAt(tabbedPane .indexOfComponent(comp))); } sb.append("]"); return (JOptionPane .showConfirmDialog( RegisterTabCloseChangeListener_SpecificMultipleVetoable.this, "Are you sure you want to close " + sb.toString() + "?") != JOptionPane.YES_OPTION); } }); this.add(jtp, BorderLayout.CENTER); this.setSize(400, 200); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } /** * The main method for <code>this</code> sample. The arguments are ignored. * * @param args * Ignored. */ public static void main(String[] args) { JFrame.setDefaultLookAndFeelDecorated(true); JDialog.setDefaultLookAndFeelDecorated(true); SwingUtilities.invokeLater(new Runnable() { public void run() { SubstanceLookAndFeel.setSkin(new BusinessBlackSteelSkin()); new RegisterTabCloseChangeListener_SpecificMultipleVetoable() .setVisible(true); } }); } }` Running the example above and Alt-clicking the close button of the third tab shows the following dialog: Clicking "No" or "Cancel" dismisses the dialog and vetoes the tab closing. Pressing "Yes" dismisses the dialog, closes the first and second tabs and produces the following output: `
    Tab (s) [tab2, tab1] closing
    2 tab(s) closed
`