Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: echopoint/TabbedPane.java


1   package echopoint;
2   
3   /* 
4    * This file is part of the Echo Point Project.  This project is a collection
5    * of Components that have extended the Echo Web Application Framework.
6    *
7    * EchoPoint is free software; you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as published by
9    * the Free Software Foundation; either version 2 of the License, or
10   * (at your option) any later version.
11   *
12   * EchoPoint is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public License
18   * along with Echo Point; if not, write to the Free Software
19   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20   */
21  
22  import java.io.Serializable;
23  import java.util.Iterator;
24  import java.util.NoSuchElementException;
25  import java.util.EventListener;
26  
27  import echopoint.tabbedpane.TabImageRenderer;
28  
29  import nextapp.echo.Color;
30  import nextapp.echo.Component;
31  import nextapp.echo.Container;
32  import nextapp.echo.EchoConstants;
33  import nextapp.echo.Font;
34  import nextapp.echo.ImageReference;
35  import nextapp.echo.Insets;
36  import nextapp.echo.ResourceImageReference;
37  import nextapp.echo.Style;
38  import nextapp.echo.event.ActionEvent;
39  import nextapp.echo.event.ActionListener;
40  import nextapp.echo.event.ChangeListener;
41  
42  import echopoint.DevNull;
43  import echopoint.EchoPointComponent;
44  import echopoint.model.DefaultSingleSelectionModel;
45  import echopoint.model.SingleSelectionModel;
46  import echopoint.positionable.Scrollable;
47  import echopoint.stylesheet.StyleAttrDescriptor;
48  import echopoint.stylesheet.StyleInfo;
49  import echopoint.stylesheet.SymbolicIntegerValue;
50  import echopoint.stylesheet.SymbolicValue;
51  import echopoint.ui.resource.ResourceNames;
52  
53  /**
54   * The <code>TabbedPane</code> component provides tabbed panes to the Echo Web Framework.  
55   * <p>
56   * Any component object can be used as the interior of the tabbed pane, however in 
57   * general you would use a Panel object as the content of a tab, and then fill that
58   * Panel with other components.
59   * <p>
60   * The <code>TabbedPane</code> uses a <code>SingleSelectionModel</code> to represent the set of tab 
61   * indices and the currently selected index. The <code>DefaultSingleSelectionModel</code> class only
62   * raises and event if the currently selected index changes.  So to "trap" the user 
63   * clicking on the same tab twice, derive your own <code>SingleSelectionModel</code> class.
64   * <p>
65   * If the tab count is greater than 0, then there will always be a selected index, 
66   * which by default will be initialized to the first tab. If the tab count is 0, 
67   * then the selected index will be -1.
68   * <p>
69   * An optional <code>TabImageRenderer</code> can be used to render "tab image representations".  
70   * If a <code>TabImageRenderer</code> is in place, then the image returned will be used
71   * as the tab representation, rather then the simple text based approach.  You will
72   * typically not want tab borders or tab insets if you are using a <code>TabImageRenderer</code>. 
73   * <p>
74   * <code>TabbedPane</code> has an optimisation in place that means that only the
75   * currently selected component is given a rendering peer.  This ensures that the
76   * smallest amount of memory is used to render the contents.  
77   * <p>
78   * The width and height of the <code>TabbedPane</code> can be set.  This sets the dimensions
79   * of the interior of the contents area.  If the width is not set, ie it is set to Integer.MAX_VALUE or
80   * Integer.MIN_VALUE, then the <code>TabbedPane</code> will fill its containing component.  
81   * <p>
82   * Scrollbars can also be used within the <code>TabbedPane</code>.
83   * <p>
84   * The TabbedPane can also have a close icon on each of the tabs.  If this
85   * is pressed, then an ActionEvent is raised.  The DefaultCloseActionListener
86   * will close the "tab" that raised the event.  To use the tab closing functionality
87   * you will need to create a new DefaultCloseActionListener and attach it as
88   * well as set a close image into the TabbedPane.
89   * <p>
90   * @see echopoint.positionable.Scrollable for more information.
91   * @author Brad Baker 
92   */
93  
94  public class TabbedPane extends EchoPointComponent implements Scrollable {
95    
96    /**
97     * Class for default close action. The class implements an <code>ActionListener</code> that
98     * removed the tabs from the <code>TabbedPane</code> after clicking on the tab closeIcon
99     * 
100    * It it possible for this class to invoke another <code>ActionListener</code> before
101    * it removes the tabs from the <code>TabbedPane</code>
102    */  
103   public static class DefaultCloseActionListener implements ActionListener {
104     private ActionListener m_beforeListener;
105     
106     /**
107      * Constructs a DefaultCloseActionListener
108      */
109     public DefaultCloseActionListener() {
110       this(null);
111     }
112 
113     /**
114      * Constructs a DefaultCloseActionListener with an <code>ActionListener</code> that is invoked 
115      * before the tabs is removed from <code>TabbedPane</code>
116      * 
117      * @param before The <code>ActionListener</code> that is invoked before
118      */
119     public DefaultCloseActionListener(ActionListener before) {
120       m_beforeListener = before;
121     }
122     
123     /**
124      * Invoked when an close action occurs.
125      *
126      * @param e The event describing the close action. The actionCommand holds the tab index
127      */
128     public void actionPerformed(ActionEvent e) {
129       if(m_beforeListener != null)
130         m_beforeListener.actionPerformed(e);
131       
132       int tabidx = Integer.parseInt(e.getActionCommand());
133       TabbedPane src = (TabbedPane)e.getSource();
134       src.remove(tabidx);      
135     }    
136   };
137   
138 
139   /** 
140    * A style constant for the Border Color property. 
141    * Values of this key must be of type <code>nextapp.echo.Color.</code>
142    */
143   public static final String STYLE_BORDER_COLOR = "borderColor";
144   /** 
145    * A style constant for the Border Size property. 
146    * Values of this key must be of type <code>Integer.</code>
147    */
148   public static final String STYLE_BORDER_SIZE = "borderSize";
149 
150   /** 
151    * A style constant for the Icon Spacing property. 
152    * Values of this key must be of type <code>Integer.</code>
153    */
154   public static final String STYLE_ICON_SPACING = "iconSpacing";
155   /** 
156    * A style constant for the Insets property. 
157    * Values of this key must be of type <code>nextapp.echo.Insets.</code>
158    */
159   public static final String STYLE_INSETS = "insets";
160 
161   /** 
162    * A style constant for the Tab Insets property. 
163    * Values of this key must be of type <code>nextapp.echo.Insets.</code>
164    */
165   public static final String STYLE_TAB_INSETS = "tabInsets";
166 
167   /** 
168    * A style constant for the RollOver Background property. 
169    * Values of this key must be of type <code>nextapp.echo.Color.</code>
170    */
171   public static final String STYLE_ROLLOVER_BACKGROUND = "rollOverBackground";
172   /** 
173    * A style constant for the RollOver Foreground property. 
174    * Values of this key must be of type <code>nextapp.echo.Color.</code>
175    */
176   public static final String STYLE_ROLLOVER_FOREGROUND = "rollOverForeground";
177 
178   /** 
179    * A style constant for the Inactive Background property. 
180    * Values of this key must be of type <code>nextapp.echo.Color.</code>
181    */
182   public static final String STYLE_INACTIVE_BACKGROUND = "inactiveBackground";
183   /** 
184    * A style constant for the Inactive Foreground property. 
185    * Values of this key must be of type <code>nextapp.echo.Color.</code>
186    */
187   public static final String STYLE_INACTIVE_FOREGROUND = "inactiveForeground";
188   /** 
189    * A style constant for the Inactive RollOver Background property. 
190    * Values of this key must be of type <code>nextapp.echo.Color.</code>
191    */
192   public static final String STYLE_INACTIVE_ROLLOVER_BACKGROUND = "inactiveRollOverBackground";
193   /** 
194    * A style constant for the Inactive RollOver Foreground property. 
195    * Values of this key must be of type <code>nextapp.echo.Color.</code>
196    */
197   public static final String STYLE_INACTIVE_ROLLOVER_FOREGROUND = "inactiveRollOverForeground";
198   /** 
199    * A style constant for the Inactive Font property. 
200    * Values of this key must be of type <code>nextapp.echo.Font.</code>
201    */
202   public static final String STYLE_INACTIVE_FONT = "inactiveFont";
203   /** 
204    * A style constant for the Inactive Font property. 
205    * Values of this key must be of type <code>nextapp.echo.Font.</code>
206    */
207   public static final String STYLE_TAB_PLACEMENT = "tabPlacement";
208 
209   /** 
210    * A style constant for the Close Image property. 
211    * Values of this key must be of type <code>nextapp.ImageReference</code>
212    */
213   public static final String STYLE_CLOSE_IMAGE = "closeImage";
214   /** 
215    * A style constant for the Close ToolTip property. 
216    * Values of this key must be of type <code>String</code>
217    */
218   public static final String STYLE_CLOSE_TOOLTIP = "closeToolTip";
219 
220   /**
221    * Helper static SymbolicValue[] - tabPlacement - top and bottom  
222    */
223   public static SymbolicValue[] tabPlacementSymbolics  = {
224     new SymbolicIntegerValue(EchoConstants.TOP,"top"),
225     new SymbolicIntegerValue(EchoConstants.BOTTOM,"bottom"),
226   };
227 
228   /** 
229    * Nested public static StyleInfo class.  For more info:
230    * @see echopoint.stylesheet.StyleInfo 
231    */
232   public static class NestedStyleInfo implements StyleInfo {
233     private static StyleAttrDescriptor[] styleDescriptors = { 
234       new StyleAttrDescriptor(STYLE_BORDER_COLOR,Color.class,"borderColor"),
235       new StyleAttrDescriptor(STYLE_BORDER_SIZE,Integer.class,"borderSize"),
236       new StyleAttrDescriptor(STYLE_ICON_SPACING,Integer.class,"iconSpacing"),
237       new StyleAttrDescriptor(STYLE_INACTIVE_BACKGROUND,Color.class,"inactiveBackground"),
238       new StyleAttrDescriptor(STYLE_INACTIVE_FONT,Font.class,"inactiveFont"),
239       new StyleAttrDescriptor(STYLE_INACTIVE_FOREGROUND,Color.class,"inactiveForeground"),
240       new StyleAttrDescriptor(STYLE_INACTIVE_ROLLOVER_BACKGROUND,Color.class,"inactiveRollOverBackground"),
241       new StyleAttrDescriptor(STYLE_INACTIVE_ROLLOVER_FOREGROUND,Color.class,"inactiveRollOverForeground"),
242       new StyleAttrDescriptor(STYLE_INSETS,Insets.class,"insets"),
243       new StyleAttrDescriptor(STYLE_TAB_INSETS,Insets.class,"tabInsets"),
244       new StyleAttrDescriptor(STYLE_ROLLOVER_BACKGROUND,Color.class,"rollOverBackground"),
245       new StyleAttrDescriptor(STYLE_ROLLOVER_FOREGROUND,Color.class,"rollOverForeground"),
246       new StyleAttrDescriptor(STYLE_TAB_PLACEMENT,Integer.class,"tabPlacement",tabPlacementSymbolics),
247       new StyleAttrDescriptor(STYLE_CLOSE_IMAGE,ImageReference.class,"closeImage"),
248       new StyleAttrDescriptor(STYLE_CLOSE_TOOLTIP,String.class,"closeToolTip"),      
249     };
250     /**
251      * @see echopoint.stylesheet.StyleInfo#getStyleDescriptors()
252      */
253     public StyleAttrDescriptor[] getStyleDescriptors() {
254       return styleDescriptors;
255     }
256   }
257 
258   /** Property Chnage Names */
259   public static final String SELECTED_INDEX_CHANGED_PROPERTY = "selindex";
260   public static final String MODEL_CHANGED_PROPERTY = "model";
261 
262   public static final String TAB_REMOVED_PROPERTY = "tabRemove";
263   public static final String TAB_ADDED_PROPERTY = "tabAdded";
264   public static final String TAB_PLACEMENT_CHANGED_PROPERTY = "tabPlacement";
265 
266   public static final String BORDER_COLOR_CHANGED_PROPERTY = "borderColor";
267   public static final String BORDER_SIZE_CHANGED_PROPERTY = "borderSize";
268 
269   public static final String ROLLOVER_FOREGROUND_CHANGED_PROPERTY = "rollOverFore";
270   public static final String ROLLOVER_BACKGROUND_CHANGED_PROPERTY = "rollOverBack";
271 
272   public static final String INACTIVE_FOREGROUND_CHANGED_PROPERTY = "inactFore";
273   public static final String INACTIVE_BACKGROUND_CHANGED_PROPERTY = "inactBack";
274   public static final String INACTIVE_ROLLOVER_FOREGROUND_CHANGED_PROPERTY = "inactRollOverFore";
275   public static final String INACTIVE_ROLLOVER_BACKGROUND_CHANGED_PROPERTY = "inactRollOverBack";
276   public static final String INACTIVE_FONT_CHANGED_PROPERTY = "inactFont";
277 
278   public static final String INSETS_CHANGED_PROPERTY = "insets";
279   public static final String TAB_INSETS_CHANGED_PROPERTY = "tabInsets";
280   public static final String ICON_SPACING_CHANGED_PROPERTY = "iconSpacing";
281   public static final String TAB_SPACING_CHANGED_PROPERTY = "tabSpacing";
282 
283   public static final String TAB_ICON_CHANGED_PROPERTY = "tabIcon";
284   public static final String TAB_TITLE_CHANGED_PROPERTY = "tabTitle";
285   public static final String TAB_TIP_CHANGED_PROPERTY = "tabTip";
286   public static final String TAB_COMPONENT_CHANGED_PROPERTY = "tabComponent";
287 
288   public static final String RENDERING_CHANGED_PROPERTY = "rendering";
289   public static final String TAB_IMAGE_RENDERER_CHANGED_PROPERTY = "tabImageRenderer";
290 
291   public static final String SCROLLBAR_POLICY_CHANGED_PROPERTY = "scrollbarsPolicy";
292   public static final String WIDTH_CHANGED_PROPERTY = "width";
293   public static final String HEIGHT_CHANGED_PROPERTY = "height";
294   public static final String SCROLL_BAR_X_CHANGED_PROPERTY = "scrollbarX";
295   public static final String SCROLL_BAR_Y_CHANGED_PROPERTY = "scrollbarX";
296 
297   public static final String CLOSE_IMAGE_CHANGED_PROPERTY = "closeImage";
298   public static final String CLOSE_TOOLTIP_CHANGED_PROPERTY = "closeToolTip";
299 
300   //
301   // defaults colors and insets
302   //
303   public static final Insets DEFAULT_INSETS = new Insets(2);
304   public static final Insets DEFAULT_TAB_INSETS = new Insets(2);
305 
306   public final static Color DEFAULT_BACKGROUND = new Color(0xc0, 0xc0, 0xc0);
307   public final static Color DEFAULT_FOREGROUND = Color.BLACK;
308 
309   public final static Color DEFAULT_ROLLOVER_BACKGROUND = DEFAULT_BACKGROUND;
310   public final static Color DEFAULT_ROLLOVER_FOREGROUND = new Color(0x77, 0x88, 0x99); // light slate grey
311 
312   public final static Color DEFAULT_INACTIVE_BACKGROUND = new Color(0xe0, 0xe0, 0xe0);
313   public final static Color DEFAULT_INACTIVE_FOREGROUND = new Color(0x80, 0x80, 0x80);
314 
315   public final static Color DEFAULT_INACTIVE_ROLLOVER_BACKGROUND = DEFAULT_INACTIVE_BACKGROUND;
316   public final static Color DEFAULT_INACTIVE_ROLLOVER_FOREGROUND = new Color(0x00, 0x00, 0x5A);
317 
318   /**
319    * default close image
320    */
321   public static ImageReference DEFAULT_CLOSE_IMAGE = null;
322   static {
323     DEFAULT_CLOSE_IMAGE = new ResourceImageReference(ResourceNames.WINDOW_CLOSE, 17, 14);
324   }
325 
326   //
327   // we always have a border for tabs for starters!
328   private Color borderColor = Color.BLACK;
329   private int borderSize = 1;
330 
331   //
332   // our rollover colors
333   private Color rollOverForeground = DEFAULT_ROLLOVER_FOREGROUND;
334   private Color rollOverBackground = DEFAULT_ROLLOVER_BACKGROUND;
335 
336   //
337   // inactive tab colors.  By default they are null.
338   private Color inactiveForeground = DEFAULT_INACTIVE_FOREGROUND;
339   private Color inactiveBackground = DEFAULT_INACTIVE_BACKGROUND;
340   private Color inactiveRollOverForeground = DEFAULT_INACTIVE_ROLLOVER_FOREGROUND;
341   private Color inactiveRollOverBackground = DEFAULT_INACTIVE_ROLLOVER_BACKGROUND;
342   private Font inactiveFont = null;
343 
344   // the insets
345   private Insets insets = DEFAULT_INSETS;
346   private Insets tabInsets = DEFAULT_TAB_INSETS;
347 
348   //
349   // the spacing to between the tab icon and text
350   private int iconSpacing = 5;
351   private int tabSpacing = 3;
352   
353   //
354   // our image renderer is initially null
355   private TabImageRenderer tabImageRender = null;
356 
357   //
358   // contain where the tabs are placed
359   private int tabPlacement = EchoConstants.TOP;
360 
361   //
362   // our width and height
363   private int width = Integer.MAX_VALUE;
364   private int height = Integer.MAX_VALUE;
365   private int scrollBarPolicy = SCROLLBARS_NEVER;
366   
367   // closeImage
368   private ImageReference closeImage = null;
369   private String closeToolTip = "Close Tab";
370   
371   //
372   // the invisible component container
373   private DevNull invisibleContainer;
374   // 
375   // the visible component container
376   private Container visibleContainer;
377 
378   //
379   // contains our list of TabContents
380   private java.util.ArrayList tabList = new java.util.ArrayList();
381 
382   /**
383    * <code>TabEntry</code> is a simple class used to hold tab entrie
384    */
385   private class TabEntry implements Serializable {
386     private String tabTitle;
387     private ImageReference tabIcon;
388     private String tabTipText;
389     private Component tabComponent;
390     private int scrollBarX = 0;
391     private int scrollBarY = 0;
392   };
393 
394   //
395   // our model
396   private SingleSelectionModel model;
397   
398   /**
399    * Constructs a TabbedPane with the tab placement as <code>EchoConstants.TOP</code>
400    * and the specified TabImageRenderer.
401    * <p>
402    * If the TabImageRenderer is non null then the borders will be removed 
403    * and the tab insets will be set to zero.  This is usually the appearance 
404    * you will want.
405    * 
406    */
407   public TabbedPane(TabImageRenderer renderer) {
408     this(EchoConstants.TOP,renderer);
409   }
410 
411   /**
412    * Constructs a TabbedPane with the tab placement as <code>EchoConstants.TOP</code>
413    */
414   public TabbedPane() {
415     this(EchoConstants.TOP);
416   }
417   
418   /**
419    * Constructs a new TabbedPane
420    * <br>
421    * @param tabPlacement  the tab placement of the tabbed pane,
422    *        can be one of the following values.
423    *        <ul>
424    *        <li>EchoConstants.TOP (the default)</li>
425    *        <li>EchoConstants.BOTTOM</li>
426    *        </ul>
427    */
428   public TabbedPane(int tabPlacement) {
429     this(tabPlacement,null);
430   }  
431   /**
432    * Constructs a new TabbedPane.  
433    * <p>
434    * If the TabImageRenderer is
435    * non null then the borders will be removed and the tab
436    * insets will be set to zero.  This is usually the appearance 
437    * you will want.
438    * <br>
439    * @param tabPlacement  the tab placement of the tabbed pane,
440    *        can be one of the following values.
441    *        <ul>
442    *        <li>EchoConstants.TOP (the default)</li>
443    *        <li>EchoConstants.BOTTOM</li>
444    *        </ul>
445    * @param renderer - the TabImageRenderer to use
446    */
447   public TabbedPane(int tabPlacement, TabImageRenderer renderer) {
448     super();
449     
450     invisibleContainer = new DevNull();
451     super.add(invisibleContainer,-1);
452     
453     visibleContainer = new Container();
454     super.add(visibleContainer,-1);
455     
456     setTabPlacement(tabPlacement);
457     setBackground(DEFAULT_BACKGROUND);
458     setForeground(DEFAULT_FOREGROUND);
459 
460     setModel(new DefaultSingleSelectionModel());
461     
462     setTabImageRender(renderer);
463     if (renderer != null) {
464       setTabInsets(new Insets(0));
465       setBorderSize(0);
466       setBorderColor(null);
467     }
468     
469   }
470 
471   /**
472    * Adds an ActionListener to the TabbedPane.  It will be informed
473    * if the Tabs have close icons and the use has asked to
474    * close the tab.
475    *  
476    * @param l - a new ActionListener
477    */  
478   public void addActionListener(ActionListener l) {
479     listenerList.addListener(ActionListener.class, l);
480   }  
481 
482   /**
483    * Removes an ActionListener to the TabbedPane.  
484    *  
485    * @param l - a ActionListener to remove
486    */  
487   public void removeActionListener(ActionListener l) {
488     listenerList.removeListener(ActionListener.class, l);
489   }  
490   
491   /**
492    * Notifies all listeners that have registered for this event type.
493    *
494    * @param e The <code>ActionEvent</code> to send.
495    */
496   public void fireActionPerformed(ActionEvent e) {
497     EventListener[] listeners = listenerList.getListeners(ActionListener.class);
498     for (int index = 0; index < listeners.length; ++index) {
499       ((ActionListener) listeners[index]).actionPerformed(e);
500     }
501   }
502   
503   /**
504    * Adds a component to the <code>TabbedPane</code>.  
505    * <p>
506    * <i>Cover method for insertTab</i>
507    *
508    */
509   public void add(String tabTitle, Component component) {
510     addTab(tabTitle, null, component, null);
511   }
512   
513   /**
514    * Adds a component to the <code>TabbedPane</code>
515    * <p>
516    * <i>Cover method for insertTab</i>
517    *
518    */
519   public void add(String tabTitle, ImageReference tabIcon, Component component) {
520     addTab(tabTitle, tabIcon, component, null);
521   }
522   /**
523    * Adds a component to the <code>TabbedPane</code>
524    * <p>
525    * <i>Cover method for insertTab</i>
526    *
527    */
528   public void add(String tabTitle, ImageReference tabIcon, Component component, String tabToolTip) {
529     insertTab(tabTitle, tabIcon, component, tabToolTip, tabList.size());
530   }
531   /**
532    * Adds a component to the <code>TabbedPane</code> with an empty title.  
533    * <p>
534    * <i>Cover method for insertTab</i>
535    *
536    */
537   public void add(Component component) {
538     insertTab(null,null,component,null,tabList.size());
539   }
540   /**
541    * Adds a component to the <code>TabbedPane</code> with an empty title.
542    * at the specified index.
543    * <p>
544    * <i>Cover method for insertTab</i>
545    *
546    */
547   public void add(Component component, int index) {
548     insertTab("", null, component, null, index);
549   }
550   /**
551    * Adds a <code>ChangeListener</code> to the tabbed pane.
552    *
553    * @param l The <code>ChangeListener</code> to be added.
554    */
555   public void addChangeListener(ChangeListener l) {
556     model.addChangeListener(l);
557   }
558   /**
559    * Adds a component to the <code>TabbedPane</code>.  
560    * <i>Cover method for insertTab</i>
561    *
562    */
563   public void addTab(String tabTitle, Component component) {
564     addTab(tabTitle, null, component, null);
565   }
566   
567   /**
568    * Adds a component to the <code>TabbedPane</code>.  
569    * <i>Cover method for insertTab</i>
570    *
571    */
572   public void addTab(ImageReference tabIcon, Component component) {
573     addTab(null, tabIcon, component, null);
574   }
575   
576   /**
577    * Adds a component to the <code>TabbedPane</code>
578    * <i>Cover method for insertTab</i>
579    *
580    */
581   public void addTab(String tabTitle, ImageReference tabIcon, Component component) {
582     addTab(tabTitle, tabIcon, component, null);
583   }
584   /**
585    * Adds a component to the <code>TabbedPane</code>
586    * <i>Cover method for insertTab</i>
587    *
588    */
589   public void addTab(String tabTitle, ImageReference tabIcon, Component component, String tabToolTip) {
590     insertTab(tabTitle, tabIcon, component, tabToolTip, tabList.size());
591   }
592   /**
593    * Applies the provided style to the component.  The base <code>nextapp.echo.Component</code>
594    * style names can be used as well.
595    */
596   public void applyStyle(Style style) {
597     super.applyStyle(style);
598 
599     if (style.hasAttribute(STYLE_BORDER_COLOR)) {
600       setBorderColor((Color) style.getAttribute(STYLE_BORDER_COLOR));
601     }
602     if (style.hasAttribute(STYLE_BORDER_SIZE)) {
603       setBorderSize(style.getIntegerAttribute(STYLE_BORDER_SIZE));
604     }
605 
606     if (style.hasAttribute(STYLE_ICON_SPACING)) {
607       setIconSpacing(style.getIntegerAttribute(STYLE_ICON_SPACING));
608     }
609 
610     if (style.hasAttribute(STYLE_ROLLOVER_BACKGROUND)) {
611       setRollOverBackground((Color) style.getAttribute(STYLE_ROLLOVER_BACKGROUND));
612     }
613     if (style.hasAttribute(STYLE_ROLLOVER_FOREGROUND)) {
614       setRollOverForeground((Color) style.getAttribute(STYLE_ROLLOVER_FOREGROUND));
615     }
616 
617     if (style.hasAttribute(STYLE_INACTIVE_BACKGROUND)) {
618       setInactiveBackground((Color) style.getAttribute(STYLE_INACTIVE_BACKGROUND));
619     }
620     if (style.hasAttribute(STYLE_INACTIVE_FOREGROUND)) {
621       setInactiveForeground((Color) style.getAttribute(STYLE_INACTIVE_FOREGROUND));
622     }
623     if (style.hasAttribute(STYLE_INACTIVE_ROLLOVER_BACKGROUND)) {
624       setInactiveRollOverBackground((Color) style.getAttribute(STYLE_INACTIVE_ROLLOVER_BACKGROUND));
625     }
626     if (style.hasAttribute(STYLE_INACTIVE_ROLLOVER_FOREGROUND)) {
627       setInactiveRollOverForeground((Color) style.getAttribute(STYLE_INACTIVE_ROLLOVER_FOREGROUND));
628     }
629     if (style.hasAttribute(STYLE_INACTIVE_FONT)) {
630       setInactiveFont((Font) style.getAttribute(STYLE_INACTIVE_FONT));
631     }
632 
633     if (style.hasAttribute(STYLE_TAB_PLACEMENT))
634       setTabPlacement(style.getIntegerAttribute(STYLE_TAB_PLACEMENT));
635 
636     if (style.hasAttribute(STYLE_INSETS)) {
637       setInsets((Insets) style.getAttribute(STYLE_INSETS));
638     }
639     if (style.hasAttribute(STYLE_TAB_INSETS)) {
640       setTabInsets((Insets) style.getAttribute(STYLE_TAB_INSETS));
641     }
642 
643     if (style.hasAttribute(STYLE_SCROLL_BAR_POLICY))
644       setScrollBarPolicy(style.getIntegerAttribute(STYLE_SCROLL_BAR_POLICY));
645 
646     if (style.hasAttribute(STYLE_HEIGHT))
647       setHeight(style.getIntegerAttribute(STYLE_HEIGHT));
648 
649     if (style.hasAttribute(STYLE_WIDTH))
650       setWidth(style.getIntegerAttribute(STYLE_WIDTH));
651 
652     if (style.hasAttribute(STYLE_CLOSE_IMAGE)) 
653       setCloseImage((ImageReference) style.getAttribute(STYLE_CLOSE_IMAGE));
654 
655     if (style.hasAttribute(STYLE_CLOSE_TOOLTIP)) 
656       setCloseToolTip(style.getStringAttribute(STYLE_CLOSE_TOOLTIP));
657 
658   }
659   /**
660    * @return The <code>Color</code> of the <code>TabbedPane's</code> border.
661    */
662   public Color getBorderColor() {
663     return borderColor;
664   }
665   /**
666    * @return The size of the <code>TabbedPane's</code> border.
667    */
668   public int getBorderSize() {
669     return borderSize;
670   }
671   /**
672    * @return The <code>Component</code> of the tab at the specified index.
673    */
674   public Component getComponentAt(int index) {
675     TabEntry te = getTabEntryAt(index);
676     return (te != null) ? te.tabComponent : null;
677   }
678   /**
679    * Returns the number of tabs within the <code>TabbedPane</code>.
680    */
681   public int getCount() {
682     return getTabCount();
683   }
684   /**
685    * Returns the height of the <code>WizardPane</code>.  If this value
686    * is -1, then no height will be used.
687    */
688   public int getHeight() {
689     return height;
690   }
691   /**
692    * @return The <code>ImageReference</code> incon of the tab at the specified index.
693    */
694   public ImageReference getIconAt(int index) {
695     TabEntry te = getTabEntryAt(index);
696     return (te != null) ? te.tabIcon : null;
697   }
698   /**
699    * @return The icon spacing of the <code>TabbedPane</code>
700    */
701   public int getIconSpacing() {
702     return iconSpacing;
703   }
704   /**
705    * @return the background <code>Color</code> of the inactive tabs
706    */
707   public Color getInactiveBackground() {
708     return inactiveBackground;
709   }
710   /**
711    * @return the <code>Font</code> of the inactive tabs
712    */
713   public Font getInactiveFont() {
714     return inactiveFont;
715   }
716   /**
717    * @return the foreground <code>Color</code> of the inactive tabs
718    */
719   public Color getInactiveForeground() {
720     return inactiveForeground;
721   }
722   /**
723    * @return the rollover background <code>Color</code> of the inactive tabs
724    */
725   public Color getInactiveRollOverBackground() {
726     return inactiveRollOverBackground;
727   }
728   /**
729    * @return the rollover foreground <code>Color</code> of the inactive tabs
730    */
731   public Color getInactiveRollOverForeground() {
732     return inactiveRollOverForeground;
733   }
734   /** 
735   * Returns the insets (margins) of the tabbed pane contents.
736   *
737   * @return The insets of the tabbed pane.
738   */
739   public Insets getInsets() {
740     return insets;
741   }
742   /**
743    * Returns the model associated with this <code>TabbedPane</code>.
744    *
745    */
746   public SingleSelectionModel getModel() {
747     return model;
748   }
749   /**
750    * @return the rollover background <code>Color</code> of the tabs
751    */
752   public Color getRollOverBackground() {
753     return rollOverBackground;
754   }
755   /**
756    * @return the rollover foreground <code>Color</code> of the tabs
757    */
758   public Color getRollOverForeground() {
759     return rollOverForeground;
760   }
761   /**
762    * Returns the ScrollBarPolicy in place
763    * 
764    * This can be one of :
765    * <ul>
766    * <li>SCOLLBARS_NONE</li>
767    * <li>SCOLLBARS_ALWAYS</li>
768    * <li>SCOLLBARS_AUTO</li>
769    * </ul>
770    */
771   public int getScrollBarPolicy() {
772     return scrollBarPolicy;
773   }
774   /**
775    * Returns the position of the horizontal scroll bar, in pixels offset from 
776    * the left of the component.
777    *
778    * @return The position of the horizontal scroll bar.
779    */
780   public int getScrollBarX() {
781     TabEntry entry = getTabEntryAt(getSelectedIndex());
782     if (entry == null)
783       return 0;
784     return entry.scrollBarX;
785   }
786   /**
787    * Returns the position of the vertical scroll bar, in pixels offset from 
788    * the top the component.
789    *
790    * @return The position of the vertical scroll bar.
791    */
792   public int getScrollBarY() {
793     TabEntry entry = getTabEntryAt(getSelectedIndex());
794     if (entry == null)
795       return 0;
796     return entry.scrollBarY;
797   }
798   /**
799    * @return the <code>Component</code> at the currently selected index or null if
800    * no tab is currently selected.
801    */
802   public Component getSelectedComponent() {
803     int index = model.getSelectedIndex();
804     if (index < 0)
805       return null;
806     return getComponentAt(index);
807   }
808   /**
809    * Returns the currently selected tab index or -1 if none is selected
810    */
811   public int getSelectedIndex() {
812     return model.getSelectedIndex();
813   }
814   /**
815    * Returns the number of tabs within the <code>TabbedPane</code>.
816    */
817   public int getTabCount() {
818     return tabList.size();
819   }
820   /**
821    * Returns the tab entry at a specified index.  Returns null if the
822    * index is out of range.
823    *
824    */
825   private TabEntry getTabEntryAt(int index) {
826     if (index < 0 || index >= tabList.size())
827       return null;
828 
829     TabEntry te = (TabEntry) tabList.get(index);
830 
831     return te;
832   }
833   /**
834    * @return The tab placement of the <code>TabbedPane</code>
835    *
836    */
837   public int getTabPlacement() {
838     return tabPlacement;
839   }
840   /**
841    * @return The title of the tab at the specified index.
842    */
843   public String getTitleAt(int index) {
844     TabEntry te = getTabEntryAt(index);
845     return (te != null) ? te.tabTitle : null;
846   }
847   /**
848    * @return The tool tip of the tab at the specified index.
849    */
850   public String getToolTipAt(int index) {
851     TabEntry te = getTabEntryAt(index);
852     return (te != null) ? te.tabTipText : null;
853   }
854   /**
855    * Returns the width of the <code>WizardPane</code>.  If this value
856    * is -1, then no width will be used.
857    */
858   public int getWidth() {
859     return width;
860   }
861   /**
862    * Returns the index of the given <code>Component</code> or -1 if it is not found
863    */
864   public int indexOfComponent(Component c) {
865     for (int i = 0; i < tabList.size(); i++) {
866       TabEntry te = getTabEntryAt(i);
867       if (te.tabComponent == c)
868         return i;
869     }
870     return -1;
871   }
872   /**
873    * Returns the index of the tab with the given title or -1 if it is not found
874    */
875   public int indexOfTab(String tabTitle) {
876     for (int i = 0; i < tabList.size(); i++) {
877       TabEntry te = getTabEntryAt(i);
878       if (te.tabTitle.equals(tabTitle))
879         return i;
880     }
881     return -1;
882   }
883   /**
884    * Returns the index of the tab with the given <code>ImageReference </code> 
885    * icon or -1 if it is not found
886    */
887   public int indexOfTab(ImageReference icon) {
888     for (int i = 0; i < tabList.size(); i++) {
889       TabEntry te = getTabEntryAt(i);
890       if (te.tabIcon == icon)
891         return i;
892     }
893     return -1;
894   }
895   
896   /**
897    * Returns the index of the specified Component or -1 if it
898    * cannot be found. 
899    * @param component - the component to search for
900    * @return - the index where ther component occurs or -1 if it cannot be found
901    */
902   public int getTabIndex(Component component) {
903     int index = 0;
904     for (Iterator iter = tabList.iterator(); iter.hasNext(); ){
905       TabEntry entry = (TabEntry)iter.next();
906       if (entry.tabComponent == component)
907         return index;
908       ++index;
909     }
910     return -1;
911   }
912   
913   /**
914    * This will set the specified Component as the selected tab.
915    *  
916    * @param component - the component to search for 
917    * @throws NoSuchElementException if the Component cannnot be found
918    */
919   public void setSelected(Component component) throws NoSuchElementException {
920     int index = getTabIndex(component);
921     if (index < 0)
922       throw new NoSuchElementException("Tab component not found");
923     setSelectedIndex(index);
924   }
925   
926   /**
927    * Insert a tab at the specified index.  
928    */
929   public void insertTab(String tabTitle, ImageReference tabIcon, Component component, String tabToolTip, int index) {
930 
931     if (index < 0)
932       index = 0;
933 
934     if (tabTitle == null && tabIcon == null)
935       tabTitle = "Tab " + index;
936 
937     TabEntry tc = new TabEntry();
938     tc.tabTitle = tabTitle;
939     tc.tabIcon = tabIcon;
940     tc.tabTipText = tabToolTip;
941     tc.tabComponent = component;
942 
943     int newIndex = -1;
944     if (index >= tabList.size()) {
945       tabList.add(tc);
946       newIndex = tabList.size() - 1;
947     } else {
948       tabList.add(index, tc);
949       newIndex = index;
950     }
951 
952     //
953     // we always have a selected Index if we have some entries
954     if (getSelectedIndex() == -1)
955       setSelectedIndex(newIndex);
956 
957     reArrangeVisibleComponents(null);
958 
959     //
960     // fire the icon property change to get the image handlers in place
961     firePropertyChange(TAB_ICON_CHANGED_PROPERTY, -1, newIndex);
962 
963     //
964     // an one for any one interested
965     firePropertyChange(TAB_ADDED_PROPERTY, -1, newIndex);
966   }
967   /**
968    * Removes a tab which corresponds to the index
969    */
970   public void remove(int index) {
971     removeTabAt(index);
972   }
973   /**
974    * Removes a tab which corresponds to the Component c.
975    */
976   public void remove(Component c) {
977     for (int i = getTabCount() - 1; i >= 0; i--) {
978 
979       TabEntry te = getTabEntryAt(i);
980       if (te == null)
981         continue;
982 
983       if (te.tabComponent == c) {
984         removeTabAt(i);
985       }
986     }
987   }
988   /**
989    * Removes all tabs entries.
990    */
991   public void removeAll() {
992     for (int i = getTabCount() - 1; i >= 0; i--) {
993       removeTabAt(i);
994     }
995   }
996   /**
997    * Removes a ChangeListener from this component.
998    *
999    * @param l the ChangeListener to remove
1000   *
1001   */
1002  public void removeChangeListener(ChangeListener l) {
1003    model.removeChangeListener(l);
1004  }
1005  /**
1006   * Removes a tab from the tabbed pane at the specified index.
1007   */
1008  public void removeTabAt(int index) {
1009    TabEntry te = getTabEntryAt(index);
1010    if (te == null)
1011      return;
1012
1013    tabList.remove(index);
1014
1015    int newIndex = index - 1;
1016    if (newIndex < 0)
1017      newIndex = 0;
1018
1019    if (tabList.size() == 0)
1020      newIndex = -1;
1021
1022    reArrangeVisibleComponents(te.tabComponent);
1023
1024    firePropertyChange(TAB_REMOVED_PROPERTY, -1, index);
1025
1026    setSelectedIndex(newIndex);
1027  }
1028
1029  
1030  /**
1031   * Called to rearrange the components inside the TabbedPane
1032   * It moves the currently selected component into the visible
1033   * container and the rest into the invisible bucket.  This 
1034   * ensures that they get no rendering peers and hence
1035   * this is more efficient. 
1036   * 
1037   * @param removedComponent - an optinal component that has been removed
1038   */
1039  private void reArrangeVisibleComponents(Component removedComponent) {
1040    
1041    Component selectedC = getSelectedComponent();
1042    for (int i = 0; i < getCount(); i++) {
1043      Component c = getComponentAt(i);
1044      if (c == selectedC) {
1045        if (! visibleContainer.isAncestorOf(c))
1046          visibleContainer.add(c);
1047      } else {
1048        if (! invisibleContainer.isAncestorOf(c))
1049          invisibleContainer.add(c);
1050      }
1051    }
1052    if (visibleContainer.isAncestorOf(removedComponent))
1053      visibleContainer.remove(removedComponent);
1054    else if (invisibleContainer.isAncestorOf(removedComponent))
1055      invisibleContainer.remove(removedComponent);
1056  }
1057  
1058  /**
1059   * Sets the border Color of the <code>TabbedPane</code>
1060   * <br>
1061   * This methods fires a <code>PropertyChangeEvent</code> with a
1062   * <code>getPropertyName()</code> value of 
1063   * <code>TabbedPane.BORDER_COLOR_CHANGED_PROPERTY</code>
1064   *
1065   */
1066  public void setBorderColor(nextapp.echo.Color newBorderColor) {
1067    Color oldValue = borderColor;
1068    borderColor = newBorderColor;
1069    firePropertyChange(BORDER_COLOR_CHANGED_PROPERTY, oldValue, newBorderColor);
1070  }
1071  /**
1072   * Sets the border size of the <code>TabbedPane</code>
1073   * <br>
1074   * This methods fires a <code>PropertyChangeEvent</code> with a
1075   * <code>getPropertyName()</code> value of 
1076   * <code>TabbedPane.BORDER_SIZE_CHANGED_PROPERTY</code>
1077   *
1078   */
1079  public void setBorderSize(int newBorderSize) {
1080    int oldValue = borderSize;
1081    borderSize = newBorderSize;
1082    firePropertyChange(BORDER_SIZE_CHANGED_PROPERTY, oldValue, newBorderSize);
1083  }
1084
1085  /**
1086   * Sets the <code>Component</code> at the specified index
1087   * <br>
1088   * This methods fires a <code>PropertyChangeEvent</code> with a
1089   * <code>getPropertyName()</code> value of 
1090   * <code>TabbedPane.TAB_COMPONENT_CHANGED_PROPERTY</code>
1091   *
1092   */
1093  public void setComponentAt(int index, Component component) {
1094
1095    TabEntry te = getTabEntryAt(index);
1096    if (te == null)
1097      return;
1098
1099    Component oldValue = te.tabComponent;
1100
1101    te.tabComponent = component;
1102
1103    firePropertyChange(TAB_COMPONENT_CHANGED_PROPERTY, oldValue, component);
1104  }
1105  /**
1106   * Sets the height of the <code>TabbedPane</code>.  If this
1107   * value is -1, then no height will be used.
1108   * <p>
1109   * Note that this is the height of the contents of the TabbedPane
1110   * not the outside of the TabbedPane.  This allows scrolling within
1111   * the contents of the TabbedPane.
1112   * <p>
1113   * This methods fires a <code>PropertyChangeEvent</code> with a
1114   * <code>getPropertyName()</code> value of 
1115   * <code>TabbedPane.HEIGHT_CHANGED_PROPERTY</code>
1116   *
1117   */
1118  public void setHeight(int newValue) {
1119    int oldValue = height;
1120    height = newValue;
1121    firePropertyChange(HEIGHT_CHANGED_PROPERTY, oldValue, newValue);
1122  }
1123  /**
1124   * Sets the <code>ImageReference</code> icon at the specified index
1125   * <br>
1126   * This methods fires a <code>PropertyChangeEvent</code> with a
1127   * <code>getPropertyName()</code> value of 
1128   * <code>TabbedPane.TAB_ICON_CHANGED_PROPERTY</code>
1129   *
1130   */
1131  public void setIconAt(int index, ImageReference newImageRef) {
1132
1133    TabEntry te = getTabEntryAt(index);
1134    if (te == null)
1135      return;
1136
1137    te.tabIcon = newImageRef;
1138
1139    //
1140    // note here that we send down the index of the changed tab icon
1141    // not the image itself.
1142    firePropertyChange(TAB_ICON_CHANGED_PROPERTY, -1, index);
1143  }
1144  /**
1145   * Sets the icon spacing of the <code>TabbedPane</code>
1146   * <br>
1147   * This methods fires a <code>PropertyChangeEvent</code> with a
1148   * <code>getPropertyName()</code> value of 
1149   * <code>TabbedPane.ICON_SPACING_CHANGED_PROPERTY</code>
1150   * 
1151   */
1152  public void setIconSpacing(int newIconSpacing) {
1153    int oldValue = iconSpacing;
1154    iconSpacing = newIconSpacing;
1155    firePropertyChange(ICON_SPACING_CHANGED_PROPERTY, oldValue, newIconSpacing);
1156  }
1157  /**
1158   * Sets the background <code>Color</code> of the <code>TabbedPane's</code> inactive tabs.
1159   * <br>
1160   * This methods fires a <code>PropertyChangeEvent</code> with a
1161   * <code>getPropertyName()</code> value of 
1162   * <code>TabbedPane.INACTIVE_BACKGROUND_CHANGED_PROPERTY</code>
1163   *
1164   */
1165  public void setInactiveBackground(Color newInactiveBackground) {
1166    Color oldValue = inactiveBackground;
1167    inactiveBackground = newInactiveBackground;
1168    firePropertyChange(INACTIVE_BACKGROUND_CHANGED_PROPERTY, oldValue, newInactiveBackground);
1169  }
1170  /**
1171   * Sets the <code>Font</code> of the <code>TabbedPane's</code> inactive tabs.
1172   * <br>
1173   * This methods fires a <code>PropertyChangeEvent</code> with a
1174   * <code>getPropertyName()</code> value of 
1175   * <code>TabbedPane.INACTIVE_FONT_CHANGED_PROPERTY</code>
1176   *
1177   */
1178  public void setInactiveFont(Font newInactiveFont) {
1179    Font oldValue = inactiveFont;
1180    inactiveFont = newInactiveFont;
1181    firePropertyChange(INACTIVE_FONT_CHANGED_PROPERTY, oldValue, newInactiveFont);
1182  }
1183  /**
1184   * Sets the foreground <code>Color</code> of the <code>TabbedPane's</code> inactive tabs.
1185   * <br>
1186   * This methods fires a <code>PropertyChangeEvent</code> with a
1187   * <code>getPropertyName()</code> value of 
1188   * <code>TabbedPane.INACTIVE_BACKGROUND_CHANGED_PROPERTY</code>
1189   *
1190   */
1191  public void setInactiveForeground(Color newInactiveForeground) {
1192    Color oldValue = inactiveForeground;
1193    inactiveForeground = newInactiveForeground;
1194    firePropertyChange(INACTIVE_BACKGROUND_CHANGED_PROPERTY, oldValue, newInactiveForeground);
1195  }
1196  /**
1197   * Sets the rollover background <code>Color</code> of the <code>TabbedPane's</code> inactive tabs.
1198   * <br>
1199   * This methods fires a <code>PropertyChangeEvent</code> with a
1200   * <code>getPropertyName()</code> value of 
1201   * <code>TabbedPane.INACTIVE_ROLLOVER_BACKGROUND_CHANGED_PROPERTY</code>
1202   *
1203   */
1204  public void setInactiveRollOverBackground(Color newInactiveRollOverBackground) {
1205    Color oldValue = inactiveRollOverBackground;
1206    inactiveRollOverBackground = newInactiveRollOverBackground;
1207    firePropertyChange(INACTIVE_ROLLOVER_BACKGROUND_CHANGED_PROPERTY, oldValue, newInactiveRollOverBackground);
1208  }
1209  /**
1210   * Sets the rollover foreground <code>Color</code> of the <code>TabbedPane's</code> inactive tabs.
1211   * <br>
1212   * This methods fires a <code>PropertyChangeEvent</code> with a
1213   * <code>getPropertyName()</code> value of 
1214   * <code>TabbedPane.INACTIVE_ROLLOVER_BACKGROUND_CHANGED_PROPERTY</code>
1215   *
1216   */
1217  public void setInactiveRollOverForeground(Color newInactiveRollOverForeground) {
1218    Color oldValue = inactiveRollOverForeground;
1219    inactiveRollOverForeground = newInactiveRollOverForeground;
1220    firePropertyChange(INACTIVE_ROLLOVER_BACKGROUND_CHANGED_PROPERTY, oldValue, newInactiveRollOverForeground);
1221  }
1222  /**
1223  * Sets the insets (margins) of the <code>TabbedPane</code>
1224  *
1225  * @param newValue An insets object that specifies the size of each margin 
1226  *        of this <code>TabbedPane</code>
1227  */
1228  public void setInsets(Insets newValue) {
1229    Insets oldValue = insets;
1230    insets = newValue;
1231    firePropertyChange(INSETS_CHANGED_PROPERTY, oldValue, newValue);
1232  }
1233  /**
1234   * Sets the model to be used with this <code>TabbedPane</code>
1235   *.
1236   * @param model the model to be used
1237   *
1238   */
1239  public void setModel(SingleSelectionModel model) {
1240    SingleSelectionModel oldModel = getModel();
1241    this.model = model;
1242    firePropertyChange(MODEL_CHANGED_PROPERTY, oldModel, model);
1243  }
1244  /**
1245   * Sets the rollover background <code>Color</code> of the <code>TabbedPane's</code> tabs.
1246   * <br>
1247   * This methods fires a <code>PropertyChangeEvent</code> with a
1248   * <code>getPropertyName()</code> value of 
1249   * <code>TabbedPane.ROLLOVER_BACKGROUND_CHANGED_PROPERTY</code>
1250   *
1251   */
1252  public void setRollOverBackground(Color newRollOverBackground) {
1253    Color oldValue = rollOverBackground;
1254    rollOverBackground = newRollOverBackground;
1255    firePropertyChange(ROLLOVER_BACKGROUND_CHANGED_PROPERTY, oldValue, newRollOverBackground);
1256  }
1257  /**
1258   * Sets the rollover foreground <code>Color</code> of the <code>TabbedPane's</code> tabs.
1259   * <br>
1260   * This methods fires a <code>PropertyChangeEvent</code> with a
1261   * <code>getPropertyName()</code> value of 
1262   * <code>TabbedPane.ROLLOVER_BACKGROUND_CHANGED_PROPERTY</code>
1263   *
1264   */
1265  public void setRollOverForeground(Color newRollOverForeground) {
1266    Color oldValue = rollOverForeground;
1267    rollOverForeground = newRollOverForeground;
1268    firePropertyChange(ROLLOVER_BACKGROUND_CHANGED_PROPERTY, oldValue, newRollOverForeground);
1269  }
1270  /**
1271   * This sets the scroll bar policy to use.
1272   * 
1273   * This can be one of :
1274   * <ul>
1275   * <li>SCOLLBARS_NONE</li>
1276   * <li>SCOLLBARS_ALWAYS</li>
1277   * <li>SCOLLBARS_AUTO</li>
1278   * </ul>
1279   *
1280   */
1281  public void setScrollBarPolicy(int newScrollBarPolicy) {
1282    int oldValue = scrollBarPolicy;
1283    scrollBarPolicy = newScrollBarPolicy;
1284    firePropertyChange(SCROLLBAR_POLICY_CHANGED_PROPERTY, oldValue, newScrollBarPolicy);
1285  }
1286  /**
1287   * Sets the position of the horizontal scroll bar, in pixels offset from 
1288   * the left of the component.
1289   *
1290   * @param newValue The new position of the horizontal scroll bar, in pixels.
1291   */
1292  public void setScrollBarX(int newValue) {
1293    TabEntry entry = getTabEntryAt(getSelectedIndex());
1294    if (entry == null)
1295      return;
1296
1297    int oldValue = entry.scrollBarX;
1298    entry.scrollBarX = newValue;
1299    firePropertyChange(SCROLL_BAR_X_CHANGED_PROPERTY, oldValue, newValue);
1300  }
1301  /**
1302   * Sets the position of the vertical scroll bar, in pixels offset from 
1303   * the top of the component.
1304   *
1305   * @param newValue The new position of the vertical scroll bar, in pixels.
1306   */
1307  public void setScrollBarY(int newValue) {
1308    TabEntry entry = getTabEntryAt(getSelectedIndex());
1309    if (entry == null)
1310      return;
1311
1312    int oldValue = entry.scrollBarY;
1313    entry.scrollBarY = newValue;
1314    firePropertyChange(SCROLL_BAR_Y_CHANGED_PROPERTY, oldValue, newValue);
1315  }
1316  /**
1317   * Sets the selected tab of the <code>TabbedPane</code>.
1318   */
1319  public void setSelectedIndex(int index) {
1320    model.setSelectedIndex(index);
1321  }
1322  /** 
1323   * Sets the tab placement of the <code>TabbedPane</code>
1324   *
1325   * @param newTabPlacement the tab placement of the tabbed pane,
1326   *        can be one of the following values.
1327   *        <ul>
1328   *        <li>EchoConstants.TOP (the default)</li>
1329   *        <li>EchoConstants.BOTTOM</li>
1330   *        </ul>
1331   */
1332  public void setTabPlacement(int newTabPlacement) {
1333    int oldValue = tabPlacement;
1334    tabPlacement = newTabPlacement;
1335    firePropertyChange(TAB_PLACEMENT_CHANGED_PROPERTY, oldValue, newTabPlacement);
1336  }
1337  /**
1338   * Sets the title at the specified index
1339   * <br>
1340   * This methods fires a <code>PropertyChangeEvent</code> wi