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