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