Merge -r 127928:132243 from trunk
[official-gcc.git] / libjava / classpath / java / awt / Container.java
blobe7622f2e839675d02ff931e16dc9494ee7518c60
1 /* Container.java -- parent container class in AWT
2 Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006
3 Free Software Foundation
5 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
40 package java.awt;
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;
63 import javax.accessibility.Accessible;
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.
70 * @author original author unknown
71 * @author Eric Blake (ebb9@email.byu.edu)
72 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
74 * @since 1.0
76 * @status still missing 1.4 support, some generics from 1.5
78 public class Container extends Component
80 /**
81 * Compatible with JDK 1.0+.
83 private static final long serialVersionUID = 4613797578919906343L;
85 /* Serialized fields from the serialization spec. */
86 int ncomponents;
87 Component[] component;
88 LayoutManager layoutMgr;
90 /**
91 * @since 1.4
93 boolean focusCycleRoot;
95 /**
96 * Indicates if this container provides a focus traversal policy.
98 * @since 1.5
100 private boolean focusTraversalPolicyProvider;
102 int containerSerializedDataVersion;
104 /* Anything else is non-serializable, and should be declared "transient". */
105 transient ContainerListener containerListener;
107 /** The focus traversal policy that determines how focus is
108 transferred between this Container and its children. */
109 private FocusTraversalPolicy focusTraversalPolicy;
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.
116 * @see #getFocusTraversalKeys(int)
117 * @see #setFocusTraversalKeys(int, Set)
118 * @since 1.4
120 transient Set[] focusTraversalKeys;
123 * Default constructor for subclasses.
125 public Container()
127 // Nothing to do here.
131 * Returns the number of components in this container.
133 * @return The number of components in this container.
135 public int getComponentCount()
137 return countComponents ();
141 * Returns the number of components in this container.
143 * @return The number of components in this container.
145 * @deprecated use {@link #getComponentCount()} instead
147 public int countComponents()
149 return ncomponents;
153 * Returns the component at the specified index.
155 * @param n The index of the component to retrieve.
157 * @return The requested component.
159 * @throws ArrayIndexOutOfBoundsException If the specified index is invalid
161 public Component getComponent(int n)
163 synchronized (getTreeLock ())
165 if (n < 0 || n >= ncomponents)
166 throw new ArrayIndexOutOfBoundsException("no such component");
168 return component[n];
173 * Returns an array of the components in this container.
175 * @return The components in this container.
177 public Component[] getComponents()
179 synchronized (getTreeLock ())
181 Component[] result = new Component[ncomponents];
183 if (ncomponents > 0)
184 System.arraycopy(component, 0, result, 0, ncomponents);
186 return result;
191 * Returns the insets for this container, which is the space used for
192 * borders, the margin, etc.
194 * @return The insets for this container.
196 public Insets getInsets()
198 return insets ();
202 * Returns the insets for this container, which is the space used for
203 * borders, the margin, etc.
205 * @return The insets for this container.
206 * @deprecated use {@link #getInsets()} instead
208 public Insets insets()
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;
219 * Adds the specified component to this container at the end of the
220 * component list.
222 * @param comp The component to add to the container.
224 * @return The same component that was added.
226 public Component add(Component comp)
228 addImpl(comp, null, -1);
229 return comp;
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>.
237 * @param name The name of the component to be added.
238 * @param comp The component to be added.
240 * @return The same component that was added.
242 * @see #add(Component,Object)
244 public Component add(String name, Component comp)
246 addImpl(comp, name, -1);
247 return comp;
251 * Adds the specified component to this container at the specified index
252 * in the component list.
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.
258 * @return The same component that was added.
260 * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
262 public Component add(Component comp, int index)
264 addImpl(comp, null, index);
265 return comp;
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.
273 * @param comp The component to be added to this container.
274 * @param constraints The layout constraints for this component.
276 public void add(Component comp, Object constraints)
278 addImpl(comp, constraints, -1);
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.
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.
291 * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
293 public void add(Component comp, Object constraints, int index)
295 addImpl(comp, constraints, index);
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.
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.
311 * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
313 protected void addImpl(Component comp, Object constraints, int index)
315 synchronized (getTreeLock ())
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();
324 // Reparent component, and make sure component is instantiated if
325 // we are.
326 if (comp.parent != null)
327 comp.parent.remove(comp);
329 if (component == null)
330 component = new Component[4]; // FIXME, better initial size?
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)
336 int nl = component.length * 2;
337 Component[] c = new Component[nl];
338 System.arraycopy(component, 0, c, 0, ncomponents);
339 component = c;
342 if (index == -1)
343 component[ncomponents++] = comp;
344 else
346 System.arraycopy(component, index, component, index + 1,
347 ncomponents - index);
348 component[index] = comp;
349 ++ncomponents;
352 // Give the new component a parent.
353 comp.parent = this;
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);
365 // Invalidate the layout of this container.
366 if (valid)
367 invalidate();
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)
373 // Notify the component that it has a new parent.
374 comp.addNotify();
377 // Notify the layout manager.
378 if (layoutMgr != null)
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)
384 LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
385 lm2.addLayoutComponent(comp, constraints);
387 else if (constraints instanceof String)
388 layoutMgr.addLayoutComponent((String) constraints, comp);
389 else
390 layoutMgr.addLayoutComponent("", comp);
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)
400 ContainerEvent ce = new ContainerEvent(this,
401 ContainerEvent.COMPONENT_ADDED,
402 comp);
403 dispatchEvent(ce);
406 // Notify hierarchy listeners.
407 comp.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, comp,
408 this, HierarchyEvent.PARENT_CHANGED);
413 * Removes the component at the specified index from this container.
415 * @param index The index of the component to remove.
417 public void remove(int index)
419 synchronized (getTreeLock ())
421 if (index < 0 || index >= ncomponents)
422 throw new ArrayIndexOutOfBoundsException();
424 Component r = component[index];
425 if (peer != null)
426 r.removeNotify();
428 if (layoutMgr != null)
429 layoutMgr.removeLayoutComponent(r);
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);
441 r.parent = null;
443 System.arraycopy(component, index + 1, component, index,
444 ncomponents - index - 1);
445 component[--ncomponents] = null;
447 if (valid)
448 invalidate();
450 if (containerListener != null
451 || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
453 // Post event to notify of removing the component.
454 ContainerEvent ce = new ContainerEvent(this,
455 ContainerEvent.COMPONENT_REMOVED,
457 dispatchEvent(ce);
460 // Notify hierarchy listeners.
461 r.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r,
462 this, HierarchyEvent.PARENT_CHANGED);
467 * Removes the specified component from this container.
469 * @param comp The component to remove from this container.
471 public void remove(Component comp)
473 synchronized (getTreeLock ())
475 for (int i = 0; i < ncomponents; ++i)
477 if (component[i] == comp)
479 remove(i);
480 break;
487 * Removes all components from this container.
489 public void removeAll()
491 synchronized (getTreeLock ())
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)
503 ncomponents--;
504 Component r = component[ncomponents];
505 component[ncomponents] = null;
507 if (peer != null)
508 r.removeNotify();
510 if (layoutMgr != null)
511 layoutMgr.removeLayoutComponent(r);
513 r.parent = null;
515 // Send ContainerEvent if necessary.
516 if (containerListener != null
517 || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
519 // Post event to notify of removing the component.
520 ContainerEvent ce
521 = new ContainerEvent(this,
522 ContainerEvent.COMPONENT_REMOVED,
524 dispatchEvent(ce);
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);
538 // Send HierarchyEvent if necessary.
539 fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, this,
540 HierarchyEvent.PARENT_CHANGED);
544 if (valid)
545 invalidate();
550 * Returns the current layout manager for this container.
552 * @return The layout manager for this container.
554 public LayoutManager getLayout()
556 return layoutMgr;
560 * Sets the layout manager for this container to the specified layout
561 * manager.
563 * @param mgr The new layout manager for this container.
565 public void setLayout(LayoutManager mgr)
567 layoutMgr = mgr;
568 if (valid)
569 invalidate();
573 * Layout the components in this container.
575 public void doLayout()
577 layout ();
581 * Layout the components in this container.
583 * @deprecated use {@link #doLayout()} instead
585 public void layout()
587 if (layoutMgr != null)
588 layoutMgr.layoutContainer (this);
592 * Invalidates this container to indicate that it (and all parent
593 * containers) need to be laid out.
595 public void invalidate()
597 super.invalidate();
598 if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
600 LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
601 lm2.invalidateLayout(this);
606 * Re-lays out the components in this container.
608 public void validate()
610 ComponentPeer p = peer;
611 if (! valid && p != null)
613 ContainerPeer cPeer = null;
614 if (p instanceof ContainerPeer)
615 cPeer = (ContainerPeer) peer;
616 synchronized (getTreeLock ())
618 if (cPeer != null)
619 cPeer.beginValidate();
620 validateTree();
621 valid = true;
622 if (cPeer != null)
623 cPeer.endValidate();
629 * Recursively invalidates the container tree.
631 private final void invalidateTree()
633 synchronized (getTreeLock())
635 for (int i = 0; i < ncomponents; i++)
637 Component comp = component[i];
638 if (comp instanceof Container)
639 ((Container) comp).invalidateTree();
640 else if (comp.valid)
641 comp.invalidate();
643 if (valid)
644 invalidate();
649 * Recursively validates the container tree, recomputing any invalid
650 * layouts.
652 protected void validateTree()
654 if (!valid)
656 ContainerPeer cPeer = null;
657 if (peer instanceof ContainerPeer)
659 cPeer = (ContainerPeer) peer;
660 cPeer.beginLayout();
663 doLayout ();
664 for (int i = 0; i < ncomponents; ++i)
666 Component comp = component[i];
668 if (comp instanceof Container && ! (comp instanceof Window)
669 && ! comp.valid)
671 ((Container) comp).validateTree();
673 else
675 comp.validate();
679 if (cPeer != null)
681 cPeer = (ContainerPeer) peer;
682 cPeer.endLayout();
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;
693 public void setFont(Font f)
695 Font oldFont = getFont();
696 super.setFont(f);
697 Font newFont = getFont();
698 if (newFont != oldFont && (oldFont == null || ! oldFont.equals(newFont)))
700 invalidateTree();
705 * Returns the preferred size of this container.
707 * @return The preferred size of this container.
709 public Dimension getPreferredSize()
711 return preferredSize ();
715 * Returns the preferred size of this container.
717 * @return The preferred size of this container.
719 * @deprecated use {@link #getPreferredSize()} instead
721 public Dimension preferredSize()
723 Dimension size = prefSize;
724 // Try to return cached value if possible.
725 if (size == null || !(prefSizeSet || valid))
727 // Need to lock here.
728 synchronized (getTreeLock())
730 LayoutManager l = layoutMgr;
731 if (l != null)
732 prefSize = l.preferredLayoutSize(this);
733 else
734 prefSize = super.preferredSizeImpl();
735 size = prefSize;
738 if (size != null)
739 return new Dimension(size);
740 else
741 return size;
745 * Returns the minimum size of this container.
747 * @return The minimum size of this container.
749 public Dimension getMinimumSize()
751 return minimumSize ();
755 * Returns the minimum size of this container.
757 * @return The minimum size of this container.
759 * @deprecated use {@link #getMinimumSize()} instead
761 public Dimension minimumSize()
763 Dimension size = minSize;
764 // Try to return cached value if possible.
765 if (size == null || !(minSizeSet || valid))
767 // Need to lock here.
768 synchronized (getTreeLock())
770 LayoutManager l = layoutMgr;
771 if (l != null)
772 minSize = l.minimumLayoutSize(this);
773 else
774 minSize = super.minimumSizeImpl();
775 size = minSize;
778 if (size != null)
779 return new Dimension(size);
780 else
781 return size;
785 * Returns the maximum size of this container.
787 * @return The maximum size of this container.
789 public Dimension getMaximumSize()
791 Dimension size = maxSize;
792 // Try to return cached value if possible.
793 if (size == null || !(maxSizeSet || valid))
795 // Need to lock here.
796 synchronized (getTreeLock())
798 LayoutManager l = layoutMgr;
799 if (l instanceof LayoutManager2)
800 maxSize = ((LayoutManager2) l).maximumLayoutSize(this);
801 else {
802 maxSize = super.maximumSizeImpl();
804 size = maxSize;
807 if (size != null)
808 return new Dimension(size);
809 else
810 return size;
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.
818 * @return The preferred alignment along the X axis.
820 public float getAlignmentX()
822 LayoutManager layout = getLayout();
823 float alignmentX = 0.0F;
824 if (layout != null && layout instanceof LayoutManager2)
826 synchronized (getTreeLock())
828 LayoutManager2 lm2 = (LayoutManager2) layout;
829 alignmentX = lm2.getLayoutAlignmentX(this);
832 else
833 alignmentX = super.getAlignmentX();
834 return alignmentX;
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.
842 * @return The preferred alignment along the Y axis.
844 public float getAlignmentY()
846 LayoutManager layout = getLayout();
847 float alignmentY = 0.0F;
848 if (layout != null && layout instanceof LayoutManager2)
850 synchronized (getTreeLock())
852 LayoutManager2 lm2 = (LayoutManager2) layout;
853 alignmentY = lm2.getLayoutAlignmentY(this);
856 else
857 alignmentY = super.getAlignmentY();
858 return alignmentY;
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.
868 * @param g - The graphics context for this paint job.
870 public void paint(Graphics g)
872 if (isShowing())
874 visitChildren(g, GfxPaintVisitor.INSTANCE, true);
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.
885 * @param g The graphics context for this update.
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.
895 public void update(Graphics g)
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())
907 ComponentPeer p = peer;
908 if (! (p instanceof LightweightPeer))
910 g.clearRect(0, 0, getWidth(), getHeight());
912 paint(g);
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.
923 * @param g The graphics context for this print job.
925 public void print(Graphics g)
927 super.print(g);
928 visitChildren(g, GfxPrintVisitor.INSTANCE, true);
932 * Paints all of the components in this container.
934 * @param g The graphics context for this paint job.
936 public void paintComponents(Graphics g)
938 if (isShowing())
939 visitChildren(g, GfxPaintAllVisitor.INSTANCE, false);
943 * Prints all of the components in this container.
945 * @param g The graphics context for this print job.
947 public void printComponents(Graphics g)
949 super.paint(g);
950 visitChildren(g, GfxPrintAllVisitor.INSTANCE, true);
954 * Adds the specified container listener to this object's list of
955 * container listeners.
957 * @param listener The listener to add.
959 public synchronized void addContainerListener(ContainerListener listener)
961 if (listener != null)
963 containerListener = AWTEventMulticaster.add(containerListener,
964 listener);
965 newEventsOnly = true;
970 * Removes the specified container listener from this object's list of
971 * container listeners.
973 * @param listener The listener to remove.
975 public synchronized void removeContainerListener(ContainerListener listener)
977 containerListener = AWTEventMulticaster.remove(containerListener, listener);
981 * @since 1.4
983 public synchronized ContainerListener[] getContainerListeners()
985 return (ContainerListener[])
986 AWTEventMulticaster.getListeners(containerListener,
987 ContainerListener.class);
991 * Returns all registered {@link EventListener}s of the given
992 * <code>listenerType</code>.
994 * @param listenerType the class of listeners to filter (<code>null</code>
995 * not permitted).
997 * @return An array of registered listeners.
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>.
1004 * @see #getContainerListeners()
1006 * @since 1.3
1008 public <T extends EventListener> T[] getListeners(Class<T> listenerType)
1010 if (listenerType == ContainerListener.class)
1011 return (T[]) getContainerListeners();
1012 return super.getListeners(listenerType);
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.
1021 * @param e The event to be processed.
1023 protected void processEvent(AWTEvent e)
1025 if (e instanceof ContainerEvent)
1026 processContainerEvent((ContainerEvent) e);
1027 else
1028 super.processEvent(e);
1032 * Called when a container event occurs if container events are enabled.
1033 * This method calls any registered listeners.
1035 * @param e The event that occurred.
1037 protected void processContainerEvent(ContainerEvent e)
1039 if (containerListener == null)
1040 return;
1041 switch (e.id)
1043 case ContainerEvent.COMPONENT_ADDED:
1044 containerListener.componentAdded(e);
1045 break;
1047 case ContainerEvent.COMPONENT_REMOVED:
1048 containerListener.componentRemoved(e);
1049 break;
1054 * AWT 1.0 event processor.
1056 * @param e The event that occurred.
1058 * @deprecated use {@link #dispatchEvent(AWTEvent)} instead
1060 public void deliverEvent(Event e)
1062 if (!handleEvent (e))
1064 synchronized (getTreeLock ())
1066 Component parent = getParent ();
1068 if (parent != null)
1069 parent.deliverEvent (e);
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.
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.
1086 * This function does not ignore invisible components. If there is an invisible
1087 * component at (x,y), it will be returned.
1089 * @param x The X coordinate of the point.
1090 * @param y The Y coordinate of the point.
1092 * @return The component containing the specified point, or
1093 * <code>null</code> if there is no such point.
1095 public Component getComponentAt(int x, int y)
1097 return locate (x, y);
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.
1107 * @param allowChildren true to allow descendents, false if pointer
1108 * must be directly over Container.
1110 * @return relative mouse pointer position
1112 * @throws HeadlessException if in a headless environment
1114 public Point getMousePosition(boolean allowChildren) throws HeadlessException
1116 return super.getMousePositionHelper(allowChildren);
1119 boolean mouseOverComponent(Component component, boolean allowChildren)
1121 if (allowChildren)
1122 return isAncestorOf(component);
1123 else
1124 return component == this;
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.
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.
1139 * This function does not ignore invisible components. If there is an invisible
1140 * component at (x,y), it will be returned.
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.
1145 * @return The component containing the specified point, or <code>null</code>
1146 * if there is no such point.
1148 * @deprecated use {@link #getComponentAt(int, int)} instead
1150 public Component locate(int x, int y)
1152 synchronized (getTreeLock ())
1154 if (!contains (x, y))
1155 return null;
1157 // First find the component closest to (x,y) that is a heavyweight.
1158 for (int i = 0; i < ncomponents; ++i)
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;
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)
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;
1178 return this;
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.
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.
1194 * This function does not ignore invisible components. If there is an invisible
1195 * component at (x,y), it will be returned.
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.
1201 public Component getComponentAt(Point p)
1203 return getComponentAt (p.x, p.y);
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.
1213 * findComponentAt differs from getComponentAt, because it recursively
1214 * searches a Container's children.
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.
1222 public Component findComponentAt(int x, int y)
1224 synchronized (getTreeLock ())
1226 if (! contains(x, y))
1227 return null;
1229 for (int i = 0; i < ncomponents; ++i)
1231 // Ignore invisible children...
1232 if (!component[i].isVisible())
1233 continue;
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)
1241 Container k = (Container) component[i];
1242 Component r = k.findComponentAt(x2, y2);
1243 if (r != null)
1244 return r;
1246 else if (component[i].contains(x2, y2))
1247 return component[i];
1250 return this;
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.
1261 * findComponentAt differs from getComponentAt, because it recursively
1262 * searches a Container's children.
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.
1269 public Component findComponentAt(Point p)
1271 return findComponentAt(p.x, p.y);
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.
1279 public void addNotify()
1281 synchronized (getTreeLock())
1283 super.addNotify();
1284 addNotifyContainerChildren();
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.
1293 public void removeNotify()
1295 synchronized (getTreeLock ())
1297 int ncomps = ncomponents;
1298 Component[] comps = component;
1299 for (int i = ncomps - 1; i >= 0; --i)
1301 Component comp = comps[i];
1302 if (comp != null)
1303 comp.removeNotify();
1305 super.removeNotify();
1310 * Tests whether or not the specified component is contained within
1311 * this components subtree.
1313 * @param comp The component to test.
1315 * @return <code>true</code> if this container is an ancestor of the
1316 * specified component, <code>false</code> otherwise.
1318 public boolean isAncestorOf(Component comp)
1320 synchronized (getTreeLock ())
1322 while (true)
1324 if (comp == null)
1325 return false;
1326 if (comp == this)
1327 return true;
1328 comp = comp.getParent();
1334 * Returns a string representing the state of this container for
1335 * debugging purposes.
1337 * @return A string representing the state of this container.
1339 protected String paramString()
1341 if (layoutMgr == null)
1342 return super.paramString();
1344 StringBuffer sb = new StringBuffer();
1345 sb.append(super.paramString());
1346 sb.append(",layout=");
1347 sb.append(layoutMgr.getClass().getName());
1348 return sb.toString();
1352 * Writes a listing of this container to the specified stream starting
1353 * at the specified indentation point.
1355 * @param out The <code>PrintStream</code> to write to.
1356 * @param indent The indentation point.
1358 public void list(PrintStream out, int indent)
1360 synchronized (getTreeLock ())
1362 super.list(out, indent);
1363 for (int i = 0; i < ncomponents; ++i)
1364 component[i].list(out, indent + 2);
1369 * Writes a listing of this container to the specified stream starting
1370 * at the specified indentation point.
1372 * @param out The <code>PrintWriter</code> to write to.
1373 * @param indent The indentation point.
1375 public void list(PrintWriter out, int indent)
1377 synchronized (getTreeLock ())
1379 super.list(out, indent);
1380 for (int i = 0; i < ncomponents; ++i)
1381 component[i].list(out, indent + 2);
1386 * Sets the focus traversal keys for a given traversal operation for this
1387 * Container.
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.
1399 * @since 1.4
1401 public void setFocusTraversalKeys(int id,
1402 Set<? extends AWTKeyStroke> keystrokes)
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 ();
1410 if (keystrokes == null)
1412 Container parent = getParent ();
1414 while (parent != null)
1416 if (parent.areFocusTraversalKeysSet (id))
1418 keystrokes = parent.getFocusTraversalKeys (id);
1419 break;
1421 parent = parent.getParent ();
1424 if (keystrokes == null)
1425 keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager ().
1426 getDefaultFocusTraversalKeys (id);
1429 Set sa;
1430 Set sb;
1431 Set sc;
1432 String name;
1433 switch (id)
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 ();
1475 int i = keystrokes.size ();
1476 Iterator iter = keystrokes.iterator ();
1478 while (--i >= 0)
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 ();
1487 if (focusTraversalKeys == null)
1488 focusTraversalKeys = new Set[4];
1490 keystrokes =
1491 Collections.unmodifiableSet(new HashSet<AWTKeyStroke>(keystrokes));
1492 firePropertyChange (name, focusTraversalKeys[id], keystrokes);
1494 focusTraversalKeys[id] = keystrokes;
1498 * Returns the Set of focus traversal keys for a given traversal operation for
1499 * this Container.
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.
1507 * @since 1.4
1509 public Set<AWTKeyStroke> getFocusTraversalKeys (int id)
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 ();
1517 Set s = null;
1519 if (focusTraversalKeys != null)
1520 s = focusTraversalKeys[id];
1522 if (s == null && parent != null)
1523 s = parent.getFocusTraversalKeys (id);
1525 return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager()
1526 .getDefaultFocusTraversalKeys(id)) : s;
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.
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.
1541 * @since 1.4
1543 public boolean areFocusTraversalKeysSet (int id)
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 ();
1551 return focusTraversalKeys != null && focusTraversalKeys[id] != null;
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.
1562 * @param c the candidate Container
1564 * @return true if c is the focus cycle root of the focus traversal
1565 * cycle to which this Container belongs, false otherwise
1567 * @since 1.4
1569 public boolean isFocusCycleRoot (Container c)
1571 if (this == c
1572 && isFocusCycleRoot ())
1573 return true;
1575 Container ancestor = getFocusCycleRootAncestor ();
1577 if (c == ancestor)
1578 return true;
1580 return false;
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.
1591 * @param policy the new focus traversal policy for this Container or null
1593 * @since 1.4
1595 public void setFocusTraversalPolicy (FocusTraversalPolicy policy)
1597 focusTraversalPolicy = policy;
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.
1607 * @return this Container's focus traversal policy or null
1609 * @since 1.4
1611 public FocusTraversalPolicy getFocusTraversalPolicy ()
1613 if (!isFocusCycleRoot ())
1614 return null;
1616 if (focusTraversalPolicy == null)
1618 Container ancestor = getFocusCycleRootAncestor ();
1620 if (ancestor != this && ancestor != null)
1621 return ancestor.getFocusTraversalPolicy ();
1622 else
1624 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
1626 return manager.getDefaultFocusTraversalPolicy ();
1629 else
1630 return focusTraversalPolicy;
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.
1639 * @return true if focus traversal policy is set, false otherwise
1641 public boolean isFocusTraversalPolicySet ()
1643 return focusTraversalPolicy == null;
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.
1658 * @param focusCycleRoot true if this is a focus cycle root, false otherwise
1660 * @since 1.4
1662 public void setFocusCycleRoot (boolean focusCycleRoot)
1664 this.focusCycleRoot = focusCycleRoot;
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.
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
1676 * @see #setFocusTraversalPolicyProvider(boolean)
1678 * @since 1.5
1680 public final boolean isFocusTraversalPolicyProvider()
1682 return focusTraversalPolicyProvider;
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.
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
1694 * @see #isFocusTraversalPolicyProvider()
1696 * @since 1.5
1698 public final void setFocusTraversalPolicyProvider(boolean b)
1700 focusTraversalPolicyProvider = b;
1704 * Check whether this Container is a focus cycle root.
1706 * @return true if this is a focus cycle root, false otherwise
1708 * @since 1.4
1710 public boolean isFocusCycleRoot ()
1712 return focusCycleRoot;
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.
1722 * @since 1.4
1724 public void transferFocusDownCycle ()
1726 if (isFocusCycleRoot())
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();
1739 * Sets the ComponentOrientation property of this container and all components
1740 * contained within it.
1742 * @exception NullPointerException If orientation is null
1744 * @since 1.4
1746 public void applyComponentOrientation (ComponentOrientation orientation)
1748 if (orientation == null)
1749 throw new NullPointerException();
1751 setComponentOrientation(orientation);
1752 for (int i = 0; i < ncomponents; i++)
1754 if (component[i] instanceof Container)
1755 ((Container) component[i]).applyComponentOrientation(orientation);
1756 else
1757 component[i].setComponentOrientation(orientation);
1761 public void addPropertyChangeListener (PropertyChangeListener listener)
1763 // TODO: Why is this overridden?
1764 super.addPropertyChangeListener(listener);
1767 public void addPropertyChangeListener (String propertyName,
1768 PropertyChangeListener listener)
1770 // TODO: Why is this overridden?
1771 super.addPropertyChangeListener(propertyName, listener);
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.
1780 * @param comp the component for which to change the Z ordering
1781 * @param index the index to set
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>
1793 * @see #getComponentZOrder(Component)
1795 * @since 1.5
1797 public final void setComponentZOrder(Component comp, int index)
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");
1807 if (comp == this)
1808 throw new IllegalArgumentException("cannot add component to itself");
1810 synchronized (getTreeLock())
1812 // FIXME: Implement reparenting.
1813 if ( comp.getParent() != this)
1814 throw new AssertionError("Reparenting is not implemented yet");
1815 else
1817 // Find current component index.
1818 int currentIndex = getComponentZOrder(comp);
1819 if (currentIndex < index)
1821 System.arraycopy(component, currentIndex + 1, component,
1822 currentIndex, index - currentIndex);
1824 else
1826 System.arraycopy(component, index, component, index + 1,
1827 currentIndex - index);
1829 component[index] = comp;
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>.
1838 * @param comp the component for which to query the Z ordering
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
1843 * @see #setComponentZOrder(Component, int)
1845 * @since 1.5
1847 public final int getComponentZOrder(Component comp)
1849 synchronized (getTreeLock())
1851 int index = -1;
1852 if (component != null)
1854 for (int i = 0; i < ncomponents; i++)
1856 if (component[i] == comp)
1858 index = i;
1859 break;
1863 return index;
1867 // Hidden helper methods.
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.
1874 * @param gfx The graphics object that will be used to derive new
1875 * graphics objects for the children.
1877 * @param visitor Object encapsulating the graphics operation that
1878 * should be performed.
1880 * @param lightweightOnly If true, only lightweight components will
1881 * be visited.
1883 private void visitChildren(Graphics gfx, GfxVisitor visitor,
1884 boolean lightweightOnly)
1886 synchronized (getTreeLock())
1888 for (int i = ncomponents - 1; i >= 0; --i)
1890 Component comp = component[i];
1891 boolean applicable = comp.isVisible()
1892 && (comp.isLightweight() || ! lightweightOnly);
1894 if (applicable)
1895 visitChild(gfx, visitor, comp);
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.
1905 * @param gfx The graphics object that will be used to derive new
1906 * graphics objects for the child.
1908 * @param visitor Object encapsulating the graphics operation that
1909 * should be performed.
1911 * @param comp The child component that should be visited.
1913 private void visitChild(Graphics gfx, GfxVisitor visitor,
1914 Component comp)
1916 Rectangle bounds = comp.getBounds();
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);
1924 g2.setFont(comp.getFont());
1925 visitor.visit(comp, g2);
1927 finally
1929 g2.dispose();
1934 * Overridden to dispatch events to lightweight descendents.
1936 * @param e the event to dispatch.
1938 void dispatchEventImpl(AWTEvent e)
1940 LightweightDispatcher dispatcher = LightweightDispatcher.getInstance();
1941 if (! isLightweight() && dispatcher.dispatchEvent(e))
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);
1950 else
1952 super.dispatchEventImpl(e);
1957 * This is called by the lightweight dispatcher to avoid recursivly
1958 * calling into the lightweight dispatcher.
1960 * @param e the event to dispatch
1962 * @see LightweightDispatcher#redispatch(MouseEvent, Component, int)
1964 void dispatchNoLightweight(AWTEvent e)
1966 super.dispatchEventImpl(e);
1970 * Tests if this container has an interest in the given event id.
1972 * @param eventId The event id to check.
1974 * @return <code>true</code> if a listener for the event id exists or
1975 * if the eventMask is set for the event id.
1977 * @see java.awt.Component#eventTypeEnabled(int)
1979 boolean eventTypeEnabled(int eventId)
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);
1989 // This is used to implement Component.transferFocus.
1990 Component findNextFocusComponent(Component child)
1992 synchronized (getTreeLock ())
1994 int start, end;
1995 if (child != null)
1997 for (start = 0; start < ncomponents; ++start)
1999 if (component[start] == child)
2000 break;
2002 end = start;
2003 // This special case lets us be sure to terminate.
2004 if (end == 0)
2005 end = ncomponents;
2006 ++start;
2008 else
2010 start = 0;
2011 end = ncomponents;
2014 for (int j = start; j != end; ++j)
2016 if (j >= ncomponents)
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;
2026 if (component[j] instanceof Container)
2028 Component c = component[j];
2029 c = c.findNextFocusComponent(null);
2030 if (c != null)
2031 return c;
2033 else if (component[j].isFocusTraversable())
2034 return component[j];
2037 return null;
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.
2046 void fireHierarchyEvent(int id, Component changed, Container parent,
2047 long flags)
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))
2055 for (int i = 0; i < ncomponents; i++)
2056 component[i].fireHierarchyEvent(id, changed, parent, flags);
2057 super.fireHierarchyEvent(id, changed, parent, flags);
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.
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
2070 void updateHierarchyListenerCount(long type, int delta)
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";
2079 if (parent != null)
2080 parent.updateHierarchyListenerCount(type, delta);
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.
2088 * @param resized true if the component has been resized, false otherwise
2089 * @param moved true if the component has been moved, false otherwise
2091 void notifyReshape(boolean resized, boolean moved)
2093 // Notify component listeners.
2094 super.notifyReshape(resized, moved);
2096 if (ncomponents > 0)
2098 // Notify hierarchy bounds listeners.
2099 if (resized)
2101 for (int i = 0; i < getComponentCount(); i++)
2103 Component child = getComponent(i);
2104 child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_RESIZED,
2105 this, parent, 0);
2108 if (moved)
2110 for (int i = 0; i < getComponentCount(); i++)
2112 Component child = getComponent(i);
2113 child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED,
2114 this, parent, 0);
2120 private void addNotifyContainerChildren()
2122 synchronized (getTreeLock ())
2124 for (int i = ncomponents; --i >= 0; )
2126 component[i].addNotify();
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>
2142 * @param s the stream to read from
2143 * @throws ClassNotFoundException if deserialization fails
2144 * @throws IOException if the stream fails
2146 private void readObject (ObjectInputStream s)
2147 throws ClassNotFoundException, IOException
2149 s.defaultReadObject ();
2150 String key = (String) s.readObject ();
2151 while (key != null)
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);
2160 key = (String) s.readObject();
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>
2173 * @param s the stream to write to
2174 * @throws IOException if the stream fails
2176 private void writeObject (ObjectOutputStream s) throws IOException
2178 s.defaultWriteObject ();
2179 AWTEventMulticaster.save (s, "containerL", containerListener);
2180 if (focusTraversalPolicy instanceof Serializable)
2181 s.writeObject (focusTraversalPolicy);
2182 else
2183 s.writeObject (null);
2186 // Nested classes.
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. */
2192 abstract static class GfxVisitor
2194 public abstract void visit(Component c, Graphics gfx);
2197 static class GfxPaintVisitor extends GfxVisitor
2199 public static final GfxVisitor INSTANCE = new GfxPaintVisitor();
2201 public void visit(Component c, Graphics gfx)
2203 c.paint(gfx);
2207 static class GfxPrintVisitor extends GfxVisitor
2209 public static final GfxVisitor INSTANCE = new GfxPrintVisitor();
2211 public void visit(Component c, Graphics gfx)
2213 c.print(gfx);
2217 static class GfxPaintAllVisitor extends GfxVisitor
2219 public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor();
2221 public void visit(Component c, Graphics gfx)
2223 c.paintAll(gfx);
2227 static class GfxPrintAllVisitor extends GfxVisitor
2229 public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor();
2231 public void visit(Component c, Graphics gfx)
2233 c.printAll(gfx);
2238 * This class provides accessibility support for subclasses of container.
2240 * @author Eric Blake (ebb9@email.byu.edu)
2242 * @since 1.3
2244 protected class AccessibleAWTContainer extends AccessibleAWTComponent
2247 * Compatible with JDK 1.4+.
2249 private static final long serialVersionUID = 5081320404842566097L;
2252 * The handler to fire PropertyChange when children are added or removed.
2254 * @serial the handler for property changes
2256 protected ContainerListener accessibleContainerHandler
2257 = new AccessibleContainerHandler();
2260 * The default constructor.
2262 protected AccessibleAWTContainer()
2264 Container.this.addContainerListener(accessibleContainerHandler);
2268 * Return the number of accessible children of the containing accessible
2269 * object (at most the total number of its children).
2271 * @return the number of accessible children
2273 public int getAccessibleChildrenCount()
2275 synchronized (getTreeLock ())
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;
2287 * Return the nth accessible child of the containing accessible object.
2289 * @param i the child to grab, zero-based
2290 * @return the accessible child, or null
2292 public Accessible getAccessibleChild(int i)
2294 synchronized (getTreeLock ())
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;
2309 * Return the accessible child located at point (in the parent's
2310 * coordinates), if one exists.
2312 * @param p the point to look at
2314 * @return an accessible object at that point, or null
2316 * @throws NullPointerException if p is null
2318 public Accessible getAccessibleAt(Point p)
2320 Component c = getComponentAt(p.x, p.y);
2321 return c != Container.this && c instanceof Accessible ? (Accessible) c
2322 : null;
2326 * This class fires a <code>PropertyChange</code> listener, if registered,
2327 * when children are added or removed from the enclosing accessible object.
2329 * @author Eric Blake (ebb9@email.byu.edu)
2331 * @since 1.3
2333 protected class AccessibleContainerHandler implements ContainerListener
2336 * Default constructor.
2338 protected AccessibleContainerHandler()
2340 // Nothing to do here.
2344 * Fired when a component is added; forwards to the PropertyChange
2345 * listener.
2347 * @param e the container event for adding
2349 public void componentAdded(ContainerEvent e)
2351 AccessibleAWTContainer.this.firePropertyChange
2352 (ACCESSIBLE_CHILD_PROPERTY, null, e.getChild());
2356 * Fired when a component is removed; forwards to the PropertyChange
2357 * listener.
2359 * @param e the container event for removing
2361 public void componentRemoved(ContainerEvent e)
2363 AccessibleAWTContainer.this.firePropertyChange
2364 (ACCESSIBLE_CHILD_PROPERTY, e.getChild(), null);
2366 } // class AccessibleContainerHandler
2367 } // class AccessibleAWTContainer
2368 } // class Container