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


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.pushingpixels.substance.api.SubstanceLookAndFeel;
import org.pushingpixels.substance.api.skin.BusinessBlackSteelSkin;
import org.pushingpixels.substance.api.tabbed.TabCloseListener;

/**
 * Test application that shows the use of the
 {@link SubstanceLookAndFeel#registerTabCloseChangeListener(JTabbedPane, org.pushingpixels.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.pushingpixels.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());

    JTabbedPane jtp = new JTabbedPane();
    jtp.addTab("tab1"new JPanel());
    jtp.addTab("tab2"new JPanel());
    jtp.addTab("tab3"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(400200);
    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.pushingpixels.substance.api.SubstanceLookAndFeel;
import org.pushingpixels.substance.api.skin.BusinessBlackSteelSkin;
import org.pushingpixels.substance.api.tabbed.VetoableTabCloseListener;

/**
 * Test application that shows the use of the
 {@link SubstanceLookAndFeel#registerTabCloseChangeListener(JTabbedPane, org.pushingpixels.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.pushingpixels.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());

    JTabbedPane jtp = new JTabbedPane();
    jtp.addTab("tab1"new JPanel());
    jtp.addTab("tab2"new JPanel());
    jtp.addTab("tab3"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(400200);
    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.pushingpixels.substance.api.SubstanceLookAndFeel;
import org.pushingpixels.substance.api.SubstanceConstants.TabCloseKind;
import org.pushingpixels.substance.api.skin.BusinessBlackSteelSkin;
import org.pushingpixels.substance.api.tabbed.MultipleTabCloseListener;
import org.pushingpixels.substance.api.tabbed.TabCloseCallback;

/**
 * Test application that shows the use of the
 {@link SubstanceLookAndFeel#registerTabCloseChangeListener(JTabbedPane, org.pushingpixels.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.pushingpixels.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());

    JTabbedPane jtp = new JTabbedPane();
    jtp.addTab("tab1"new JPanel());
    jtp.addTab("tab2"new JPanel());
    jtp.addTab("tab3"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(400200);
    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.pushingpixels.substance.api.SubstanceLookAndFeel;
import org.pushingpixels.substance.api.SubstanceConstants.TabCloseKind;
import org.pushingpixels.substance.api.skin.BusinessBlackSteelSkin;
import org.pushingpixels.substance.api.tabbed.TabCloseCallback;
import org.pushingpixels.substance.api.tabbed.VetoableMultipleTabCloseListener;

/**
 * Test application that shows the use of the
 {@link SubstanceLookAndFeel#registerTabCloseChangeListener(JTabbedPane, org.pushingpixels.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.pushingpixels.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());

    JTabbedPane jtp = new JTabbedPane();
    jtp.addTab("tab1"new JPanel());
    jtp.addTab("tab2"new JPanel());
    jtp.addTab("tab3"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(400200);
    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