package call.gui;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;
public class CloseableTab extends JPanel {
private static final long serialVersionUID = 2770093778823348453L;
private final String title;
private CloseableTab(String title) {
super();
this.title = title;
}
public static String getTitleAt(JTabbedPane tabs, int index) {
Component component = tabs.getTabComponentAt(index);
if (component instanceof CloseableTab) {
return ((CloseableTab) component).title;
} else {
return tabs.getTitleAt(index);
}
}
public static int indexOfTab(JTabbedPane tabs, String title) {
for (int i = 0; i < tabs.getTabCount(); ++i) {
if (title.equals(getTitleAt(tabs, i))) {
return i;
}
}
return -1;
}
public String getTitle() {
return title;
}
/**
* Adds a component to a JTabbedPane with a little "close tab" button on the
* right side of the tab.
*
* @param tabbedPane
* the JTabbedPane
* @param c
* any JComponent
* @param title
* the title for the tab
* @param icon
* the icon for the tab, if desired
*/
public static void addClosableTab(final JTabbedPane tabbedPane, final JComponent c, final String title,
final Icon icon) {
// Add the tab to the pane without any label
tabbedPane.addTab(null, c);
int pos = tabbedPane.indexOfComponent(c);
// Create a FlowLayout that will space things 5px apart
FlowLayout layout = new FlowLayout(FlowLayout.CENTER, 5, 0);
// Make a small JPanel with the layout and make it non-opaque
CloseableTab closeabletab = new CloseableTab(title);
closeabletab.setLayout(layout);
closeabletab.setOpaque(false);
// Add a JLabel with title and the left-side tab icon
JLabel lblTitle = new JLabel(title);
lblTitle.setFont(Resources.FONT_TABTITLE);
if (icon != null) {
lblTitle.setIcon(icon);
}
// Create a JButton for the close tab button
JButton btnClose = new JButton();
btnClose.setOpaque(false);
// Configure icon and rollover icon for button
btnClose.setRolloverIcon(Resources.ICON_TAB_CLOSE_HOVER);
btnClose.setRolloverEnabled(true);
btnClose.setIcon(Resources.ICON_TAB_CLOSE);
// Set border null so the button doesn't make the tab too big
btnClose.setBorder(null);
// Make sure the button can't get focus, otherwise it looks funny
btnClose.setFocusable(false);
// Put the panel together
closeabletab.add(lblTitle);
closeabletab.add(btnClose);
// Add a thin border to keep the image below the top edge of the tab
// when the tab is selected
closeabletab.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
// Now assign the component for the tab
tabbedPane.setTabComponentAt(pos, closeabletab);
// Add the listener that removes the tab
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// The component parameter must be declared "final" so that it
// can be
// referenced in the anonymous listener class like this.
tabbedPane.remove(c);
}
};
btnClose.addActionListener(listener);
// Optionally bring the new tab to the front
tabbedPane.setSelectedComponent(c);
// -------------------------------------------------------------
// Bonus: Adding a <Ctrl-W> keystroke binding to close the tab
// -------------------------------------------------------------
AbstractAction closeTabAction = new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
tabbedPane.remove(c);
}
};
// Create a keystroke
KeyStroke controlW = KeyStroke.getKeyStroke("control W");
// Get the appropriate input map using the JComponent constants.
// This one works well when the component is a container.
InputMap inputMap = c.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
// Add the key binding for the keystroke to the action name
inputMap.put(controlW, "closeTab");
// Now add a single binding for the action name to the anonymous action
c.getActionMap().put("closeTab", closeTabAction);
}
}