xref: /titanic_44/usr/src/cmd/krb5/kadmin/gui/visualrt/sunsoft/jws/visual/rt/base/AttributeManager.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  * @(#) AttributeManager.java 1.83 - last change made 07/29/97
34  */
35 
36 package sunsoft.jws.visual.rt.base;
37 
38 import sunsoft.jws.visual.rt.type.Op;
39 
40 import java.awt.Event;
41 import java.util.*;
42 
43 /*
44  * NOTE: Whenever a new public or protected variable is added to this
45  * class
46  * the name of the variable must be added to the reserved words list
47  * in the
48  * Root class so that the user doesn't use it in one of the
49  * generated Root
50  * sub-classes.
51  */
52 
53 /**
54  * The AttributeManager class is a base class for objects that
55  * have attributes.  The Shadow and Group classes are sub-classed
56  * from AttributeManager.
57  * <p>
58  * The attributes available for this
59  * class are listed below.  In the type column, type names beginning
60  * with "sunsoft.jws.visual.rt" have been abbreviated to begin
61  * with "rt".
62  *
63  * <pre>
64  * name            type                      default value
65  * -----------------------------------------------------------------------
66  * name            java.lang.String          null
67 *  < /pre>
68 *
69 * @version 1.83, 07/29/97
70 */
71 public class AttributeManager {
72     /**
73      * Flags
74      */
75 
76     /**
77      * Indicates a readonly attribute.  An attempt
78      * to set the attribute will result in an error.
79      */
80     public static final int READONLY = 0x1;
81 
82     /**
83      * Flags attributes that will not be shown in the Visual Java
84      * attribute editor.
85      */
86     public static final int HIDDEN = 0x2;
87 
88     /**
89      * Flags attributes that will not be stored in the
90      * save file.
91      */
92     public static final int TRANSIENT = 0x4;
93 
94     /**
95      * The parent will be notified by calling updateContainerAttribute
96      * on the parent whenever a CONTAINER attribute is changed.
97      */
98     public static final int CONTAINER = 0x8;
99 
100     /**
101      * This flag indicates that the default value for the attribute
102      * matches the default value for the AWT body.  If this flag is
103      * set, the setOnBody method will not be called during
104      * creation unless the value is actually changed.
105      * <p>
106      * Similarly for groups, if the DEFAULT flag is set, then
107      * setOnGroup will only be called during initialization if the
108      * attribute has actually changed.  Otherwise setOnGroup will
109      * be called regardless of whether the attribute has changed.
110      * <p>
111      * Note: This flag should only be used where performance is a
112      * concern, since resetting the default value on the AWT body
113      * should not change its behavior.
114      * <p>
115      */
116     public static final int DEFAULT = 0x10;
117 
118     /**
119      * This flag tells the attribute manager to not refetch the value
120      * of the attribute list during the refetchAttributes call.  This
121      * is useful for the AWT component fonts and colors that are
122      * inherited from their parent when set to null.
123      * If this flag were not set for those attributes, then they
124      * would end up everywhere in the save file.
125      */
126     public static final int DONTFETCH = 0x20;
127 
128     /**
129      * This flag tells the attribute editor's slot that it should
130      * not use
131      * a type editor for this attribute, even if there is one
132      * registered.
133      */
134     public static final int NOEDITOR = 0x400;
135 
136     /**
137      * The table where attributes are stored.
138      * Attributes may be added to this list during construction, but
139      * should not be added at any other time.
140      */
141     protected AttributeList attributes;
142 
143     /**
144      * The parent of this object.
145      */
146     AMContainer parent;
147 
148     /**
149      * A flag that is true once create() has been performed on a shadow
150      * object and remains so until destroy() is called.
151      */
152     boolean isCreated = false;
153 
154     /**
155      * Flag for storing the return value of inDesignerRoot while we
156      * are created.  This speeds up the check in sendToOps.
157      */
158     private Boolean inDesignerRoot = null;
159 
160     /**
161      * Creates the attributes list and assigns a unique name to this
162      * attribute manager.  Attributes may be added to the list of
163      * attributes
164      * in sub-class constructors, but should not be added at any
165      * other time.
166      */
AttributeManager()167     public AttributeManager() {
168         attributes = new AttributeList();
169 
170         // name will be set around the time this object is added
171         // to a container
172         attributes.add(/* NOI18N */"name",
173 		       /* NOI18N */"java.lang.String", null,
174 		       Shadow.NONBODY | NOEDITOR);
175 
176         // operations for defining callbacks
177         attributes.add(/* NOI18N */"operations",
178 		       /* NOI18N */"[Lsunsoft.jws.visual.rt.type.Op;", null,
179 		       Shadow.NONBODY);
180     }
181 
182     /**
183      * Returns the parent for this attribute manager.
184      */
getParent()185     public AMContainer getParent() {
186         return parent;
187     }
188 
189     /**
190      * Sets the parent for this attribute manager.
191      */
setParent(AMContainer parent)192     public void setParent(AMContainer parent) {
193         this.parent = parent;
194     }
195 
196     /**
197      * Returns true if we are not running inside the designer.
198      */
isLive()199     public boolean isLive() {
200         Root r = getRoot();
201         while (r != null) {
202             if (r.isLoadedRoot())
203                 return false;
204 
205             Group group = r.getGroup();
206             if (group == null)
207                 break;
208 
209             r = group.getRoot();
210         }
211 
212         return true;
213     }
214 
215     /**
216      * Returns true if this instance is a direct descendant
217      * of the designer root.  Being a direct descendant means
218      * that there are no intermediate groups between this
219      * attribute manager and the root.
220      * The designer root is the root that is built inside
221      * Visual Java.
222      */
inDesignerRoot()223     public boolean inDesignerRoot() {
224         if (inDesignerRoot != null)
225             return inDesignerRoot.booleanValue();
226         else
227             return checkDesignerRoot();
228     }
229 
checkDesignerRoot()230     private boolean checkDesignerRoot() {
231         Root myRoot = getRoot();
232         return (myRoot != null && myRoot.isLoadedRoot());
233     }
234 
235     /**
236      * Returns a type name suitable for use in making unique names for
237      * instances of this class (or one of its sub-classes).  This should
238      * be overridden in sub-classes to give more useful names.
239      */
getUserTypeName()240     protected String getUserTypeName() {
241         return (/* NOI18N */"manager");
242     }
243 
244     /**
245      * Puts an attribute's value directly into the attribute table.
246      */
putInTable(String key, Object value)247     protected final void putInTable(String key, Object value) {
248         Attribute a = attributes.get(key);
249         if (a == null)
250             throw new Error(Global.fmtMsg(
251 "sunsoft.jws.visual.rt.base.AttributeManager.SetInvalidAttribute", key));
252         if (a.flagged(READONLY))
253             throw new Error(Global.fmtMsg(
254 "sunsoft.jws.visual.rt.base.AttributeManager.ReadonlyAttribute", key));
255 
256         a.setValue(value);
257     }
258 
259     /**
260      * Gets an attribute's value directly from the attribute table.
261      */
getFromTable(String key)262     protected final Object getFromTable(String key) {
263         Attribute a = attributes.get(key);
264         if (a == null)
265             throw new Error(Global.fmtMsg(
266 "sunsoft.jws.visual.rt.base.AttributeManager.GetInvalidAttribute", key));
267 
268         return (a.getValue());
269     }
270 
271     /**
272      * Sets an attribute in this object's attribute list.  This may be
273      * overridden in sub-classes to introduce special behavior for the
274      * setting of some attributes.
275      */
set(String key, Object value)276     public void set(String key, Object value) {
277         putInTable(key, value);
278 
279         // update the the global register for unsaved changes
280         if (inDesignerRoot())
281             DesignerAccess.setChangesMade(true);
282     }
283 
284     /**
285      * Gets an attribute from this shadow object's attribute list.  This
286      * may be overridden in sub-classes to introduce special behavior
287      * for the getting of some attributes.
288      */
get(String key)289     public Object get(String key) {
290         return (getFromTable(key));
291     }
292 
293     /**
294      * Returns the type string for the attribute,
295      * or null if the attribute does not exist.
296      */
getType(String key)297     public String getType(String key) {
298         Attribute attr = attributes.get(key);
299         if (attr != null)
300             return attr.getType();
301         else
302             return null;
303     }
304 
305     /**
306      * Returns true if the attribute has the flag set, otherwise false.
307      */
getFlags(String key)308     public int getFlags(String key) {
309         Attribute attr = attributes.get(key);
310         if (attr != null)
311             return attr.getFlags();
312         else
313             return 0;
314     }
315 
316     /**
317      * Returns true if the attribute exists, otherwise return false.
318      */
hasAttribute(String key)319     public boolean hasAttribute(String key) {
320         return (attributes.get(key) != null);
321     }
322 
323     /**
324      * Return true if the attribute exists and the type matches,
325      * otherwise return false.
326      */
hasAttribute(String key, String type)327     public boolean hasAttribute(String key, String type) {
328         Attribute attr = attributes.get(key);
329         if (attr != null)
330             return attr.getType().equals(type);
331         else
332             return false;
333     }
334 
335     /**
336      * Apply all the CONTAINER attributes in the child to the
337      * given parent.
338      */
updateContainerAttributes(AMContainer parent, AttributeManager child)339     public void updateContainerAttributes(AMContainer parent,
340 					  AttributeManager child)
341     {
342         Enumeration e = child.attributes.elements();
343         while (e.hasMoreElements()) {
344             Attribute a = (Attribute)e.nextElement();
345             if (a.flagged(CONTAINER))
346                 parent.updateContainerAttribute(child, a.getName(),
347 						a.getValue());
348         }
349     }
350 
351     /**
352      * Return a reference to the entire table of attributes.
353      */
getAttributeList()354     public AttributeList getAttributeList() {
355         refetchAttributeList();
356 
357         // Perhaps the attribute list should be cloned here.
358         // But this would
359         // cause a performance loss.  Anyone using getAttributeList
360         // should NOT modify the values of any of the attributes,
361         // especially those
362         // that have the DONTFETCH flag set.
363         return attributes;
364     }
365 
getAttribute(String name)366     Attribute getAttribute(String name) {
367         return (Attribute)attributes.get(name);
368     }
369 
370     /**
371      * Calls get for all the attributes, and then stores the values
372      * directly in the attribute hash table.  This ensures that the
373      * list of attributes is up to date.
374      */
refetchAttributeList()375     public void refetchAttributeList() {
376         Enumeration e = attributes.elements();
377         while (e.hasMoreElements()) {
378             Attribute attr = (Attribute)e.nextElement();
379             if (!attr.flagged(DONTFETCH | READONLY)) {
380                 String name = attr.getName();
381                 putInTable(name, get(name));
382             }
383         }
384     }
385 
386     /*
387      * Finds a component recursively by name.
388      */
resolve(String name)389     public AttributeManager resolve(String name) {
390         if (name == null)
391             return null;
392 
393         if (name.equals(getFromTable(/* NOI18N */"name")))
394             return this;
395 
396         if (this instanceof AMContainer) {
397             for (Enumeration e = ((AMContainer) this).getChildList();
398 		 /* JSTYLED */
399 		 e.hasMoreElements(); ) {
400 		AttributeManager child = (AttributeManager)
401 		    e.nextElement();
402 		AttributeManager s = child.resolve(name);
403 		if (s != null)
404 		    return s;
405 	    }
406 	}
407 
408 	return null;
409     }
410 
411     /**
412      * Finds a component from its full path name.
413      */
resolveFullName(String name)414     public AttributeManager resolveFullName(String name) {
415 	Group group = getGroup();
416 	if (group != null)
417 	    return group.resolveFullName(name);
418 	else
419 	    return null;
420     }
421 
422     /**
423      * Returns the body for a shadow after resolving it.
424      */
resolveBody(String name)425     public Object resolveBody(String name) {
426 	AttributeManager obj = resolve(name);
427 	if (obj == null)
428 	    return null;
429 	if (!(obj instanceof Shadow))
430 	    return null;
431 
432 	return ((Shadow)obj).getBody();
433     }
434 
435     /**
436      * Returns the name for this attribute manager.
437      */
getName()438     public String getName() {
439 	return (String)get(/* NOI18N */"name");
440     }
441 
442     /**
443      * Returns a hierarchy name based on the group tree.
444      */
getFullName()445     public String getFullName() {
446 	String name = getName();
447 
448 	Group group = getGroup();
449 	if (group != null) {
450 	    String groupName = group.getFullName();
451 	    if (groupName != null)
452 		name = groupName + /* NOI18N */"." + name;
453 	}
454 
455 	return name;
456     }
457 
458     /**
459      * Initialize the object.  Only useful for groups.
460      */
initialize()461     public void initialize() {
462     }
463 
464     /**
465      * Create the object.  The AWT components are constructed
466      * during creation.
467      */
create()468     public void create() {
469 	isCreated = true;
470 	inDesignerRoot = new Boolean(checkDesignerRoot());
471 
472 	// if this is a container create its children
473 	if (this instanceof AMContainer)
474 	    ((AMContainer) this).createChildren();
475     }
476 
477     /**
478      * Returns true if the attribute manager is created.
479      */
isCreated()480     public boolean isCreated() {
481 	return isCreated;
482     }
483 
484     /**
485      * Recreates this object after a CONSTRUCTOR attribute has been set
486      * (overridden in Shadow).
487      */
recreate()488     public void recreate() {
489     }
490 
491     /**
492      * This method is overridden in most sub-classes.  It should be the
493      * opposite of create() and should have the same ability to be
494      * called safely multiple times.
495      */
destroy()496     public void destroy() {
497 	isCreated = false;
498 	inDesignerRoot = null;
499 
500 	// destroy all the children of this shadow object
501 	if (this instanceof AMContainer)
502 	    ((AMContainer) this).destroyChildren();
503     }
504 
505     /**
506      * Returns a string that shows the hierarchy of shadow objects.
507      * Starts first one (the caller) off as the top level.
508      */
hierarchy()509     public String hierarchy() {
510 	return (hierarchy(0));
511     }
512 
513     /**
514      * Returns a string that shows the hierarchy of shadow objects.
515      */
hierarchy(int level)516     private String hierarchy(int level) {
517 	String indent = /* NOI18N */"";
518 	for (int i = 0; i < level; i++)
519 	    indent = indent + /* NOI18N */"    ";
520 
521 	String kids = /* NOI18N */"";
522 	if (this instanceof AMContainer) {
523 	    for (Enumeration e = ((AMContainer) this).getChildList();
524 		 /* JSTYLED */
525 		 e.hasMoreElements(); )
526 		kids = kids + ((AttributeManager)
527 			       e.nextElement()).hierarchy(level + 1);
528 	}
529 
530 	return (indent + getFromTable(/* NOI18N */"name")
531 		+ Global.newline() + kids);
532     }
533 
534     /**
535      * Returns a String that represents the value of this Object.
536      */
toString()537     public String toString() {
538 	return (super.toString() + /* NOI18N */"["
539 		+ ((this instanceof AMContainer) ?
540 		   /* NOI18N */"container" : /* NOI18N */"nonContainer")
541 		+ /* NOI18N */"]");
542     }
543 
544     /**
545      * Returns the root for this object, or null if these is no root.
546      */
getRoot()547     public Root getRoot() {
548 	AttributeManager mgr = this;
549 
550 	while (mgr != null && !(mgr instanceof Root))
551 	    mgr = (AttributeManager)mgr.getParent();
552 
553 	return (Root)mgr;
554     }
555 
556     /**
557      * Returns the group for this object, or null if there is none.
558      */
getGroup()559     public Group getGroup() {
560 	Root root = getRoot();
561 	if (root != null)
562 	    return root.getGroup();
563 	else
564 	    return null;
565     }
566 
567     /**
568      * Returns the group that is forwarding the specified attribute
569      * to this attribute manager.  Return null if the attribute is not
570      * being forwarded from any group.
571      */
getForwardingGroup(String attributeName)572     protected Group getForwardingGroup(String attributeName) {
573 	Root root = getRoot();
574 	Group group = root.getGroup();
575 	Group parent;
576 
577 	if (group != null) {
578 	    if (group.hasAttributeForward(this, attributeName)) {
579 		parent = group.getParentGroup();
580 		while (parent != null &&
581 		       parent.hasAttributeForward(group, attributeName)) {
582 		    group = parent;
583 		    parent = group.getParentGroup();
584 		}
585 		return group;
586 	    }
587 	}
588 
589 	return null;
590     }
591 
592     /**
593      * replicate is used by Visual Java for cut and paste.
594      */
replicate()595     public AttributeManager replicate() {
596 	// Create a new instance of the AttributeManager
597 	AttributeManager newMgr = null;
598 	try {
599 	    newMgr = (AttributeManager)getClass().newInstance();
600 	}
601 	catch (InstantiationException ex) {
602 	    // Perhaps this should be an Exception?
603 	    System.out.println(ex.getMessage()
604 			       + /* NOI18N */" " + this);
605 	}
606 	catch (IllegalAccessException ex) {
607 	    // Perhaps this should be an Exception?
608 	    System.out.println(ex.getMessage()
609 			       + /* NOI18N */" " + this);
610 	}
611 	if (newMgr == null)
612 	    return null;
613 
614 	// Copy the attribute list
615 	AttributeList list = getAttributeList();
616 	Enumeration e = list.elements();
617 	while (e.hasMoreElements()) {
618 	    Attribute attr = (Attribute)e.nextElement();
619 	    if (!attr.flagged(TRANSIENT | READONLY))
620 		newMgr.set(attr.getName(), attr.getValue());
621 	}
622 
623 	// Replicate the children
624 	if (this instanceof AMContainer) {
625 	    AMContainer newCntr = (AMContainer)newMgr;
626 	    e = ((AMContainer)this).getChildList();
627 
628 	    while (e.hasMoreElements()) {
629 		AttributeManager child = (AttributeManager)
630 		    e.nextElement();
631 		newCntr.add(child.replicate());
632 	    }
633 	}
634 
635 	return newMgr;
636     }
637 
638     //
639     // Events
640     //
641 
642     /**
643      * Posts a message to this object's parent.
644      */
postMessageToParent(Message msg)645     public void postMessageToParent(Message msg) {
646 	if (parent != null)
647 	    ((AttributeManager)parent).postMessage(msg);
648     }
649 
650     /**
651      * Posts a message to this object.
652      */
postMessage(Message msg)653     public void postMessage(Message msg) {
654 	if (inDesignerRoot())
655 	    sendToOps(msg);
656 
657 	if (!handleMessage(msg) && parent != null)
658 	    ((AttributeManager)parent).postMessage(msg);
659     }
660 
sendToOps(Message msg)661     private void sendToOps(Message msg) {
662 	Op ops[] = (Op[])get(/* NOI18N */"operations");
663 	if (ops != null) {
664 	    for (int i = 0; i < ops.length; i++) {
665 		ops[i].filter.target = this;
666 
667 		if (ops[i].scope == null)
668 		    ops[i].scope = getRoot();
669 
670 		// Don't handle GROUP actions
671 		if (ops[i].action != null &&
672 		    ops[i].action.target != null &&
673 		    ops[i].action.target.getName() != null &&
674 		    ops[i].action.target.getName().equals(/* NOI18N */"GROUP"))
675 		    continue;
676 
677 		ops[i].handleMessage(msg);
678 	    }
679 	}
680     }
681 
682     /**
683      * May be overridden by subclasses that want to act
684      * on messages that are sent to this object.
685      */
handleMessage(Message msg)686     public boolean handleMessage(Message msg) {
687 	if (msg.isAWT)
688 	    return handleEvent(msg, (Event)msg.arg);
689 	else
690 	    return false;
691     }
692 
693     /**
694      * May be overridden by subclasses that want to act
695      * on AWT events that are sent to this object.
696      */
handleEvent(Message msg, Event evt)697     public boolean handleEvent(Message msg, Event evt) {
698 	switch (evt.id) {
699         case Event.MOUSE_ENTER:
700 	    return mouseEnter(msg, evt, evt.x, evt.y);
701         case Event.MOUSE_EXIT:
702 	    return mouseExit(msg, evt, evt.x, evt.y);
703         case Event.MOUSE_MOVE:
704 	    return mouseMove(msg, evt, evt.x, evt.y);
705         case Event.MOUSE_DOWN:
706 	    return mouseDown(msg, evt, evt.x, evt.y);
707         case Event.MOUSE_DRAG:
708 	    return mouseDrag(msg, evt, evt.x, evt.y);
709         case Event.MOUSE_UP:
710 	    return mouseUp(msg, evt, evt.x, evt.y);
711 
712         case Event.KEY_PRESS:
713         case Event.KEY_ACTION:
714 	    return keyDown(msg, evt, evt.key);
715         case Event.KEY_RELEASE:
716         case Event.KEY_ACTION_RELEASE:
717 	    return keyUp(msg, evt, evt.key);
718 
719         case Event.ACTION_EVENT:
720 	    return action(msg, evt, evt.arg);
721         case Event.GOT_FOCUS:
722 	    return gotFocus(msg, evt, evt.arg);
723         case Event.LOST_FOCUS:
724 	    return lostFocus(msg, evt, evt.arg);
725 
726         default:
727 	    return false;
728 	}
729     }
730 
mouseDown(Message msg, Event evt, int x, int y)731     public boolean mouseDown(Message msg, Event evt, int x, int y) {
732 	return false;
733     }
734 
mouseDrag(Message msg, Event evt, int x, int y)735     public boolean mouseDrag(Message msg, Event evt, int x, int y) {
736 	return false;
737     }
738 
mouseUp(Message msg, Event evt, int x, int y)739     public boolean mouseUp(Message msg, Event evt, int x, int y) {
740 	return false;
741     }
742 
mouseMove(Message msg, Event evt, int x, int y)743     public boolean mouseMove(Message msg, Event evt, int x, int y) {
744 	return false;
745     }
746 
mouseEnter(Message msg, Event evt, int x, int y)747     public boolean mouseEnter(Message msg, Event evt, int x, int y) {
748 	return false;
749     }
750 
mouseExit(Message msg, Event evt, int x, int y)751     public boolean mouseExit(Message msg, Event evt, int x, int y) {
752 	return false;
753     }
754 
keyDown(Message msg, Event evt, int key)755     public boolean keyDown(Message msg, Event evt, int key) {
756 	return false;
757     }
758 
keyUp(Message msg, Event evt, int key)759     public boolean keyUp(Message msg, Event evt, int key) {
760 	return false;
761     }
762 
action(Message msg, Event evt, Object what)763     public boolean action(Message msg, Event evt, Object what) {
764 	return false;
765     }
766 
gotFocus(Message msg, Event evt, Object what)767     public boolean gotFocus(Message msg, Event evt, Object what) {
768 	return false;
769     }
770 
lostFocus(Message msg, Event evt, Object what)771     public boolean lostFocus(Message msg, Event evt, Object what) {
772 	return false;
773     }
774 
775     /**
776      * isLayoutMode - Are we in layout mode?
777      */
778     private boolean layoutMode = false;
779 
780     /**
781      * Returns a boolean indicating if this object is in layout mode.
782      */
isLayoutMode()783     public boolean isLayoutMode() {
784 	return layoutMode;
785     }
786 
787     /**
788      * Called when Visual Java switches to layout mode.
789      */
layoutMode()790     public void layoutMode() {
791 	layoutMode = true;
792     }
793 
794     /**
795      * Called when Visual Java switches to preview mode.
796      */
previewMode()797     public void previewMode() {
798 	layoutMode = false;
799     }
800 
801     /**
802      * Called after addNotify and before the window is reshaped.
803      */
preValidate()804     protected void preValidate() {
805     }
806 }
807