PageRenderTime 203ms CodeModel.GetById 61ms app.highlight 73ms RepoModel.GetById 37ms app.codeStats 1ms

/src/mpv5/ui/misc/CloseableTabbedPane.java

http://mp-rechnungs-und-kundenverwaltung.googlecode.com/
Java | 718 lines | 368 code | 76 blank | 274 comment | 66 complexity | e6febc48cacf3fa685d547af1a626d09 MD5 | raw file
  1/*
  2 *  This file is part of YaBS.
  3 *
  4 *  YaBS is free software: you can redistribute it and/or modify
  5 *  it under the terms of the GNU General Public License as published by
  6 *  the Free Software Foundation, either version 3 of the License, or
  7 *  (at your option) any later version.
  8 *
  9 *  YaBS is distributed in the hope that it will be useful,
 10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12 *  GNU General Public License for more details.
 13 *
 14 *  You should have received a copy of the GNU General Public License
 15 *  along with YaBS.  If not, see <http://www.gnu.org/licenses/>.
 16 */
 17package mpv5.ui.misc;
 18
 19import java.awt.BorderLayout;
 20import java.util.EventListener;
 21
 22import javax.swing.Icon;
 23import javax.swing.JComponent;
 24import javax.swing.JTabbedPane;
 25import javax.swing.JViewport;
 26import javax.swing.SwingUtilities;
 27
 28import java.awt.Color;
 29import java.awt.Component;
 30import java.awt.FontMetrics;
 31import java.awt.Graphics;
 32import java.awt.Point;
 33import java.awt.Rectangle;
 34
 35import java.awt.event.MouseEvent;
 36import java.awt.event.MouseListener;
 37import java.awt.event.MouseMotionListener;
 38
 39import javax.swing.ImageIcon;
 40import javax.swing.border.EmptyBorder;
 41import javax.swing.event.EventListenerList;
 42
 43import javax.swing.plaf.basic.BasicTabbedPaneUI;
 44import javax.swing.plaf.metal.MetalTabbedPaneUI;
 45import mpv5.YabsView;
 46import mpv5.logging.Log;
 47import mpv5.ui.frames.MPView;
 48
 49
 50/**
 51 * A JTabbedPane which has a close ('X') icon on each tab.
 52 *
 53 * To add a tab, use the method addTab(String, Component)
 54 *
 55 * To have an extra icon on each tab (e.g. like in JBuilder, showing the file
 56 * type) use the method addTab(String, Component, Icon). Only clicking the 'X'
 57 * closes the tab.
 58 *
 59 * @author http://forums.sun.com/profile.jspa?userID=484725
 60 */
 61public final class CloseableTabbedPane extends JTabbedPane implements MouseListener,
 62        MouseMotionListener {
 63
 64    /**
 65     * The <code>EventListenerList</code>.
 66     */
 67    private EventListenerList listenerList = null;
 68    /**
 69     * The viewport of the scrolled tabs.
 70     */
 71    private JViewport headerViewport = null;
 72    /**
 73     * The normal closeicon.
 74     */
 75    private Icon normalCloseIcon = null;
 76    /**
 77     * The closeicon when the mouse is over.
 78     */
 79    private Icon hooverCloseIcon = null;
 80    /**
 81     * The closeicon when the mouse is pressed.
 82     */
 83    private Icon pressedCloseIcon = null;
 84    private YabsView parentv;
 85    private volatile int oldSelection;
 86
 87    /**
 88     * Creates a new instance of <code>CloseableTabbedPane</code>
 89     * @param view
 90     */
 91    public CloseableTabbedPane(YabsView view) {
 92        super();
 93        init(SwingUtilities.LEFT);
 94        setCloseIcons(new ImageIcon(CloseableTabbedPane.class.getResource("/mpv5/resources/images/close.png")),
 95                new ImageIcon(CloseableTabbedPane.class.getResource("/mpv5/resources/images/closehoover.png")),
 96                new ImageIcon(CloseableTabbedPane.class.getResource("/mpv5/resources/images/closeclick.png")));
 97
 98
 99        setBorder(new EmptyBorder(0, 0,0, 0));
100        this.parentv = view;
101        setLayout(new BorderLayout());
102    }
103
104    /**
105     * Creates a new instance of <code>CloseableTabbedPane</code>
106     * @param horizontalTextPosition the horizontal position of the text (e.g.
107     * SwingUtilities.TRAILING or SwingUtilities.LEFT)
108     */
109    public CloseableTabbedPane(int horizontalTextPosition) {
110        super();
111        init(horizontalTextPosition);
112    }
113
114    /**
115     * Initializes the <code>CloseableTabbedPane</code>
116     * @param horizontalTextPosition the horizontal position of the text (e.g.
117     * SwingUtilities.TRAILING or SwingUtilities.LEFT)
118     */
119    private void init(int horizontalTextPosition) {
120        listenerList = new EventListenerList();
121        addMouseListener(this);
122        addMouseMotionListener(this);
123        setUI(new CloseableTabbedPaneUI(horizontalTextPosition));
124    }
125
126    /**
127     * Allows setting own closeicons.
128     * @param normal the normal closeicon
129     * @param hoover the closeicon when the mouse is over
130     * @param pressed the closeicon when the mouse is pressed
131     */
132    public void setCloseIcons(Icon normal, Icon hoover, Icon pressed) {
133        normalCloseIcon = normal;
134        hooverCloseIcon = hoover;
135        pressedCloseIcon = pressed;
136    }
137
138    @Override
139    public void setSelectedComponent(Component component) {
140        int index = indexOfComponent(component);
141        if (index != -1) {
142            setSelectedIndex(index);
143        } else {
144            throw new IllegalArgumentException("Component not found in this tabbed pane");
145        }
146    }
147
148    @Override
149    public void setSelectedIndex(int index) {
150
151        try {
152            super.setSelectedIndex(index);
153        } catch (Exception e) {
154            Log.Debug(this, e.getMessage());
155        }
156//        boolean enable = false;
157//        Class[] faces = getSelectedComponent().getClass().getInterfaces();
158//        for (int i = 0; i < faces.length; i++) {
159//            if (faces[i].getName().equals("mpv5.ui.panels.DataPanel")) {
160//                enable = true;
161//            }
162//        }
163//        parentv.enableToolBar(enable);
164    }
165
166    /**
167     * Adds a <code>Component</code> represented by a title and no icon.
168     * @param title the title to be displayed in this tab
169     * @param component the component to be displayed when this tab is clicked
170     */
171    @Override
172    public void addTab(String title, Component component) {
173        addTab(title, component, null);
174    }
175
176    /**
177     * Adds a <code>Component</code> represented by a title and an icon.
178     * @param title the title to be displayed in this tab
179     * @param component the component to be displayed when this tab is clicked
180     * @param extraIcon the icon to be displayed in this tab
181     */
182    public void addTab(String title, Component component, Icon extraIcon) {
183        boolean doPaintCloseIcon = true;
184        try {
185            Object prop = null;
186            if ((prop = ((JComponent) component).getClientProperty("isClosable")) != null) {
187                doPaintCloseIcon = (Boolean) prop;
188            }
189        } catch (Exception ignored) {/*Could probably be a ClassCastException*/
190
191        }
192        
193
194        super.addTab(title,
195                doPaintCloseIcon ? new CloseTabIcon(extraIcon) : null,
196                component);
197
198        if (headerViewport == null) {
199            for (Component c : getComponents()) {
200                if ("TabbedPane.scrollableViewport".equals(c.getName())) {
201                    headerViewport = (JViewport) c;
202                }
203            }
204        }
205
206
207
208    }
209
210    /**
211     * Invoked when the mouse button has been clicked (pressed and released) on
212     * a component.
213     * @param e the <code>MouseEvent</code>
214     */
215    public void mouseClicked(MouseEvent e) {
216        processMouseEvents(e);
217    }
218
219    /**
220     * Invoked when the mouse enters a component.
221     * @param e the <code>MouseEvent</code>
222     */
223    public void mouseEntered(MouseEvent e) {
224                oldSelection = getSelectedIndex();
225    }
226
227    /**
228     * Invoked when the mouse exits a component.
229     * @param e the <code>MouseEvent</code>
230     */
231    public void mouseExited(MouseEvent e) {
232        for (int i = 0; i < getTabCount(); i++) {
233            CloseTabIcon icon = (CloseTabIcon) getIconAt(i);
234            if (icon != null) {
235                icon.mouseover = false;
236            }
237        }
238        repaint();
239    }
240
241    /**
242     * Invoked when a mouse button has been pressed on a component.
243     * @param e the <code>MouseEvent</code>
244     */
245    public void mousePressed(MouseEvent e) {
246        processMouseEvents(e);
247    }
248
249    /**
250     * Invoked when a mouse button has been released on a component.
251     * @param e the <code>MouseEvent</code>
252     */
253    public void mouseReleased(MouseEvent e) {
254    }
255
256    /**
257     * Invoked when a mouse button is pressed on a component and then dragged.
258     * <code>MOUSE_DRAGGED</code> events will continue to be delivered to the
259     * component where the drag originated until the mouse button is released
260     * (regardless of whether the mouse position is within the bounds of the
261     * component).<br/>
262     * <br/>
263     * Due to platform-dependent Drag&Drop implementations,
264     * <code>MOUSE_DRAGGED</code> events may not be delivered during a native
265     * Drag&amp;Drop operation.
266     * @param e the <code>MouseEvent</code>
267     */
268    public void mouseDragged(MouseEvent e) {
269        processMouseEvents(e);
270    }
271
272    /**
273     * Invoked when the mouse cursor has been moved onto a component but no
274     * buttons have been pushed.
275     * @param e the <code>MouseEvent</code>
276     */
277    public void mouseMoved(MouseEvent e) {
278        processMouseEvents(e);
279    }
280
281    /**
282     * Processes all caught <code>MouseEvent</code>s.
283     * @param e the <code>MouseEvent</code>
284     */
285    private void processMouseEvents(MouseEvent e) {
286        int tabNumber = getUI().tabForCoordinate(this, e.getX(), e.getY());
287        if (tabNumber < 0) {
288            return;
289        }
290        CloseTabIcon icon = (CloseTabIcon) getIconAt(tabNumber);
291        if (icon != null) {
292            Rectangle rect = icon.getBounds();
293            Point pos = headerViewport == null ? new Point() : headerViewport.getViewPosition();
294            Rectangle drawRect = new Rectangle(
295                    rect.x - pos.x, rect.y - pos.y, rect.width, rect.height);
296
297            if (e.getID() == e.MOUSE_PRESSED) {
298                icon.mousepressed = e.getModifiers() == e.BUTTON1_MASK;
299                repaint(drawRect);
300            } else if (e.getID() == e.MOUSE_MOVED || e.getID() == e.MOUSE_DRAGGED ||
301                    e.getID() == e.MOUSE_CLICKED) {
302                pos.x += e.getX();
303                pos.y += e.getY();
304                if (rect.contains(pos)) {
305                    if (e.getID() == e.MOUSE_CLICKED) {
306                        int selIndex = getSelectedIndex();
307                        if (fireCloseTab(selIndex)) {
308                            if (selIndex > 0) {
309                                // to prevent uncatchable null-pointers
310                                Rectangle rec = getUI().getTabBounds(this, selIndex - 1);
311
312                                MouseEvent event = new MouseEvent((Component) e.getSource(),
313                                        e.getID() + 1,
314                                        System.currentTimeMillis(),
315                                        e.getModifiers(),
316                                        rec.x,
317                                        rec.y,
318                                        e.getClickCount(),
319                                        e.isPopupTrigger(),
320                                        e.getButton());
321                                dispatchEvent(event);
322                            }
323                            //the tab is being closed
324                            //removeTabAt(tabNumber);
325                            remove(selIndex);
326                            try {
327                                if (selIndex < oldSelection) {
328                                    setSelectedIndex(oldSelection-1);
329                                } else if (selIndex > oldSelection){
330                                    setSelectedIndex(oldSelection);
331                                }
332                            } catch (Exception selex) {
333                                Log.Debug(selex);
334                            }
335                        } else {
336                            icon.mouseover = false;
337                            icon.mousepressed = false;
338                            repaint(drawRect);
339                        }
340                    } else {
341                        icon.mouseover = true;
342                        icon.mousepressed = e.getModifiers() == e.BUTTON1_MASK;
343                    }
344                } else {
345                    icon.mouseover = false;
346                }
347                repaint(drawRect);
348            }
349        }
350        e.consume();
351    }
352
353    /**
354     * Adds an <code>CloseableTabbedPaneListener</code> to the tabbedpane.
355     * @param l the <code>CloseableTabbedPaneListener</code> to be added
356     */
357    public void addCloseableTabbedPaneListener(CloseableTabbedPaneListener l) {
358        listenerList.add(CloseableTabbedPaneListener.class, l);
359    }
360
361    /**
362     * Removes an <code>CloseableTabbedPaneListener</code> from the tabbedpane.
363     * @param l the listener to be removed
364     */
365    public void removeCloseableTabbedPaneListener(CloseableTabbedPaneListener l) {
366        listenerList.remove(CloseableTabbedPaneListener.class, l);
367    }
368
369    /**
370     * Returns an array of all the <code>SearchListener</code>s added to this
371     * <code>SearchPane</code> with addSearchListener().
372     * @return all of the <code>SearchListener</code>s added or an empty array if
373     * no listeners have been added
374     */
375    public CloseableTabbedPaneListener[] getCloseableTabbedPaneListener() {
376        return listenerList.getListeners(CloseableTabbedPaneListener.class);
377    }
378
379    /**
380     * Notifies all listeners that have registered interest for notification on
381     * this event type.
382     * @param tabIndexToClose the index of the tab which should be closed
383     * @return true if the tab can be closed, false otherwise
384     */
385    protected boolean fireCloseTab(int tabIndexToClose) {
386        boolean closeit = true;
387        // Guaranteed to return a non-null array
388        Object[] listeners = listenerList.getListenerList();
389        for (Object i : listeners) {
390            if (i instanceof CloseableTabbedPaneListener) {
391                if (!((CloseableTabbedPaneListener) i).closeTab(tabIndexToClose)) {
392                    closeit = false;
393                    break;
394                }
395            }
396        }
397        return closeit;
398    }
399
400    /**
401     * Removes all tabs but the selected one
402     */
403    public void removeAllButSelected() {
404        //        int index = getSelectedIndex();
405        //        for (int i = 0; i < getTabCount(); i++) {
406        //            if(i!=index)remove(i);
407        //
408        //        }
409        //        validate();
410       try {
411            Component selected = getSelectedComponent();
412            String title = getTitleAt(getSelectedIndex());
413            removeAll();
414            add(title, selected);
415        } catch (Exception e) {
416            Log.Debug(e);
417        }
418    }
419
420    /**
421     * The class which generates the 'X' icon for the tabs. The constructor
422     * accepts an icon which is extra to the 'X' icon, so you can have tabs
423     * like in JBuilder. This value is null if no extra icon is required.
424     */
425    class CloseTabIcon implements Icon {
426
427        /**
428         * the x position of the icon
429         */
430        private int x_pos;
431        /**
432         * the y position of the icon
433         */
434        private int y_pos;
435        /**
436         * the width the icon
437         */
438        private int width;
439        /**
440         * the height the icon
441         */
442        private int height;
443        /**
444         * the additional fileicon
445         */
446        private Icon fileIcon;
447        /**
448         * true whether the mouse is over this icon, false otherwise
449         */
450        private boolean mouseover = false;
451        /**
452         * true whether the mouse is pressed on this icon, false otherwise
453         */
454        private boolean mousepressed = false;
455
456        /**
457         * Creates a new instance of <code>CloseTabIcon</code>
458         * @param fileIcon the additional fileicon, if there is one set
459         */
460        public CloseTabIcon(Icon fileIcon) {
461            this.fileIcon = fileIcon;
462            width = 16;
463            height = 16;
464        }
465
466        /**
467         * Draw the icon at the specified location. Icon implementations may use the
468         * Component argument to get properties useful for painting, e.g. the
469         * foreground or background color.
470         * @param c the component which the icon belongs to
471         * @param g the graphic object to draw on
472         * @param x the upper left point of the icon in the x direction
473         * @param y the upper left point of the icon in the y direction
474         */
475        public void paintIcon(Component c, Graphics g, int x, int y) {
476            boolean doPaintCloseIcon = true;
477            try {
478                // JComponent.putClientProperty("isClosable", new Boolean(false));
479                JTabbedPane tabbedpane = (JTabbedPane) c;
480                int tabNumber = tabbedpane.getUI().tabForCoordinate(tabbedpane, x, y);
481                JComponent curPanel = (JComponent) tabbedpane.getComponentAt(tabNumber);
482                Object prop = null;
483                if ((prop = curPanel.getClientProperty("isClosable")) != null) {
484                    doPaintCloseIcon = (Boolean) prop;
485                }
486            } catch (Exception ignored) {/*Could probably be a ClassCastException*/
487
488            }
489            if (doPaintCloseIcon) {
490                x_pos = x;
491                y_pos = y;
492                int y_p = y + 1;
493
494                if (normalCloseIcon != null && !mouseover) {
495                    normalCloseIcon.paintIcon(c, g, x, y_p);
496                } else if (hooverCloseIcon != null && mouseover && !mousepressed) {
497                    hooverCloseIcon.paintIcon(c, g, x, y_p);
498                } else if (pressedCloseIcon != null && mousepressed) {
499                    pressedCloseIcon.paintIcon(c, g, x, y_p);
500                } else {
501                    y_p++;
502
503                    Color col = g.getColor();
504
505                    if (mousepressed && mouseover) {
506                        g.setColor(Color.WHITE);
507                        g.fillRect(x + 1, y_p, 12, 13);
508                    }
509
510                    g.setColor(Color.black);
511                    g.drawLine(x + 1, y_p, x + 12, y_p);
512                    g.drawLine(x + 1, y_p + 13, x + 12, y_p + 13);
513                    g.drawLine(x, y_p + 1, x, y_p + 12);
514                    g.drawLine(x + 13, y_p + 1, x + 13, y_p + 12);
515                    g.drawLine(x + 3, y_p + 3, x + 10, y_p + 10);
516                    if (mouseover) {
517                        g.setColor(Color.GRAY);
518                    }
519                    g.drawLine(x + 3, y_p + 4, x + 9, y_p + 10);
520                    g.drawLine(x + 4, y_p + 3, x + 10, y_p + 9);
521                    g.drawLine(x + 10, y_p + 3, x + 3, y_p + 10);
522                    g.drawLine(x + 10, y_p + 4, x + 4, y_p + 10);
523                    g.drawLine(x + 9, y_p + 3, x + 3, y_p + 9);
524                    g.setColor(col);
525                    if (fileIcon != null) {
526                        fileIcon.paintIcon(c, g, x + width, y_p);
527                    }
528                }
529            }
530        }
531
532        /**
533         * Returns the icon's width.
534         * @return an int specifying the fixed width of the icon.
535         */
536        public int getIconWidth() {
537            return width + (fileIcon != null ? fileIcon.getIconWidth() : 0);
538        }
539
540        /**
541         * Returns the icon's height.
542         * @return an int specifying the fixed height of the icon.
543         */
544        public int getIconHeight() {
545            return height;
546        }
547
548        /**
549         * Gets the bounds of this icon in the form of a <code>Rectangle<code>
550         * object. The bounds specify this icon's width, height, and location
551         * relative to its parent.
552         * @return a rectangle indicating this icon's bounds
553         */
554        public Rectangle getBounds() {
555            return new Rectangle(x_pos, y_pos, width, height);
556        }
557    }
558
559    /**
560     * A specific <code>BasicTabbedPaneUI</code>.
561     */
562    class CloseableTabbedPaneUI extends BasicTabbedPaneUI {
563
564        /**
565         * the horizontal position of the text
566         */
567        private int horizontalTextPosition = SwingUtilities.LEFT;
568
569        /**
570         * Creates a new instance of <code>CloseableTabbedPaneUI</code>
571         */
572        public CloseableTabbedPaneUI() {
573        }
574
575        /**
576         * Creates a new instance of <code>CloseableTabbedPaneUI</code>
577         * @param horizontalTextPosition the horizontal position of the text (e.g.
578         * SwingUtilities.TRAILING or SwingUtilities.LEFT)
579         */
580        public CloseableTabbedPaneUI(int horizontalTextPosition) {
581            this.horizontalTextPosition = horizontalTextPosition;
582        }
583
584        /**
585         * Layouts the label
586         * @param tabPlacement the placement of the tabs
587         * @param metrics the font metrics
588         * @param tabIndex the index of the tab
589         * @param title the title of the tab
590         * @param icon the icon of the tab
591         * @param tabRect the tab boundaries
592         * @param iconRect the icon boundaries
593         * @param textRect the text boundaries
594         * @param isSelected true whether the tab is selected, false otherwise
595         */
596        @Override
597        protected void layoutLabel(int tabPlacement, FontMetrics metrics,
598                int tabIndex, String title, Icon icon,
599                Rectangle tabRect, Rectangle iconRect,
600                Rectangle textRect, boolean isSelected) {
601
602            textRect.x = textRect.y = iconRect.x = iconRect.y = 0;
603
604            javax.swing.text.View v = getTextViewForTab(tabIndex);
605            if (v != null) {
606                tabPane.putClientProperty("html", v);
607
608            }
609
610            SwingUtilities.layoutCompoundLabel((JComponent) tabPane,
611                    metrics, title, icon,
612                    SwingUtilities.CENTER,
613                    SwingUtilities.CENTER,
614                    SwingUtilities.CENTER,
615                    //SwingUtilities.TRAILING,
616                    horizontalTextPosition,
617                    tabRect,
618                    iconRect,
619                    textRect,
620                    textIconGap + 0);
621
622            tabPane.putClientProperty("html", null);
623
624            int xNudge = getTabLabelShiftX(tabPlacement, tabIndex, isSelected);
625            int yNudge = getTabLabelShiftY(tabPlacement, tabIndex, isSelected);
626            iconRect.x += xNudge;
627            iconRect.y += yNudge;
628            textRect.x += xNudge;
629            textRect.y += yNudge;
630        }
631    }
632
633    /**
634     * A specific <code>MetalTabbedPaneUI</code>.
635     */
636    class CloseableMetalTabbedPaneUI extends MetalTabbedPaneUI {
637
638        /**
639         * the horizontal position of the text
640         */
641        private int horizontalTextPosition = SwingUtilities.LEFT;
642
643        /**
644         * Creates a new instance of <code>CloseableMetalTabbedPaneUI</code>
645         */
646        public CloseableMetalTabbedPaneUI() {
647        }
648
649        /**
650         * Creates a new instance of <code>CloseableMetalTabbedPaneUI</code>
651         * @param horizontalTextPosition the horizontal position of the text (e.g.
652         * SwingUtilities.TRAILING or SwingUtilities.LEFT)
653         */
654        public CloseableMetalTabbedPaneUI(int horizontalTextPosition) {
655            this.horizontalTextPosition = horizontalTextPosition;
656        }
657
658        /**
659         * Layouts the label
660         * @param tabPlacement the placement of the tabs
661         * @param metrics the font metrics
662         * @param tabIndex the index of the tab
663         * @param title the title of the tab
664         * @param icon the icon of the tab
665         * @param tabRect the tab boundaries
666         * @param iconRect the icon boundaries
667         * @param textRect the text boundaries
668         * @param isSelected true whether the tab is selected, false otherwise
669         */
670        protected void layoutLabel(int tabPlacement, FontMetrics metrics,
671                int tabIndex, String title, Icon icon,
672                Rectangle tabRect, Rectangle iconRect,
673                Rectangle textRect, boolean isSelected) {
674
675            textRect.x = textRect.y = iconRect.x = iconRect.y = 0;
676
677            javax.swing.text.View v = getTextViewForTab(tabIndex);
678            if (v != null) {
679                tabPane.putClientProperty("html", v);
680            }
681
682            SwingUtilities.layoutCompoundLabel((JComponent) tabPane,
683                    metrics, title, icon,
684                    SwingUtilities.CENTER,
685                    SwingUtilities.CENTER,
686                    SwingUtilities.CENTER,
687                    //SwingUtilities.TRAILING,
688                    horizontalTextPosition,
689                    tabRect,
690                    iconRect,
691                    textRect,
692                    textIconGap + 2);
693
694            tabPane.putClientProperty("html", null);
695
696            int xNudge = getTabLabelShiftX(tabPlacement, tabIndex, isSelected);
697            int yNudge = getTabLabelShiftY(tabPlacement, tabIndex, isSelected);
698            iconRect.x += xNudge;
699            iconRect.y += yNudge;
700            textRect.x += xNudge;
701            textRect.y += yNudge;
702        }
703    }
704}
705/**
706 * The listener that's notified when an tab should be closed in the
707 * <code>CloseableTabbedPane</code>.
708 */
709interface CloseableTabbedPaneListener extends EventListener {
710
711    /**
712     * Informs all <code>CloseableTabbedPaneListener</code>s when a tab should be
713     * closed
714     * @param tabIndexToClose the index of the tab which should be closed
715     * @return true if the tab can be closed, false otherwise
716     */
717    boolean closeTab(int tabIndexToClose);
718}