001    package sale.multiwindow;
002    
003    import java.awt.*;
004    import java.awt.event.MouseAdapter;
005    import java.awt.event.MouseEvent;
006    
007    import javax.swing.ImageIcon;
008    import javax.swing.JTabbedPane;
009    import resource.util.ResourceManager;
010    import java.lang.reflect.*;
011    
012    /**
013     * A JTabbedPane which has a close ('X') icon on each tab.
014     *
015     * It is also possible to render the tabs unclosable, i.e. without an icon.
016     */
017    public class IconTabbedPane extends JTabbedPane {
018    
019        /**
020         * Indicates whether the tabs can be closed or not.
021         */
022        private boolean m_fAllowClose = true;
023    
024        /**
025         * The tab whose close button has been clicked most recently.
026         */
027        private int tabNumber;
028    
029        /**
030         * The imageIcon to be used as close icon.
031         */
032        protected static ImageIcon CLOSE_ICON = new ImageIcon(ResourceManager.getInstance().getResource(
033                ResourceManager.RESOURCE_GIF, "icon.icon_closetab_16x16"));
034    
035    
036        /**
037         * Creates an IconTabbedPane. A MouseListener is added tat listens to clicks on the close button if set.
038         * @param fAllowClose Indicates if close buttons should be set or not.
039         */
040        public IconTabbedPane(boolean fAllowClose) {
041            super();
042            m_fAllowClose = fAllowClose;
043            addMouseListener(new MouseAdapter() {
044                public void mouseClicked(MouseEvent e) {
045                    if (getAllowClose()) {
046                        tabNumber = getUI().tabForCoordinate(IconTabbedPane.this, e.getX(), e.getY());
047                        if (tabNumber < 0) {
048                            return;
049                        }
050                        Rectangle rect = ((CloseTabIcon)getIconAt(tabNumber)).getBounds();
051                        if (rect.contains(e.getX(), e.getY())) {
052                            getIconClicked();
053                        }
054                    }
055                }
056            });
057        }
058    
059        /**
060         * Specifies a new close icon. Icons which are set on currently open tabs will not be changed
061         * automatically.
062         * @param iNewIcon the new ImageIcon to be used as close icon.
063         */
064        public void setCloseIcon(ImageIcon iNewIcon) {
065            CLOSE_ICON = iNewIcon;
066        }
067    
068        /**
069         * Creates an IconTabbedPane with close buttons set. Calls <code>IconTabbedPane(true)</code>
070         */
071        public IconTabbedPane() {
072            this(true);
073        }
074    
075        /**
076         * Adds a tab to the IconTabbedPane. Depending on whether closing is allowed or not a close icon
077         * will be set or not, respectively.
078         * @param title the component's title
079         * @param component the compoment to be added as tab
080         */
081        public void addTab(String title, Component component) {
082            CloseTabIcon cti = getAllowClose() ? new CloseTabIcon(CLOSE_ICON) : null;
083            super.addTab(title, cti, component);
084        }
085    
086        /*public void removeTabAt(final int i) {
087    
088            try {
089                javax.swing.SwingUtilities.invokeAndWait(new Thread() {
090                    public void run() {
091                        IconTabbedPane.super.removeTabAt(i);
092                    }
093                });
094            }
095            catch (InvocationTargetException ex) {
096            }
097            catch (InterruptedException ex) {
098            }
099            //System.out.println(javax.swing.SwingUtilities.isEventDispatchThread());
100            //super.removeTabAt(i);
101        }*/
102    
103        /**
104         * @return the index of the tab whose close icon has been clicked most recently
105         */
106        public int getIconClicked() {
107            return tabNumber;
108        }
109    
110        /**
111         * Specifies if closing of tabs should be permitted or not.
112         * @param fAllowClose
113         */
114        public void setAllowClose(boolean fAllowClose) {
115            m_fAllowClose = fAllowClose;
116        }
117    
118        /**
119         * @return if closing of tabs is allowed or not.
120         */
121        public boolean getAllowClose() {
122            return m_fAllowClose;
123        }
124    
125        /**
126         * Extends ImageIcon by method <code>getBounds</code> to make it possible to determine the coordinates of
127         * the icon on the screen.
128         */
129        protected class CloseTabIcon extends ImageIcon {
130            private int x_pos;
131            private int y_pos;
132            private int width;
133            private int height;
134            private ImageIcon imageIcon;
135    
136            /**
137             * Creates a CloseTabIcon from an ImageIcon.
138             */
139            public CloseTabIcon(ImageIcon icon) {
140                this.imageIcon = icon;
141                width = imageIcon.getIconWidth();
142                height = imageIcon.getIconHeight();
143            }
144    
145            /**
146             * Returns the image of the ImageIcon.
147             */
148            public Image getImage() {
149                return imageIcon.getImage();
150            }
151    
152            /**
153             * Paints the Icon. This method is usually not called directly.
154             */
155            public void paintIcon(Component c, Graphics g, int x, int y) {
156                imageIcon.paintIcon(c, g, x, y);
157                this.x_pos = x;
158                this.y_pos = y;
159            }
160    
161            /**
162             * Returns the icon's width.
163             */
164            public int getIconWidth() {
165                return width;
166            }
167    
168            /**
169             * Returns the icon's height.
170             */
171            public int getIconHeight() {
172                return height;
173            }
174    
175            /**
176             * Returns the position of the icon on the screen. Used to check for mouse clicks on the icon.
177             */
178            public Rectangle getBounds() {
179                return new Rectangle(x_pos, y_pos, width, height);
180            }
181        }
182    
183    }
184    
185