package com.vci.client.ui.swing.components; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Transparency; import javax.swing.Icon; import javax.swing.JFrame; import javax.swing.JTabbedPane; import javax.swing.UIManager; import javax.swing.event.EventListenerList; import com.vci.client.ui.swing.VCISwingUtil; //import java.awt.geom.AffineTransform; //import java.util.ArrayList; //import java.util.HashMap; /** * A JTabbedPane which has a close ('X') icon on each tab. * To add a tab, use the method addTab(String, Component) * To have an extra icon on each tab (e.g. like in JBuilder, * showing the file type) use the method * addTab(String, Component, Icon). * Only clicking the 'X' closes the tab. */ public class JClosableTabbedPane extends JTabbedPane { private static final long serialVersionUID = -5331239697810133531L; private EventListenerList closeListenerList = new EventListenerList(); public JClosableTabbedPane() { super(); setFont(VCISwingUtil.FONT_DEFAULT); } public void addTab(String title, Component component, boolean closeable) { this.addTab(title, component, null, closeable); } public void addTab(String title, Component component, Icon extraIcon, boolean closeable) { this.addTab(title, component, extraIcon, null, closeable); } public void addTab(String title, Component component, Icon extraIcon, String tip, boolean closeable) { if (closeable) { super.add(title, component); int index = getTabCount() - 1; TabTitleComponent tabComponent = new TabTitleComponent(this, component); tabComponent.setTitle(title); this.setTabComponentAt(index, tabComponent); } else { super.addTab(title, extraIcon, component, tip); } } public void addCloseListener(CloseListener l){ this.closeListenerList.add(CloseListener.class, l); } public void removeCloseListener(CloseListener l){ if(l != null){ this.closeListenerList.remove(CloseListener.class, l); } } private final String BEFORECLOSEING = "beforeCloseing"; private final String AFTERCLOSED = "afterClosed"; private void invokeBeforeCloseing(int index, Component tabCompt){ invoke(index, BEFORECLOSEING, tabCompt); } private void invokeAfterClosed(int index, Component tabCompt){ invoke(index, AFTERCLOSED, tabCompt); } private void invoke(int index, String method, Component tabCompt){ CloseListener[] listeners = getCloseListeners(); if(listeners != null){ for(CloseListener l : listeners){ CloseEvent e = new CloseEvent(this, index, tabCompt); invoke(l, e, method); } } } private void invoke(CloseListener l, CloseEvent e, String method){ if(method.equalsIgnoreCase(BEFORECLOSEING)){ l.beforeCloseing(e); } else if(method.equals(AFTERCLOSED)){ l.afterClosed(e); } } private CloseListener[] getCloseListeners(){ CloseListener[] listeners = closeListenerList.getListeners(CloseListener.class); return listeners; } public void removeTabAt(int index) { Component tabCompt = getTabComponentAt(index); invokeBeforeCloseing(index, tabCompt); super.removeTabAt(index); invokeAfterClosed(index, tabCompt); } public static void main(String args[]) { try { UIManager .setLookAndFeel(VCISwingUtil.LOOK_AND_FEEL_NimbusLookAndFeel); } catch (Exception e) { e.printStackTrace(); } final JClosableTabbedPane pane = new JClosableTabbedPane(); for (int i = 0; i < 20; i++) { pane.addTab("Title " + String.valueOf(i), new VCIJPanel(), true); } pane.addCloseListener(new CloseListener() { @Override public void beforeCloseing(CloseEvent e) { // TODO Auto-generated method stub VCIJOptionPane.showMessage(pane, "BeforeCloseing:" + String.valueOf(e.getTabIndex())); } @Override public void afterClosed(CloseEvent e) { // TODO Auto-generated method stub VCIJOptionPane.showMessage(pane, "AfterClosed:" + String.valueOf(e.getTabIndex())); } }); JFrame frame = new JFrame("Demo"); frame.getContentPane().add(pane, BorderLayout.CENTER); frame.setSize(500, 300); frame.setLocation(300, 200); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } } /** * The class which generates the 'X' icon for the tabs. The constructor * accepts an icon which is extra to the 'X' icon, so you can have tabs * like in JBuilder. This value is null if no extra icon is required. */ class CloseTabIcon implements Icon { private int x_pos; private int y_pos; private int width; private int height; private Icon fileIcon; public CloseTabIcon(Icon fileIcon) { this.fileIcon = fileIcon; width = 16; height = 16; } public void paintIcon(Component c, Graphics g, int x, int y) { this.x_pos = x; this.y_pos = y; if(g instanceof Graphics2D){ Graphics2D g2d = (Graphics2D)g; g2d.getDeviceConfiguration().createCompatibleImage(width*2, height*2, Transparency.TRANSLUCENT); } Color col = g.getColor(); g.setColor(Color.black); int y_p = y + 2; g.drawLine(x + 1, y_p, x + 12, y_p); g.drawLine(x + 1, y_p + 13, x + 12, y_p + 13); g.drawLine(x, y_p + 1, x, y_p + 12); g.drawLine(x + 13, y_p + 1, x + 13, y_p + 12); g.drawLine(x + 3, y_p + 3, x + 10, y_p + 10); g.drawLine(x + 3, y_p + 4, x + 9, y_p + 10); g.drawLine(x + 4, y_p + 3, x + 10, y_p + 9); g.drawLine(x + 10, y_p + 3, x + 3, y_p + 10); g.drawLine(x + 10, y_p + 4, x + 4, y_p + 10); g.drawLine(x + 9, y_p + 3, x + 3, y_p + 9); g.setColor(col); if (fileIcon != null) { fileIcon.paintIcon(c, g, x + width, y_p); } } public int getIconWidth() { return width + (fileIcon != null ? fileIcon.getIconWidth() : 0); } public int getIconHeight() { return height; } public Rectangle getBounds() { return new Rectangle(x_pos, y_pos, width, height); } }