xref: /titanic_41/usr/src/cmd/krb5/kadmin/gui/visualrt/sunsoft/jws/visual/rt/base/Shadow.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  * @(#) Shadow.java 1.89 - last change made 07/25/97
34  */
35 
36 package sunsoft.jws.visual.rt.base;
37 
38 import java.util.Enumeration;
39 import java.util.StringTokenizer;
40 
41 /**
42  * This class implements the basic interfaces
43  * that Visual Java requires
44  * for its visual components.  Objects that wish to be added to
45  * the Visual Java palette must be sub-classed from Shadow.
46  * <p>
47  * The attributes this class adds to an AttributeManager
48  * class are listed below.  In the type column, type names beginning
49  * with "sunsoft.jws.visual.rt" have been abbreviated to begin
50  * with "rt".
51  *
52  * <pre>
53  * name            type                      default value
54  * --------------------------------------------------------------------
55  * none
56 *  < /pre>
57 *
58 * Check the super class for additional attributes.
59 *
60 * @version 1.89, 07/25/97
61 */
62 public class Shadow extends AttributeManager {
63     /**
64      * Flags
65      */
66 
67     /**
68      * When this flag is set, a provision must be made in order
69      * to set
70      * the attribute in the body's constructor.  It is up to the
71      * caller to call
72      * recreate on the shadow and validate on the shadow's
73      * parent after
74      * a constructor attribute has been set.
75      */
76     public static final int CONSTRUCTOR = 0x40;
77 
78     /**
79      * This flag signifies that the attribute has nothing to
80      * do with a shadow 'body' and therefore
81      * <a href="sunsoft.jws.visual.rt.base.Shadow.html
82      * #getOnBody(java.lang.String)">getOnBody</a> and
83      * <a href="sunsoft.jws.visual.rt.base.Shadow.html
84      * #setOnBody(java.lang.String, java.lang.Object)">setOnBody</a>
85      * will not be called for this attribute.
86      */
87     public static final int NONBODY = 0x80;
88 
89     /**
90      * Constructor
91      */
Shadow()92     public Shadow() {
93         super();
94     }
95 
96     /**
97      * The AWT component for this shadow.
98      */
99     protected Object body;
100 
101     /**
102      * Returns the AWT component for this shadow.
103      * The return value is of
104      * type Object, therefore the caller must do a cast to the
105      * appropriate AWT component type.
106      */
getBody()107     public Object getBody() {
108         return (body);
109     }
110 
111     /**
112      * Returns a type name suitable for use in naming instances of
113      * shadow sub-classes (i.e. names that make sense to a user.)
114      *  This
115      * can be overridden in sub-classes to give more useful
116      * names when
117      * this (default) algorithm comes up with something ugly.
118      */
getUserTypeName()119     protected String getUserTypeName() {
120         // get the final word after the last '.'
121         String last = /* NOI18N */"unknown";
122         StringTokenizer st = new StringTokenizer(
123 			 getClass().getName(), /* NOI18N */".", false);
124         while (st.hasMoreTokens()) {
125             last = st.nextToken();
126         }
127 
128         // remove "Shadow" from the end of the string
129         int index = last.lastIndexOf(/* NOI18N */"Shadow");
130         if (index != -1) {
131             last = last.substring(0, index);
132         }
133 
134         // always return a lower case word
135         if (last.length() > 0)
136             return (last.toLowerCase());
137         else
138             return (/* NOI18N */"shadow");
139     }
140 
141     /**
142      * Gets attributes from this shadow's body.
143      * Should be overridden in each sub-class which has its own
144      * attributes.  There should be an entry for every
145      * attribute that
146      * doesn't have the NONBODY flag, even if it's just to return
147      * the value from the attribute list when a certain attribute
148      * can't
149      * be looked up from the body.
150      */
getOnBody(String key)151     protected Object getOnBody(String key) {
152         throw new Error(Global.fmtMsg(
153 		"sunsoft.jws.visual.rt.base.Shadow.NoSuchKey", key));
154     }
155 
156     /**
157      * Gets an attribute either from the body (if available)
158      * or from the
159      * shadow's attribute list.
160      */
get(String key)161     public Object get(String key) {
162         key = attributes.resolveAlias(key);
163         if (attributes.contains(key)) {
164             Attribute a = attributes.get(key);
165             if (body != null && !a.flagged(NONBODY))
166                 return (getOnBody(key));
167             else
168                 return (a.getValue());
169         } else {
170             throw new Error(Global.fmtMsg(
171 		    "sunsoft.jws.visual.rt.base.Shadow.UnknownAttribute",
172 					  key, getClass().getName()));
173         }
174     }
175 
176     /**
177      * Sets attributes on this shadow's body.
178      * Should be overridden in each sub-class which has its own
179      * attributes. There should be an entry for every attribute that
180      * doesn't have the NONBODY flag, even if it's just to set the
181      * value in the attribute list when a certain attribute
182      * can't be set on the body.
183      */
setOnBody(String key, Object value)184     protected void setOnBody(String key, Object value) {
185         throw new Error(Global.fmtMsg(
186 		"sunsoft.jws.visual.rt.base.Shadow.NoSuchKey2", key));
187     }
188 
189     /**
190      * Sets an attribute either in the body (if available) or in the
191      * shadow's attribute list.  Destroys the body when
192      * a CONSTRUCTOR attribute is set.
193      * It is up to the caller to call
194      * recreate on the shadow and validate on the shadow's
195      * parent after a constructor attribute has been set.
196      */
set(String key, Object value)197     public void set(String key, Object value) {
198         key = attributes.resolveAlias(key);
199         Attribute a = attributes.get(key);
200         if (a == null)
201             throw new Error(Global.fmtMsg(
202 		    "sunsoft.jws.visual.rt.base.Shadow.InvalidAttributeSet",
203 		    key));
204         if (a.flagged(READONLY))
205             throw new Error(Global.fmtMsg(
206 		    "sunsoft.jws.visual.rt.base.Shadow.ReadOnlyAttributeSet",
207 		    key));
208 
209         if (a.flagged(CONSTRUCTOR)) {
210             if (isCreated) {
211                 isCreated = false;
212                 refetchAttributeList();
213                 unregisterBody();
214                 destroyBody();
215                 if (body != null)
216                     throw new Error(Global.getMsg(
217 		    "sunsoft.jws.visual.rt.base.Shadow.BodyNotDestroyed"));
218             }
219         }
220 
221         // Save the previous value
222         Object prev = a.getValue();
223         a.setValue(value);
224 
225         if (body != null && !a.flagged(NONBODY)) {
226             // If setOnBody throws a VJException, then restore
227             // the old value.  I couldn't just move the setValue
228             // to be after
229             // setOnBody, because many shadows depend on the value
230             // being set first.
231             try {
232                 setOnBody(key, value);
233             }
234             catch (VJException ex) {
235                 a.setValue(prev);
236                 throw ex;
237             }
238         }
239 
240         // update the the global register for unsaved changes
241         if (inDesignerRoot())
242             DesignerAccess.setChangesMade(true);
243 
244         if (parent != null && a.flagged(CONTAINER))
245             ((AMContainer)parent).updateContainerAttribute(this,
246 							   key, value);
247     }
248 
249     /**
250      * Creates this shadow.
251      * It is safe to call create multiple times on a shadow object.
252      */
create()253     public void create() {
254         if (!isCreated) {
255             isCreated = true;
256 
257             if (getGroup() == null || !getGroup().hasBase()) {
258                 throw new Error(Global.getMsg(
259 		"sunsoft.jws.visual.rt.base.Group.ShadowCreationWarning"));
260             }
261 
262             if (body == null)
263                 createBody();
264             if (body == null)
265                 throw new Error(Global.getMsg(
266 			"sunsoft.jws.visual.rt.base.Group.BodyNotCreated"));
267 
268             registerBody();
269 
270             super.create();
271             if (parent != null && body != null)
272                 parent.addChildBody(this);
273 
274             postCreate();
275         } else {
276             super.create();
277             if (parent != null && body != null)
278                 parent.addChildBody(this);
279         }
280     }
281 
282     /**
283      * Called just after this shadow has been created.
284      */
postCreate()285     protected void postCreate() {};
286 
287     /**
288      * Creates the AWT component for this shadow.
289      * Sub-classes must override this method.
290      */
createBody()291     public void createBody() {};
292 
293     /**
294      * Registers newly created shadows.
295      * Sub-classes should not override
296      * this method.
297      */
registerBody()298     protected void registerBody() {
299         // Add this shadow's body to the global shadow table.
300         DesignerAccess.getShadowTable().put(body, this);
301 
302         // Set attributes on the new body
303         for (Enumeration e = attributes.attributesWithoutFlags(
304 					       NONBODY|READONLY);
305 	     /* JSTYLED */
306 	     e.hasMoreElements(); ) {
307 	    Attribute a = (Attribute) e.nextElement();
308 	    if (a.isModified() || !a.flagged(DEFAULT)) {
309 		setOnBody(a.getName(), a.getValue());
310 	    }
311 	}
312 
313 	// System.out.println("Shadow created: " + toString());
314     }
315 
316     /**
317      * Creates this shadow again after a constructor
318      * attribute has been set.
319      */
recreate()320     public void recreate() {
321 	if (!isCreated) {
322 	    isCreated = true;
323 
324 	    createBody();
325 
326 	    // Reparent the children
327 	    if (this instanceof AMContainer)
328 		((AMContainer)this).reparentChildren();
329 
330 	    registerBody();
331 
332 	    postCreate();
333 	}
334 
335 	if (parent != null && body != null)
336 	    parent.addChildBody(this);
337     }
338 
339     /**
340      * Destroys this shadow and all its children.
341      */
destroy()342     public void destroy() {
343 	if (isCreated) {
344 	    isCreated = false;
345 
346 	    preDestroy();
347 
348 	    super.destroy();
349 
350 	    unregisterBody();
351 
352 	    destroyBody();
353 	    if (body != null)
354 		throw new Error(Global.getMsg(
355 			"sunsoft.jws.visual.rt.base.Shadow.BodyNotDestroyed"));
356 	} else {
357 	    super.destroy();
358 	}
359     }
360 
361     /**
362      * Called during destroy, but before the children are
363      * destroyed.  By the time destroyBody is called, all
364      * the children have already been destroyed.
365      */
preDestroy()366     protected void preDestroy() {
367     }
368 
369     /**
370      * Destroys the body for this shadow.
371      * Sub-classes are not required  to override this method.
372      */
destroyBody()373     protected void destroyBody() {
374 	body = null;
375     }
376 
377     /**
378      * Unregisters destroyed shadows.  Sub-classes should not
379      * override this method.
380      */
unregisterBody()381     protected void unregisterBody() {
382 	// remove this shadow's body from its container and from the
383 	// global shadow table
384 	if (body != null) {
385 	    if (parent != null && body != null)
386 		parent.removeChildBody(this);
387 	    DesignerAccess.getShadowTable().remove(body);
388 	}
389     }
390 
toString()391     public String toString() {
392 	return (super.toString() + /* NOI18N */"["
393 		+ /* NOI18N */"," + /* NOI18N */"body=" +
394 		((body == null) ? /* NOI18N */"null" : body.toString())
395 		+ /* NOI18N */"]");
396     }
397 }
398