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 * @(#) Root.java 1.88 - last change made 07/25/97 34 */ 35 36 package sunsoft.jws.visual.rt.base; 37 38 import sunsoft.jws.visual.rt.shadow.java.awt.*; 39 40 import java.awt.Event; 41 import java.awt.Frame; 42 import java.util.*; 43 44 /* 45 * NOTE: Whenever a new public or protected variable is added to this 46 * class the name of the variable must be added to the reservedWords 47 * list, so that the user doesn't use it in one of the generated Root 48 * sub-classes. 49 */ 50 51 /** 52 * Instances of the Root class are used for the root of the group's 53 * shadow tree. The direct child shadows of an instantiation of this 54 * object will typically be top-level windows or the top panel of an 55 * applet. 56 * 57 * @version 1.88, 07/25/97 58 */ 59 public class Root extends AttributeManager implements AMContainer { 60 61 private AMContainerHelper containerHelper = new AMContainerHelper(this); 62 63 /** 64 * This flag is set to true if this is the loaded root. 65 */ 66 private boolean isLoadedRoot = false; 67 68 /** 69 * The constructor defines the Root's attributes. 70 */ Root()71 public Root() { 72 attributes.add(/* NOI18N */"generateClass", 73 /* NOI18N */"java.lang.String", null, 0); 74 attributes.add(/* NOI18N */"generateDirectory", 75 /* NOI18N */"java.lang.String", null, 0); 76 attributes.add(/* NOI18N */"generatePackage", 77 /* NOI18N */"java.lang.String", null, 0); 78 attributes.add(/* NOI18N */"willGenerateGUI", 79 /* NOI18N */"java.lang.Boolean", Boolean.TRUE, 0); 80 attributes.add(/* NOI18N */"willGenerateMain", 81 /* NOI18N */"java.lang.Boolean", Boolean.TRUE, 0); 82 attributes.add(/* NOI18N */"willGenerateGroup", 83 /* NOI18N */"java.lang.Boolean", Boolean.FALSE, 0); 84 attributes.add(/* NOI18N */"willGenerateHTML", 85 /* NOI18N */"java.lang.Boolean", Boolean.FALSE, 0); 86 attributes.add(/* NOI18N */"suffixForGUIClass", 87 /* NOI18N */"java.lang.String", /* NOI18N */"Root", 0); 88 attributes.add(/* NOI18N */"suffixForMainClass", 89 /* NOI18N */"java.lang.String", /* NOI18N */"Main", 0); 90 attributes.add(/* NOI18N */"suffixForOpsClass", 91 /* NOI18N */"java.lang.String", /* NOI18N */"Ops", 0); 92 attributes.add(/* NOI18N */"suffixForGroupClass", 93 /* NOI18N */"java.lang.String", /* NOI18N */"", 0); 94 attributes.add(/* NOI18N */"showGenerateConsole", 95 /* NOI18N */"java.lang.Boolean", Boolean.TRUE, 0); 96 97 attributes.add(/* NOI18N */"groupType", 98 /* NOI18N */"java.lang.String", null, 0); 99 attributes.add(/* NOI18N */"appletSize", 100 /* NOI18N */"java.awt.Dimension", null, 0); 101 102 /** 103 * When autoNaming is true, new shadows added somewhere 104 * under the 105 * root will automatically be assigned unique names if their 106 * name 107 * attribute is null (see AMContainerHelper.) 108 */ 109 attributes.add(/* NOI18N */"autoNaming", 110 /* NOI18N */"java.lang.Boolean", Boolean.TRUE, 111 HIDDEN | TRANSIENT); 112 113 set(/* NOI18N */"name", getUniqueName(this)); 114 } 115 getUserTypeName()116 protected String getUserTypeName() { 117 return (/* NOI18N */"root"); 118 } 119 120 /** 121 * Sets the loaded root flag for this root. 122 */ setLoadedRoot(boolean flag)123 void setLoadedRoot(boolean flag) { 124 isLoadedRoot = flag; 125 } 126 127 /** 128 * Returns the value of the loaded root flag. 129 */ isLoadedRoot()130 public boolean isLoadedRoot() { 131 return isLoadedRoot; 132 } 133 134 /** 135 * The first child in the children vector is the main container. 136 * To set the main child, we simply move the item to be selected 137 * to the top of the list. 138 * 139 * This method should only called by the builder because this method 140 * assumes that panels are wrapped with a window shadow. 141 */ setMainChild(AttributeManager container, boolean isPanel)142 void setMainChild(AttributeManager container, boolean isPanel) { 143 AttributeManager prev = getMainChild(); 144 145 // menubar should be removed from a frame about to become the 146 // surrounder for a main panel 147 if ((container instanceof FrameShadow) && 148 !((FrameShadow)container).isPanel() && 149 isPanel && container.get(/* NOI18N */"menubar") != null) { 150 container.set(/* NOI18N */"menubar", null); 151 } 152 153 WindowShadow win = null; 154 WindowShadow prevwin = null; 155 156 if (container instanceof WindowShadow) 157 win = (WindowShadow)container; 158 if (prev instanceof WindowShadow) 159 prevwin = (WindowShadow)prev; 160 161 if (prev == container) { 162 if (win != null) { 163 win.isPanel(isPanel); 164 win.show(); 165 } 166 } else { 167 if (prevwin != null) 168 prevwin.isPanel(false); 169 170 // Select the prev so that the NameEditor will 171 // load prev's "title" 172 // attribute. This way, when we switch off of prev, 173 // prev's title won't 174 // be wiped out by the name editor. 175 observerSelect(prev); 176 177 if (win != null) { 178 win.isPanel(isPanel); 179 win.show(); 180 } 181 182 Vector children = containerHelper.getChildren(); 183 if (!children.removeElement(container)) 184 throw new Error(Global.fmtMsg( 185 "sunsoft.jws.visual.rt.base.Root.RootMissingContainer", 186 getName(), container.getName())); 187 children.insertElementAt(container, 0); 188 } 189 190 observerReload(); 191 observerSelect(container); 192 } 193 194 /** 195 * Returns the main child of the root. This will typically be 196 * either a window or a panel. 197 */ getMainChild()198 public AttributeManager getMainChild() { 199 Vector children = containerHelper.getChildren(); 200 if (children.size() > 0) 201 return (AttributeManager)children.elementAt(0); 202 else 203 return null; 204 } 205 206 // List of root observers 207 private Hashtable observers = new Hashtable(); 208 209 /** 210 * Registers an observer for this root object. 211 * The observer will receive 212 * updates concerning groups or window shadows that are 213 * added or removed 214 * from this root. 215 */ addRootObserver(RootObserver observer)216 void addRootObserver(RootObserver observer) { 217 if (observer == null) 218 return; 219 220 if (observers.put(observer, observer) != null) 221 return; 222 223 observer.clear(); 224 Enumeration e = getChildList(); 225 while (e.hasMoreElements()) { 226 AttributeManager mgr = (AttributeManager)e.nextElement(); 227 observer.add(mgr); 228 } 229 } 230 231 /** 232 * Unregisters an observer for this root object. 233 */ removeRootObserver(RootObserver observer)234 void removeRootObserver(RootObserver observer) { 235 if (observer == null) 236 return; 237 238 observers.remove(observer); 239 } 240 observerAdd(AttributeManager mgr)241 private void observerAdd(AttributeManager mgr) { 242 if (!(mgr instanceof WindowShadow) && !(mgr instanceof Group) && 243 !(mgr instanceof BeanShadow)) 244 return; 245 246 Enumeration e = observers.elements(); 247 while (e.hasMoreElements()) 248 ((RootObserver)e.nextElement()).add(mgr); 249 } 250 observerRemove(AttributeManager mgr)251 private void observerRemove(AttributeManager mgr) { 252 if (!(mgr instanceof WindowShadow) && !(mgr instanceof Group) && 253 !(mgr instanceof BeanShadow)) 254 return; 255 256 Enumeration e = observers.elements(); 257 while (e.hasMoreElements()) 258 ((RootObserver)e.nextElement()).remove(mgr); 259 } 260 observerSelect(AttributeManager mgr)261 private void observerSelect(AttributeManager mgr) { 262 Enumeration e = observers.elements(); 263 264 while (e.hasMoreElements()) 265 ((RootObserver)e.nextElement()).select(mgr); 266 } 267 observerReload()268 private void observerReload() { 269 Enumeration e1 = observers.elements(); 270 271 while (e1.hasMoreElements()) { 272 RootObserver observer = (RootObserver)e1.nextElement(); 273 274 observer.clear(); 275 Enumeration e2 = containerHelper.getChildren().elements(); 276 while (e2.hasMoreElements()) 277 observer.add((AttributeManager)e2.nextElement()); 278 } 279 } 280 281 // Naming children validly and uniquely 282 283 /** 284 * A table containing ever-increasing counters for unique new names. 285 * Isn't needed in runtime mode, only when the designer is running. 286 */ 287 private Hashtable uniqueNameTable = null; 288 289 /** 290 * Clears the hashtable of unique name counters. 291 * Should only be used when 292 * restarting (user selects "File->New"). 293 */ clearUniqueNameTable()294 void clearUniqueNameTable() { 295 uniqueNameTable = null; 296 } 297 298 /** 299 * Returns true if the name chosen is unique and has not already 300 * been used by one of the descendants of this root object. 301 */ isUniqueName(String name)302 boolean isUniqueName(String name) { 303 return isUniqueName(this, name, null, null); 304 } 305 306 /** 307 * Returns true if the name chosen is unique and has not already 308 * been used by something under this root. When encountered, the 309 * "self" object is not compared, so you can also use this function 310 * to test whether the name of an object that is within the tree is 311 * unique unto itself. 312 */ isUniqueName(String name, AttributeManager skip)313 boolean isUniqueName(String name, AttributeManager skip) { 314 return isUniqueName(this, name, skip, null); 315 } 316 isUniqueName(String name, AttributeManager skip, AttributeManager prune)317 boolean isUniqueName(String name, 318 AttributeManager skip, AttributeManager prune) { 319 return isUniqueName(this, name, skip, prune); 320 } 321 322 /** 323 * Returns true if the name chosen is unique and has not already 324 * been used by one of the descendants of the given AMContainer 325 * object. When encountered, the "self" object is not compared, 326 * so you can also use this function to test whether the name of an 327 * object that is within the tree is unique unto itself. 328 */ isUniqueName(AttributeManager mgr, String name, AttributeManager skip, AttributeManager prune)329 private boolean isUniqueName(AttributeManager mgr, 330 String name, 331 AttributeManager skip, 332 AttributeManager prune) 333 { 334 if (mgr == prune) 335 return true; 336 337 if ((mgr != skip) && name.equals(mgr.get(/* NOI18N */"name"))) 338 return false; 339 340 if (mgr instanceof AMContainer) { 341 AMContainer cntr = (AMContainer)mgr; 342 Enumeration e = cntr.getChildList(); 343 while (e.hasMoreElements()) { 344 mgr = (AttributeManager)e.nextElement(); 345 if (!isUniqueName(mgr, name, skip, prune)) 346 return false; 347 } 348 } 349 350 return true; 351 } 352 353 /** 354 * The list of reserved words. The java language reserved words and 355 * also instance variable names already taken in the 356 * AttributeManager or Root classes that cannot be used in names of 357 * objects in the designer. 358 */ 359 private static final String reservedWords[] = { 360 /* NOI18N */"abstract", /* NOI18N */"boolean", 361 /* NOI18N */"break", /* NOI18N */"byte", 362 /* NOI18N */"byvalue", 363 /* NOI18N */"case", /* NOI18N */"cast", 364 /* NOI18N */"catch", /* NOI18N */"char", /* NOI18N */"class", 365 /* NOI18N */"const", /* NOI18N */"continue", 366 /* NOI18N */"default", /* NOI18N */"do", 367 /* NOI18N */"double", /* NOI18N */"else", 368 /* NOI18N */"extends", 369 /* NOI18N */"false", /* NOI18N */"final", 370 /* NOI18N */"finally", /* NOI18N */"float", 371 /* NOI18N */"for", /* NOI18N */"future", 372 /* NOI18N */"generic", /* NOI18N */"goto", 373 /* NOI18N */"if", 374 /* NOI18N */"implements", /* NOI18N */"import", 375 /* NOI18N */"inner", /* NOI18N */"instanceof", 376 /* NOI18N */"int", 377 /* NOI18N */"interface", /* NOI18N */"long", 378 /* NOI18N */"native", 379 /* NOI18N */"new", /* NOI18N */"null", 380 /* NOI18N */"operator", /* NOI18N */"outer", 381 /* NOI18N */"package", 382 /* NOI18N */"private", 383 /* NOI18N */"protected", /* NOI18N */"public", 384 /* NOI18N */"rest", /* NOI18N */"return", 385 /* NOI18N */"short", /* NOI18N */"static", 386 /* NOI18N */"super", /* NOI18N */"switch", 387 /* NOI18N */"synchronized", /* NOI18N */"this", 388 /* NOI18N */"throw", 389 /* NOI18N */"throws", 390 /* NOI18N */"transient", /* NOI18N */"true", /* NOI18N */"try", 391 /* NOI18N */"var", /* NOI18N */"void", /* NOI18N */"volatile", 392 /* NOI18N */"while", 393 /* NOI18N */"containerHelper", /* NOI18N */"READONLY", 394 /* NOI18N */"HIDDEN", /* NOI18N */"TRANSIENT", 395 /* NOI18N */"CONTAINER", /* NOI18N */"attributes", 396 /* NOI18N */"parent", /* NOI18N */"isCreated", 397 /* NOI18N */"GROUP", /* NOI18N */"ROOT" }; 398 399 // valid characters in variable names 400 // I18N bug 401 // private static final String 402 // validNameStarters="$abcdefghijklmnopqrstuvwxyz"; 403 // private static final String 404 // validNameAnys=validNameStarters + "_0123456789"; 405 406 /** 407 * Returns true if the given name could be legally 408 * placed in generated 409 * code where it would be compiled as a variable name. 410 */ isValidName(String name)411 static boolean isValidName(String name) { 412 // check that the name isn't blank 413 if (name == null || name.length() == 0) 414 return (false); 415 416 // check that the name is not a reserved word (case counts!) 417 for (int i = 0; i < reservedWords.length; i++) 418 if (name.equals(reservedWords[i])) 419 return (false); 420 /* JSTYLED */ 421 /* I18n BUG 422 // check that the name starts with a valid start 423 // character (not a number) 424 String s = name.toLowerCase(); 425 if (validNameStarters.indexOf(s.substring(0, 1)) == -1) 426 return (false); 427 428 // check that the rest of the characters in the name 429 // are valid 430 for (int i = 1; i < name.length(); i++) 431 if (validNameAnys.indexOf(s.substring(i, i+1)) == -1) 432 return (false); 433 */ 434 435 for (int i = 0; i < name.length(); i++) { 436 if ((i == 0) && 437 (!Character.isJavaIdentifierStart(name.charAt(i)))) 438 return false; 439 else 440 if (!Character.isJavaIdentifierPart(name.charAt(i))) 441 return false; 442 } 443 return (true); 444 } 445 446 /** 447 * Returns a unique name that can be used for a new 448 * shadow object. 449 * The names are guaranteed to be valid variable names for a 450 * generated Root sub-class later on. 451 */ getUniqueName(AttributeManager child)452 String getUniqueName(AttributeManager child) { 453 // delayed creation of the table (this routine never 454 // called in runtime) 455 if (uniqueNameTable == null) 456 uniqueNameTable = new Hashtable(); 457 458 String type = child.getUserTypeName(); 459 String retval = null; 460 461 while (retval == null || !isUniqueName(retval) || 462 !isValidName(retval)) { 463 if (uniqueNameTable.containsKey(type)) { 464 int count = ((Integer) 465 uniqueNameTable.get(type)).intValue(); 466 uniqueNameTable.put(type, new Integer(count + 1)); 467 retval = type + Integer.toString(count); 468 } else { 469 uniqueNameTable.put(type, new Integer(2)); 470 retval = type + /* NOI18N */"1"; 471 } 472 } 473 return (retval); 474 } 475 476 /** 477 * Returns a name that is unique not only within this root, 478 * but within 479 * another as well. This is useful when merging two roots. 480 */ getUniqueName(AttributeManager child, Root otherTree)481 String getUniqueName(AttributeManager child, Root otherTree) { 482 // because of the unique name counters, we can repeatedly call 483 // getUniqueName without getting the same name over again 484 String newName = getUniqueName(child); 485 while (!otherTree.isUniqueName(newName)) 486 newName = getUniqueName(child); 487 return (newName); 488 } 489 490 /** 491 * Returns a string describing what is wrong with given 492 * name choice. 493 * The string can be used in an error popup or status bar line. 494 * Null is returned when there is no problem with the name. 495 */ getProblemWithName(String name)496 String getProblemWithName(String name) { 497 String errorMsg = null; 498 499 if (name == null || name.length() == 0) 500 errorMsg = Global.getMsg( 501 "sunsoft.jws.visual.rt.base.Root.NeedName"); 502 else if (!isUniqueName(name)) 503 errorMsg = Global.fmtMsg( 504 "sunsoft.jws.visual.rt.base.Root.NotUniqueName", name); 505 else if (!isValidName(name)) 506 errorMsg = Global.fmtMsg( 507 "sunsoft.jws.visual.rt.base.Root.NotValidName", name); 508 509 return (errorMsg); 510 } 511 512 // 513 // Overridden to deal with the special "GROUP" and "ROOT" names. 514 // resolve(String name)515 public AttributeManager resolve(String name) { 516 if (name == null) 517 return null; 518 else if (name.equals(/* NOI18N */"GROUP")) 519 return group; 520 else if (name.equals(/* NOI18N */"ROOT")) 521 return this; 522 else 523 return super.resolve(name); 524 } 525 526 // AMContainer interfaces 527 add(AttributeManager child)528 public void add(AttributeManager child) { 529 containerHelper.add(child); 530 observerAdd(child); 531 } 532 remove(AttributeManager child)533 public void remove(AttributeManager child) { 534 containerHelper.remove(child); 535 observerRemove(child); 536 } 537 538 // 539 // The root's "addChildBody" and "removeChildBody" 540 // methods are only 541 // called when the root has a panel as a child. 542 // In this case, it should 543 // add the panel as a child of the group's parent. 544 // 545 addChildBody(Shadow child)546 public void addChildBody(Shadow child) { 547 // Don't add frames and dialogs to the group's parent 548 if (child instanceof WindowShadow) 549 return; 550 551 if (group == null) 552 return; 553 554 AMContainer parent = group.getParent(); 555 if (parent == null) 556 return; 557 558 if (child != null && child.getBody() != null) 559 parent.addChildBody(child); 560 } 561 updateContainerAttribute(AttributeManager child, String key, Object value)562 public void updateContainerAttribute(AttributeManager child, 563 String key, Object value) { 564 if (group == null) 565 return; 566 567 AMContainer parent = (AMContainer)group.getParent(); 568 if (parent == null) 569 return; 570 571 parent.updateContainerAttribute(child, key, value); 572 } 573 removeChildBody(Shadow child)574 public void removeChildBody(Shadow child) { 575 // Don't need to remove frames and dialogs from 576 // the group's parent 577 if (child instanceof WindowShadow) 578 return; 579 580 if (group == null) 581 return; 582 583 AMContainer parent = group.getParent(); 584 if (parent == null) 585 return; 586 587 if (child != null && child.getBody() != null) 588 parent.removeChildBody(child); 589 } 590 createChildren()591 public void createChildren() { 592 containerHelper.createChildren(); 593 } 594 reparentChildren()595 public void reparentChildren() { 596 containerHelper.reparentChildren(); 597 } 598 destroyChildren()599 public void destroyChildren() { 600 containerHelper.destroyChildren(); 601 } 602 getChild(String name)603 public AttributeManager getChild(String name) { 604 return (containerHelper.getChild(name)); 605 } 606 getChildList()607 public Enumeration getChildList() { 608 return (containerHelper.getChildList()); 609 } 610 getChildCount()611 public int getChildCount() { 612 return (containerHelper.getChildCount()); 613 } 614 615 /** 616 * Groups 617 */ 618 619 private Group group; 620 setGroup(Group group)621 public void setGroup(Group group) { 622 if (this.group != null) 623 this.group.removeRootChildren(this); 624 625 this.group = group; 626 627 if (this.group != null) 628 this.group.addRootChildren(this); 629 } 630 getGroup()631 public Group getGroup() { 632 return group; 633 } 634 635 /** 636 * Sets the cursor for all of the root's frames. This method is 637 * declared package private so that it won't be 638 * confused with the 639 * group's setCursor method. 640 */ setCursor(int cursor)641 void setCursor(int cursor) { 642 Enumeration e = getChildList(); 643 while (e.hasMoreElements()) { 644 AttributeManager mgr = (AttributeManager)e.nextElement(); 645 if (mgr instanceof FrameShadow) { 646 FrameShadow fs = (FrameShadow)mgr; 647 Frame f = (Frame)fs.getBody(); 648 649 if (f != null) { 650 int prevCursor = f.getCursorType(); 651 if (cursor == prevCursor) { 652 JAShadowAccess.incrCursor(fs); 653 } else if (cursor == Group.RESTORE_CURSOR) { 654 if (JAShadowAccess.decrCursor(fs) == 0) { 655 f.setCursor( 656 JAShadowAccess.getPrevCursor(fs)); 657 JAShadowAccess.setPrevCursor(fs, 658 Frame.DEFAULT_CURSOR); 659 } 660 } else { 661 JAShadowAccess.setPrevCursor(fs, prevCursor); 662 f.setCursor(cursor); 663 f.getToolkit().sync(); 664 } 665 } 666 } 667 } 668 } 669 670 /** 671 * Maps all the visible children of the root. Do not call this 672 * method directly. It is called from the Group class when the 673 * group is shown. 674 */ showRoot()675 public void showRoot() { 676 AttributeManager mgr; 677 Enumeration e = getChildList(); 678 679 while (e.hasMoreElements()) { 680 mgr = (AttributeManager)e.nextElement(); 681 if (mgr instanceof ComponentShadow) { 682 ComponentShadow comp = (ComponentShadow)mgr; 683 Boolean v = (Boolean)comp.get(/* NOI18N */"visible"); 684 if (v.booleanValue()) 685 comp.showComponent(); 686 } else if (mgr instanceof Group) { 687 Group group = (Group)mgr; 688 Boolean v = (Boolean)group.get(/* NOI18N */"visible"); 689 if (v.booleanValue()) 690 group.internalShowGroup(); 691 } 692 } 693 } 694 695 /** 696 * Unmaps all the children of the root. Do not call this 697 * method directly. It is called from the Group class when the 698 * group is hidden. 699 */ hideRoot()700 public void hideRoot() { 701 AttributeManager mgr; 702 Enumeration e = getChildList(); 703 704 while (e.hasMoreElements()) { 705 mgr = (AttributeManager)e.nextElement(); 706 if (mgr instanceof ComponentShadow) 707 ((ComponentShadow)mgr).hideComponent(); 708 else if (mgr instanceof Group) 709 ((Group)mgr).internalHideGroup(); 710 } 711 } 712 713 /** 714 * Events 715 */ 716 717 private boolean eventForwardingDisabled; 718 postMessageToParent(Message msg)719 public void postMessageToParent(Message msg) { 720 if (group != null && !eventForwardingDisabled) 721 group.postMessage(msg); 722 } 723 postMessage(Message msg)724 public void postMessage(Message msg) { 725 if (!handleMessage(msg) && group != null && 726 !eventForwardingDisabled) 727 group.postMessage(msg); 728 } 729 postEvent(Message msg)730 public void postEvent(Message msg) { 731 if (handleMessage(msg)) 732 return; 733 734 if (group != null && !eventForwardingDisabled) 735 group.postMessage(msg); 736 } 737 disableEventForwarding()738 void disableEventForwarding() { 739 eventForwardingDisabled = true; 740 } 741 enableEventForwarding()742 void enableEventForwarding() { 743 eventForwardingDisabled = false; 744 } 745 layoutMode()746 public void layoutMode() { 747 super.layoutMode(); 748 containerHelper.layoutMode(); 749 } 750 previewMode()751 public void previewMode() { 752 super.previewMode(); 753 containerHelper.previewMode(); 754 } 755 } 756