KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > nextapp > echo2 > app > Component


1 /*
2  * This file is part of the Echo Web Application Framework (hereinafter "Echo").
3  * Copyright (C) 2002-2005 NextApp, Inc.
4  *
5  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * Alternatively, the contents of this file may be used under the terms of
18  * either the GNU General Public License Version 2 or later (the "GPL"), or
19  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20  * in which case the provisions of the GPL or the LGPL are applicable instead
21  * of those above. If you wish to allow use of your version of this file only
22  * under the terms of either the GPL or the LGPL, and not to allow others to
23  * use your version of this file under the terms of the MPL, indicate your
24  * decision by deleting the provisions above and replace them with the notice
25  * and other provisions required by the GPL or the LGPL. If you do not delete
26  * the provisions above, a recipient may use your version of this file under
27  * the terms of any one of the MPL, the GPL or the LGPL.
28  */

29
30 package nextapp.echo2.app;
31
32 import java.beans.PropertyChangeListener JavaDoc;
33 import java.beans.PropertyChangeSupport JavaDoc;
34 import java.io.Serializable JavaDoc;
35 import java.util.ArrayList JavaDoc;
36 import java.util.Iterator JavaDoc;
37 import java.util.List JavaDoc;
38 import java.util.Locale JavaDoc;
39
40 import nextapp.echo2.app.event.EventListenerList;
41
42 /**
43  * A representation of an Echo component. This is an abstract base class from
44  * which all Echo components are derived.
45  * <p>
46  * A hierarchy of <code>Component</code> objects is used to represent the
47  * state of an application's user interface. A <code>Component</code> may have
48  * a single parent <code>Component</code> and may contain zero or more child
49  * <code>Component</code>s. Certain <code>Component</code>s may limit the
50  * number or type(s) of children which may be added to them, and may even
51  * establish requirements for what type(s) of parent <code>Component</code>s
52  * they may be added to. In the event that an application attempts to add a
53  * child <code>Component</code> to a parent <code>Component</code> in spite
54  * of these requirements, an <code>IllegalChildException</code> is thrown.
55  *
56  * <h3>Properties and Styles</h3>
57  * <p>
58  * The state of a single <code>Component</code> is represented by its
59  * properties. Properties can be categorized into two types: "style" and
60  * "non-style". Style properties are generally used to represent the
61  * "look-and-feel" of a Component--information such as colors, fonts, location,
62  * and borders. "Non-style" properties are generally used to represent
63  * non-stylistic information such as data models, selection models, and locale.
64  * <p>
65  * "Style Properties" have a special definition because they may be stored in
66  * <code>Style</code> or <code>StyleSheet</code> objects instead of as
67  * properties of a specific <code>Component</code> instance. Property values
68  * contained in a relevant <code>Style</code> or <code>StyleSheet</code>
69  * will be used for rendering when the property values are not specified by a
70  * <code>Component</code> itself. Style properties are identified by the
71  * presence of a public static constant name in a <code>Component</code>
72  * implementation with the prefix <code>PROPERTY_</code>. In the base
73  * <code>Component</code> class itself there are several examples of style
74  * properties, such as <code>PROPERTY_BACKGROUND</code>,<code>PROPERTY_FONT</code>
75  * and <code>PROPERTY_LAYOUT_DATA</code>. The rendering application container
76  * will use the <code>Component.getRenderProperty()</code> and
77  * <code>Component.getRenderIndexedProperty()</code> to retrieve the values of
78  * stylistic properties, in order that their values might be obtained from
79  * the <code>Component</code>'s shared <code>Style</code> or the
80  * <code>ApplicationInstance</code>'s <code>StyleSheet</code> in the event
81  * they are not directly set in the <code>Component</code>.
82  * <p>
83  * A <code>Component</code> implementation should not store the values of
84  * style properties as instance variables. Rather, the values of style
85  * properties should be stored in the local <code>Style</code> instance, by
86  * way of the <code>setProperty()</code> method. The
87  * <code>getProperty()</code> method may be used to obtain the value of such
88  * properties. Only style properties should be stored using these methods;
89  * properties such as models should never be stored using the
90  * <code>getProperty()</code>/<code>setProperty()</code> interface.
91  *
92  * <h3>Events</h3>
93  * <p>
94  * Many <code>Component</code>s will provide the capability to register
95  * <code>EventListener</code>s to notify interested parties when various
96  * state changes occur. The base <code>Component</code> class provides an
97  * <code>EventListenerList</code> as a convenient and memory efficient means
98  * of storing such listeners. The internal <code>EventListenerList</code> may
99  * be obtained using the <code>getEventListenerList()</code> method. The
100  * <code>EventListenerList</code> is lazy-created and will only be
101  * instantiated on the first invocation of the
102  * <code>getEventListenerList()</code> method. If the intent is only to
103  * inquire about the state of event listeners without necessarily forcing
104  * instantiation of an <code>EventListenerList</code>, the
105  * <code>hasEventListenerList()</code> should be queried prior to invoking
106  * <code>getEventListenerList()</code>.
107  */

108 public abstract class Component
109 implements RenderIdSupport, Serializable JavaDoc {
110
111     /**
112      * <code>ArrayList</code> capacity for child storage.
113      */

114     private static final int CHILD_LIST_CAPACITY = 3;
115     
116     /**
117      * Empty array returned by <code>getComponents()</code> when a
118      * <code>Component</code> has no children.
119      */

120     private static final Component[] EMPTY_COMPONENT_ARRAY = new Component[0];
121
122     /**
123      * Flag indicating the <code>Component</code> is enabled.
124      */

125     private static final int FLAG_ENABLED = 0x1;
126
127     /**
128      * Flag indicating the <code>Component</code> is visible.
129      */

130     private static final int FLAG_VISIBLE = 0x2;
131     
132     /**
133      * Flag indicating the <code>Component</code> will participate in the
134      * focus traversal order.
135      */

136     private static final int FLAG_FOCUS_TRAVERSAL_PARTICIPANT= 0x4;
137     
138     /**
139      * Flag indicating that the <code>Component</code> is currently undergoing
140      * registration to an <code>ApplicationInstance</code>.
141      */

142     private static final int FLAG_REGISTERING = 0x8;
143     
144     private static final int FLAG_INIT_IN_PROGRESS = 0x10;
145     
146     private static final int FLAG_DISPOSE_IN_PROGRESS = 0x20;
147     
148     private static final int FLAG_INITIALIZED = 0x40;
149     
150     /**
151      * Flag mask of bits used for storage of focus traversal index.
152      */

153     private static final int FLAGS_FOCUS_TRAVERSAL_INDEX = 0x7fff0000;
154     
155     public static final String JavaDoc CHILDREN_CHANGED_PROPERTY = "children";
156     public static final String JavaDoc ENABLED_CHANGED_PROPERTY = "enabled";
157     public static final String JavaDoc FOCUS_TRAVERSAL_INDEX_CHANGED_PROPERTY = "focusTraversalIndex";
158     public static final String JavaDoc FOCUS_TRAVERSAL_PARTICIPANT_CHANGED_PROPERTY = "focusTraversalParticipant";
159     public static final String JavaDoc LAYOUT_DIRECTION_CHANGED_PROPERTY = "layoutDirection";
160     public static final String JavaDoc LOCALE_CHANGED_PROPERTY = "locale";
161     
162     public static final String JavaDoc PROPERTY_BACKGROUND = "background";
163     public static final String JavaDoc PROPERTY_FONT = "font";
164     public static final String JavaDoc PROPERTY_FOREGROUND = "foreground";
165     public static final String JavaDoc PROPERTY_LAYOUT_DATA = "layoutData";
166     public static final String JavaDoc STYLE_CHANGED_PROPERTY = "style";
167     public static final String JavaDoc STYLE_NAME_CHANGED_PROPERTY = "styleName";
168     public static final String JavaDoc VISIBLE_CHANGED_PROPERTY = "visible";
169     
170     //TODO. Doc/move to util.
171
private static final boolean isLetter(char ch) {
172         return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
173     }
174     
175     //TODO. Doc/move to util.
176
private static final boolean isLetterOrDigit(char ch) {
177         return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9');
178     }
179     
180     /** The <code>ApplicationInstance</code> to which the component is registered. */
181     private ApplicationInstance applicationInstance;
182     
183     /**
184      * An ordered collection of references to child components.
185      * This object is lazily instantiated.
186      */

187     private List JavaDoc children;
188     
189     /**
190      * Boolean flags for this component, including enabled state, visibility,
191      * focus traversal participation, and focus traversal index.
192      * Multiple booleans are wrapped in a single integer
193      * to save memory, since many <code>Component</code>instances will be
194      * created.
195      */

196     private int flags;
197     
198     /**
199      * A user-defined identifier for this component.
200      * This identifier is not related in any way to <code>renderId</code>.
201      */

202     private String JavaDoc id;
203     
204     /**
205      * The layout direction of the component.
206      * This property is generally unset, as layout direction information is
207      * normally inherited from the <code>ApplicationInstance</code> or from
208      * an ancestor <code>Component</code> in the hierarchy.
209      */

210     private LayoutDirection layoutDirection;
211     
212     /** Listener storage. */
213     private EventListenerList listenerList;
214
215     /**
216      * The locale of the component.
217      * This property is generally unset, as locale information is normally
218      * inherited from the <code>ApplicationInstance</code> or from an ancestor
219      * <code>Component</code> in the hierarchy.
220      */

221     private Locale JavaDoc locale;
222     
223     /** Local style data storage for properties directly set on component itself. */
224     private MutableStyle localStyle;
225     
226     /** The parent component. */
227     private Component parent;
228     
229     /**
230      * The property change event dispatcher.
231      * This object is lazily instantiated.
232      */

233     private PropertyChangeSupport JavaDoc propertyChangeSupport;
234     
235     /**
236      * A application-wide unique identifier for this component.
237      * This identifier is not related in any way to <code>id</code>.
238      */

239     private String JavaDoc renderId;
240     
241     /** Shared style. */
242     private Style sharedStyle;
243     
244     /** Name of style to use from application style sheet */
245     private String JavaDoc styleName;
246     
247     /**
248      * Creates a new <code>Component</code>.
249      */

250     public Component() {
251         super();
252         flags = FLAG_ENABLED | FLAG_VISIBLE | FLAG_FOCUS_TRAVERSAL_PARTICIPANT;
253         localStyle = new MutableStyle();
254     }
255     
256     /**
257      * Adds the specified <code>Component</code> as a child of this
258      * <code>Component</code>. The child will be added at the greatest
259      * index.
260      *
261      * @param c the child <code>Component</code> to add
262      */

263     public void add(Component c) {
264         add(c, -1);
265     }
266
267     /**
268      * Adds the specified <code>Component</code> as the <code>n</code>th
269      * child of this component.
270      * All component-add operations use this method to add components.
271      * <code>Component</code>s that require notification of all child additions
272      * should override this method (making sure to call the superclass'
273      * implementation).
274      *
275      * @param c the child component to add
276      * @param n the index at which to add the child component, or -1 to add the
277      * component at the end
278      * @throws IllegalChildException if the child is not allowed to be added
279      * to this component, because it is either not valid for the
280      * component's state or is of an invalid type
281      */

282     public void add(Component c, int n)
283     throws IllegalChildException {
284         
285         // Ensure child is acceptable to this component.
286
if (!isValidChild(c)) {
287             throw new IllegalChildException(this, c);
288         }
289         
290         // Ensure child component finds this component acceptable as a parent.
291
if (!c.isValidParent(this)) {
292             throw new IllegalChildException(this, c);
293         }
294
295         // Remove child from it's current parent if required.
296
if (c.parent != null) {
297             c.parent.remove(c);
298         }
299         
300         // Lazy-create child collection if necessary.
301
if (children == null) {
302             children = new ArrayList JavaDoc(CHILD_LIST_CAPACITY);
303         }
304
305         // Connect child to parent.
306
c.parent = this;
307         if (n == -1) {
308             children.add(c);
309         } else {
310             children.add(n, c);
311         }
312         
313         // Flag child as registered.
314
if (applicationInstance != null) {
315             c.register(applicationInstance);
316         }
317
318         // Notify PropertyChangeListeners of change.
319
firePropertyChange(CHILDREN_CHANGED_PROPERTY, null, c);
320
321         // Initialize component.
322
c.doInit();
323     }
324     
325     /**
326      * Adds a property change listener to this component.
327      *
328      * @param l the listener to add
329      */

330     public void addPropertyChangeListener(PropertyChangeListener JavaDoc l) {
331         if (propertyChangeSupport == null) {
332             propertyChangeSupport = new PropertyChangeSupport JavaDoc(this);
333         }
334         propertyChangeSupport.addPropertyChangeListener(l);
335     }
336
337     /**
338      * Internal method to set the render identifier of the<code>Component</code>.
339      * This method is invoked by the <code>ApplicationInstance</code>
340      * when the component is registered or unregistered, or by manual
341      * invocation of <code>setRenderId()</code>. This method performs no
342      * error checking.
343      *
344      * @param renderId the new identifier
345      * @see #getRenderId()
346      * @see #setRenderId()
347      */

348     void assignRenderId(String JavaDoc renderId) {
349         this.renderId = renderId;
350     }
351     
352     /**
353      * Life-cycle method invoked when the <code>Component</code> is removed
354      * from a registered hierarchy. Implementations should always invoke
355      * <code>super.dispose()</code>.
356      * Modifications to the component hierarchy are not allowed within this
357      * method.
358      */

359     public void dispose() { }
360     
361     /**
362      * Recursively executes the <code>dispose()</code> life-cycle methods of
363      * this <code>Component</code> and its descendants.
364      */

365     void doDispose() {
366         if (applicationInstance == null) {
367             return;
368         }
369         if ((flags & (FLAG_INIT_IN_PROGRESS | FLAG_DISPOSE_IN_PROGRESS)) != 0) {
370             throw new IllegalStateException JavaDoc(
371                     "Attempt to dispose component when initialize or dispose operation already in progress.");
372         }
373         flags |= FLAG_DISPOSE_IN_PROGRESS;
374         try {
375             if (children != null) {
376                 Iterator JavaDoc it = children.iterator();
377                 while (it.hasNext()) {
378                     ((Component) it.next()).doDispose();
379                 }
380             }
381             if ((flags & FLAG_INITIALIZED) == 0) {
382                 // Component already disposed.
383
return;
384             }
385             dispose();
386             flags &= ~FLAG_INITIALIZED;
387         } finally {
388             flags &= ~FLAG_DISPOSE_IN_PROGRESS;
389         }
390     }
391     
392     /**
393      * Recursively executes the <code>init()</code> life-cycle methods of
394      * this <code>Component</code> and its descendants.
395      */

396     void doInit() {
397         if (applicationInstance == null) {
398             return;
399         }
400         if ((flags & FLAG_INITIALIZED) != 0) {
401             // Component already initialized.
402
return;
403         }
404         
405         if ((flags & (FLAG_INIT_IN_PROGRESS | FLAG_DISPOSE_IN_PROGRESS)) != 0) {
406             throw new IllegalStateException JavaDoc(
407                     "Attempt to initialize component when initialize or dispose operation already in progress.");
408         }
409         flags |= FLAG_INIT_IN_PROGRESS;
410         try {
411             init();
412             flags |= FLAG_INITIALIZED;
413             if (children != null) {
414                 Iterator JavaDoc it = children.iterator();
415                 while (it.hasNext()) {
416                     ((Component) it.next()).doInit();
417                 }
418             }
419         } finally {
420             flags &= ~FLAG_INIT_IN_PROGRESS;
421         }
422     }
423     
424     /**
425      * Reports a bound property change to <code>PropertyChangeListener</code>s
426      * and to the <code>ApplicationInstance</code>'s update management system.
427      *
428      * @param propertyName the name of the changed property
429      * @param oldValue the previous value of the property
430      * @param newValue the present value of the property
431      */

432     protected void firePropertyChange(String JavaDoc propertyName, Object JavaDoc oldValue, Object JavaDoc newValue) {
433         // Report to PropertyChangeListeners.
434
if (propertyChangeSupport != null) {
435             propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
436         }
437         
438         // Report to ApplicationInstance.
439
// The ApplicationInstance is notified directly in order to reduce
440
// per-Component-instance memory requirements, i.e., it enables the
441
// PropertyChangeSupport object to only be instantiated on Components
442
// that have ProperyChangeListeners registered by a third party.
443
if (applicationInstance != null) {
444             applicationInstance.notifyComponentPropertyChange(this, propertyName, oldValue, newValue);
445         }
446     }
447     
448     /**
449      * Returns the <code>ApplicationInstance</code> to which this
450      * <code>Component</code> is registered, or null if it is not currently
451      * registered.
452      *
453      * @return the application instance
454      */

455     public ApplicationInstance getApplicationInstance() {
456         return applicationInstance;
457     }
458     
459     /**
460      * Returns the default/base background color of the <code>Component</code>.
461      * This property may not be relevant to certain components, though
462      * even in such cases may be useful for setting a default for
463      * children.
464      *
465      * @return the background color
466      */

467     public Color getBackground() {
468         return (Color) localStyle.getProperty(PROPERTY_BACKGROUND);
469     }
470     
471     /**
472      * Returns the <code>n</code>th immediate child component.
473      *
474      * @param n the index of the <code>Component</code> to retrieve
475      * @return the <code>Component</code> at index <code>n</code>
476      * @throws IndexOutOfBoundsException when the index is invalid
477      */

478     public final Component getComponent(int n) {
479         if (children == null) {
480             throw new IndexOutOfBoundsException JavaDoc();
481         }
482         
483         return (Component) children.get(n);
484     }
485     
486     /**
487      * Recursively searches for the component with the specified id
488      * by querying this component and its descendants.
489      * The id value is that retrieved and set via the <code>getId()</code>
490      * and <code>setId()</code> methods. This method is in no way
491      * related to <code>renderId</code>s.
492      *
493      * @param id the user-defined id of the component to be retrieved
494      * @return the component with the specified id, if it either is this
495      * component or is a descendant of it, or null otherwise
496      */

497     public final Component getComponent(String JavaDoc id) {
498         if (id.equals(this.id)) {
499             return this;
500         }
501         if (children == null) {
502             return null;
503         }
504         Iterator JavaDoc it = children.iterator();
505         while (it.hasNext()) {
506             Component testComponent = (Component) it.next();
507             Component targetComponent = testComponent.getComponent(id);
508             if (targetComponent != null) {
509                 return targetComponent;
510             }
511         }
512         return null;
513     }
514     
515     /**
516      * Returns the number of immediate child <code>Component</code>s.
517      *
518      * @return the number of immediate child <code>Component</code>s
519      */

520     public final int getComponentCount() {
521         if (children == null) {
522             return 0;
523         } else {
524             return children.size();
525         }
526     }
527     
528     /**
529      * Returns an array of all immediate child <code>Component</code>s.
530      *
531      * @return an array of all immediate child <code>Component</code>s
532      */

533     public final Component[] getComponents() {
534         if (children == null) {
535             return EMPTY_COMPONENT_ARRAY;
536         } else {
537             return (Component[]) children.toArray(new Component[children.size()]);
538         }
539     }
540     
541     /**
542      * Returns the local <code>EventListenerList</code>.
543      * The listener list is lazily created; invoking this method will
544      * create the <code>EventListenerList</code> if required.
545      *
546      * @return the listener list
547      */

548     protected EventListenerList getEventListenerList() {
549         if (listenerList == null) {
550             listenerList = new EventListenerList();
551         }
552         return listenerList;
553     }
554     
555     /**
556      * Returns the focus traversal (tab) index of the component.
557      * Components with numerically lower indices will be focused before
558      * components with numerically higher indices. The value 0 has special
559      * meaning, in that components with a value of 0 will be focused last.
560      * The default value is 0.
561      *
562      * @return the focus traversal index, a value between 0 and 32767
563      */

564     public final int getFocusTraversalIndex() {
565         return (flags & FLAGS_FOCUS_TRAVERSAL_INDEX) >> 16;
566     }
567     
568     /**
569      * Returns the default/base font of the component.
570      * This property may not be relevant to certain components, though
571      * even in such cases may be useful for setting a default for
572      * children.
573      *
574      * @return the font
575      */

576     public Font getFont() {
577         return (Font) localStyle.getProperty(PROPERTY_FONT);
578     }
579     
580     /**
581      * Returns the default/base foreground color of the <code>Component</code>.
582      * This property may not be relevant to certain components, though
583      * even in such cases may be useful for setting a default for
584      * children.
585      *
586      * @return the foreground color
587      */

588     public Color getForeground() {
589         return (Color) localStyle.getProperty(PROPERTY_FOREGROUND);
590     }
591     
592     /**
593      * Returns the user-defined identifier of the <code>Component</code>.
594      * Note that the user defined identifier has no relation to the
595      * <code>renderId</code>.
596      *
597      * @return the user-defined identifier
598      */

599     public String JavaDoc getId() {
600         return id;
601     }
602     
603     /**
604      * Returns the value of the specified indexed property.
605      * This method is generally used only internally by a
606      * <code>Component</code>, however there are exceptions.
607      * The more specific <code>getXXX()</code> methods to retrieve
608      * property values from a <code>Component</code> whenever
609      * possible.
610      * See the class-level documentation for a more detailed
611      * explanation of the use of this method.
612      *
613      * @param propertyName the property name
614      * @param propertyIndex the property index
615      * @return the property value
616      */

617     public final Object JavaDoc getIndexedProperty(String JavaDoc propertyName, int propertyIndex) {
618         return localStyle.getIndexedProperty(propertyName, propertyIndex);
619     }
620     
621     /**
622      * Returns the <code>LayoutData</code> object used to describe how this
623      * <code>Component</code> should be laid out within its parent container.
624      *
625      * @return the layout data, or null if unset
626      * @see LayoutData
627      */

628     public LayoutData getLayoutData() {
629         return (LayoutData) localStyle.getProperty(PROPERTY_LAYOUT_DATA);
630     }
631     
632     /**
633      * Returns the specific layout direction setting of this component, if any.
634      * This method will return null unless a <code>LayoutDirection</code> is
635      * specifically set on <strong>this</strong> <code>Component</code>.
636      *
637      * @return the layout direction property of <strong>this</strong>
638      * <code>Component</code>
639      * @see #getRenderLayoutDirection()
640      */

641     public LayoutDirection getLayoutDirection() {
642         return layoutDirection;
643     }
644
645     /**
646      * Returns the specific locale setting of this component, if any.
647      * This method will return null unless a <code>Locale</code> is
648      * specifically set on <strong>this</strong> <code>Component</code>.
649      *
650      * @return the locale property of <strong>this</strong>
651      * <code>Component</code>
652      * @see #getRenderLocale()
653      */

654     public Locale JavaDoc getLocale() {
655         return locale;
656     }
657     
658     /**
659      * Returns the parent component.
660      *
661      * @return the parent component, or null if this component has no parent
662      */

663     public final Component getParent() {
664         return parent;
665     }
666     
667     /**
668      * Returns the value of the specified property.
669      * This method is generally used only internally by a
670      * <code>Component</code>, however there are exceptions.
671      * The more specific <code>getXXX()</code> methods to retrieve
672      * property values from a <code>Component</code> whenever
673      * possible.
674      * See the class-level documentation for a more detailed
675      * explanation of the use of this method.
676      *
677      * @param propertyName the property name
678      * @return the property value
679      */

680     public final Object JavaDoc getProperty(String JavaDoc propertyName) {
681         return localStyle.getProperty(propertyName);
682     }
683     
684     /**
685      * Returns the render id of this component.
686      * This id is only guaranteed to be unique within
687      * the <code>ApplicationInstance</code> to which this component is
688      * registered. This method returns null in the event that the
689      * component is not registered to an <code>ApplicationInstance</code>.
690      *
691      * @return the <code>ApplicationInstance</code>-wide unique id of this
692      * component
693      * @see nextapp.echo2.app.RenderIdSupport#getRenderId()
694      */

695     public String JavaDoc getRenderId() {
696         return renderId;
697     }
698
699     /**
700      * Determines the &quot;rendered state&quot; of an indexed property.
701      * The rendered state is determined by first determining if the given
702      * property is locally set on this <code>Component</code>, and returning
703      * it in that case. If the property state is not set locally, the
704      * shared <code>Style</code> assigned to this component will be queried
705      * for the property value. If the property state is not set in the
706      * shared <code>Style</code>, the <code>StyleSheet</code> of the
707      * <code>ApplicationInstance</code> to which this <code>Component</code>
708      * is registered will be queried for the property value.
709      * In the event the property is not set in any of these resources,
710      * null is returned.
711      * <p>
712      * The application container will invoke this method
713      * rather than individual property getter methods to determine the state
714      * of properties when rendering.
715      *
716      * @param propertyName the name of the property
717      * @return the rendered property value
718      */

719     public final Object JavaDoc getRenderIndexedProperty(String JavaDoc propertyName, int propertyIndex) {
720         return getRenderIndexedProperty(propertyName, propertyIndex, null);
721     }
722     
723     /**
724      * Determines the &quot;rendered state&quot; of an indexed property.
725      * The rendered state is determined by first determining if the given
726      * property is locally set on this <code>Component</code>, and returning
727      * it in that case. If the property state is not set locally, the
728      * shared <code>Style</code> assigned to this component will be queried
729      * for the property value. If the property state is not set in the
730      * shared <code>Style</code>, the <code>StyleSheet</code> of the
731      * <code>ApplicationInstance</code> to which this <code>Component</code>
732      * is registered will be queried for the property value.
733      * In the event the property is not set in any of these resources,
734      * <code>defaultValue</code> is returned.
735      *
736      * @param propertyName the name of the property
737      * @param defaultValue the value to be returned if the property is not set
738      * @return the property state
739      */

740     public final Object JavaDoc getRenderIndexedProperty(String JavaDoc propertyName, int propertyIndex, Object JavaDoc defaultValue) {
741         if (localStyle.isIndexedPropertySet(propertyName, propertyIndex)) {
742             // Return local style value.
743
return localStyle.getIndexedProperty(propertyName, propertyIndex);
744         } else if (sharedStyle != null && sharedStyle.isIndexedPropertySet(propertyName, propertyIndex)) {
745             // Return style value specified in shared style.
746
return sharedStyle.getIndexedProperty(propertyName, propertyIndex);
747         } else {
748             if (applicationInstance != null) {
749                 Style applicationStyle = applicationInstance.getStyle(getClass(), styleName);
750                 if (applicationStyle != null && applicationStyle.isIndexedPropertySet(propertyName, propertyIndex)) {
751                     // Return style value specified in application.
752
return applicationStyle.getIndexedProperty(propertyName, propertyIndex);
753                 }
754             }
755             return defaultValue;
756         }
757     }
758     
759     /**
760      * Returns the rendered <code>LayoutDirection</code> of the
761      * <code>Component</code>.
762      *
763      * @return the layout direction of this component
764      */

765     public final LayoutDirection getRenderLayoutDirection() {
766         if (layoutDirection == null) {
767             if (locale == null) {
768                 if (parent == null) {
769                     if (applicationInstance == null) {
770                         return null;
771                     } else {
772                         return applicationInstance.getLayoutDirection();
773                     }
774                 } else {
775                     return parent.getRenderLayoutDirection();
776                 }
777             } else {
778                 return LayoutDirection.forLocale(locale);
779             }
780         } else {
781             return layoutDirection;
782         }
783     }
784     
785     /**
786      * Returns the rendered <code>Locale</code> of the <code>Component</code>.
787      * If this <code>Component</code> does not itself specify a locale, its
788      * ancestors will be queried recursively until a <code>Component</code>
789      * providing a <code>Locale</code> is found. If no ancestors have
790      * <code>Locale</code>s set, the <code>ApplicationInstance</code>'s
791      * locale will be returned. In the event that no locale information is
792      * available from the ancestral hierarchy of <code>Component</code>s and
793      * no <code>ApplicationInstance</code> is registered, null is returned.
794      *
795      * @return the locale for this component
796      */

797     public final Locale JavaDoc getRenderLocale() {
798         if (locale == null) {
799             if (parent == null) {
800                 if (applicationInstance == null) {
801                     return null;
802                 } else {
803                     return applicationInstance.getLocale();
804                 }
805             } else {
806                 return parent.getRenderLocale();
807             }
808         } else {
809             return locale;
810         }
811     }
812     
813     /**
814      * Determines the &quot;rendered state&quot; of a property.
815      * The rendered state is determined by first determining if the given
816      * property is locally set on this <code>Component</code>, and returning
817      * it in that case. If the property state is not set locally, the
818      * shared <code>Style</code> assigned to this component will be queried
819      * for the property value. If the property state is not set in the
820      * shared <code>Style</code>, the <code>StyleSheet</code> of the
821      * <code>ApplicationInstance</code> to which this <code>Component</code>
822      * is registered will be queried for the property value.
823      * In the event the property is not set in any of these resources,
824      * null is returned.
825      * <p>
826      * The application container will invoke this method
827      * rather than individual property getter methods to determine the state
828      * of properties when rendering.
829      *
830      * @param propertyName the name of the property
831      * @return the rendered property value
832      */

833     public final Object JavaDoc getRenderProperty(String JavaDoc propertyName) {
834         return getRenderProperty(propertyName, null);
835     }
836
837     /**
838      * Determines the &quot;rendered state&quot; of a property.
839      * The rendered state is determined by first determining if the given
840      * property is locally set on this <code>Component</code>, and returning
841      * it in that case. If the property state is not set locally, the
842      * shared <code>Style</code> assigned to this component will be queried
843      * for the property value. If the property state is not set in the
844      * shared <code>Style</code>, the <code>StyleSheet</code> of the
845      * <code>ApplicationInstance</code> to which this <code>Component</code>
846      * is registered will be queried for the property value.
847      * In the event the property is not set in any of these resources,
848      * <code>defaultValue</code> is returned.
849      *
850      * @param propertyName the name of the property
851      * @param defaultValue the value to be returned if the property is not set
852      * @return the property state
853      */

854     public final Object JavaDoc getRenderProperty(String JavaDoc propertyName, Object JavaDoc defaultValue) {
855         Object JavaDoc propertyValue = localStyle.getProperty(propertyName);
856         if (propertyValue != null) {
857             return propertyValue;
858         }
859         if (sharedStyle != null) {
860             propertyValue = sharedStyle.getProperty(propertyName);
861             if (propertyValue != null) {
862                 return propertyValue;
863             }
864         }
865         if (applicationInstance != null) {
866             Style applicationStyle = applicationInstance.getStyle(getClass(), styleName);
867             if (applicationStyle != null) {
868                 // Return style value specified in application.
869
propertyValue = applicationStyle.getProperty(propertyName);
870                 if (propertyValue != null) {
871                     return propertyValue;
872                 }
873             }
874         }
875         return defaultValue;
876     }
877     
878     /**
879      * Returns the shared <code>Style</code> object assigned to this
880      * <code>Component</code>.
881      * As its name implies, the <strong>shared</strong> <code>Style</code>
882      * may be shared amongst multiple <code>Component</code>s.
883      * Style properties will be rendered from the specified <code>Style</code>
884      * when they are not specified locally in the <code>Component</code>
885      * itself.
886      *
887      * @return the shared <code>Style</code>
888      */

889     public final Style getStyle() {
890         return sharedStyle;
891     }
892     
893     /**
894      * Returns the name of the <code>Style</code> in the
895      * <code>ApplicationInstance</code>'s<code>StyleSheet</code> from
896      * which the renderer will retrieve properties. The renderer will only query
897      * the <code>StyleSheet</code> when properties are not specified directly
898      * by the <code>Component</code> or by the <code>Component</code>'s
899      * shared <code>Style</code>.
900      *
901      * @return the style name
902      */

903     public final String JavaDoc getStyleName() {
904         return styleName;
905     }
906     
907     /**
908      * Returns the <code>n</code>th immediate <strong>visible</strong>
909      * child <code>Component</code>.
910      *
911      * @param n the index of the <code>Component</code> to retrieve
912      * @return the <code>Component</code> at index <code>n</code>
913      * @throws IndexOutOfBoundsException when the index is invalid
914      */

915     public final Component getVisibleComponent(int n) {
916         if (children == null) {
917             throw new IndexOutOfBoundsException JavaDoc(Integer.toString(n));
918         }
919         int visibleComponentCount = 0;
920         Component component = null;
921         Iterator JavaDoc it = children.iterator();
922         while (visibleComponentCount <= n) {
923             if (!it.hasNext()) {
924               throw new IndexOutOfBoundsException JavaDoc(Integer.toString(n));
925             }
926             component = (Component) it.next();
927             if (component.isVisible()) {
928                 ++visibleComponentCount;
929             }
930         }
931         return component;
932     }
933
934     /**
935      * Returns the number of <strong>visible</strong> immediate child
936      * <code>Component</code>s.
937      *
938      * @return the number of <strong>visible</strong> immediate child
939      * <code>Component</code>s
940      */

941     public final int getVisibleComponentCount() {
942         if (children == null) {
943             return 0;
944         } else {
945             int visibleComponentCount = 0;
946             Iterator JavaDoc it = children.iterator();
947             while (it.hasNext()) {
948                 Component component = (Component) it.next();
949                 if (component.isVisible()) {
950                     ++visibleComponentCount;
951                 }
952             }
953             return visibleComponentCount;
954         }
955     }
956     
957     /**
958      * Returns an array of all <strong>visible</strong> immediate child
959      * <code>Component</code>s.
960      *
961      * @return an array of all <strong>visible</strong> immediate child
962      * <code>Component</code>s
963      */

964     public final Component[] getVisibleComponents() {
965         if (children == null) {
966             return EMPTY_COMPONENT_ARRAY;
967         } else {
968             Iterator JavaDoc it = children.iterator();
969             List JavaDoc visibleChildList = new ArrayList JavaDoc();
970             while (it.hasNext()) {
971                 Component component = (Component) it.next();
972                 if (component.isVisible()) {
973                     visibleChildList.add(component);
974                 }
975             }
976             return (Component[]) visibleChildList.toArray(new Component[visibleChildList.size()]);
977         }
978     }
979     
980     /**
981      * Determines if a local <code>EventListenerList</code> exists.
982      * If no listener list exists, it can be assured that there are thus no
983      * listeners registered to it. This method should be invoked by event
984      * firing code prior to invoking <code>getListenerList()</code> to avoid
985      * unnecessary creation of an <code>EventListenerList</code> in response
986      * to their query.
987      *
988      * @return true if a local <code>EventListenerList</code> exists
989      */

990     protected boolean hasEventListenerList() {
991         return listenerList != null;
992     }
993     
994     /**
995      * Determines the index of the given <code>Component</code> within the
996      * children of this <code>Component</code>. If the given
997      * <code>Component</code> is not a child, <code>-1</code> is returned.
998      *
999      * @param c the <code>Component</code> to analyze
1000     * @return the index of the specified <code>Component</code> amongst the
1001     * children of this <code>Component</code>
1002     */

1003    public final int indexOf(Component c) {
1004        return children == null ? -1 : children.indexOf(c);
1005    }
1006    
1007    /**
1008     * Life-cycle method invoked when the <code>Component</code> is added
1009     * to a registered hierarchy. Implementations should always invoke
1010     * <code>super.init()</code>.
1011     * Modifications to the component hierarchy are not allowed within this
1012     * method.
1013     */

1014    public void init() { }
1015    
1016    /**
1017     * Determines if this <code>Component</code> is or is an ancestor of
1018     * the specified <code>Component</code>.
1019     *
1020     * @param c the <code>Component</code> to test for ancestry
1021     * @return true if this <code>Component</code> is an ancestor of the
1022     * specified <code>Component</code>
1023     */

1024    public final boolean isAncestorOf(Component c) {
1025        while (c != null && c != this) {
1026            c = c.parent;
1027        }
1028        return c == this;
1029    }
1030    
1031    /**
1032     * Determines the enabled state of this <code>Component</code>.
1033     * Disabled<code>Component</code>s are not eligible to receive user input.
1034     * The application container may render disabled components with an altered
1035     * appearance.
1036     *
1037     * @return true if the component is enabled
1038     * @see #verifyInput(java.lang.String, java.lang.Object)
1039     */

1040    public final boolean isEnabled() {
1041        return (flags & FLAG_ENABLED) != 0;
1042    }
1043    
1044    /**
1045     * Determines if the <code>Component</code> participates in (tab) focus
1046     * traversal.
1047     *
1048     * @return true if the <code>Component</code> participates in focus
1049     * traversal
1050     */

1051    public boolean isFocusTraversalParticipant() {
1052        return (flags & FLAG_FOCUS_TRAVERSAL_PARTICIPANT) != 0;
1053    }
1054
1055    /**
1056     * Determines if the <code>Component</code> is registered to an
1057     * <code>ApplicationInstance</code>.
1058     *
1059     * @return true if the <code>Component</code> is registered to an
1060     * <code>ApplicationInstance</code>
1061     */

1062    public final boolean isRegistered() {
1063        return applicationInstance != null;
1064    }
1065    
1066    /**
1067     * Determines whether this <code>Component</code> should be rendered with
1068     * an enabled state.
1069     * Disabled<code>Component</code>s are not eligible to receive user input.
1070     * The application container may render disabled components with an altered
1071     * appearance.
1072     *
1073     * @return true if the component should be rendered enabled.
1074     */

1075    public final boolean isRenderEnabled() {
1076        Component component = this;
1077        while (component != null) {
1078            if ((component.flags & FLAG_ENABLED) == 0) {
1079                return false;
1080            }
1081            component = component.parent;
1082        }
1083        return true;
1084    }
1085    
1086    /**
1087     * Determines if the <code>Component</code> and all of its parents are
1088     * visible.
1089     *
1090     * @return true if the <code>Component</code> is recursively visible
1091     */

1092    public final boolean isRenderVisible() {
1093        Component component = this;
1094        while (component != null) {
1095            if ((component.flags & FLAG_VISIBLE) == 0) {
1096                return false;
1097            }
1098            component = component.parent;
1099        }
1100        return true;
1101    }
1102    
1103    /**
1104     * Determines if a given <code>Component</code> is valid to be added as a
1105     * child to this <code>Component</code>. Default implementation always
1106     * returns true, may be overridden to provide specific behavior.
1107     *
1108     * @param child the <code>Component</code> to evaluate as a child
1109     * @return true if the <code>Component</code> is a valid child
1110     */

1111    public boolean isValidChild(Component child) {
1112        return true;
1113    }
1114    
1115    /**
1116     * Determines if this <code>Component</code> is valid to be added as a
1117     * child of the given parent <code>Component</code>. Default
1118     * implementation always returns true, may be overridden to provide specific
1119     * behavior.
1120     *
1121     * @param parent the <code>Component</code> to evaluate as a parent
1122     * @return true if the <code>Component</code> is a valid parent
1123     */

1124    public boolean isValidParent(Component parent) {
1125        return true;
1126    }
1127    
1128    /**
1129     * Returns the visibility state of this <code>Component</code>.
1130     * Non-visible components will not be seen by the rendering application
1131     * container, and will not be rendered in any fashion on the user
1132     * interface. Rendering Application Containers should ensure that no
1133     * information about the state of an invisible component is provided to
1134     * the user interface for security purposes.
1135     *
1136     * @return the visibility state of this <code>Component</code>
1137     */

1138    public final boolean isVisible() {
1139        return (FLAG_VISIBLE & flags) != 0;
1140    }
1141    
1142    /**
1143     * Processes client input specific to the <code>Component</code>
1144     * received from the <code>UpdateManager</code>.
1145     * Derivative implementations should take care to invoke
1146     * <code>super.processInput()</code>.
1147     *
1148     * @param inputName the name of the input
1149     * @param inputValue the value of the input
1150     * @see nextapp.echo2.app.update.UpdateManager
1151     */

1152    public void processInput(String JavaDoc inputName, Object JavaDoc inputValue) { }
1153    
1154    /**
1155     * Sets the <code>ApplicationInstance</code> to which this component is
1156     * registered.
1157     * <p>
1158     * The <code>ApplicationInstance</code> to which a component is registered
1159     * may not be changed directly from one to another, i.e., if the component
1160     * is registered to instance "A" and an attempt is made to set it to
1161     * instance "B", an <code>IllegalStateException</code> will be thrown. In
1162     * order to change the instance to which a component is registered, the
1163     * instance must first be set to null.
1164     *
1165     * @param newValue the new <code>ApplicationInstance</code>
1166     * @throws IllegalStateException in the event that an attempt is made to
1167     * re-add a <code>Component</code> to a hierarchy during a
1168     * <code>dispose()</code> operation or if an attempt is made to
1169     * remove a <code>Component</code> during an <code>init()</code>
1170     * operation.
1171     */

1172    void register(ApplicationInstance newValue) {
1173        // Verifying 'registering' flag is not set.
1174
if ((flags & FLAG_REGISTERING) != 0) {
1175            throw new IllegalStateException JavaDoc(
1176                    "Illegal attempt to register/unregister Component from within invocation of registration change " +
1177                    "life-cycle method.");
1178        }
1179        try {
1180            // Set 'registering' flag.
1181
flags |= FLAG_REGISTERING;
1182            
1183            if (applicationInstance == newValue) {
1184                // Child component added/removed during init()/dispose(): do nothing.
1185
return;
1186            }
1187            
1188            if (applicationInstance != null && newValue != null) {
1189                throw new IllegalStateException JavaDoc(
1190                        "Illegal attempt to re-register Component to alternate ApplicationInstance.");
1191            }
1192            
1193            if (newValue == null) { // unregistering
1194
if (children != null) {
1195                    Iterator JavaDoc it = children.iterator();
1196                    while (it.hasNext()) {
1197                        ((Component) it.next()).register(null); // Recursively unregister children.
1198
}
1199                }
1200                
1201                applicationInstance.unregisterComponent(this);
1202            }
1203            
1204            applicationInstance = newValue;
1205            
1206            if (newValue != null) { // registering
1207
applicationInstance.registerComponent(this);
1208    
1209                if (children != null) {
1210                    Iterator JavaDoc it = children.iterator();
1211                    while (it.hasNext()) {
1212                        ((Component) it.next()).register(newValue); // Recursively register children.
1213
}
1214                }
1215            }
1216        } finally {
1217            // Clear 'registering' flag.
1218
flags &= ~FLAG_REGISTERING;
1219        }
1220    }
1221    
1222    /**
1223     * Removes the specified child <code>Component</code> from this
1224     * <code>Component</code>.
1225     * <p>
1226     * All <code>Component</code> remove operations use this method to
1227     * remove <code>Component</code>s. <code>Component</code>s that require
1228     * notification of all child removals should
1229     * override this method (while ensuring to call the superclass'
1230     * implementation).
1231     *
1232     * @param c the child <code>Component</code> to remove
1233     */

1234    public void remove(Component c) {
1235
1236        if (children == null || !children.contains(c)) {
1237            // Do-nothing if component is not a child.
1238
return;
1239        }
1240
1241        c.doDispose();
1242        
1243        // Deregister child.
1244
if (applicationInstance != null) {
1245            c.register(null);
1246        }
1247        
1248        // Dissolve references between parent and child.
1249
children.remove(c);
1250        c.parent = null;
1251
1252        // Notify PropertyChangeListeners of change.
1253
firePropertyChange(CHILDREN_CHANGED_PROPERTY, c, null);
1254    }
1255    
1256    /**
1257     * Removes the <code>Component</code> at the <code>n</code>th index.
1258     *
1259     * @param n the index of the child <code>Component</code> to remove
1260     * @throws IndexOutOfBoundsException if the index is not valid
1261     */

1262    public void remove(int n) {
1263        if (children == null) {
1264            throw new IndexOutOfBoundsException JavaDoc();
1265        }
1266        remove(getComponent(n));
1267    }
1268    
1269    /**
1270     * Removes all child <code>Component</code>s.
1271     */

1272    public void removeAll() {
1273        if (children != null) {
1274            while (children.size() > 0) {
1275                Component c = (Component) children.get(children.size() - 1);
1276                remove(c);
1277            }
1278            children = null;
1279        }
1280    }
1281    
1282    /**
1283     * Removes a property change listener from this <code>Component</code>.
1284     *
1285     * @param l the listener to be removed
1286     */

1287    public void removePropertyChangeListener(PropertyChangeListener JavaDoc l) {
1288        if (propertyChangeSupport != null) {
1289            propertyChangeSupport.removePropertyChangeListener(l);
1290        }
1291    }
1292    
1293    /**
1294     * Sets the default background color of the <code>Component</code>.
1295     *
1296     * @param newValue the new background <code>Color</code>
1297     */

1298    public void setBackground(Color newValue) {
1299        setProperty(PROPERTY_BACKGROUND, newValue);
1300    }
1301    
1302    /**
1303     * Sets the enabled state of the <code>Component</code>.
1304     *
1305     * @param newValue the new state
1306     * @see #isEnabled
1307     */

1308    public void setEnabled(boolean newValue) {
1309        boolean oldValue = (flags & FLAG_ENABLED) != 0;
1310        if (oldValue != newValue) {
1311            flags ^= FLAG_ENABLED; // Toggle FLAG_ENABLED bit.
1312
firePropertyChange(ENABLED_CHANGED_PROPERTY, new Boolean JavaDoc(oldValue), new Boolean JavaDoc(newValue));
1313        }
1314    }
1315    
1316    /**
1317     * Sets the focus traversal (tab) index of the component.
1318     *
1319     * @param newValue the new focus traversal index
1320     * @see #getFocusTraversalIndex()
1321     */

1322    public void setFocusTraversalIndex(int newValue) {
1323        int oldValue = getFocusTraversalIndex();
1324        newValue &= 0x7fff;
1325        flags = flags & ((~FLAGS_FOCUS_TRAVERSAL_INDEX)) | (newValue << 16);
1326        firePropertyChange(FOCUS_TRAVERSAL_INDEX_CHANGED_PROPERTY, new Integer JavaDoc(oldValue), new Integer JavaDoc(newValue));
1327    }
1328    
1329    /**
1330     * Sets whether the component participates in the focus traversal order
1331     * (tab order).
1332     *
1333     * @param newValue true if the component participates in the focus
1334     * traversal order
1335     */

1336    public void setFocusTraversalParticipant(boolean newValue) {
1337        boolean oldValue = isFocusTraversalParticipant();
1338        if (oldValue != newValue) {
1339            flags ^= FLAG_FOCUS_TRAVERSAL_PARTICIPANT; // Toggle FLAG_FOCUS_TRAVERSAL_PARTICIPANT bit.
1340
firePropertyChange(FOCUS_TRAVERSAL_PARTICIPANT_CHANGED_PROPERTY, new Boolean JavaDoc(oldValue), new Boolean JavaDoc(newValue));
1341        }
1342    }
1343
1344    /**
1345     * Sets the default text font of the <code>Component</code>.
1346     *
1347     * @param newValue the new <code>Font</code>
1348     */

1349    public void setFont(Font newValue) {
1350        setProperty(PROPERTY_FONT, newValue);
1351    }
1352    
1353    /**
1354     * Sets the default foreground color of the <code>Component</code>.
1355     *
1356     * @param newValue the new foreground <code>Color</code>
1357     */

1358    public void setForeground(Color newValue) {
1359        setProperty(PROPERTY_FOREGROUND, newValue);
1360    }
1361    
1362    /**
1363     * Sets a user-defined identifier for this <code>Component</code>.
1364     *
1365     * @param id the new identifier
1366     */

1367    public void setId(String JavaDoc id) {
1368        this.id = id;
1369    }
1370    
1371    /**
1372     * Sets a generic indexed property of the <code>Component</code>.
1373     * The value will be stored in this <code>Component</code>'s local style.
1374     *
1375     * @param propertyName the name of the property
1376     * @param propertyIndex the index of the property
1377     * @param newValue the value of the property
1378     *
1379     * @see #getIndexedProperty(java.lang.String, int)
1380     */

1381    public void setIndexedProperty(String JavaDoc propertyName, int propertyIndex, Object JavaDoc newValue) {
1382        localStyle.setIndexedProperty(propertyName, propertyIndex, newValue);
1383        firePropertyChange(propertyName, null, null);
1384    }
1385    
1386    /**
1387     * Sets the <code>LayoutData</code> of this <code>Component</code>.
1388     * A <code>LayoutData</code> implementation describes how this
1389     * <code>Component</code> is laid out within/interacts with its
1390     * containing parent <code>Component</code>.
1391     *
1392     * @param newValue the new <code>LayoutData</code>
1393     * @see LayoutData
1394     */

1395    public void setLayoutData(LayoutData newValue) {
1396        setProperty(PROPERTY_LAYOUT_DATA, newValue);
1397    }
1398    
1399    /**
1400     * Sets the <code>LayoutDirection</code> of this <code>Component</code>,
1401     * describing whether content is rendered left-to-right or right-to-left.
1402     *
1403     * @param newValue the new <code>LayoutDirection</code>.
1404     */

1405    public void setLayoutDirection(LayoutDirection newValue) {
1406        LayoutDirection oldValue = layoutDirection;
1407        layoutDirection = newValue;
1408        firePropertyChange(LAYOUT_DIRECTION_CHANGED_PROPERTY, oldValue, newValue);
1409    }
1410    
1411    /**
1412     * Sets the locale of the <code>Component</code>.
1413     *
1414     * @param newValue the new locale
1415     * @see #getLocale()
1416     */

1417    public void setLocale(Locale JavaDoc newValue) {
1418        Locale JavaDoc oldValue = locale;
1419        locale = newValue;
1420        firePropertyChange(LOCALE_CHANGED_PROPERTY, oldValue, newValue);
1421    }
1422    
1423    /**
1424     * Sets a generic property of the <code>Component</code>.
1425     * The value will be stored in this <code>Component</code>'s local style.
1426     *
1427     * @param propertyName the name of the property
1428     * @param newValue the value of the property
1429     * @see #getProperty(java.lang.String)
1430     */

1431    public void setProperty(String JavaDoc propertyName, Object JavaDoc newValue) {
1432        Object JavaDoc oldValue = localStyle.getProperty(propertyName);
1433        localStyle.setProperty(propertyName, newValue);
1434        firePropertyChange(propertyName, oldValue, newValue);
1435    }
1436    
1437    /**
1438     * Sets a custom render identifier for this <code>Component</code>.
1439     * The identifier may be changed without notification if another
1440     * component is already using it.
1441     * Identifiers are limited to ASCII alphanumeric values.
1442     * The first character must be an upper- or lower-case ASCII letter.
1443     * Underscores and other punctuation characters are not permitted.
1444     * Use of "TitleCase" or "camelCase" is recommended.
1445     *
1446     * @param renderId the new identifier
1447     */

1448    public void setRenderId(String JavaDoc renderId) {
1449        if (this.renderId != null && renderId != null && this.applicationInstance != null) {
1450            throw new IllegalStateException JavaDoc("Cannot set renderId while component is registered.");
1451        }
1452        if (renderId != null) {
1453            int length = renderId.length();
1454            if (!isLetter(renderId.charAt(0))) {
1455                throw new IllegalArgumentException JavaDoc("Invalid identifier:" + renderId);
1456            }
1457            for (int i = 1; i < length; ++i) {
1458                if (!isLetterOrDigit(renderId.charAt(i))) {
1459                    throw new IllegalArgumentException JavaDoc("Invalid identifier:" + renderId);
1460                }
1461            }
1462            
1463        }
1464        assignRenderId(renderId);
1465    }
1466    
1467    /**
1468     * Sets the shared style of the <code>Component</code>.
1469     * Setting the shared style will have no impact on the local stylistic
1470     * properties of the <code>Component</code>.
1471     *
1472     * @param newValue the new shared style
1473     * @see #getStyle()
1474     */

1475    public void setStyle(Style newValue) {
1476        Style oldValue = sharedStyle;
1477        sharedStyle = newValue;
1478        firePropertyChange(STYLE_CHANGED_PROPERTY, oldValue, newValue);
1479    }
1480    
1481    /**
1482     * Sets the name of the style to use from the
1483     * <code>ApplicationInstance</code>-defined <code>StyleSheet</code>.
1484     * Setting the style name will have no impact on the local stylistic
1485     * properties of the <code>Component</code>.
1486     *
1487     * @param newValue the new style name
1488     * @see #getStyleName
1489     */

1490    public void setStyleName(String JavaDoc newValue) {
1491        String JavaDoc oldValue = styleName;
1492        styleName = newValue;
1493        firePropertyChange(STYLE_NAME_CHANGED_PROPERTY, oldValue, newValue);
1494    }
1495    
1496    /**
1497     * Sets the visibility state of this <code>Component</code>.
1498     *
1499     * @param newValue the new visibility state
1500     * @see #isVisible()
1501     */

1502    public void setVisible(boolean newValue) {
1503        boolean oldValue = (flags & FLAG_VISIBLE) != 0;
1504        if (oldValue != newValue) {
1505            flags ^= FLAG_VISIBLE; // Toggle FLAG_VISIBLE bit.
1506
firePropertyChange(VISIBLE_CHANGED_PROPERTY, new Boolean JavaDoc(oldValue), new Boolean JavaDoc(newValue));
1507        }
1508    }
1509
1510    /**
1511     * A life-cycle method invoked before the component is rendered to ensure it
1512     * is in a valid state. Default implementation is empty. Overriding
1513     * implementations should ensure to invoke <code>super.validate()</code>
1514     * out of convention.
1515     */

1516    public void validate() { }
1517    
1518    /**
1519     * Invoked by the <code>ClientUpdateManager</code> on each component in the
1520     * hierarchy whose <code>processInput()</code> method will layer be invoked
1521     * in the current transaction. This method should return true if the
1522     * component will be capable of processing the given input in its current
1523     * state or false otherwise. This method should not do any of the actual
1524     * processing work if overridden (any actual processing should be done in
1525     * the <code>processInput()</code> implementation).
1526     * <p>
1527     * The default implementation verifies that the component is visible,
1528     * enabled, and not "obscured" by the presence of any modal component.
1529     * If overriding this method, your implementation should invoke
1530     * <code>super.verifyInput()</code>.
1531     *
1532     * @param inputName the name of the input
1533     * @param inputValue the value of the input
1534     * @return true if the input is allowed to be processed by this component
1535     * in its current state
1536     */

1537    public boolean verifyInput(String JavaDoc inputName, Object JavaDoc inputValue) {
1538        if (applicationInstance != null && !applicationInstance.verifyModalContext(this)) {
1539            return false;
1540        }
1541        return isVisible() && isEnabled();
1542    }
1543
1544    /**
1545     * Determines the index of the given <code>Component</code> within the
1546     * <strong>visible</strong> children of this <code>Component</code>. If the
1547     * given <code>Component</code> is not a child, <code>-1</code> is
1548     * returned.
1549     *
1550     * @param c the <code>Component</code> to analyze
1551     * @return the index of the specified <code>Component</code> amongst the
1552     * <strong>visible</strong> children of this <code>Component</code>
1553     */

1554    public final int visibleIndexOf(Component c) {
1555        if (!c.isVisible()) {
1556            return -1;
1557        }
1558        if (children == null) {
1559            return -1;
1560        }
1561        int visibleIndex = 0;
1562        Iterator JavaDoc it = children.iterator();
1563        while (it.hasNext()) {
1564            Component component = (Component) it.next();
1565            if (!component.isVisible()) {
1566                continue;
1567            }
1568            if (component.equals(c)) {
1569                return visibleIndex;
1570            }
1571            ++visibleIndex;
1572        }
1573        return -1;
1574    }
1575}
1576
Popular Tags