GNU Classpath (0.97.2) | |
Frames | No Frames |
1: /* Container.java -- parent container class in AWT 2: Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006 3: Free Software Foundation 4: 5: This file is part of GNU Classpath. 6: 7: GNU Classpath is free software; you can redistribute it and/or modify 8: it under the terms of the GNU General Public License as published by 9: the Free Software Foundation; either version 2, or (at your option) 10: any later version. 11: 12: GNU Classpath is distributed in the hope that it will be useful, but 13: WITHOUT ANY WARRANTY; without even the implied warranty of 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15: General Public License for more details. 16: 17: You should have received a copy of the GNU General Public License 18: along with GNU Classpath; see the file COPYING. If not, write to the 19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20: 02110-1301 USA. 21: 22: Linking this library statically or dynamically with other modules is 23: making a combined work based on this library. Thus, the terms and 24: conditions of the GNU General Public License cover the whole 25: combination. 26: 27: As a special exception, the copyright holders of this library give you 28: permission to link this library with independent modules to produce an 29: executable, regardless of the license terms of these independent 30: modules, and to copy and distribute the resulting executable under 31: terms of your choice, provided that you also meet, for each linked 32: independent module, the terms and conditions of the license of that 33: module. An independent module is a module which is not derived from 34: or based on this library. If you modify this library, you may extend 35: this exception to your version of the library, but you are not 36: obligated to do so. If you do not wish to do so, delete this 37: exception statement from your version. */ 38: 39: 40: package java.awt; 41: 42: import java.awt.event.ContainerEvent; 43: import java.awt.event.ContainerListener; 44: import java.awt.event.HierarchyEvent; 45: import java.awt.event.KeyEvent; 46: import java.awt.event.MouseEvent; 47: import java.awt.peer.ComponentPeer; 48: import java.awt.peer.ContainerPeer; 49: import java.awt.peer.LightweightPeer; 50: import java.beans.PropertyChangeListener; 51: import java.io.IOException; 52: import java.io.ObjectInputStream; 53: import java.io.ObjectOutputStream; 54: import java.io.PrintStream; 55: import java.io.PrintWriter; 56: import java.io.Serializable; 57: import java.util.Collections; 58: import java.util.EventListener; 59: import java.util.HashSet; 60: import java.util.Iterator; 61: import java.util.Set; 62: 63: import javax.accessibility.Accessible; 64: 65: /** 66: * A generic window toolkit object that acts as a container for other objects. 67: * Components are tracked in a list, and new elements are at the end of the 68: * list or bottom of the stacking order. 69: * 70: * @author original author unknown 71: * @author Eric Blake (ebb9@email.byu.edu) 72: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 73: * 74: * @since 1.0 75: * 76: * @status still missing 1.4 support, some generics from 1.5 77: */ 78: public class Container extends Component 79: { 80: /** 81: * Compatible with JDK 1.0+. 82: */ 83: private static final long serialVersionUID = 4613797578919906343L; 84: 85: /* Serialized fields from the serialization spec. */ 86: int ncomponents; 87: Component[] component; 88: LayoutManager layoutMgr; 89: 90: /** 91: * @since 1.4 92: */ 93: boolean focusCycleRoot; 94: 95: /** 96: * Indicates if this container provides a focus traversal policy. 97: * 98: * @since 1.5 99: */ 100: private boolean focusTraversalPolicyProvider; 101: 102: int containerSerializedDataVersion; 103: 104: /* Anything else is non-serializable, and should be declared "transient". */ 105: transient ContainerListener containerListener; 106: 107: /** The focus traversal policy that determines how focus is 108: transferred between this Container and its children. */ 109: private FocusTraversalPolicy focusTraversalPolicy; 110: 111: /** 112: * The focus traversal keys, if not inherited from the parent or default 113: * keyboard manager. These sets will contain only AWTKeyStrokes that 114: * represent press and release events to use as focus control. 115: * 116: * @see #getFocusTraversalKeys(int) 117: * @see #setFocusTraversalKeys(int, Set) 118: * @since 1.4 119: */ 120: transient Set[] focusTraversalKeys; 121: 122: /** 123: * Default constructor for subclasses. 124: */ 125: public Container() 126: { 127: // Nothing to do here. 128: } 129: 130: /** 131: * Returns the number of components in this container. 132: * 133: * @return The number of components in this container. 134: */ 135: public int getComponentCount() 136: { 137: return countComponents (); 138: } 139: 140: /** 141: * Returns the number of components in this container. 142: * 143: * @return The number of components in this container. 144: * 145: * @deprecated use {@link #getComponentCount()} instead 146: */ 147: public int countComponents() 148: { 149: return ncomponents; 150: } 151: 152: /** 153: * Returns the component at the specified index. 154: * 155: * @param n The index of the component to retrieve. 156: * 157: * @return The requested component. 158: * 159: * @throws ArrayIndexOutOfBoundsException If the specified index is invalid 160: */ 161: public Component getComponent(int n) 162: { 163: synchronized (getTreeLock ()) 164: { 165: if (n < 0 || n >= ncomponents) 166: throw new ArrayIndexOutOfBoundsException("no such component"); 167: 168: return component[n]; 169: } 170: } 171: 172: /** 173: * Returns an array of the components in this container. 174: * 175: * @return The components in this container. 176: */ 177: public Component[] getComponents() 178: { 179: synchronized (getTreeLock ()) 180: { 181: Component[] result = new Component[ncomponents]; 182: 183: if (ncomponents > 0) 184: System.arraycopy(component, 0, result, 0, ncomponents); 185: 186: return result; 187: } 188: } 189: 190: /** 191: * Returns the insets for this container, which is the space used for 192: * borders, the margin, etc. 193: * 194: * @return The insets for this container. 195: */ 196: public Insets getInsets() 197: { 198: return insets (); 199: } 200: 201: /** 202: * Returns the insets for this container, which is the space used for 203: * borders, the margin, etc. 204: * 205: * @return The insets for this container. 206: * @deprecated use {@link #getInsets()} instead 207: */ 208: public Insets insets() 209: { 210: Insets i; 211: if (peer == null || peer instanceof LightweightPeer) 212: i = new Insets (0, 0, 0, 0); 213: else 214: i = ((ContainerPeer) peer).getInsets (); 215: return i; 216: } 217: 218: /** 219: * Adds the specified component to this container at the end of the 220: * component list. 221: * 222: * @param comp The component to add to the container. 223: * 224: * @return The same component that was added. 225: */ 226: public Component add(Component comp) 227: { 228: addImpl(comp, null, -1); 229: return comp; 230: } 231: 232: /** 233: * Adds the specified component to the container at the end of the 234: * component list. This method should not be used. Instead, use 235: * <code>add(Component, Object)</code>. 236: * 237: * @param name The name of the component to be added. 238: * @param comp The component to be added. 239: * 240: * @return The same component that was added. 241: * 242: * @see #add(Component,Object) 243: */ 244: public Component add(String name, Component comp) 245: { 246: addImpl(comp, name, -1); 247: return comp; 248: } 249: 250: /** 251: * Adds the specified component to this container at the specified index 252: * in the component list. 253: * 254: * @param comp The component to be added. 255: * @param index The index in the component list to insert this child 256: * at, or -1 to add at the end of the list. 257: * 258: * @return The same component that was added. 259: * 260: * @throws ArrayIndexOutOfBoundsException If the specified index is invalid. 261: */ 262: public Component add(Component comp, int index) 263: { 264: addImpl(comp, null, index); 265: return comp; 266: } 267: 268: /** 269: * Adds the specified component to this container at the end of the 270: * component list. The layout manager will use the specified constraints 271: * when laying out this component. 272: * 273: * @param comp The component to be added to this container. 274: * @param constraints The layout constraints for this component. 275: */ 276: public void add(Component comp, Object constraints) 277: { 278: addImpl(comp, constraints, -1); 279: } 280: 281: /** 282: * Adds the specified component to this container at the specified index 283: * in the component list. The layout manager will use the specified 284: * constraints when layout out this component. 285: * 286: * @param comp The component to be added. 287: * @param constraints The layout constraints for this component. 288: * @param index The index in the component list to insert this child 289: * at, or -1 to add at the end of the list. 290: * 291: * @throws ArrayIndexOutOfBoundsException If the specified index is invalid. 292: */ 293: public void add(Component comp, Object constraints, int index) 294: { 295: addImpl(comp, constraints, index); 296: } 297: 298: /** 299: * This method is called by all the <code>add()</code> methods to perform 300: * the actual adding of the component. Subclasses who wish to perform 301: * their own processing when a component is added should override this 302: * method. Any subclass doing this must call the superclass version of 303: * this method in order to ensure proper functioning of the container. 304: * 305: * @param comp The component to be added. 306: * @param constraints The layout constraints for this component, or 307: * <code>null</code> if there are no constraints. 308: * @param index The index in the component list to insert this child 309: * at, or -1 to add at the end of the list. 310: * 311: * @throws ArrayIndexOutOfBoundsException If the specified index is invalid. 312: */ 313: protected void addImpl(Component comp, Object constraints, int index) 314: { 315: synchronized (getTreeLock ()) 316: { 317: if (index > ncomponents 318: || (index < 0 && index != -1) 319: || comp instanceof Window 320: || (comp instanceof Container 321: && ((Container) comp).isAncestorOf(this))) 322: throw new IllegalArgumentException(); 323: 324: // Reparent component, and make sure component is instantiated if 325: // we are. 326: if (comp.parent != null) 327: comp.parent.remove(comp); 328: 329: if (component == null) 330: component = new Component[4]; // FIXME, better initial size? 331: 332: // This isn't the most efficient implementation. We could do less 333: // copying when growing the array. It probably doesn't matter. 334: if (ncomponents >= component.length) 335: { 336: int nl = component.length * 2; 337: Component[] c = new Component[nl]; 338: System.arraycopy(component, 0, c, 0, ncomponents); 339: component = c; 340: } 341: 342: if (index == -1) 343: component[ncomponents++] = comp; 344: else 345: { 346: System.arraycopy(component, index, component, index + 1, 347: ncomponents - index); 348: component[index] = comp; 349: ++ncomponents; 350: } 351: 352: // Give the new component a parent. 353: comp.parent = this; 354: 355: // Update the counter for Hierarchy(Bounds)Listeners. 356: int childHierarchyListeners = comp.numHierarchyListeners; 357: if (childHierarchyListeners > 0) 358: updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, 359: childHierarchyListeners); 360: int childHierarchyBoundsListeners = comp.numHierarchyBoundsListeners; 361: if (childHierarchyBoundsListeners > 0) 362: updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 363: childHierarchyListeners); 364: 365: // Invalidate the layout of this container. 366: if (valid) 367: invalidate(); 368: 369: // Create the peer _after_ the component has been added, so that 370: // the peer gets to know about the component hierarchy. 371: if (peer != null) 372: { 373: // Notify the component that it has a new parent. 374: comp.addNotify(); 375: } 376: 377: // Notify the layout manager. 378: if (layoutMgr != null) 379: { 380: // If we have a LayoutManager2 the constraints are "real", 381: // otherwise they are the "name" of the Component to add. 382: if (layoutMgr instanceof LayoutManager2) 383: { 384: LayoutManager2 lm2 = (LayoutManager2) layoutMgr; 385: lm2.addLayoutComponent(comp, constraints); 386: } 387: else if (constraints instanceof String) 388: layoutMgr.addLayoutComponent((String) constraints, comp); 389: else 390: layoutMgr.addLayoutComponent("", comp); 391: } 392: 393: // We previously only sent an event when this container is showing. 394: // Also, the event was posted to the event queue. A Mauve test shows 395: // that this event is not delivered using the event queue and it is 396: // also sent when the container is not showing. 397: if (containerListener != null 398: || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) 399: { 400: ContainerEvent ce = new ContainerEvent(this, 401: ContainerEvent.COMPONENT_ADDED, 402: comp); 403: dispatchEvent(ce); 404: } 405: 406: // Notify hierarchy listeners. 407: comp.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, comp, 408: this, HierarchyEvent.PARENT_CHANGED); 409: } 410: } 411: 412: /** 413: * Removes the component at the specified index from this container. 414: * 415: * @param index The index of the component to remove. 416: */ 417: public void remove(int index) 418: { 419: synchronized (getTreeLock ()) 420: { 421: if (index < 0 || index >= ncomponents) 422: throw new ArrayIndexOutOfBoundsException(); 423: 424: Component r = component[index]; 425: if (peer != null) 426: r.removeNotify(); 427: 428: if (layoutMgr != null) 429: layoutMgr.removeLayoutComponent(r); 430: 431: // Update the counter for Hierarchy(Bounds)Listeners. 432: int childHierarchyListeners = r.numHierarchyListeners; 433: if (childHierarchyListeners > 0) 434: updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, 435: -childHierarchyListeners); 436: int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners; 437: if (childHierarchyBoundsListeners > 0) 438: updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 439: -childHierarchyListeners); 440: 441: r.parent = null; 442: 443: System.arraycopy(component, index + 1, component, index, 444: ncomponents - index - 1); 445: component[--ncomponents] = null; 446: 447: if (valid) 448: invalidate(); 449: 450: if (containerListener != null 451: || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) 452: { 453: // Post event to notify of removing the component. 454: ContainerEvent ce = new ContainerEvent(this, 455: ContainerEvent.COMPONENT_REMOVED, 456: r); 457: dispatchEvent(ce); 458: } 459: 460: // Notify hierarchy listeners. 461: r.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, 462: this, HierarchyEvent.PARENT_CHANGED); 463: } 464: } 465: 466: /** 467: * Removes the specified component from this container. 468: * 469: * @param comp The component to remove from this container. 470: */ 471: public void remove(Component comp) 472: { 473: synchronized (getTreeLock ()) 474: { 475: for (int i = 0; i < ncomponents; ++i) 476: { 477: if (component[i] == comp) 478: { 479: remove(i); 480: break; 481: } 482: } 483: } 484: } 485: 486: /** 487: * Removes all components from this container. 488: */ 489: public void removeAll() 490: { 491: synchronized (getTreeLock ()) 492: { 493: // In order to allow the same bad tricks to be used as in RI 494: // this code has to stay exactly that way: In a real-life app 495: // a Container subclass implemented its own vector for 496: // subcomponents, supplied additional addXYZ() methods 497: // and overrode remove(int) and removeAll (the latter calling 498: // super.removeAll() ). 499: // By doing it this way, user code cannot prevent the correct 500: // removal of components. 501: while (ncomponents > 0) 502: { 503: ncomponents--; 504: Component r = component[ncomponents]; 505: component[ncomponents] = null; 506: 507: if (peer != null) 508: r.removeNotify(); 509: 510: if (layoutMgr != null) 511: layoutMgr.removeLayoutComponent(r); 512: 513: r.parent = null; 514: 515: // Send ContainerEvent if necessary. 516: if (containerListener != null 517: || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) 518: { 519: // Post event to notify of removing the component. 520: ContainerEvent ce 521: = new ContainerEvent(this, 522: ContainerEvent.COMPONENT_REMOVED, 523: r); 524: dispatchEvent(ce); 525: } 526: 527: // Update the counter for Hierarchy(Bounds)Listeners. 528: int childHierarchyListeners = r.numHierarchyListeners; 529: if (childHierarchyListeners > 0) 530: updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, 531: -childHierarchyListeners); 532: int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners; 533: if (childHierarchyBoundsListeners > 0) 534: updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 535: -childHierarchyListeners); 536: 537: 538: // Send HierarchyEvent if necessary. 539: fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, this, 540: HierarchyEvent.PARENT_CHANGED); 541: 542: } 543: 544: if (valid) 545: invalidate(); 546: } 547: } 548: 549: /** 550: * Returns the current layout manager for this container. 551: * 552: * @return The layout manager for this container. 553: */ 554: public LayoutManager getLayout() 555: { 556: return layoutMgr; 557: } 558: 559: /** 560: * Sets the layout manager for this container to the specified layout 561: * manager. 562: * 563: * @param mgr The new layout manager for this container. 564: */ 565: public void setLayout(LayoutManager mgr) 566: { 567: layoutMgr = mgr; 568: if (valid) 569: invalidate(); 570: } 571: 572: /** 573: * Layout the components in this container. 574: */ 575: public void doLayout() 576: { 577: layout (); 578: } 579: 580: /** 581: * Layout the components in this container. 582: * 583: * @deprecated use {@link #doLayout()} instead 584: */ 585: public void layout() 586: { 587: if (layoutMgr != null) 588: layoutMgr.layoutContainer (this); 589: } 590: 591: /** 592: * Invalidates this container to indicate that it (and all parent 593: * containers) need to be laid out. 594: */ 595: public void invalidate() 596: { 597: super.invalidate(); 598: if (layoutMgr != null && layoutMgr instanceof LayoutManager2) 599: { 600: LayoutManager2 lm2 = (LayoutManager2) layoutMgr; 601: lm2.invalidateLayout(this); 602: } 603: } 604: 605: /** 606: * Re-lays out the components in this container. 607: */ 608: public void validate() 609: { 610: ComponentPeer p = peer; 611: if (! valid && p != null) 612: { 613: ContainerPeer cPeer = null; 614: if (p instanceof ContainerPeer) 615: cPeer = (ContainerPeer) peer; 616: synchronized (getTreeLock ()) 617: { 618: if (cPeer != null) 619: cPeer.beginValidate(); 620: validateTree(); 621: valid = true; 622: if (cPeer != null) 623: cPeer.endValidate(); 624: } 625: } 626: } 627: 628: /** 629: * Recursively invalidates the container tree. 630: */ 631: private final void invalidateTree() 632: { 633: synchronized (getTreeLock()) 634: { 635: for (int i = 0; i < ncomponents; i++) 636: { 637: Component comp = component[i]; 638: if (comp instanceof Container) 639: ((Container) comp).invalidateTree(); 640: else if (comp.valid) 641: comp.invalidate(); 642: } 643: if (valid) 644: invalidate(); 645: } 646: } 647: 648: /** 649: * Recursively validates the container tree, recomputing any invalid 650: * layouts. 651: */ 652: protected void validateTree() 653: { 654: if (!valid) 655: { 656: ContainerPeer cPeer = null; 657: if (peer instanceof ContainerPeer) 658: { 659: cPeer = (ContainerPeer) peer; 660: cPeer.beginLayout(); 661: } 662: 663: doLayout (); 664: for (int i = 0; i < ncomponents; ++i) 665: { 666: Component comp = component[i]; 667: 668: if (comp instanceof Container && ! (comp instanceof Window) 669: && ! comp.valid) 670: { 671: ((Container) comp).validateTree(); 672: } 673: else 674: { 675: comp.validate(); 676: } 677: } 678: 679: if (cPeer != null) 680: { 681: cPeer = (ContainerPeer) peer; 682: cPeer.endLayout(); 683: } 684: } 685: 686: /* children will call invalidate() when they are layed out. It 687: is therefore important that valid is not set to true 688: until after the children have been layed out. */ 689: valid = true; 690: 691: } 692: 693: public void setFont(Font f) 694: { 695: Font oldFont = getFont(); 696: super.setFont(f); 697: Font newFont = getFont(); 698: if (newFont != oldFont && (oldFont == null || ! oldFont.equals(newFont))) 699: { 700: invalidateTree(); 701: } 702: } 703: 704: /** 705: * Returns the preferred size of this container. 706: * 707: * @return The preferred size of this container. 708: */ 709: public Dimension getPreferredSize() 710: { 711: return preferredSize (); 712: } 713: 714: /** 715: * Returns the preferred size of this container. 716: * 717: * @return The preferred size of this container. 718: * 719: * @deprecated use {@link #getPreferredSize()} instead 720: */ 721: public Dimension preferredSize() 722: { 723: Dimension size = prefSize; 724: // Try to return cached value if possible. 725: if (size == null || !(prefSizeSet || valid)) 726: { 727: // Need to lock here. 728: synchronized (getTreeLock()) 729: { 730: LayoutManager l = layoutMgr; 731: if (l != null) 732: prefSize = l.preferredLayoutSize(this); 733: else 734: prefSize = super.preferredSizeImpl(); 735: size = prefSize; 736: } 737: } 738: if (size != null) 739: return new Dimension(size); 740: else 741: return size; 742: } 743: 744: /** 745: * Returns the minimum size of this container. 746: * 747: * @return The minimum size of this container. 748: */ 749: public Dimension getMinimumSize() 750: { 751: return minimumSize (); 752: } 753: 754: /** 755: * Returns the minimum size of this container. 756: * 757: * @return The minimum size of this container. 758: * 759: * @deprecated use {@link #getMinimumSize()} instead 760: */ 761: public Dimension minimumSize() 762: { 763: Dimension size = minSize; 764: // Try to return cached value if possible. 765: if (size == null || !(minSizeSet || valid)) 766: { 767: // Need to lock here. 768: synchronized (getTreeLock()) 769: { 770: LayoutManager l = layoutMgr; 771: if (l != null) 772: minSize = l.minimumLayoutSize(this); 773: else 774: minSize = super.minimumSizeImpl(); 775: size = minSize; 776: } 777: } 778: if (size != null) 779: return new Dimension(size); 780: else 781: return size; 782: } 783: 784: /** 785: * Returns the maximum size of this container. 786: * 787: * @return The maximum size of this container. 788: */ 789: public Dimension getMaximumSize() 790: { 791: Dimension size = maxSize; 792: // Try to return cached value if possible. 793: if (size == null || !(maxSizeSet || valid)) 794: { 795: // Need to lock here. 796: synchronized (getTreeLock()) 797: { 798: LayoutManager l = layoutMgr; 799: if (l instanceof LayoutManager2) 800: maxSize = ((LayoutManager2) l).maximumLayoutSize(this); 801: else { 802: maxSize = super.maximumSizeImpl(); 803: } 804: size = maxSize; 805: } 806: } 807: if (size != null) 808: return new Dimension(size); 809: else 810: return size; 811: } 812: 813: /** 814: * Returns the preferred alignment along the X axis. This is a value 815: * between 0 and 1 where 0 represents alignment flush left and 816: * 1 means alignment flush right, and 0.5 means centered. 817: * 818: * @return The preferred alignment along the X axis. 819: */ 820: public float getAlignmentX() 821: { 822: LayoutManager layout = getLayout(); 823: float alignmentX = 0.0F; 824: if (layout != null && layout instanceof LayoutManager2) 825: { 826: synchronized (getTreeLock()) 827: { 828: LayoutManager2 lm2 = (LayoutManager2) layout; 829: alignmentX = lm2.getLayoutAlignmentX(this); 830: } 831: } 832: else 833: alignmentX = super.getAlignmentX(); 834: return alignmentX; 835: } 836: 837: /** 838: * Returns the preferred alignment along the Y axis. This is a value 839: * between 0 and 1 where 0 represents alignment flush top and 840: * 1 means alignment flush bottom, and 0.5 means centered. 841: * 842: * @return The preferred alignment along the Y axis. 843: */ 844: public float getAlignmentY() 845: { 846: LayoutManager layout = getLayout(); 847: float alignmentY = 0.0F; 848: if (layout != null && layout instanceof LayoutManager2) 849: { 850: synchronized (getTreeLock()) 851: { 852: LayoutManager2 lm2 = (LayoutManager2) layout; 853: alignmentY = lm2.getLayoutAlignmentY(this); 854: } 855: } 856: else 857: alignmentY = super.getAlignmentY(); 858: return alignmentY; 859: } 860: 861: /** 862: * Paints this container. The implementation of this method in this 863: * class forwards to any lightweight components in this container. If 864: * this method is subclassed, this method should still be invoked as 865: * a superclass method so that lightweight components are properly 866: * drawn. 867: * 868: * @param g - The graphics context for this paint job. 869: */ 870: public void paint(Graphics g) 871: { 872: if (isShowing()) 873: { 874: visitChildren(g, GfxPaintVisitor.INSTANCE, true); 875: } 876: } 877: 878: /** 879: * Updates this container. The implementation of this method in this 880: * class forwards to any lightweight components in this container. If 881: * this method is subclassed, this method should still be invoked as 882: * a superclass method so that lightweight components are properly 883: * drawn. 884: * 885: * @param g The graphics context for this update. 886: * 887: * @specnote The specification suggests that this method forwards the 888: * update() call to all its lightweight children. Tests show 889: * that this is not done either in the JDK. The exact behaviour 890: * seems to be that the background is cleared in heavyweight 891: * Containers, and all other containers 892: * directly call paint(), causing the (lightweight) children to 893: * be painted. 894: */ 895: public void update(Graphics g) 896: { 897: // It seems that the JDK clears the background of containers like Panel 898: // and Window (within this method) but not of 'plain' Containers or 899: // JComponents. This could 900: // lead to the assumption that it only clears heavyweight containers. 901: // However that is not quite true. In a test with a custom Container 902: // that overrides isLightweight() to return false, the background is 903: // also not cleared. So we do a check on !(peer instanceof LightweightPeer) 904: // instead. 905: if (isShowing()) 906: { 907: ComponentPeer p = peer; 908: if (! (p instanceof LightweightPeer)) 909: { 910: g.clearRect(0, 0, getWidth(), getHeight()); 911: } 912: paint(g); 913: } 914: } 915: 916: /** 917: * Prints this container. The implementation of this method in this 918: * class forwards to any lightweight components in this container. If 919: * this method is subclassed, this method should still be invoked as 920: * a superclass method so that lightweight components are properly 921: * drawn. 922: * 923: * @param g The graphics context for this print job. 924: */ 925: public void print(Graphics g) 926: { 927: super.print(g); 928: visitChildren(g, GfxPrintVisitor.INSTANCE, true); 929: } 930: 931: /** 932: * Paints all of the components in this container. 933: * 934: * @param g The graphics context for this paint job. 935: */ 936: public void paintComponents(Graphics g) 937: { 938: if (isShowing()) 939: visitChildren(g, GfxPaintAllVisitor.INSTANCE, false); 940: } 941: 942: /** 943: * Prints all of the components in this container. 944: * 945: * @param g The graphics context for this print job. 946: */ 947: public void printComponents(Graphics g) 948: { 949: super.paint(g); 950: visitChildren(g, GfxPrintAllVisitor.INSTANCE, true); 951: } 952: 953: /** 954: * Adds the specified container listener to this object's list of 955: * container listeners. 956: * 957: * @param listener The listener to add. 958: */ 959: public synchronized void addContainerListener(ContainerListener listener) 960: { 961: if (listener != null) 962: { 963: containerListener = AWTEventMulticaster.add(containerListener, 964: listener); 965: newEventsOnly = true; 966: } 967: } 968: 969: /** 970: * Removes the specified container listener from this object's list of 971: * container listeners. 972: * 973: * @param listener The listener to remove. 974: */ 975: public synchronized void removeContainerListener(ContainerListener listener) 976: { 977: containerListener = AWTEventMulticaster.remove(containerListener, listener); 978: } 979: 980: /** 981: * @since 1.4 982: */ 983: public synchronized ContainerListener[] getContainerListeners() 984: { 985: return (ContainerListener[]) 986: AWTEventMulticaster.getListeners(containerListener, 987: ContainerListener.class); 988: } 989: 990: /** 991: * Returns all registered {@link EventListener}s of the given 992: * <code>listenerType</code>. 993: * 994: * @param listenerType the class of listeners to filter (<code>null</code> 995: * not permitted). 996: * 997: * @return An array of registered listeners. 998: * 999: * @throws ClassCastException if <code>listenerType</code> does not implement 1000: * the {@link EventListener} interface. 1001: * @throws NullPointerException if <code>listenerType</code> is 1002: * <code>null</code>. 1003: * 1004: * @see #getContainerListeners() 1005: * 1006: * @since 1.3 1007: */ 1008: public <T extends EventListener> T[] getListeners(Class<T> listenerType) 1009: { 1010: if (listenerType == ContainerListener.class) 1011: return (T[]) getContainerListeners(); 1012: return super.getListeners(listenerType); 1013: } 1014: 1015: /** 1016: * Processes the specified event. This method calls 1017: * <code>processContainerEvent()</code> if this method is a 1018: * <code>ContainerEvent</code>, otherwise it calls the superclass 1019: * method. 1020: * 1021: * @param e The event to be processed. 1022: */ 1023: protected void processEvent(AWTEvent e) 1024: { 1025: if (e instanceof ContainerEvent) 1026: processContainerEvent((ContainerEvent) e); 1027: else 1028: super.processEvent(e); 1029: } 1030: 1031: /** 1032: * Called when a container event occurs if container events are enabled. 1033: * This method calls any registered listeners. 1034: * 1035: * @param e The event that occurred. 1036: */ 1037: protected void processContainerEvent(ContainerEvent e) 1038: { 1039: if (containerListener == null) 1040: return; 1041: switch (e.id) 1042: { 1043: case ContainerEvent.COMPONENT_ADDED: 1044: containerListener.componentAdded(e); 1045: break; 1046: 1047: case ContainerEvent.COMPONENT_REMOVED: 1048: containerListener.componentRemoved(e); 1049: break; 1050: } 1051: } 1052: 1053: /** 1054: * AWT 1.0 event processor. 1055: * 1056: * @param e The event that occurred. 1057: * 1058: * @deprecated use {@link #dispatchEvent(AWTEvent)} instead 1059: */ 1060: public void deliverEvent(Event e) 1061: { 1062: if (!handleEvent (e)) 1063: { 1064: synchronized (getTreeLock ()) 1065: { 1066: Component parent = getParent (); 1067: 1068: if (parent != null) 1069: parent.deliverEvent (e); 1070: } 1071: } 1072: } 1073: 1074: /** 1075: * Returns the component located at the specified point. This is done 1076: * by checking whether or not a child component claims to contain this 1077: * point. The first child component that does is returned. If no 1078: * child component claims the point, the container itself is returned, 1079: * unless the point does not exist within this container, in which 1080: * case <code>null</code> is returned. 1081: * 1082: * When components overlap, the first component is returned. The component 1083: * that is closest to (x, y), containing that location, is returned. 1084: * Heavyweight components take precedence of lightweight components. 1085: * 1086: * This function does not ignore invisible components. If there is an invisible 1087: * component at (x,y), it will be returned. 1088: * 1089: * @param x The X coordinate of the point. 1090: * @param y The Y coordinate of the point. 1091: * 1092: * @return The component containing the specified point, or 1093: * <code>null</code> if there is no such point. 1094: */ 1095: public Component getComponentAt(int x, int y) 1096: { 1097: return locate (x, y); 1098: } 1099: 1100: /** 1101: * Returns the mouse pointer position relative to this Container's 1102: * top-left corner. If allowChildren is false, the mouse pointer 1103: * must be directly over this container. If allowChildren is true, 1104: * the mouse pointer may be over this container or any of its 1105: * descendents. 1106: * 1107: * @param allowChildren true to allow descendents, false if pointer 1108: * must be directly over Container. 1109: * 1110: * @return relative mouse pointer position 1111: * 1112: * @throws HeadlessException if in a headless environment 1113: */ 1114: public Point getMousePosition(boolean allowChildren) throws HeadlessException 1115: { 1116: return super.getMousePositionHelper(allowChildren); 1117: } 1118: 1119: boolean mouseOverComponent(Component component, boolean allowChildren) 1120: { 1121: if (allowChildren) 1122: return isAncestorOf(component); 1123: else 1124: return component == this; 1125: } 1126: 1127: /** 1128: * Returns the component located at the specified point. This is done 1129: * by checking whether or not a child component claims to contain this 1130: * point. The first child component that does is returned. If no 1131: * child component claims the point, the container itself is returned, 1132: * unless the point does not exist within this container, in which 1133: * case <code>null</code> is returned. 1134: * 1135: * When components overlap, the first component is returned. The component 1136: * that is closest to (x, y), containing that location, is returned. 1137: * Heavyweight components take precedence of lightweight components. 1138: * 1139: * This function does not ignore invisible components. If there is an invisible 1140: * component at (x,y), it will be returned. 1141: * 1142: * @param x The x position of the point to return the component at. 1143: * @param y The y position of the point to return the component at. 1144: * 1145: * @return The component containing the specified point, or <code>null</code> 1146: * if there is no such point. 1147: * 1148: * @deprecated use {@link #getComponentAt(int, int)} instead 1149: */ 1150: public Component locate(int x, int y) 1151: { 1152: synchronized (getTreeLock ()) 1153: { 1154: if (!contains (x, y)) 1155: return null; 1156: 1157: // First find the component closest to (x,y) that is a heavyweight. 1158: for (int i = 0; i < ncomponents; ++i) 1159: { 1160: Component comp = component[i]; 1161: int x2 = x - comp.x; 1162: int y2 = y - comp.y; 1163: if (comp.contains (x2, y2) && !comp.isLightweight()) 1164: return comp; 1165: } 1166: 1167: // if a heavyweight component is not found, look for a lightweight 1168: // closest to (x,y). 1169: for (int i = 0; i < ncomponents; ++i) 1170: { 1171: Component comp = component[i]; 1172: int x2 = x - comp.x; 1173: int y2 = y - comp.y; 1174: if (comp.contains (x2, y2) && comp.isLightweight()) 1175: return comp; 1176: } 1177: 1178: return this; 1179: } 1180: } 1181: 1182: /** 1183: * Returns the component located at the specified point. This is done 1184: * by checking whether or not a child component claims to contain this 1185: * point. The first child component that does is returned. If no 1186: * child component claims the point, the container itself is returned, 1187: * unless the point does not exist within this container, in which 1188: * case <code>null</code> is returned. 1189: * 1190: * The top-most child component is returned in the case where components overlap. 1191: * This is determined by finding the component closest to (x,y) and contains 1192: * that location. Heavyweight components take precedence of lightweight components. 1193: * 1194: * This function does not ignore invisible components. If there is an invisible 1195: * component at (x,y), it will be returned. 1196: * 1197: * @param p The point to return the component at. 1198: * @return The component containing the specified point, or <code>null</code> 1199: * if there is no such point. 1200: */ 1201: public Component getComponentAt(Point p) 1202: { 1203: return getComponentAt (p.x, p.y); 1204: } 1205: 1206: /** 1207: * Locates the visible child component that contains the specified position. 1208: * The top-most child component is returned in the case where there is overlap 1209: * in the components. If the containing child component is a Container, 1210: * this method will continue searching for the deepest nested child 1211: * component. Components which are not visible are ignored during the search. 1212: * 1213: * findComponentAt differs from getComponentAt, because it recursively 1214: * searches a Container's children. 1215: * 1216: * @param x - x coordinate 1217: * @param y - y coordinate 1218: * @return null if the component does not contain the position. 1219: * If there is no child component at the requested point and the point is 1220: * within the bounds of the container the container itself is returned. 1221: */ 1222: public Component findComponentAt(int x, int y) 1223: { 1224: synchronized (getTreeLock ()) 1225: { 1226: if (! contains(x, y)) 1227: return null; 1228: 1229: for (int i = 0; i < ncomponents; ++i) 1230: { 1231: // Ignore invisible children... 1232: if (!component[i].isVisible()) 1233: continue; 1234: 1235: int x2 = x - component[i].x; 1236: int y2 = y - component[i].y; 1237: // We don't do the contains() check right away because 1238: // findComponentAt would redundantly do it first thing. 1239: if (component[i] instanceof Container) 1240: { 1241: Container k = (Container) component[i]; 1242: Component r = k.findComponentAt(x2, y2); 1243: if (r != null) 1244: return r; 1245: } 1246: else if (component[i].contains(x2, y2)) 1247: return component[i]; 1248: } 1249: 1250: return this; 1251: } 1252: } 1253: 1254: /** 1255: * Locates the visible child component that contains the specified position. 1256: * The top-most child component is returned in the case where there is overlap 1257: * in the components. If the containing child component is a Container, 1258: * this method will continue searching for the deepest nested child 1259: * component. Components which are not visible are ignored during the search. 1260: * 1261: * findComponentAt differs from getComponentAt, because it recursively 1262: * searches a Container's children. 1263: * 1264: * @param p - the component's location 1265: * @return null if the component does not contain the position. 1266: * If there is no child component at the requested point and the point is 1267: * within the bounds of the container the container itself is returned. 1268: */ 1269: public Component findComponentAt(Point p) 1270: { 1271: return findComponentAt(p.x, p.y); 1272: } 1273: 1274: /** 1275: * Called when this container is added to another container to inform it 1276: * to create its peer. Peers for any child components will also be 1277: * created. 1278: */ 1279: public void addNotify() 1280: { 1281: synchronized (getTreeLock()) 1282: { 1283: super.addNotify(); 1284: addNotifyContainerChildren(); 1285: } 1286: } 1287: 1288: /** 1289: * Called when this container is removed from its parent container to 1290: * inform it to destroy its peer. This causes the peers of all child 1291: * component to be destroyed as well. 1292: */ 1293: public void removeNotify() 1294: { 1295: synchronized (getTreeLock ()) 1296: { 1297: int ncomps = ncomponents; 1298: Component[] comps = component; 1299: for (int i = ncomps - 1; i >= 0; --i) 1300: { 1301: Component comp = comps[i]; 1302: if (comp != null) 1303: comp.removeNotify(); 1304: } 1305: super.removeNotify(); 1306: } 1307: } 1308: 1309: /** 1310: * Tests whether or not the specified component is contained within 1311: * this components subtree. 1312: * 1313: * @param comp The component to test. 1314: * 1315: * @return <code>true</code> if this container is an ancestor of the 1316: * specified component, <code>false</code> otherwise. 1317: */ 1318: public boolean isAncestorOf(Component comp) 1319: { 1320: synchronized (getTreeLock ()) 1321: { 1322: while (true) 1323: { 1324: if (comp == null) 1325: return false; 1326: comp = comp.getParent(); 1327: if (comp == this) 1328: return true; 1329: } 1330: } 1331: } 1332: 1333: /** 1334: * Returns a string representing the state of this container for 1335: * debugging purposes. 1336: * 1337: * @return A string representing the state of this container. 1338: */ 1339: protected String paramString() 1340: { 1341: if (layoutMgr == null) 1342: return super.paramString(); 1343: 1344: StringBuffer sb = new StringBuffer(); 1345: sb.append(super.paramString()); 1346: sb.append(",layout="); 1347: sb.append(layoutMgr.getClass().getName()); 1348: return sb.toString(); 1349: } 1350: 1351: /** 1352: * Writes a listing of this container to the specified stream starting 1353: * at the specified indentation point. 1354: * 1355: * @param out The <code>PrintStream</code> to write to. 1356: * @param indent The indentation point. 1357: */ 1358: public void list(PrintStream out, int indent) 1359: { 1360: synchronized (getTreeLock ()) 1361: { 1362: super.list(out, indent); 1363: for (int i = 0; i < ncomponents; ++i) 1364: component[i].list(out, indent + 2); 1365: } 1366: } 1367: 1368: /** 1369: * Writes a listing of this container to the specified stream starting 1370: * at the specified indentation point. 1371: * 1372: * @param out The <code>PrintWriter</code> to write to. 1373: * @param indent The indentation point. 1374: */ 1375: public void list(PrintWriter out, int indent) 1376: { 1377: synchronized (getTreeLock ()) 1378: { 1379: super.list(out, indent); 1380: for (int i = 0; i < ncomponents; ++i) 1381: component[i].list(out, indent + 2); 1382: } 1383: } 1384: 1385: /** 1386: * Sets the focus traversal keys for a given traversal operation for this 1387: * Container. 1388: * 1389: * @exception IllegalArgumentException If id is not one of 1390: * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 1391: * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 1392: * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, 1393: * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, 1394: * or if keystrokes contains null, or if any Object in keystrokes is not an 1395: * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event, or if any 1396: * keystroke already maps to another focus traversal operation for this 1397: * Container. 1398: * 1399: * @since 1.4 1400: */ 1401: public void setFocusTraversalKeys(int id, 1402: Set<? extends AWTKeyStroke> keystrokes) 1403: { 1404: if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && 1405: id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && 1406: id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS && 1407: id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS) 1408: throw new IllegalArgumentException (); 1409: 1410: if (keystrokes == null) 1411: { 1412: Container parent = getParent (); 1413: 1414: while (parent != null) 1415: { 1416: if (parent.areFocusTraversalKeysSet (id)) 1417: { 1418: keystrokes = parent.getFocusTraversalKeys (id); 1419: break; 1420: } 1421: parent = parent.getParent (); 1422: } 1423: 1424: if (keystrokes == null) 1425: keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager (). 1426: getDefaultFocusTraversalKeys (id); 1427: } 1428: 1429: Set sa; 1430: Set sb; 1431: Set sc; 1432: String name; 1433: switch (id) 1434: { 1435: case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS: 1436: sa = getFocusTraversalKeys 1437: (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); 1438: sb = getFocusTraversalKeys 1439: (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); 1440: sc = getFocusTraversalKeys 1441: (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS); 1442: name = "forwardFocusTraversalKeys"; 1443: break; 1444: case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS: 1445: sa = getFocusTraversalKeys 1446: (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); 1447: sb = getFocusTraversalKeys 1448: (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); 1449: sc = getFocusTraversalKeys 1450: (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS); 1451: name = "backwardFocusTraversalKeys"; 1452: break; 1453: case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS: 1454: sa = getFocusTraversalKeys 1455: (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); 1456: sb = getFocusTraversalKeys 1457: (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); 1458: sc = getFocusTraversalKeys 1459: (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS); 1460: name = "upCycleFocusTraversalKeys"; 1461: break; 1462: case KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS: 1463: sa = getFocusTraversalKeys 1464: (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); 1465: sb = getFocusTraversalKeys 1466: (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); 1467: sc = getFocusTraversalKeys 1468: (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); 1469: name = "downCycleFocusTraversalKeys"; 1470: break; 1471: default: 1472: throw new IllegalArgumentException (); 1473: } 1474: 1475: int i = keystrokes.size (); 1476: Iterator iter = keystrokes.iterator (); 1477: 1478: while (--i >= 0) 1479: { 1480: Object o = iter.next (); 1481: if (!(o instanceof AWTKeyStroke) 1482: || sa.contains (o) || sb.contains (o) || sc.contains (o) 1483: || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED) 1484: throw new IllegalArgumentException (); 1485: } 1486: 1487: if (focusTraversalKeys == null) 1488: focusTraversalKeys = new Set[4]; 1489: 1490: keystrokes = 1491: Collections.unmodifiableSet(new HashSet<AWTKeyStroke>(keystrokes)); 1492: firePropertyChange (name, focusTraversalKeys[id], keystrokes); 1493: 1494: focusTraversalKeys[id] = keystrokes; 1495: } 1496: 1497: /** 1498: * Returns the Set of focus traversal keys for a given traversal operation for 1499: * this Container. 1500: * 1501: * @exception IllegalArgumentException If id is not one of 1502: * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 1503: * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 1504: * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, 1505: * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS. 1506: * 1507: * @since 1.4 1508: */ 1509: public Set<AWTKeyStroke> getFocusTraversalKeys (int id) 1510: { 1511: if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && 1512: id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && 1513: id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS && 1514: id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS) 1515: throw new IllegalArgumentException (); 1516: 1517: Set s = null; 1518: 1519: if (focusTraversalKeys != null) 1520: s = focusTraversalKeys[id]; 1521: 1522: if (s == null && parent != null) 1523: s = parent.getFocusTraversalKeys (id); 1524: 1525: return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager() 1526: .getDefaultFocusTraversalKeys(id)) : s; 1527: } 1528: 1529: /** 1530: * Returns whether the Set of focus traversal keys for the given focus 1531: * traversal operation has been explicitly defined for this Container. 1532: * If this method returns false, this Container is inheriting the Set from 1533: * an ancestor, or from the current KeyboardFocusManager. 1534: * 1535: * @exception IllegalArgumentException If id is not one of 1536: * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 1537: * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 1538: * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, 1539: * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS. 1540: * 1541: * @since 1.4 1542: */ 1543: public boolean areFocusTraversalKeysSet (int id) 1544: { 1545: if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && 1546: id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && 1547: id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS && 1548: id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS) 1549: throw new IllegalArgumentException (); 1550: 1551: return focusTraversalKeys != null && focusTraversalKeys[id] != null; 1552: } 1553: 1554: /** 1555: * Check whether the given Container is the focus cycle root of this 1556: * Container's focus traversal cycle. If this Container is a focus 1557: * cycle root itself, then it will be in two different focus cycles 1558: * -- it's own, and that of its ancestor focus cycle root's. In 1559: * that case, if <code>c</code> is either of those containers, this 1560: * method will return true. 1561: * 1562: * @param c the candidate Container 1563: * 1564: * @return true if c is the focus cycle root of the focus traversal 1565: * cycle to which this Container belongs, false otherwise 1566: * 1567: * @since 1.4 1568: */ 1569: public boolean isFocusCycleRoot (Container c) 1570: { 1571: if (this == c 1572: && isFocusCycleRoot ()) 1573: return true; 1574: 1575: Container ancestor = getFocusCycleRootAncestor (); 1576: 1577: if (c == ancestor) 1578: return true; 1579: 1580: return false; 1581: } 1582: 1583: /** 1584: * If this Container is a focus cycle root, set the focus traversal 1585: * policy that determines the focus traversal order for its 1586: * children. If non-null, this policy will be inherited by all 1587: * inferior focus cycle roots. If <code>policy</code> is null, this 1588: * Container will inherit its policy from the closest ancestor focus 1589: * cycle root that's had its policy set. 1590: * 1591: * @param policy the new focus traversal policy for this Container or null 1592: * 1593: * @since 1.4 1594: */ 1595: public void setFocusTraversalPolicy (FocusTraversalPolicy policy) 1596: { 1597: focusTraversalPolicy = policy; 1598: } 1599: 1600: /** 1601: * Return the focus traversal policy that determines the focus 1602: * traversal order for this Container's children. This method 1603: * returns null if this Container is not a focus cycle root. If the 1604: * focus traversal policy has not been set explicitly, then this 1605: * method will return an ancestor focus cycle root's policy instead. 1606: * 1607: * @return this Container's focus traversal policy or null 1608: * 1609: * @since 1.4 1610: */ 1611: public FocusTraversalPolicy getFocusTraversalPolicy () 1612: { 1613: if (!isFocusCycleRoot ()) 1614: return null; 1615: 1616: if (focusTraversalPolicy == null) 1617: { 1618: Container ancestor = getFocusCycleRootAncestor (); 1619: 1620: if (ancestor != this && ancestor != null) 1621: return ancestor.getFocusTraversalPolicy (); 1622: else 1623: { 1624: KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); 1625: 1626: return manager.getDefaultFocusTraversalPolicy (); 1627: } 1628: } 1629: else 1630: return focusTraversalPolicy; 1631: } 1632: 1633: /** 1634: * Check whether this Container's focus traversal policy has been 1635: * explicitly set. If it has not, then this Container will inherit 1636: * its focus traversal policy from one of its ancestor focus cycle 1637: * roots. 1638: * 1639: * @return true if focus traversal policy is set, false otherwise 1640: */ 1641: public boolean isFocusTraversalPolicySet () 1642: { 1643: return focusTraversalPolicy == null; 1644: } 1645: 1646: /** 1647: * Set whether or not this Container is the root of a focus 1648: * traversal cycle. This Container's focus traversal policy 1649: * determines the order of focus traversal. Some policies prevent 1650: * the focus from being transferred between two traversal cycles 1651: * until an up or down traversal operation is performed. In that 1652: * case, normal traversal (not up or down) is limited to this 1653: * Container and all of this Container's descendents that are not 1654: * descendents of inferior focus cycle roots. In the default case 1655: * however, ContainerOrderFocusTraversalPolicy is in effect, and it 1656: * supports implicit down-cycle traversal operations. 1657: * 1658: * @param focusCycleRoot true if this is a focus cycle root, false otherwise 1659: * 1660: * @since 1.4 1661: */ 1662: public void setFocusCycleRoot (boolean focusCycleRoot) 1663: { 1664: this.focusCycleRoot = focusCycleRoot; 1665: } 1666: 1667: /** 1668: * Set to <code>true</code> if this container provides a focus traversal 1669: * policy, <code>false</code> when the root container's focus 1670: * traversal policy should be used. 1671: * 1672: * @return <code>true</code> if this container provides a focus traversal 1673: * policy, <code>false</code> when the root container's focus 1674: * traversal policy should be used 1675: * 1676: * @see #setFocusTraversalPolicyProvider(boolean) 1677: * 1678: * @since 1.5 1679: */ 1680: public final boolean isFocusTraversalPolicyProvider() 1681: { 1682: return focusTraversalPolicyProvider; 1683: } 1684: 1685: /** 1686: * Set to <code>true</code> if this container provides a focus traversal 1687: * policy, <code>false</code> when the root container's focus 1688: * traversal policy should be used. 1689: * 1690: * @param b <code>true</code> if this container provides a focus traversal 1691: * policy, <code>false</code> when the root container's focus 1692: * traversal policy should be used 1693: * 1694: * @see #isFocusTraversalPolicyProvider() 1695: * 1696: * @since 1.5 1697: */ 1698: public final void setFocusTraversalPolicyProvider(boolean b) 1699: { 1700: focusTraversalPolicyProvider = b; 1701: } 1702: 1703: /** 1704: * Check whether this Container is a focus cycle root. 1705: * 1706: * @return true if this is a focus cycle root, false otherwise 1707: * 1708: * @since 1.4 1709: */ 1710: public boolean isFocusCycleRoot () 1711: { 1712: return focusCycleRoot; 1713: } 1714: 1715: /** 1716: * Transfer focus down one focus traversal cycle. If this Container 1717: * is a focus cycle root, then its default component becomes the 1718: * focus owner, and this Container becomes the current focus cycle 1719: * root. No traversal will occur if this Container is not a focus 1720: * cycle root. 1721: * 1722: * @since 1.4 1723: */ 1724: public void transferFocusDownCycle () 1725: { 1726: if (isFocusCycleRoot()) 1727: { 1728: KeyboardFocusManager fm = 1729: KeyboardFocusManager.getCurrentKeyboardFocusManager(); 1730: fm.setGlobalCurrentFocusCycleRoot(this); 1731: FocusTraversalPolicy policy = getFocusTraversalPolicy(); 1732: Component defaultComponent = policy.getDefaultComponent(this); 1733: if (defaultComponent != null) 1734: defaultComponent.requestFocus(); 1735: } 1736: } 1737: 1738: /** 1739: * Sets the ComponentOrientation property of this container and all components 1740: * contained within it. 1741: * 1742: * @exception NullPointerException If orientation is null 1743: * 1744: * @since 1.4 1745: */ 1746: public void applyComponentOrientation (ComponentOrientation orientation) 1747: { 1748: if (orientation == null) 1749: throw new NullPointerException(); 1750: 1751: setComponentOrientation(orientation); 1752: for (int i = 0; i < ncomponents; i++) 1753: { 1754: if (component[i] instanceof Container) 1755: ((Container) component[i]).applyComponentOrientation(orientation); 1756: else 1757: component[i].setComponentOrientation(orientation); 1758: } 1759: } 1760: 1761: public void addPropertyChangeListener (PropertyChangeListener listener) 1762: { 1763: // TODO: Why is this overridden? 1764: super.addPropertyChangeListener(listener); 1765: } 1766: 1767: public void addPropertyChangeListener (String propertyName, 1768: PropertyChangeListener listener) 1769: { 1770: // TODO: Why is this overridden? 1771: super.addPropertyChangeListener(propertyName, listener); 1772: } 1773: 1774: 1775: /** 1776: * Sets the Z ordering for the component <code>comp</code> to 1777: * <code>index</code>. Components with lower Z order paint above components 1778: * with higher Z order. 1779: * 1780: * @param comp the component for which to change the Z ordering 1781: * @param index the index to set 1782: * 1783: * @throws NullPointerException if <code>comp == null</code> 1784: * @throws IllegalArgumentException if comp is an ancestor of this container 1785: * @throws IllegalArgumentException if <code>index</code> is not in 1786: * <code>[0, getComponentCount()]</code> for moving between 1787: * containers or <code>[0, getComponentCount() - 1]</code> for moving 1788: * inside this container 1789: * @throws IllegalArgumentException if <code>comp == this</code> 1790: * @throws IllegalArgumentException if <code>comp</code> is a 1791: * <code>Window</code> 1792: * 1793: * @see #getComponentZOrder(Component) 1794: * 1795: * @since 1.5 1796: */ 1797: public final void setComponentZOrder(Component comp, int index) 1798: { 1799: if (comp == null) 1800: throw new NullPointerException("comp must not be null"); 1801: if (comp instanceof Container && ((Container) comp).isAncestorOf(this)) 1802: throw new IllegalArgumentException("comp must not be an ancestor of " 1803: + "this"); 1804: if (comp instanceof Window) 1805: throw new IllegalArgumentException("comp must not be a Window"); 1806: 1807: if (comp == this) 1808: throw new IllegalArgumentException("cannot add component to itself"); 1809: 1810: synchronized (getTreeLock()) 1811: { 1812: // FIXME: Implement reparenting. 1813: if ( comp.getParent() != this) 1814: throw new AssertionError("Reparenting is not implemented yet"); 1815: else 1816: { 1817: // Find current component index. 1818: int currentIndex = getComponentZOrder(comp); 1819: if (currentIndex < index) 1820: { 1821: System.arraycopy(component, currentIndex + 1, component, 1822: currentIndex, index - currentIndex); 1823: } 1824: else 1825: { 1826: System.arraycopy(component, index, component, index + 1, 1827: currentIndex - index); 1828: } 1829: component[index] = comp; 1830: } 1831: } 1832: } 1833: 1834: /** 1835: * Returns the Z ordering index of <code>comp</code>. If <code>comp</code> 1836: * is not a child component of this Container, this returns <code>-1</code>. 1837: * 1838: * @param comp the component for which to query the Z ordering 1839: * 1840: * @return the Z ordering index of <code>comp</code> or <code>-1</code> if 1841: * <code>comp</code> is not a child of this Container 1842: * 1843: * @see #setComponentZOrder(Component, int) 1844: * 1845: * @since 1.5 1846: */ 1847: public final int getComponentZOrder(Component comp) 1848: { 1849: synchronized (getTreeLock()) 1850: { 1851: int index = -1; 1852: if (component != null) 1853: { 1854: for (int i = 0; i < ncomponents; i++) 1855: { 1856: if (component[i] == comp) 1857: { 1858: index = i; 1859: break; 1860: } 1861: } 1862: } 1863: return index; 1864: } 1865: } 1866: 1867: // Hidden helper methods. 1868: 1869: /** 1870: * Perform a graphics operation on the children of this container. 1871: * For each applicable child, the visitChild() method will be called 1872: * to perform the graphics operation. 1873: * 1874: * @param gfx The graphics object that will be used to derive new 1875: * graphics objects for the children. 1876: * 1877: * @param visitor Object encapsulating the graphics operation that 1878: * should be performed. 1879: * 1880: * @param lightweightOnly If true, only lightweight components will 1881: * be visited. 1882: */ 1883: private void visitChildren(Graphics gfx, GfxVisitor visitor, 1884: boolean lightweightOnly) 1885: { 1886: synchronized (getTreeLock()) 1887: { 1888: for (int i = ncomponents - 1; i >= 0; --i) 1889: { 1890: Component comp = component[i]; 1891: boolean applicable = comp.isVisible() 1892: && (comp.isLightweight() || ! lightweightOnly); 1893: 1894: if (applicable) 1895: visitChild(gfx, visitor, comp); 1896: } 1897: } 1898: } 1899: 1900: /** 1901: * Perform a graphics operation on a child. A translated and clipped 1902: * graphics object will be created, and the visit() method of the 1903: * visitor will be called to perform the operation. 1904: * 1905: * @param gfx The graphics object that will be used to derive new 1906: * graphics objects for the child. 1907: * 1908: * @param visitor Object encapsulating the graphics operation that 1909: * should be performed. 1910: * 1911: * @param comp The child component that should be visited. 1912: */ 1913: private void visitChild(Graphics gfx, GfxVisitor visitor, 1914: Component comp) 1915: { 1916: Rectangle bounds = comp.getBounds(); 1917: 1918: if(!gfx.hitClip(bounds.x,bounds.y, bounds.width, bounds.height)) 1919: return; 1920: Graphics g2 = gfx.create(bounds.x, bounds.y, bounds.width, 1921: bounds.height); 1922: try 1923: { 1924: g2.setFont(comp.getFont()); 1925: visitor.visit(comp, g2); 1926: } 1927: finally 1928: { 1929: g2.dispose(); 1930: } 1931: } 1932: 1933: /** 1934: * Overridden to dispatch events to lightweight descendents. 1935: * 1936: * @param e the event to dispatch. 1937: */ 1938: void dispatchEventImpl(AWTEvent e) 1939: { 1940: LightweightDispatcher dispatcher = LightweightDispatcher.getInstance(); 1941: if (! isLightweight() && dispatcher.dispatchEvent(e)) 1942: { 1943: // Some lightweight descendent got this event dispatched. Consume 1944: // it and let the peer handle it. 1945: e.consume(); 1946: ComponentPeer p = peer; 1947: if (p != null) 1948: p.handleEvent(e); 1949: } 1950: else 1951: { 1952: super.dispatchEventImpl(e); 1953: } 1954: } 1955: 1956: /** 1957: * This is called by the lightweight dispatcher to avoid recursivly 1958: * calling into the lightweight dispatcher. 1959: * 1960: * @param e the event to dispatch 1961: * 1962: * @see LightweightDispatcher#redispatch(MouseEvent, Component, int) 1963: */ 1964: void dispatchNoLightweight(AWTEvent e) 1965: { 1966: super.dispatchEventImpl(e); 1967: } 1968: 1969: /** 1970: * Tests if this container has an interest in the given event id. 1971: * 1972: * @param eventId The event id to check. 1973: * 1974: * @return <code>true</code> if a listener for the event id exists or 1975: * if the eventMask is set for the event id. 1976: * 1977: * @see java.awt.Component#eventTypeEnabled(int) 1978: */ 1979: boolean eventTypeEnabled(int eventId) 1980: { 1981: if(eventId <= ContainerEvent.CONTAINER_LAST 1982: && eventId >= ContainerEvent.CONTAINER_FIRST) 1983: return containerListener != null 1984: || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0; 1985: else 1986: return super.eventTypeEnabled(eventId); 1987: } 1988: 1989: // This is used to implement Component.transferFocus. 1990: Component findNextFocusComponent(Component child) 1991: { 1992: synchronized (getTreeLock ()) 1993: { 1994: int start, end; 1995: if (child != null) 1996: { 1997: for (start = 0; start < ncomponents; ++start) 1998: { 1999: if (component[start] == child) 2000: break; 2001: } 2002: end = start; 2003: // This special case lets us be sure to terminate. 2004: if (end == 0) 2005: end = ncomponents; 2006: ++start; 2007: } 2008: else 2009: { 2010: start = 0; 2011: end = ncomponents; 2012: } 2013: 2014: for (int j = start; j != end; ++j) 2015: { 2016: if (j >= ncomponents) 2017: { 2018: // The JCL says that we should wrap here. However, that 2019: // seems wrong. To me it seems that focus order should be 2020: // global within in given window. So instead if we reach 2021: // the end we try to look in our parent, if we have one. 2022: if (parent != null) 2023: return parent.findNextFocusComponent(this); 2024: j -= ncomponents; 2025: } 2026: if (component[j] instanceof Container) 2027: { 2028: Component c = component[j]; 2029: c = c.findNextFocusComponent(null); 2030: if (c != null) 2031: return c; 2032: } 2033: else if (component[j].isFocusTraversable()) 2034: return component[j]; 2035: } 2036: 2037: return null; 2038: } 2039: } 2040: 2041: /** 2042: * Fires hierarchy events to the children of this container and this 2043: * container itself. This overrides {@link Component#fireHierarchyEvent} 2044: * in order to forward this event to all children. 2045: */ 2046: void fireHierarchyEvent(int id, Component changed, Container parent, 2047: long flags) 2048: { 2049: // Only propagate event if there is actually a listener waiting for it. 2050: if ((id == HierarchyEvent.HIERARCHY_CHANGED && numHierarchyListeners > 0) 2051: || ((id == HierarchyEvent.ANCESTOR_MOVED 2052: || id == HierarchyEvent.ANCESTOR_RESIZED) 2053: && numHierarchyBoundsListeners > 0)) 2054: { 2055: for (int i = 0; i < ncomponents; i++) 2056: component[i].fireHierarchyEvent(id, changed, parent, flags); 2057: super.fireHierarchyEvent(id, changed, parent, flags); 2058: } 2059: } 2060: 2061: /** 2062: * Adjusts the number of hierarchy listeners of this container and all of 2063: * its parents. This is called by the add/remove listener methods and 2064: * structure changing methods in Container. 2065: * 2066: * @param type the type, either {@link AWTEvent#HIERARCHY_BOUNDS_EVENT_MASK} 2067: * or {@link AWTEvent#HIERARCHY_EVENT_MASK} 2068: * @param delta the number of listeners added or removed 2069: */ 2070: void updateHierarchyListenerCount(long type, int delta) 2071: { 2072: if (type == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) 2073: numHierarchyBoundsListeners += delta; 2074: else if (type == AWTEvent.HIERARCHY_EVENT_MASK) 2075: numHierarchyListeners += delta; 2076: else 2077: assert false : "Should not reach here"; 2078: 2079: if (parent != null) 2080: parent.updateHierarchyListenerCount(type, delta); 2081: } 2082: 2083: /** 2084: * Notifies interested listeners about resizing or moving the container. 2085: * This performs the super behaviour (sending component events) and 2086: * additionally notifies any hierarchy bounds listeners on child components. 2087: * 2088: * @param resized true if the component has been resized, false otherwise 2089: * @param moved true if the component has been moved, false otherwise 2090: */ 2091: void notifyReshape(boolean resized, boolean moved) 2092: { 2093: // Notify component listeners. 2094: super.notifyReshape(resized, moved); 2095: 2096: if (ncomponents > 0) 2097: { 2098: // Notify hierarchy bounds listeners. 2099: if (resized) 2100: { 2101: for (int i = 0; i < getComponentCount(); i++) 2102: { 2103: Component child = getComponent(i); 2104: child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_RESIZED, 2105: this, parent, 0); 2106: } 2107: } 2108: if (moved) 2109: { 2110: for (int i = 0; i < getComponentCount(); i++) 2111: { 2112: Component child = getComponent(i); 2113: child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED, 2114: this, parent, 0); 2115: } 2116: } 2117: } 2118: } 2119: 2120: private void addNotifyContainerChildren() 2121: { 2122: synchronized (getTreeLock ()) 2123: { 2124: for (int i = ncomponents; --i >= 0; ) 2125: { 2126: component[i].addNotify(); 2127: } 2128: } 2129: } 2130: 2131: /** 2132: * Deserialize this Container: 2133: * <ol> 2134: * <li>Read from the stream the default serializable fields.</li> 2135: * <li>Read a list of serializable ContainerListeners as optional 2136: * data. If the list is null, no listeners will be registered.</li> 2137: * <li>Read this Container's FocusTraversalPolicy as optional data. 2138: * If this is null, then this Container will use a 2139: * DefaultFocusTraversalPolicy.</li> 2140: * </ol> 2141: * 2142: * @param s the stream to read from 2143: * @throws ClassNotFoundException if deserialization fails 2144: * @throws IOException if the stream fails 2145: */ 2146: private void readObject (ObjectInputStream s) 2147: throws ClassNotFoundException, IOException 2148: { 2149: s.defaultReadObject (); 2150: String key = (String) s.readObject (); 2151: while (key != null) 2152: { 2153: Object object = s.readObject (); 2154: if ("containerL".equals (key)) 2155: addContainerListener((ContainerListener) object); 2156: // FIXME: under what key is the focus traversal policy stored? 2157: else if ("focusTraversalPolicy".equals (key)) 2158: setFocusTraversalPolicy ((FocusTraversalPolicy) object); 2159: 2160: key = (String) s.readObject(); 2161: } 2162: } 2163: 2164: /** 2165: * Serialize this Container: 2166: * <ol> 2167: * <li>Write to the stream the default serializable fields.</li> 2168: * <li>Write the list of serializable ContainerListeners as optional 2169: * data.</li> 2170: * <li>Write this Container's FocusTraversalPolicy as optional data.</li> 2171: * </ol> 2172: * 2173: * @param s the stream to write to 2174: * @throws IOException if the stream fails 2175: */ 2176: private void writeObject (ObjectOutputStream s) throws IOException 2177: { 2178: s.defaultWriteObject (); 2179: AWTEventMulticaster.save (s, "containerL", containerListener); 2180: if (focusTraversalPolicy instanceof Serializable) 2181: s.writeObject (focusTraversalPolicy); 2182: else 2183: s.writeObject (null); 2184: } 2185: 2186: // Nested classes. 2187: 2188: /* The following classes are used in concert with the 2189: visitChildren() method to implement all the graphics operations 2190: that requires traversal of the containment hierarchy. */ 2191: 2192: abstract static class GfxVisitor 2193: { 2194: public abstract void visit(Component c, Graphics gfx); 2195: } 2196: 2197: static class GfxPaintVisitor extends GfxVisitor 2198: { 2199: public static final GfxVisitor INSTANCE = new GfxPaintVisitor(); 2200: 2201: public void visit(Component c, Graphics gfx) 2202: { 2203: c.paint(gfx); 2204: } 2205: } 2206: 2207: static class GfxPrintVisitor extends GfxVisitor 2208: { 2209: public static final GfxVisitor INSTANCE = new GfxPrintVisitor(); 2210: 2211: public void visit(Component c, Graphics gfx) 2212: { 2213: c.print(gfx); 2214: } 2215: } 2216: 2217: static class GfxPaintAllVisitor extends GfxVisitor 2218: { 2219: public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor(); 2220: 2221: public void visit(Component c, Graphics gfx) 2222: { 2223: c.paintAll(gfx); 2224: } 2225: } 2226: 2227: static class GfxPrintAllVisitor extends GfxVisitor 2228: { 2229: public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor(); 2230: 2231: public void visit(Component c, Graphics gfx) 2232: { 2233: c.printAll(gfx); 2234: } 2235: } 2236: 2237: /** 2238: * This class provides accessibility support for subclasses of container. 2239: * 2240: * @author Eric Blake (ebb9@email.byu.edu) 2241: * 2242: * @since 1.3 2243: */ 2244: protected class AccessibleAWTContainer extends AccessibleAWTComponent 2245: { 2246: /** 2247: * Compatible with JDK 1.4+. 2248: */ 2249: private static final long serialVersionUID = 5081320404842566097L; 2250: 2251: /** 2252: * The handler to fire PropertyChange when children are added or removed. 2253: * 2254: * @serial the handler for property changes 2255: */ 2256: protected ContainerListener accessibleContainerHandler 2257: = new AccessibleContainerHandler(); 2258: 2259: /** 2260: * The default constructor. 2261: */ 2262: protected AccessibleAWTContainer() 2263: { 2264: Container.this.addContainerListener(accessibleContainerHandler); 2265: } 2266: 2267: /** 2268: * Return the number of accessible children of the containing accessible 2269: * object (at most the total number of its children). 2270: * 2271: * @return the number of accessible children 2272: */ 2273: public int getAccessibleChildrenCount() 2274: { 2275: synchronized (getTreeLock ()) 2276: { 2277: int count = 0; 2278: int i = component == null ? 0 : component.length; 2279: while (--i >= 0) 2280: if (component[i] instanceof Accessible) 2281: count++; 2282: return count; 2283: } 2284: } 2285: 2286: /** 2287: * Return the nth accessible child of the containing accessible object. 2288: * 2289: * @param i the child to grab, zero-based 2290: * @return the accessible child, or null 2291: */ 2292: public Accessible getAccessibleChild(int i) 2293: { 2294: synchronized (getTreeLock ()) 2295: { 2296: if (component == null) 2297: return null; 2298: int index = -1; 2299: while (i >= 0 && ++index < component.length) 2300: if (component[index] instanceof Accessible) 2301: i--; 2302: if (i < 0) 2303: return (Accessible) component[index]; 2304: return null; 2305: } 2306: } 2307: 2308: /** 2309: * Return the accessible child located at point (in the parent's 2310: * coordinates), if one exists. 2311: * 2312: * @param p the point to look at 2313: * 2314: * @return an accessible object at that point, or null 2315: * 2316: * @throws NullPointerException if p is null 2317: */ 2318: public Accessible getAccessibleAt(Point p) 2319: { 2320: Component c = getComponentAt(p.x, p.y); 2321: return c != Container.this && c instanceof Accessible ? (Accessible) c 2322: : null; 2323: } 2324: 2325: /** 2326: * This class fires a <code>PropertyChange</code> listener, if registered, 2327: * when children are added or removed from the enclosing accessible object. 2328: * 2329: * @author Eric Blake (ebb9@email.byu.edu) 2330: * 2331: * @since 1.3 2332: */ 2333: protected class AccessibleContainerHandler implements ContainerListener 2334: { 2335: /** 2336: * Default constructor. 2337: */ 2338: protected AccessibleContainerHandler() 2339: { 2340: // Nothing to do here. 2341: } 2342: 2343: /** 2344: * Fired when a component is added; forwards to the PropertyChange 2345: * listener. 2346: * 2347: * @param e the container event for adding 2348: */ 2349: public void componentAdded(ContainerEvent e) 2350: { 2351: AccessibleAWTContainer.this.firePropertyChange 2352: (ACCESSIBLE_CHILD_PROPERTY, null, e.getChild()); 2353: } 2354: 2355: /** 2356: * Fired when a component is removed; forwards to the PropertyChange 2357: * listener. 2358: * 2359: * @param e the container event for removing 2360: */ 2361: public void componentRemoved(ContainerEvent e) 2362: { 2363: AccessibleAWTContainer.this.firePropertyChange 2364: (ACCESSIBLE_CHILD_PROPERTY, e.getChild(), null); 2365: } 2366: } // class AccessibleContainerHandler 2367: } // class AccessibleAWTContainer 2368: } // class Container
GNU Classpath (0.97.2) |