Source for java.awt.Container

   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: