xref: /titanic_44/usr/src/cmd/krb5/kadmin/gui/visualrt/sunsoft/jws/visual/rt/base/Group.java (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * ident	"%Z%%M%	%I%	%E% SMI"
24  *
25  * Copyright (c) 2000 by Sun Microsystems, Inc.
26  * All rights reserved.
27  */
28 
29 /*
30  *        Copyright (C) 1996  Active Software, Inc.
31  *                  All rights reserved.
32  *
33  * @(#) Group.java 1.143 - last change made 07/25/97
34  */
35 
36 package sunsoft.jws.visual.rt.base;
37 
38 import sunsoft.jws.visual.rt.awt.RootFrame;
39 import sunsoft.jws.visual.rt.shadow.*;
40 import sunsoft.jws.visual.rt.shadow.java.awt.*;
41 import sunsoft.jws.visual.rt.type.Converter;
42 import sunsoft.jws.visual.rt.type.AMConverter;
43 import sunsoft.jws.visual.rt.type.AMRef;
44 import sunsoft.jws.visual.rt.base.Global;
45 
46 
47 import java.awt.*;
48 import java.util.*;
49 import java.net.URL;
50 import java.applet.Applet;
51 
52 /**
53  * The base class for every kind of group.
54  * <p>
55  * The attributes available for this
56  * class are listed below.  In the type column, type names beginning
57  * with "sunsoft.jws.visual.rt" have been abbreviated to begin
58  * with "rt".
59  *
60  * <pre>
61  * name            type                      default value
62  * ---------------------------------------------------------------
63  * visible         java.lang.Boolean         true
64 *  < /pre>
65 *
66 * Check the super class for additional attributes.
67 *
68 * @version 	1.143, 07/25/97
69 */
70 public abstract class Group extends AttributeManager {
71 
72     // Print the warning message only once.
73     private boolean warned = false;
74 
75     /**
76      * This flag is used to detect when showGroup is called
77      * recursively during create.
78      * We don't want to execute the showGroup code twice
79      * because modal dialogs block during "show".
80      * This means that if
81      * show is called twice, the modal dialog will pop up
82      * again after it is hidden.
83      */
84     private boolean doingShow = false;
85 
86     /**
87      * This flag indicates whether or not the group is
88      * currently shown.
89      */
90     private boolean isShowing = false;
91 
92     /**
93      * This flag is set for forwarded attributes in a group.
94      */
95     public static final int FORWARD = 0x100;
96 
97     /**
98      * This flag is set for forwarded attributes that will
99      * be removed during initialization if the group's
100      * container does not define the attribute.
101      */
102     public static final int FORWARD_REMOVE = 0x200;
103 
104     /**
105      * This constant can be passed to the setCursor call.
106      * It indicates
107      * that the cursor should be restored to its previous value.
108      */
109     public static final int RESTORE_CURSOR = 50000;
110 
111     public static final int BACKSPACE_KEY = 8;
112     public static final int TAB_KEY = 9;
113     public static final int RETURN_KEY = 10;
114     public static final int ESCAPE_KEY = 27;
115     public static final int DELETE_KEY = 127;
116 
117     // The root of the shadow tree.
118     private Root root;
119 
120     /**
121      * Set to true when this group is initialized.
122      */
123     private boolean isInitialized;
124 
125     /**
126      * Set to true when this group has been started, but
127      * has not yet been stopped.
128      */
129     private boolean isStarted = false;
130 
131     /**
132      * Parent group for this group.
133      */
134     private Group parentGroup = null;
135 
136     private Vector children = new Vector();
137 
138     // Operations
139     private Vector operations = null;
140 
141     /**
142      * Time Bomb
143      */
checkDate()144     private void checkDate() {
145         // August 1, 1996   : 838882801
146         // August 15, 1996  : 840092401
147         // October 15, 1996 : 845362801
148 
149         Date date = new Date(840092401000L);
150         if (System.currentTimeMillis() >= 840092401000L) {
151             throw new Error(Global.getMsg(
152 		    "sunsoft.jws.visual.rt.base.Group.ExpiredVersion"));
153         } else if (!warned) {
154             warned = true;
155             System.out.println(Global.fmtMsg(
156 		    "sunsoft.jws.visual.rt.base.Group.ExpiredVersionDate",
157 		    date.toString()));
158         }
159     }
160 
161     // NOTE: Any changes made to this comment should also
162     // be made in the lib/visual/gen/group.java file.
163     /**
164      * All the attributes used by this group must be defined in the
165      * constructor.  setOnGroup is called at initialization for all
166      * the attributes.  If the attribute has not been set prior to
167      * initialization, setOnGroup is called with the default value.
168      */
Group()169     public Group() {
170         // The "visible" attribute MUST have the DEFAULT
171         // flag set!  We don't want "visible"
172         // being set during initialization.
173         attributes.add(/* NOI18N */"visible",
174 		    /* NOI18N */"java.lang.Boolean", Boolean.TRUE, DEFAULT);
175     }
176 
177     /**
178      * Initialize the group.  The shadow tree for the group
179      * is created during initialization.
180      */
initialize()181 	public void initialize() {
182 		boolean wasInitialized = isInitialized;
183 
184 		if (!isInitialized) {
185 			if (!hasEnvironment()) {
186 				throw new Error(Global.getMsg(
187 "sunsoft.jws.visual.rt.base.Group.GroupInitializationWarning"));
188 			}
189 
190 			isInitialized = true;
191 
192 			/**
193 			 * AMREF: We could have started a recording of all
194 			 * new AMRef's
195 			 * here, but it's a performance hit that doesn't buy us
196 			 * anything, the user shouldn't be making AMRef's
197 			 * that point to
198 			 * an object by a certain name, changing the name
199 			 * of that object, and expecting it to work.
200 			 *  The stopRecording call
201 			 * further down goes with this call.
202 			 */
203 			// AMRef.startRecording();
204 
205 			root = initRoot();
206 
207 			if (root == null && !(this instanceof NVGroup))
208 				throw new Error(Global.fmtMsg(
209 "sunsoft.jws.visual.rt.base.Group.RootIsNull", this.getClass().getName()));
210 
211 			/** AMREF: resolves all AMRef's loaded */
212 			// AMRef.stopRecording(root);
213 
214 			removeForwardedAttributes();
215 
216 			initGroup();
217 
218 			if (operations != null) {
219 				Enumeration e = operations.elements();
220 				while (e.hasMoreElements()) {
221 					Operations ops =
222 						(Operations)e.nextElement();
223 					ops.setRoot(root);
224 				}
225 			}
226 		}
227 
228 		// Initialize the visible sub-groups
229 		Enumeration e = getChildList();
230 		while (e.hasMoreElements()) {
231 			Group child = (Group)e.nextElement();
232 			if (wouldBeVisible(child))
233 				child.initialize();
234 		}
235 
236 		if (!wasInitialized) {
237 			// Set attributes on the newly initialized group
238 			e = attributes.elements();
239 			while (e.hasMoreElements()) {
240 				Attribute a = (Attribute) e.nextElement();
241 				String name = a.getName();
242 
243 				if (a.isModified() ||
244 				    !a.flagged(DEFAULT | READONLY)) {
245 					set(name, a.getValue());
246 				}
247 			}
248 
249 			if (isLayoutMode()) {
250 				WindowShadow s = getWindow();
251 				if (s != null)
252 					s.setLayout(true);
253 			}
254 		}
255 	}
256 
257 	/**
258 	 * Returns true if the group is currently initialized.
259 	 */
isInitialized()260     public boolean isInitialized() {
261         return isInitialized;
262     }
263 
264     // NOTE: Any changes made to this comment should
265     // also be made in the
266     // lib/visual/gen/group.java file.
267     /**
268      * initRoot must be overridden in group subclasses to
269      * initialize the shadow tree.  The return value must be the
270      * root of the newly initialized shadow tree.
271      */
initRoot()272     protected abstract Root initRoot();
273 
274     // NOTE: Any changes made to this comment should
275     // also be made in the
276     // lib/visual/gen/group.java file.
277     /**
278      * Called during initialization.  It is called just after
279      * initRoot is called, but before the sub-groups
280      * are initialized and
281      * before the attributes are sent to the setOnGroup method.
282      *
283      * initGroup is only called once in the lifetime of the Group.
284      * This is because groups cannot be uninitialized.
285      * Anything that
286      * needs to be cleaned up should be created in
287      * createGroup instead
288      * of initGroup, and then can be cleaned up in destroyGroup.
289      * createGroup and destroyGroup may be called multiple
290      * times during
291      * the lifetime of a group.
292      */
initGroup()293     protected void initGroup() {};
294 
295     /**
296      * Returns a type name for this group to be used by visual java.
297      * May be overridden in sub-classes to give more useful names.
298      */
getUserTypeName()299     protected String getUserTypeName() {
300         return (Converter.shortClassName(getClass().getName()).toLowerCase());
301     }
302 
303     /**
304      * Returns the main container for this group.  This can
305      * be either a WindowShadow or a PanelShadow.
306      */
getContainer()307     public ContainerShadow getContainer() {
308         if (root == null)
309             return null;
310 
311         AttributeManager mgr = root.getMainChild();
312         if (mgr == null)
313             return null;
314         else if (mgr instanceof ContainerShadow)
315             return (ContainerShadow)mgr;
316         else if (mgr instanceof Group)
317             return ((Group)mgr).getContainer();
318         else
319             throw new Error(Global.fmtMsg(
320 		    "sunsoft.jws.visual.rt.base.Group.UnexpectedMainChildType",
321 		    mgr));
322     }
323 
324     /**
325      * Returns the main panel for this group.  Returns
326      * null if the main container is not a panel.
327      */
getPanel()328     public PanelShadow getPanel() {
329         ContainerShadow c = getContainer();
330         if (c instanceof PanelShadow)
331             return (PanelShadow)c;
332         else
333             return null;
334     }
335 
336     /**
337      * Returns the main window for this group.  Returns
338      * null if the main container is not a window.
339      */
getWindow()340     public WindowShadow getWindow() {
341         ContainerShadow c = getContainer();
342         if (c instanceof WindowShadow)
343             return (WindowShadow)c;
344         else
345             return null;
346     }
347 
348     /**
349      * Calls show or hide, depending on the value of cond.
350      */
show(boolean cond)351     public void show(boolean cond) {
352         if (cond)
353             show();
354         else
355             hide();
356     }
357 
358     /**
359      * Shows the group by setting the visible attribute to true.
360      */
show()361     public void show() {
362         set(/* NOI18N */"visible", Boolean.TRUE);
363     }
364 
365     /**
366      * Hides the group by setting the visible attribute to false.
367      */
hide()368     public void hide() {
369         set(/* NOI18N */"visible", Boolean.FALSE);
370     }
371 
372     /**
373      * Returns true if the group is currently visible.
374      *
375      * If the application has not yet been fully initialized
376      * and created,
377      * then isVisible may return true for a group that is  not yet
378      * visible on the screen.  This means that by the time the
379      * initialization is complete, the group will be visible
380      * on the screen.
381      */
isVisible()382     public boolean isVisible() {
383         Group base = getBase();
384         if (base == null)
385             return false;
386         else
387             return base.wouldBeVisible(this);
388     }
389 
390     /**
391      * Returns true if the child group passed as a parameter
392      * will be visible
393      * when this group is made visible.  If the group parameter
394      * is not a
395      * child of this group, then the return value will be false.
396      */
wouldBeVisible(Group group)397     public boolean wouldBeVisible(Group group) {
398         while (group != null && group != this) {
399             Boolean v = (Boolean)group.get(/* NOI18N */"visible");
400             if (!v.booleanValue())
401                 return false;
402 
403             AttributeManager mgr = (AttributeManager)group.getParent();
404             while (!(mgr instanceof Root)) {
405                 v = (Boolean)mgr.get(/* NOI18N */"visible");
406                 if (!v.booleanValue())
407                     return false;
408                 mgr = (AttributeManager)mgr.getParent();
409             }
410 
411             if (mgr == null)
412                 return false;
413 
414             group = ((Root)mgr).getGroup();
415         }
416 
417         if (group == null)
418             return false;
419 
420         return true;
421     }
422 
423     /**
424      * Returns true if the group is currently showing.
425      */
isShowing()426     public boolean isShowing() {
427         return isShowing;
428     }
429 
430     /**
431      * The only reason that this method exists if because
432      *  the FrameEditor
433      * bypasses the visible attribute, and calls internalShowGroup
434      * directly.  This means that the group becomes visible
435      * even though
436      * the visible attribute is set to false.  In this situation, we
437      * still want the isVisible call for child groups to
438      * return true,
439      * hence the need for the isContainerVisible method.
440      */
isContainerVisible()441     private boolean isContainerVisible() {
442         if (inDesignerRoot()) {
443             ComponentShadow s = getContainer();
444             if (s == null)
445                 return false;
446 
447             Component comp = (Component)s.getBody();
448             if (comp == null)
449                 return false;
450 
451             return comp.isVisible();
452         } else {
453             return false;
454         }
455     }
456 
457     // NOTE: Any changes made to this comment should also
458     // be made in the
459     // lib/visual/gen/group.java file.
460     /**
461      * May be overridden by group subclasses that want
462      * to know when the group becomes visible.
463      *  It is called just before
464      * the group becomes visible.
465      *  The group will already be initialized
466      * and created at this point.
467      */
showGroup()468     protected void showGroup() {
469     }
470 
471     /**
472      * Shows the group.  Calling internalShowGroup does
473      * not affect the
474      * value of the visible attribute.
475      */
internalShowGroup()476     void internalShowGroup() {
477         Group base = null;
478 
479         // Initialize ourselves if we haven't been initialized yet
480         if (!isInitialized) {
481             base = getBase();
482             if (base != null)
483                 base.setCursor(Frame.WAIT_CURSOR);
484 
485             initialize();
486         }
487 
488         // Create ourselves if we haven't been created yet
489         if (!isCreated) {
490             doingShow = true;
491             create();
492             doingShow = false;
493         }
494 
495         if (!isShowing) {
496             isShowing = true;
497 
498             if (root != null)
499                 showGroup();
500 
501             // showGroup might call hide (trust me, it can happen)
502             if (!isShowing)
503                 return;
504         }
505 
506         //
507         // Invoke "show" on all the child groups that
508         // are not directly
509         // descended from the root.  This solves two problems:
510         //
511         // 1) Panel groups are not immediate children of the root,
512         //    therefore showRoot does not show the panel groups.
513         //
514         // 2) Some of the groups may not yet be created due
515         // to delayed
516         // instantiation.  Calling internalShowGroup
517         // on these groups
518         // will cause them to be initialized and created, as well as
519         // shown. For example, say that this group was created while
520         // its visible attribute was set to false.  This means that
521         //   none of its child groups would be created because
522         // isVisible
523         //    would return false for them.
524         //  Now say that visibile is set
525         //   to true for this group, causing internalShowGroup to be
526         //    called.  At this point, the child groups need to be
527         //    initialized, created and shown, because now
528         // isVisible will
529         //    return true for them.
530         //
531         // Note that this needs to be done before the call
532         // to showRoot.
533         // This is because panel groups must be created
534         // before the frames
535         // that contain them are shown in showRoot,or else the frame
536 	// will come up the wrong size.
537         //
538         Enumeration e = children.elements();
539         while (e.hasMoreElements()) {
540             Group child = (Group)e.nextElement();
541             if (wouldBeVisible(child) && child.getParent() != root)
542                 child.internalShowGroup();
543         }
544 
545         // Invoke "show" on all the children of the root
546         if (root != null)
547             root.showRoot();
548 
549         // Start the group if it isn't already started
550         if (hasStarted() && !isStarted)
551             start();
552 
553         // Revert the cursor
554         if (base != null)
555             base.setCursor(RESTORE_CURSOR);
556     }
557 
558     // NOTE: Any changes made to this comment should
559     // also be made in the
560     // lib/visual/gen/group.java file.
561     /**
562      * May be overridden by group subclasses that want
563      * to know when the group becomes non-visible.
564      *  It is called just
565      * before the group becomes non-visible.
566      */
hideGroup()567     protected void hideGroup() {
568     }
569 
570     /**
571      * Hides the group.  Calling hideGroup does not affect the
572      * value of the visible attribute.
573      *  You should normally use "hide"
574      * instead of "hideGroup" so that the visible attribute is
575      * properly
576      * updated.
577      */
internalHideGroup()578     void internalHideGroup() {
579         if (!isInitialized)
580             return;
581 
582         if (isShowing) {
583             isShowing = false;
584             if (root != null)
585                 hideGroup();
586         }
587 
588         // Invoke "hide" on all the child groups
589         Enumeration e = children.elements();
590         while (e.hasMoreElements()) {
591             Group group = (Group)e.nextElement();
592             if (group.getParent() != root)
593                 group.internalHideGroup();
594         }
595 
596         // Invoke "hide" on all the children of the root
597         if (root != null)
598             root.hideRoot();
599     }
600 
601     //
602     // Create and Destroy - Life span of the shadow bodies
603     //
604 
605     /**
606      * Create the group.  Creating the group causes
607      * all the AWT components
608      * to be created.  Also, the createGroup method is called during
609      * group creation.
610      */
create()611     public void create() {
612         // Initialize ourselves if we haven't been initialized yet
613         if (!isInitialized)
614             initialize();
615 
616         if (!hasBase()) {
617             throw new Error(Global.getMsg(
618 		    "sunsoft.jws.visual.rt.base.Group.GroupCreationWarning"));
619         }
620 
621         boolean wasCreated = isCreated;
622         boolean tmpShow = doingShow;
623         boolean shouldShow = false;
624 
625         if (!wasCreated && !doingShow() && isVisible()) {
626             // Set the doingShow flag to true so that the windows
627             // under the
628             // root will not show while they are being created.
629             //  We want to
630             // have them wait to be shown until internalShowGroup
631             // is called.
632             doingShow = true;
633             shouldShow = true;
634         }
635 
636         super.create();
637 
638         if (root == null && !(this instanceof NVGroup))
639             throw new Error(Global.getMsg(
640 		    "sunsoft.jws.visual.rt.base.Group.RootIsNull2"));
641 
642         if (root != null)
643             root.create();
644 
645         if (!wasCreated) {
646             createGroup();
647 
648             // Show the group if it is visible
649             if (shouldShow)
650                 internalShowGroup();
651         }
652 
653         doingShow = tmpShow;
654     }
655 
656     // NOTE: Any changes made to this comment should
657     // also be made in the
658     // lib/visual/gen/group.java file.
659     /**
660      * Called during group creation.  Groups can be
661      * created and destroyed multiple times during their lifetime.
662      * Anything that is created in createGroup should be cleaned up
663      * in destroyGroup.  createGroup is called just after the group
664      * has been created.  Anything that needs to be done before the
665      * group is created should be done in initGroup.
666      */
createGroup()667     protected void createGroup() {}
668 
669     /**
670      * Destroy the group.  This will destroy all AWT components, but
671      * does not destroy the shadow tree or the group tree. The group
672      * can be created again after a destroy by calling the "create"
673      * method.
674      */
destroy()675     public void destroy() {
676         if (!isInitialized)
677             return;
678 
679         stop();
680 
681         if (isCreated)
682             destroyGroup();
683 
684         super.destroy();
685 
686         if (root != null)
687             root.destroy();
688     }
689 
690     // NOTE: Any changes made to this comment should also
691     // be made in the
692     // lib/visual/gen/group.java file.
693     /**
694      * Called during the destroy operation.  Groups can
695      * be created and destroyed multiple times during their
696      * lifetime.
697      * Anything that has been created in createGroup should be
698      * cleaned up
699      * in destroyGroup.  destroyGroup is called just before the
700      * group
701      * is destroyed.
702      */
destroyGroup()703     protected void destroyGroup() {}
704 
705     //
706     // start/stop
707     //
708 
709     /**
710      * This method should not be overridden by group subclasses.
711      * The "startGroup" method should be overridden instead.
712      */
start()713     public void start() {
714         if (!isInitialized)
715             return;
716 
717         if (!isCreated)
718             create();
719 
720         if (!isStarted) {
721             isStarted = true;
722             startGroup();
723         }
724 
725         Enumeration e = children.elements();
726         while (e.hasMoreElements()) {
727             Group child = (Group)e.nextElement();
728             if (wouldBeVisible(child))
729                 child.start();
730         }
731     }
732 
733     // NOTE: Any changes made to this comment should also
734     // be made in the
735     // lib/visual/gen/group.java file.
736     /**
737      * May be overridden by group subclasses that want
738      * to be informed when the application is starting.
739      *  This method is
740      * only called after the entire application has been
741      * initialized and created.
742      *
743      * For applets, startGroup is called whenever start
744      * is called on the  applet.
745      */
startGroup()746     protected void startGroup() {}
747 
748     /**
749      * Returns true if the group is currently started.
750      */
isStarted()751     public boolean isStarted() {
752         return isStarted;
753     }
754 
755     /**
756      * This method should not be overridden by group subclasses.
757      * The "stopGroup" method should be overridden instead.
758      */
stop()759     public void stop() {
760         if (!isInitialized)
761             return;
762 
763         if (isStarted) {
764             isStarted = false;
765             stopGroup();
766         }
767 
768         Enumeration e = children.elements();
769         while (e.hasMoreElements())
770             ((Group)e.nextElement()).stop();
771     }
772 
773     // NOTE: Any changes made to this comment should also
774     // be made in the
775     // lib/visual/gen/group.java file.
776     /**
777      * May be overridden by group subclasses that want
778      * to be informed when the application is stopping.  This method
779      * will be called before a destroy is done.
780      *
781      * For applets, stopGroup is called whenever stop is called
782      * on the applet.
783      */
stopGroup()784     protected void stopGroup() {}
785 
786     /**
787      * Returns true if the base group has been started.
788      */
hasStarted()789     protected boolean hasStarted() {
790         if (isBase()) {
791             return isStarted;
792         } else if (parentGroup != null) {
793             return parentGroup.hasStarted();
794         } else {
795             return false;
796         }
797     }
798 
799     //
800     // Group tree - An group can be either a node or a leaf.
801     //
802 
add(Group child)803     void add(Group child) {
804         if (!children.contains(child)) {
805             child.setParentGroup(this);
806             children.addElement(child);
807         }
808     }
809 
remove(Group child)810     void remove(Group child) {
811         if (children.contains(child)) {
812             child.setParentGroup(null);
813             children.removeElement(child);
814         }
815     }
816 
addRootChildren(Root root)817     void addRootChildren(Root root) {
818         addChildren((AMContainer)root);
819     }
820 
addChildren(AMContainer cntr)821     private void addChildren(AMContainer cntr) {
822         Enumeration e = cntr.getChildList();
823         while (e.hasMoreElements()) {
824             AttributeManager child = (AttributeManager)e.nextElement();
825             if (child instanceof Group)
826                 add((Group)child);
827             if (child instanceof AMContainer)
828                 addChildren((AMContainer)child);
829         }
830     }
831 
removeRootChildren(Root root)832     void removeRootChildren(Root root) {
833         Enumeration e = children.elements();
834         while (e.hasMoreElements()) {
835             Group child = (Group)e.nextElement();
836             if (child.getRoot() == root)
837                 remove(child);
838         }
839     }
840 
841     /**
842      * Looks up a named child group of this group.  Not recursive.
843      */
getChild(String name)844     public Group getChild(String name) {
845         for (Enumeration e = children.elements(); e.hasMoreElements(); )
846 	    {
847 		Group child = (Group)e.nextElement();
848 		if (name.equals(child.get(/* NOI18N */"name")))
849 		    return (child);
850 	    }
851         return (null);
852     }
853 
854     /**
855      * Returns an enumerated list of this group's children. The list
856      * is cloned because the caller might use it for removing child
857      * groups from this group.
858      */
getChildList()859     public Enumeration getChildList() {
860         return ((Vector)children.clone()).elements();
861     }
862 
setParentGroup(Group parent)863     private void setParentGroup(Group parent) {
864         parentGroup = parent;
865     }
866 
867     /**
868      * Returns this group's parent.
869      */
getParentGroup()870     public Group getParentGroup() {
871         return parentGroup;
872     }
873 
874     /**
875      * Returns this group (overrides the behavior of getGroup
876      * as defined in AttributeManager).
877      */
getGroup()878     public Group getGroup() {
879         return this;
880     }
881 
882     /**
883      * Returns a hierarchy name based on the group tree.
884      */
getFullName()885     public String getFullName() {
886         String name = getName();
887         if (name == null)
888             return null;
889 
890         if (parentGroup != null) {
891             String parentName = parentGroup.getFullName();
892             if (parentName != null)
893                 name = parentName + /* NOI18N */"." + name;
894         }
895 
896         return name;
897     }
898 
899     /**
900      * Find a component from its full path name.
901      */
resolveFullName(String name)902     public AttributeManager resolveFullName(String name) {
903         AttributeManager mgr = null;
904         Group group = this;
905         Group newGroup;
906 
907         while (group != null && !group.isBase())
908             group = group.parentGroup;
909         if (group == null)
910             return null;
911 
912         StringTokenizer st = new StringTokenizer(name, /* NOI18N */".");
913 
914         if (group.getName() != null) {
915             if (!st.hasMoreTokens())
916                 return null;
917 
918             name = st.nextToken();
919             if (!name.equals(group.getName()))
920                 return null;
921         }
922 
923         while (st.hasMoreTokens()) {
924             name = st.nextToken();
925             newGroup = group.resolveGroup(name);
926 
927             if (newGroup == null) {
928                 if (group.root == null)
929                     return null;
930 
931                 mgr = group.root.resolve(name);
932                 break;
933             } else {
934                 group = newGroup;
935             }
936         }
937 
938         if (st.hasMoreTokens())
939             return null;
940 
941         return mgr;
942     }
943 
944     /**
945      * Recursively looks for a named sub-group of this group.
946      */
resolveGroup(String name)947     public Group resolveGroup(String name) {
948         Group group;
949         String groupName;
950 
951         Enumeration e = children.elements();
952         while (e.hasMoreElements()) {
953             group = (Group)e.nextElement();
954             groupName = group.getName();
955             if (groupName != null &&
956 		groupName.equals(name)) {
957                 return group;
958             }
959         }
960 
961         return null;
962     }
963 
964     //
965     // AWT parenting
966     //
967 
setParentBody()968     void setParentBody() {
969         if (root != null)
970             root.addChildBody(getContainer());
971     }
972 
unsetParentBody()973     void unsetParentBody() {
974         if (root != null)
975             root.removeChildBody(getContainer());
976     }
977 
978     /**
979      * Add an operations class.
980      */
addOperations(Operations ops)981     public synchronized void addOperations(Operations ops) {
982         if (operations == null)
983             operations = new Vector();
984 
985         if (!operations.contains(ops)) {
986             ops.setGroup(this);
987             if (root != null)
988                 ops.setRoot(root);
989             operations.addElement(ops);
990         }
991     }
992 
993     /**
994      * Remove an operations class.
995      */
removeOperations(Operations ops)996     public synchronized void removeOperations(Operations ops) {
997         if (operations != null)
998             operations.removeElement(ops);
999     }
1000 
1001     //
1002     // Events
1003     //
1004 
1005     /**
1006      * Posts a message to this group's parent.  This method should
1007      * be used when sending a message from within this group.
1008      */
postMessageToParent(Message msg)1009     public void postMessageToParent(Message msg) {
1010         if (parentGroup != null)
1011             parentGroup.postMessage(msg);
1012     }
1013 
1014     /**
1015      * Posts a message to this group.  This method should
1016      * be used when sending a message to this group.
1017      */
postMessage(Message msg)1018     public void postMessage(Message msg) {
1019         // Distribute the message to the operations classes
1020         if (operations != null) {
1021             Enumeration e = operations.elements();
1022             while (e.hasMoreElements()) {
1023                 Operations ops = (Operations)e.nextElement();
1024                 if (ops.handleMessage(msg))
1025                     return;
1026             }
1027         }
1028 
1029         // Handle the message
1030         if (handleMessage(msg))
1031             return;
1032 
1033         // Don't pass AWT events up to the parent.  If you want
1034         // an AWT event
1035         // to go to the parent group, call
1036         // "parent.postEvent()" directly.
1037         if (!msg.isAWT && parentGroup != null)
1038             parentGroup.postMessage(msg);
1039     }
1040 
1041     // NOTE: Any changes made to this comment should also be
1042     // made in the
1043     // lib/visual/gen/group.java file.
1044     /**
1045      * May be overridden by subclasses that want to act
1046      * on messages that are sent to the group.
1047      * Typically, messages are
1048      * either AWT events that have been translated to
1049      * messages, or they
1050      * are messages that have been sent by other groups.
1051      * super.handleMessage should be called for any messages
1052      * that aren't handled.  If super.handleMessage is not
1053      * called, then handleEvent
1054      * will not be called.
1055      * <p>
1056      * AWT events are not propagated regardless of the return
1057      * value from
1058      * handleEvent.  If you want an AWT event to go to the parent
1059      * group, you need to call postMessageToParent()
1060      * with the event message.
1061      * <p>
1062      */
handleMessage(Message msg)1063     public boolean handleMessage(Message msg) {
1064         if (msg.isAWT) {
1065             Event evt = (Event)msg.arg;
1066 
1067             handleEvent(msg, evt);
1068 
1069             // Post AcceleratorKey messages for certain keys
1070             if (evt.id == Event.KEY_PRESS && evt.key != 0 &&
1071 		(evt.key < 32 || evt.key >= 127)) {
1072                 postMessage(new Message(this,
1073 					/* NOI18N */"AcceleratorKey", evt));
1074             }
1075 
1076             return true;
1077         }
1078 
1079         return false;
1080     }
1081 
1082     // NOTE: Any changes made to this comment should also be
1083     // made in the
1084     // lib/visual/gen/group.java file.
1085     /**
1086      * May be overridden by subclasses that want to get
1087      * notified when AWT events that are sent by the gui components.
1088      * The return value should be true for handled events, and
1089      * super.handleEvent should be called for unhandled events.
1090      * If super.handleEvent is not called, then the specific event
1091      * handling methods will not be called.
1092      * <p>
1093      * The message's target is set to the shadow that sent
1094      * the event.
1095      * The event's target is set to the AWT component that
1096      * sent the event.
1097      * <p>
1098      * The following more specific methods may also be overridden:
1099      * <pre>
1100      * public boolean mouseDown(Message msg,
1101      * Event evt, int x, int y);
1102      * public boolean mouseDrag(Message msg, Event evt,
1103      * int x, int y);
1104      * public boolean mouseUp(Message msg, Event evt, int x, int y);
1105      * public boolean mouseMove(Message msg, Event evt,
1106      * int x, int y);
1107      * public boolean mouseEnter(Message msg, Event evt,
1108      * int x, int y);
1109      * public boolean mouseExit(Message msg, Event evt,
1110      * int x, int y);
1111      * public boolean keyDown(Message msg, Event evt, int key);
1112      * public boolean keyUp(Message msg, Event evt, int key);
1113      * public boolean action(Message msg, Event evt, Object what);
1114      * public boolean gotFocus(Message msg, Event evt, Object what);
1115      * public boolean lostFocus(Message msg,
1116      * Event evt, Object what);
1117      * </pre>
1118      */
handleEvent(Message msg, Event evt)1119     public boolean handleEvent(Message msg, Event evt) {
1120         if (super.handleEvent(msg, evt))
1121             return true;
1122 
1123         // Intercept some of the WINDOW events.
1124         //  Sub-groups that want to do
1125         // something different with these WINDOW events
1126         // should return true
1127         // after handling the event.
1128 
1129         switch (evt.id) {
1130 	case Event.WINDOW_DESTROY:
1131             windowDestroy(msg);
1132             return true;
1133 
1134 	case Event.WINDOW_ICONIFY:
1135             if (evt.target instanceof Window) {
1136                 if (isBaseWindow((Window)evt.target)) {
1137                     hide();
1138                     return true;
1139                 }
1140             }
1141             return false;
1142 
1143 	case Event.WINDOW_DEICONIFY:
1144             if (evt.target instanceof Window) {
1145                 if (isBaseWindow((Window)evt.target)) {
1146                     show();
1147                     return true;
1148                 }
1149             }
1150             return false;
1151         }
1152 
1153         return false;
1154     }
1155 
1156     /**
1157      * Exit the application with no error code.
1158      */
exit()1159     public void exit() {
1160         exit(0);
1161     }
1162 
1163     /**
1164      * Exit the application.  Calls exit on the parent
1165      * if there is a parent.
1166      * Only calls System.exit() if there is no applet.
1167      */
exit(int errCode)1168     public void exit(int errCode) {
1169         if (isBase()) {
1170             destroy();
1171             if (applet == null)
1172                 System.exit(errCode);
1173         } else if (parentGroup != null) {
1174             parentGroup.exit(errCode);
1175         } else {
1176             destroy();
1177         }
1178     }
1179 
1180     /**
1181      * Called when a WINDOW_DESTROY event is received by this group.
1182      * The default behavior for WINDOW_DESTROY events is to
1183      * set the visible
1184      * attribute to false for the target of the event.
1185      * If the target of
1186      * the event is the main window, then set this group's
1187      * visible attribute
1188      * to false.  If this group is the base group, then exit the
1189      * application.
1190      */
windowDestroy(Message msg)1191     protected void windowDestroy(Message msg) {
1192         if (msg.target == getContainer()) {
1193             if (inDesignerRoot())
1194                 internalHideGroup();
1195             else if (isBase())
1196                 exit();
1197             else
1198                 hide();
1199         } else {
1200             if (msg.target instanceof AttributeManager)
1201                 ((AttributeManager)msg.target).set(/* NOI18N */"visible",
1202 						Boolean.FALSE);
1203             else if (msg.target instanceof Component)
1204                 ((Component)msg.target).hide();
1205         }
1206     }
1207 
1208     /**
1209      * Attribute forwarding
1210      */
1211 
1212     private Vector forwardVector = new Vector();
1213 
1214     /**
1215      * Adds the attribute manager to the list of forwards.  When
1216      * an attribute is set and is flagged FORWARD, the value for the
1217      * attribute will be forwarded to every matching attribute
1218      * manager
1219      * in the list of forwards.
1220      */
addAttributeForward(AttributeManager mgr)1221     protected void addAttributeForward(AttributeManager mgr) {
1222         if (forwardVector.contains(mgr))
1223             return;
1224 
1225         // Add this guy to the list of attribute forwards
1226         forwardVector.addElement(mgr);
1227 
1228         // Override values in mgr with values from forwards
1229         Enumeration e = attributes.attributesWithFlags(FORWARD);
1230 
1231         while (e.hasMoreElements()) {
1232             Attribute attr = (Attribute)e.nextElement();
1233             String name = attr.getName();
1234             String type = attr.getType();
1235 
1236             if (mgr.hasAttribute(name, type)) {
1237                 Object value = mgr.get(name);
1238 
1239                 if (!attr.flagged(READONLY)) {
1240                     if (!attr.isModified())
1241                         putInTable(name, value);
1242                     else
1243                         if (!mgr.getAttribute(name).flagged(READONLY))
1244 			    mgr.set(name, attr.getValue());
1245                 }
1246 
1247                 attr.setDefaultValue(value);
1248             }
1249         }
1250     }
1251 
1252     /**
1253      * Adds a set of attributes to this group that
1254      * are suitable for forwarding to a frame, dialog or panel.
1255      */
addForwardedAttributes()1256     protected void addForwardedAttributes() {
1257         if (genericAttrList == null) {
1258             genericAttrList = new AttributeList();
1259             mergeForward(genericAttrList, new VJPanelShadow());
1260             mergeForward(genericAttrList, new FrameShadow());
1261             mergeForward(genericAttrList, new DialogShadow());
1262         }
1263 
1264         Enumeration e = genericAttrList.elements();
1265         while (e.hasMoreElements()) {
1266             Attribute attr = (Attribute)e.nextElement();
1267             if (!hasAttribute(attr.getName()))
1268                 attributes.add((Attribute)attr.clone());
1269         }
1270 
1271         if (!hasAttribute(/* NOI18N */"text"))
1272             attributes.alias(/* NOI18N */"text", /* NOI18N */"title");
1273     }
1274 
mergeForward(AttributeList list, Shadow shadow)1275     private void mergeForward(AttributeList list, Shadow shadow) {
1276         AttributeList shadowList =
1277 	    (AttributeList)shadow.getAttributeList().clone();
1278         Enumeration e = shadowList.elements();
1279 
1280         while (e.hasMoreElements()) {
1281             Attribute attr = (Attribute)e.nextElement();
1282             if (!list.contains(attr.getName())) {
1283                 // System.out.println(/* NOI18N */"add " +
1284                 // attr.getName() + /* NOI18N */" " + attr.getType());
1285                 attr.addFlags(FORWARD | FORWARD_REMOVE);
1286                 list.add(attr);
1287             }
1288         }
1289     }
1290 
removeForwardedAttributes()1291     private void removeForwardedAttributes() {
1292         ContainerShadow cntr = getContainer();
1293         if (cntr == null)
1294             return;
1295 
1296         Enumeration e = attributes.attributesWithFlags(FORWARD_REMOVE);
1297         while (e.hasMoreElements()) {
1298             Attribute attr = (Attribute)e.nextElement();
1299             if (!cntr.hasAttribute(attr.getName())) {
1300                 attributes.remove(attr.getName());
1301             }
1302         }
1303     }
1304 
1305     /**
1306      * Return true if we are forwarding the attribute "attrName"
1307      * to "mgr",
1308      * otherwise return false.
1309      */
hasAttributeForward(AttributeManager mgr, String attrName)1310     boolean hasAttributeForward(AttributeManager mgr, String attrName) {
1311         return (forwardVector.contains(mgr) &&
1312 		attributes.get(attrName).flagged(FORWARD));
1313     }
1314 
1315     /**
1316      * These are helper routines for the group.
1317      * If you are fowarding
1318      * attributes to a component, dialog or frame, you should call
1319      * one of these methods in the constructor.
1320      */
1321 
1322     private static AttributeList genericAttrList = null;
1323 
1324     /**
1325      * Compatibility method - do not use!
1326      */
addComponentAttributes()1327     protected void addComponentAttributes() {
1328         addForwardedAttributes();
1329     }
1330 
1331     /**
1332      * Compatibility method - do not use!
1333      */
addPanelAttributes()1334     protected void addPanelAttributes() {
1335         addForwardedAttributes();
1336     }
1337 
1338     /**
1339      * Compatibility method - do not use!
1340      */
addFrameAttributes()1341     protected void addFrameAttributes() {
1342         addForwardedAttributes();
1343     }
1344 
1345     /**
1346      * Compatibility method - do not use!
1347      */
addDialogAttributes()1348     protected void addDialogAttributes() {
1349         addForwardedAttributes();
1350     }
1351 
1352     //
1353     // Attributes - get and set
1354     //
1355 
1356     /**
1357      * Get the value of a named attribute.
1358      */
get(String key)1359     public Object get(String key) {
1360         Attribute attr = attributes.get(key);
1361 
1362         if (key.equals(/* NOI18N */"name")) {
1363             return super.get(key);
1364         } else if (key.equals(/* NOI18N */"visible")) {
1365             return super.get(key);
1366         } else if (!isInitialized) {
1367             return super.get(key);
1368         } else if (attr != null && attr.flagged(FORWARD)) {
1369             Enumeration e = forwardVector.elements();
1370             AttributeManager mgr;
1371 
1372             while (e.hasMoreElements()) {
1373                 mgr = (AttributeManager)e.nextElement();
1374                 if (mgr.hasAttribute(key, attr.getType())) {
1375                     return mgr.get(key);
1376                 }
1377             }
1378 
1379             return null;
1380         } else {
1381             return getOnGroup(key);
1382         }
1383     }
1384 
1385     // NOTE: Any changes made to this comment should also
1386     // be made in the
1387     // lib/visual/gen/group.java file.
1388     /**
1389      * May be overridden by sub-groups that
1390      * store attribute values themselves, and do not depend on the
1391      * group superclass to store them.
1392      * This method should be overridden
1393      * instead of "get".  Any attributes handled in setOnGroup where
1394      * super.setOnGroup is not called must also be handled
1395      * in getOnGroup.
1396      * <p>
1397      * The default implementation of getOnGroup retrieves the value
1398      * from the attribute table.
1399      * <p>
1400      * The reason that "getOnGroup" should be overridden instead
1401      * of "get" is that "getOnGroup" is guaranteed not to be called
1402      * until the group class is initialized.
1403      * This means that initRoot
1404      * will always be called before any calls to getOnGroup
1405      * are made.
1406      * <p>
1407      * Also, this method is only for attributes that are defined
1408      * in the
1409      * sub-groups.  It is not called for forwarded attributes.
1410      * <p>
1411      */
getOnGroup(String key)1412     protected Object getOnGroup(String key) {
1413         return super.get(key);
1414     }
1415 
1416     /**
1417      * Set the value of a named attribute.
1418      */
set(String key, Object value)1419     public void set(String key, Object value) {
1420         Attribute attr = attributes.get(key);
1421 
1422         if (key.equals(/* NOI18N */"name")) {
1423             super.set(key, value);
1424         } else if (key.equals(/* NOI18N */"visible")) {
1425             super.set(key, value);
1426             if (((Boolean)value).booleanValue()) {
1427                 if (isVisible())
1428                     internalShowGroup();
1429             } else
1430                 internalHideGroup();
1431         } else if (!isInitialized) {
1432             super.set(key, value);
1433         } else if (attr != null && attr.flagged(FORWARD)) {
1434             super.set(key, value);
1435 
1436             Enumeration e = forwardVector.elements();
1437             AttributeManager mgr;
1438             boolean set = false;
1439 
1440             while (e.hasMoreElements()) {
1441                 mgr = (AttributeManager)e.nextElement();
1442                 if (mgr.hasAttribute(key, attr.getType())) {
1443                     mgr.set(key, value);
1444                     set = true;
1445                 }
1446             }
1447 
1448             if (set) {
1449                 // update the the global register for unsaved changes
1450                 if (inDesignerRoot())
1451                     DesignerAccess.setChangesMade(true);
1452             }
1453         } else {
1454             setOnGroup(key, value);
1455         }
1456     }
1457 
1458     // NOTE: Any changes made to this comment should also
1459     // be made in the
1460     // lib/visual/gen/group.java file.
1461     /**
1462      * May be overridden by sub-groups that
1463      * want notification when attributes are changed.  This method
1464      * should be overridden instead of "set".
1465      * Any attributes handled
1466      * in setOnGroup where super.setOnGroup is not called
1467      * must also be
1468      * handled in getOnGroup.
1469      * <p>
1470      * The default implementation of setOnGroup puts the value
1471      * in the attribute table.
1472      * <p>
1473      * The reason that "setOnGroup" should be overridden instead
1474      * of "set" is that "setOnGroup" is guaranteed not to be called
1475      * until the group class is initialized.
1476      * This means that initRoot
1477      * will always be called before any calls to setOnGroup
1478      * are made.
1479      * <p>
1480      * During initialization, "setOnGroup" will be called for all
1481      * the group's attributes even if they have not be changed from
1482      * the default value.  But for attributes that have the DEFAULT
1483      * flag set, "setOnGroup" will only be called if the value
1484      * of the attribute has changed from the default.
1485      * <p>
1486      * Also, this method is only called when attributes defined
1487      * in the
1488      * sub-groups are updated.  It is not called for forwarded
1489      * attributes.
1490      * <p>
1491      */
setOnGroup(String key, Object value)1492     protected void setOnGroup(String key, Object value) {
1493         super.set(key, value);
1494     }
1495 
1496     /**
1497      * Base group information.
1498      */
1499 
1500     private Applet applet = null;
1501     private String cmdLineArgs[];
1502     private Frame topLevel = null;
1503     private Registry registry = null;
1504 
1505     private boolean hasEnvironment = false;
1506 
hasEnvironment()1507     private boolean hasEnvironment() {
1508         if (hasEnvironment)
1509             return true;
1510         else if (parentGroup != null)
1511             return parentGroup.hasEnvironment();
1512         else
1513             return false;
1514     }
1515 
1516     /**
1517      * Returns true if this group is the base group.
1518      */
isBase()1519     public boolean isBase() {
1520         return hasEnvironment;
1521     }
1522 
1523     /**
1524      * Returns true if the given window this group's base window.
1525      */
isBaseWindow(Window win)1526     protected boolean isBaseWindow(Window win) {
1527         WindowShadow shadow =
1528 	    (WindowShadow)DesignerAccess.getShadowTable().get(win);
1529         return (isBase() && (getWindow() == shadow));
1530     }
1531 
1532     /**
1533      * Returns true if this group is either the base group
1534      * or is a descendant
1535      * of the base group.
1536      */
hasBase()1537     public boolean hasBase() {
1538         if (hasEnvironment)
1539             return true;
1540         else if (parentGroup != null)
1541             return parentGroup.hasBase();
1542         else
1543             return false;
1544     }
1545 
1546     /**
1547      * Returns the base group.
1548      */
getBase()1549     public Group getBase() {
1550         if (hasEnvironment)
1551             return this;
1552         else if (parentGroup != null)
1553             return parentGroup.getBase();
1554         else
1555             return null;
1556     }
1557 
1558     /**
1559      * Returns true if we are doing a create operation in the
1560      * middle of a show operation.  Create likes to call show if the
1561      * visible attribute is set to true, but create shouldn't call
1562      * show if show caused create to be called if the first place.
1563      */
doingShow()1564     boolean doingShow() {
1565         if (doingShow)
1566             return true;
1567         else if (parentGroup != null)
1568             return parentGroup.doingShow();
1569         else
1570             return false;
1571     }
1572 
1573     /**
1574      * Sets the environment information for the group.
1575      * This method should
1576      * be invoked only on the top-most group in the application.
1577      * Invoking
1578      * setEnvironmentInfo and setTopLevel on a group makes
1579      * it the base group.
1580      */
setEnvironmentInfo(Applet applet, String args[])1581     public void setEnvironmentInfo(Applet applet, String args[]) {
1582         // checkDate();
1583         this.applet = applet;
1584         this.cmdLineArgs = args;
1585         hasEnvironment = true;
1586     }
1587 
1588     /**
1589      * Sets the top level frame for the group.  This method should
1590      * be invoked only on the top most group in the application.
1591      * Invoking setEnvironmentInfo and setTopLevel on a group
1592      * makes it
1593      * the base group.
1594      */
setTopLevel(Frame topLevel)1595     public void setTopLevel(Frame topLevel) {
1596         this.topLevel = topLevel;
1597     }
1598 
1599     /**
1600      * Sets the cursor for all of the group's frames to the given
1601      * cursor value.  Calls setCursor on all the child groups.
1602      */
setCursor(int cursor)1603     public void setCursor(int cursor) {
1604         if (root != null)
1605             root.setCursor(cursor);
1606 
1607         Enumeration e = children.elements();
1608         while (e.hasMoreElements()) {
1609             Group child = (Group)e.nextElement();
1610             child.setCursor(cursor);
1611         }
1612     }
1613 
1614     /**
1615      * Accessor method for the applet. Null is returned
1616      * when you're not
1617      * running as an applet.
1618      */
getApplet()1619     public Applet getApplet() {
1620         if (applet != null)
1621             return applet;
1622         else if (parentGroup != null)
1623             return parentGroup.getApplet();
1624         else
1625             return null;
1626     }
1627 
1628     /**
1629      * Accessor method for the command line arguments.
1630      * Null is returned
1631      * when you're not running from the command line.
1632      */
getCmdLineArgs()1633     public String[] getCmdLineArgs() {
1634         if (cmdLineArgs != null)
1635             return cmdLineArgs;
1636         else if (parentGroup != null)
1637             return parentGroup.getCmdLineArgs();
1638         else
1639             return null;
1640     }
1641 
1642     /**
1643      * Returns the first frame found while traversing up the
1644      * group tree.  If no frame is found, then the top level
1645      * frame is returned.
1646      */
getFrame()1647     public Frame getFrame() {
1648         WindowShadow win = getWindow();
1649         if (win != null && win.getBody() != null)
1650 	    {
1651 		if (win instanceof DialogShadow)
1652 		    return (Frame)((Window) win.getBody()).getParent();
1653 		else
1654 		    return (Frame)win.getBody();
1655 	    } else if (parentGroup != null)
1656 		return parentGroup.getFrame();
1657         else
1658             return getTopLevel();
1659     }
1660 
1661     /**
1662      * Accessor method for the top level frame.  This will not
1663      * return null providing that the base group has been
1664      * initialized  properly.
1665      */
getTopLevel()1666     public Frame getTopLevel() {
1667         if (topLevel != null)
1668             return topLevel;
1669         else if (parentGroup != null)
1670             return parentGroup.getTopLevel();
1671         else
1672             return null;
1673     }
1674 
1675     /**
1676      * Accessor method for the registry.  The registry is
1677      * created when
1678      * the application starts.
1679      */
getRegistry()1680     public Registry getRegistry() {
1681         if (isBase()) {
1682             initRegistry();
1683             return registry;
1684         } else if (parentGroup != null)
1685             return parentGroup.getRegistry();
1686         else
1687             return null;
1688     }
1689 
initRegistry()1690     private synchronized void initRegistry() {
1691         if (registry == null)
1692             registry = new Registry();
1693     }
1694 
layoutMode()1695     public void layoutMode() {
1696         super.layoutMode();
1697 
1698         WindowShadow s = getWindow();
1699         if (s != null)
1700             s.setLayout(true);
1701     }
1702 
previewMode()1703     public void previewMode() {
1704         super.previewMode();
1705 
1706         WindowShadow s = getWindow();
1707         if (s != null)
1708             s.setPreview(true);
1709     }
1710 
preValidate()1711     protected void preValidate() {
1712         PanelShadow panel = getPanel();
1713         if (panel != null)
1714             panel.preValidate();
1715     }
1716 }
1717