Merge from mainline.
[official-gcc.git] / libjava / classpath / java / awt / Container.java
blob2419a7bd24ac2cf5ad1ce6f549d96241cc6fc1b3
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.ComponentListener;
43 import java.awt.event.ContainerEvent;
44 import java.awt.event.ContainerListener;
45 import java.awt.event.KeyEvent;
46 import java.awt.peer.ComponentPeer;
47 import java.awt.peer.ContainerPeer;
48 import java.awt.peer.LightweightPeer;
49 import java.beans.PropertyChangeListener;
50 import java.io.IOException;
51 import java.io.ObjectInputStream;
52 import java.io.ObjectOutputStream;
53 import java.io.PrintStream;
54 import java.io.PrintWriter;
55 import java.io.Serializable;
56 import java.util.Collections;
57 import java.util.EventListener;
58 import java.util.HashSet;
59 import java.util.Iterator;
60 import java.util.Set;
62 import javax.accessibility.Accessible;
64 /**
65 * A generic window toolkit object that acts as a container for other objects.
66 * Components are tracked in a list, and new elements are at the end of the
67 * list or bottom of the stacking order.
69 * @author original author unknown
70 * @author Eric Blake (ebb9@email.byu.edu)
72 * @since 1.0
74 * @status still missing 1.4 support
76 public class Container extends Component
78 /**
79 * Compatible with JDK 1.0+.
81 private static final long serialVersionUID = 4613797578919906343L;
83 /* Serialized fields from the serialization spec. */
84 int ncomponents;
85 Component[] component;
86 LayoutManager layoutMgr;
88 Dimension maxSize;
90 /**
91 * Keeps track if the Container was cleared during a paint/update.
93 private boolean backCleared;
95 /**
96 * @since 1.4
98 boolean focusCycleRoot;
100 int containerSerializedDataVersion;
102 /* Anything else is non-serializable, and should be declared "transient". */
103 transient ContainerListener containerListener;
105 /** The focus traversal policy that determines how focus is
106 transferred between this Container and its children. */
107 private FocusTraversalPolicy focusTraversalPolicy;
110 * The focus traversal keys, if not inherited from the parent or default
111 * keyboard manager. These sets will contain only AWTKeyStrokes that
112 * represent press and release events to use as focus control.
114 * @see #getFocusTraversalKeys(int)
115 * @see #setFocusTraversalKeys(int, Set)
116 * @since 1.4
118 transient Set[] focusTraversalKeys;
121 * Default constructor for subclasses.
123 public Container()
125 // Nothing to do here.
129 * Returns the number of components in this container.
131 * @return The number of components in this container.
133 public int getComponentCount()
135 return countComponents ();
139 * Returns the number of components in this container.
141 * @return The number of components in this container.
143 * @deprecated use {@link #getComponentCount()} instead
145 public int countComponents()
147 return ncomponents;
151 * Returns the component at the specified index.
153 * @param n The index of the component to retrieve.
155 * @return The requested component.
157 * @throws ArrayIndexOutOfBoundsException If the specified index is invalid
159 public Component getComponent(int n)
161 synchronized (getTreeLock ())
163 if (n < 0 || n >= ncomponents)
164 throw new ArrayIndexOutOfBoundsException("no such component");
166 return component[n];
171 * Returns an array of the components in this container.
173 * @return The components in this container.
175 public Component[] getComponents()
177 synchronized (getTreeLock ())
179 Component[] result = new Component[ncomponents];
181 if (ncomponents > 0)
182 System.arraycopy(component, 0, result, 0, ncomponents);
184 return result;
189 * Returns the insets for this container, which is the space used for
190 * borders, the margin, etc.
192 * @return The insets for this container.
194 public Insets getInsets()
196 return insets ();
200 * Returns the insets for this container, which is the space used for
201 * borders, the margin, etc.
203 * @return The insets for this container.
204 * @deprecated use {@link #getInsets()} instead
206 public Insets insets()
208 if (peer == null)
209 return new Insets (0, 0, 0, 0);
211 return ((ContainerPeer) peer).getInsets ();
215 * Adds the specified component to this container at the end of the
216 * component list.
218 * @param comp The component to add to the container.
220 * @return The same component that was added.
222 public Component add(Component comp)
224 addImpl(comp, null, -1);
225 return comp;
229 * Adds the specified component to the container at the end of the
230 * component list. This method should not be used. Instead, use
231 * <code>add(Component, Object)</code>.
233 * @param name The name of the component to be added.
234 * @param comp The component to be added.
236 * @return The same component that was added.
238 * @see #add(Component,Object)
240 public Component add(String name, Component comp)
242 addImpl(comp, name, -1);
243 return comp;
247 * Adds the specified component to this container at the specified index
248 * in the component list.
250 * @param comp The component to be added.
251 * @param index The index in the component list to insert this child
252 * at, or -1 to add at the end of the list.
254 * @return The same component that was added.
256 * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
258 public Component add(Component comp, int index)
260 addImpl(comp, null, index);
261 return comp;
265 * Adds the specified component to this container at the end of the
266 * component list. The layout manager will use the specified constraints
267 * when laying out this component.
269 * @param comp The component to be added to this container.
270 * @param constraints The layout constraints for this component.
272 public void add(Component comp, Object constraints)
274 addImpl(comp, constraints, -1);
278 * Adds the specified component to this container at the specified index
279 * in the component list. The layout manager will use the specified
280 * constraints when layout out this component.
282 * @param comp The component to be added.
283 * @param constraints The layout constraints for this component.
284 * @param index The index in the component list to insert this child
285 * at, or -1 to add at the end of the list.
287 * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
289 public void add(Component comp, Object constraints, int index)
291 addImpl(comp, constraints, index);
295 * This method is called by all the <code>add()</code> methods to perform
296 * the actual adding of the component. Subclasses who wish to perform
297 * their own processing when a component is added should override this
298 * method. Any subclass doing this must call the superclass version of
299 * this method in order to ensure proper functioning of the container.
301 * @param comp The component to be added.
302 * @param constraints The layout constraints for this component, or
303 * <code>null</code> if there are no constraints.
304 * @param index The index in the component list to insert this child
305 * at, or -1 to add at the end of the list.
307 * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
309 protected void addImpl(Component comp, Object constraints, int index)
311 synchronized (getTreeLock ())
313 if (index > ncomponents
314 || (index < 0 && index != -1)
315 || comp instanceof Window
316 || (comp instanceof Container
317 && ((Container) comp).isAncestorOf(this)))
318 throw new IllegalArgumentException();
320 // Reparent component, and make sure component is instantiated if
321 // we are.
322 if (comp.parent != null)
323 comp.parent.remove(comp);
324 comp.parent = this;
326 if (peer != null)
328 // Notify the component that it has a new parent.
329 comp.addNotify();
331 if (comp.isLightweight ())
333 enableEvents (comp.eventMask);
334 if (!isLightweight ())
335 enableEvents (AWTEvent.PAINT_EVENT_MASK);
339 // Invalidate the layout of the added component and its ancestors.
340 comp.invalidate();
342 if (component == null)
343 component = new Component[4]; // FIXME, better initial size?
345 // This isn't the most efficient implementation. We could do less
346 // copying when growing the array. It probably doesn't matter.
347 if (ncomponents >= component.length)
349 int nl = component.length * 2;
350 Component[] c = new Component[nl];
351 System.arraycopy(component, 0, c, 0, ncomponents);
352 component = c;
355 if (index == -1)
356 component[ncomponents++] = comp;
357 else
359 System.arraycopy(component, index, component, index + 1,
360 ncomponents - index);
361 component[index] = comp;
362 ++ncomponents;
365 // Notify the layout manager.
366 if (layoutMgr != null)
368 // If we have a LayoutManager2 the constraints are "real",
369 // otherwise they are the "name" of the Component to add.
370 if (layoutMgr instanceof LayoutManager2)
372 LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
373 lm2.addLayoutComponent(comp, constraints);
375 else if (constraints instanceof String)
376 layoutMgr.addLayoutComponent((String) constraints, comp);
377 else
378 layoutMgr.addLayoutComponent("", comp);
381 // We previously only sent an event when this container is showing.
382 // Also, the event was posted to the event queue. A Mauve test shows
383 // that this event is not delivered using the event queue and it is
384 // also sent when the container is not showing.
385 ContainerEvent ce = new ContainerEvent(this,
386 ContainerEvent.COMPONENT_ADDED,
387 comp);
388 ContainerListener[] listeners = getContainerListeners();
389 for (int i = 0; i < listeners.length; i++)
390 listeners[i].componentAdded(ce);
395 * Removes the component at the specified index from this container.
397 * @param index The index of the component to remove.
399 public void remove(int index)
401 synchronized (getTreeLock ())
403 Component r = component[index];
405 ComponentListener[] list = r.getComponentListeners();
406 for (int j = 0; j < list.length; j++)
407 r.removeComponentListener(list[j]);
409 r.removeNotify();
411 System.arraycopy(component, index + 1, component, index,
412 ncomponents - index - 1);
413 component[--ncomponents] = null;
415 invalidate();
417 if (layoutMgr != null)
418 layoutMgr.removeLayoutComponent(r);
420 r.parent = null;
422 if (isShowing ())
424 // Post event to notify of removing the component.
425 ContainerEvent ce = new ContainerEvent(this,
426 ContainerEvent.COMPONENT_REMOVED,
428 getToolkit().getSystemEventQueue().postEvent(ce);
434 * Removes the specified component from this container.
436 * @param comp The component to remove from this container.
438 public void remove(Component comp)
440 synchronized (getTreeLock ())
442 for (int i = 0; i < ncomponents; ++i)
444 if (component[i] == comp)
446 remove(i);
447 break;
454 * Removes all components from this container.
456 public void removeAll()
458 synchronized (getTreeLock ())
460 while (ncomponents > 0)
461 remove(0);
466 * Returns the current layout manager for this container.
468 * @return The layout manager for this container.
470 public LayoutManager getLayout()
472 return layoutMgr;
476 * Sets the layout manager for this container to the specified layout
477 * manager.
479 * @param mgr The new layout manager for this container.
481 public void setLayout(LayoutManager mgr)
483 layoutMgr = mgr;
484 invalidate();
488 * Layout the components in this container.
490 public void doLayout()
492 layout ();
496 * Layout the components in this container.
498 * @deprecated use {@link #doLayout()} instead
500 public void layout()
502 if (layoutMgr != null)
503 layoutMgr.layoutContainer (this);
507 * Invalidates this container to indicate that it (and all parent
508 * containers) need to be laid out.
510 public void invalidate()
512 super.invalidate();
513 if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
515 LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
516 lm2.invalidateLayout(this);
521 * Re-lays out the components in this container.
523 public void validate()
525 synchronized (getTreeLock ())
527 if (! isValid() && peer != null)
529 validateTree();
535 * Recursively invalidates the container tree.
537 void invalidateTree()
539 super.invalidate(); // Clean cached layout state.
540 for (int i = 0; i < ncomponents; i++)
542 Component comp = component[i];
543 comp.invalidate();
544 if (comp instanceof Container)
545 ((Container) comp).invalidateTree();
548 if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
550 LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
551 lm2.invalidateLayout(this);
556 * Recursively validates the container tree, recomputing any invalid
557 * layouts.
559 protected void validateTree()
561 if (valid)
562 return;
564 ContainerPeer cPeer = null;
565 if (peer != null && ! (peer instanceof LightweightPeer))
567 cPeer = (ContainerPeer) peer;
568 cPeer.beginValidate();
571 for (int i = 0; i < ncomponents; ++i)
573 Component comp = component[i];
575 if (comp.getPeer () == null)
576 comp.addNotify();
579 doLayout ();
580 for (int i = 0; i < ncomponents; ++i)
582 Component comp = component[i];
584 if (! comp.isValid())
586 if (comp instanceof Container)
588 ((Container) comp).validateTree();
590 else
592 component[i].validate();
597 /* children will call invalidate() when they are layed out. It
598 is therefore important that valid is not set to true
599 until after the children have been layed out. */
600 valid = true;
602 if (cPeer != null)
603 cPeer.endValidate();
606 public void setFont(Font f)
608 if( (f != null && (font == null || !font.equals(f)))
609 || f == null)
611 super.setFont(f);
612 // FIXME: Although it might make more sense to invalidate only
613 // those children whose font == null, Sun invalidates all children.
614 // So we'll do the same.
615 invalidateTree();
620 * Returns the preferred size of this container.
622 * @return The preferred size of this container.
624 public Dimension getPreferredSize()
626 return preferredSize ();
630 * Returns the preferred size of this container.
632 * @return The preferred size of this container.
634 * @deprecated use {@link #getPreferredSize()} instead
636 public Dimension preferredSize()
638 synchronized(treeLock)
640 if(valid && prefSize != null)
641 return new Dimension(prefSize);
642 LayoutManager layout = getLayout();
643 if (layout != null)
645 Dimension layoutSize = layout.preferredLayoutSize(this);
646 if(valid)
647 prefSize = layoutSize;
648 return new Dimension(layoutSize);
650 else
651 return super.preferredSize ();
656 * Returns the minimum size of this container.
658 * @return The minimum size of this container.
660 public Dimension getMinimumSize()
662 return minimumSize ();
666 * Returns the minimum size of this container.
668 * @return The minimum size of this container.
670 * @deprecated use {@link #getMinimumSize()} instead
672 public Dimension minimumSize()
674 if(valid && minSize != null)
675 return new Dimension(minSize);
677 LayoutManager layout = getLayout();
678 if (layout != null)
680 minSize = layout.minimumLayoutSize (this);
681 return minSize;
683 else
684 return super.minimumSize ();
688 * Returns the maximum size of this container.
690 * @return The maximum size of this container.
692 public Dimension getMaximumSize()
694 if (valid && maxSize != null)
695 return new Dimension(maxSize);
697 LayoutManager layout = getLayout();
698 if (layout != null && layout instanceof LayoutManager2)
700 LayoutManager2 lm2 = (LayoutManager2) layout;
701 maxSize = lm2.maximumLayoutSize(this);
702 return maxSize;
704 else
705 return super.getMaximumSize();
709 * Returns the preferred alignment along the X axis. This is a value
710 * between 0 and 1 where 0 represents alignment flush left and
711 * 1 means alignment flush right, and 0.5 means centered.
713 * @return The preferred alignment along the X axis.
715 public float getAlignmentX()
717 LayoutManager layout = getLayout();
718 float alignmentX = 0.0F;
719 if (layout != null && layout instanceof LayoutManager2)
721 LayoutManager2 lm2 = (LayoutManager2) layout;
722 alignmentX = lm2.getLayoutAlignmentX(this);
724 else
725 alignmentX = super.getAlignmentX();
726 return alignmentX;
730 * Returns the preferred alignment along the Y axis. This is a value
731 * between 0 and 1 where 0 represents alignment flush top and
732 * 1 means alignment flush bottom, and 0.5 means centered.
734 * @return The preferred alignment along the Y axis.
736 public float getAlignmentY()
738 LayoutManager layout = getLayout();
739 float alignmentY = 0.0F;
740 if (layout != null && layout instanceof LayoutManager2)
742 LayoutManager2 lm2 = (LayoutManager2) layout;
743 alignmentY = lm2.getLayoutAlignmentY(this);
745 else
746 alignmentY = super.getAlignmentY();
747 return alignmentY;
751 * Paints this container. The implementation of this method in this
752 * class forwards to any lightweight components in this container. If
753 * this method is subclassed, this method should still be invoked as
754 * a superclass method so that lightweight components are properly
755 * drawn.
757 * @param g - The graphics context for this paint job.
759 public void paint(Graphics g)
761 if (!isShowing())
762 return;
764 // Visit heavyweights if the background was cleared
765 // for this container.
766 visitChildren(g, GfxPaintVisitor.INSTANCE, !backCleared);
767 backCleared = false;
771 * Updates this container. The implementation of this method in this
772 * class forwards to any lightweight components in this container. If
773 * this method is subclassed, this method should still be invoked as
774 * a superclass method so that lightweight components are properly
775 * drawn.
777 * @param g The graphics context for this update.
779 * @specnote The specification suggests that this method forwards the
780 * update() call to all its lightweight children. Tests show
781 * that this is not done either in the JDK. The exact behaviour
782 * seems to be that the background is cleared in heavyweight
783 * Containers, and all other containers
784 * directly call paint(), causing the (lightweight) children to
785 * be painted.
787 public void update(Graphics g)
789 // It seems that the JDK clears the background of containers like Panel
790 // and Window (within this method) but not of 'plain' Containers or
791 // JComponents. This could
792 // lead to the assumption that it only clears heavyweight containers.
793 // However that is not quite true. In a test with a custom Container
794 // that overrides isLightweight() to return false, the background is
795 // also not cleared. So we do a check on !(peer instanceof LightweightPeer)
796 // instead.
797 ComponentPeer p = peer;
798 if (p != null && ! (p instanceof LightweightPeer))
800 g.clearRect(0, 0, getWidth(), getHeight());
801 backCleared = true;
804 paint(g);
808 * Prints this container. The implementation of this method in this
809 * class forwards to any lightweight components in this container. If
810 * this method is subclassed, this method should still be invoked as
811 * a superclass method so that lightweight components are properly
812 * drawn.
814 * @param g The graphics context for this print job.
816 public void print(Graphics g)
818 super.print(g);
819 visitChildren(g, GfxPrintVisitor.INSTANCE, true);
823 * Paints all of the components in this container.
825 * @param g The graphics context for this paint job.
827 public void paintComponents(Graphics g)
829 paint(g);
830 visitChildren(g, GfxPaintAllVisitor.INSTANCE, true);
834 * Prints all of the components in this container.
836 * @param g The graphics context for this print job.
838 public void printComponents(Graphics g)
840 super.paint(g);
841 visitChildren(g, GfxPrintAllVisitor.INSTANCE, true);
845 * Adds the specified container listener to this object's list of
846 * container listeners.
848 * @param listener The listener to add.
850 public synchronized void addContainerListener(ContainerListener listener)
852 containerListener = AWTEventMulticaster.add(containerListener, listener);
856 * Removes the specified container listener from this object's list of
857 * container listeners.
859 * @param listener The listener to remove.
861 public synchronized void removeContainerListener(ContainerListener listener)
863 containerListener = AWTEventMulticaster.remove(containerListener, listener);
867 * @since 1.4
869 public synchronized ContainerListener[] getContainerListeners()
871 return (ContainerListener[])
872 AWTEventMulticaster.getListeners(containerListener,
873 ContainerListener.class);
877 * Returns all registered {@link EventListener}s of the given
878 * <code>listenerType</code>.
880 * @param listenerType the class of listeners to filter (<code>null</code>
881 * not permitted).
883 * @return An array of registered listeners.
885 * @throws ClassCastException if <code>listenerType</code> does not implement
886 * the {@link EventListener} interface.
887 * @throws NullPointerException if <code>listenerType</code> is
888 * <code>null</code>.
890 * @see #getContainerListeners()
892 * @since 1.3
894 public EventListener[] getListeners(Class listenerType)
896 if (listenerType == ContainerListener.class)
897 return getContainerListeners();
898 return super.getListeners(listenerType);
902 * Processes the specified event. This method calls
903 * <code>processContainerEvent()</code> if this method is a
904 * <code>ContainerEvent</code>, otherwise it calls the superclass
905 * method.
907 * @param e The event to be processed.
909 protected void processEvent(AWTEvent e)
911 if (e instanceof ContainerEvent)
912 processContainerEvent((ContainerEvent) e);
913 else
914 super.processEvent(e);
918 * Called when a container event occurs if container events are enabled.
919 * This method calls any registered listeners.
921 * @param e The event that occurred.
923 protected void processContainerEvent(ContainerEvent e)
925 if (containerListener == null)
926 return;
927 switch (e.id)
929 case ContainerEvent.COMPONENT_ADDED:
930 containerListener.componentAdded(e);
931 break;
933 case ContainerEvent.COMPONENT_REMOVED:
934 containerListener.componentRemoved(e);
935 break;
940 * AWT 1.0 event processor.
942 * @param e The event that occurred.
944 * @deprecated use {@link #dispatchEvent(AWTEvent)} instead
946 public void deliverEvent(Event e)
948 if (!handleEvent (e))
950 synchronized (getTreeLock ())
952 Component parent = getParent ();
954 if (parent != null)
955 parent.deliverEvent (e);
961 * Returns the component located at the specified point. This is done
962 * by checking whether or not a child component claims to contain this
963 * point. The first child component that does is returned. If no
964 * child component claims the point, the container itself is returned,
965 * unless the point does not exist within this container, in which
966 * case <code>null</code> is returned.
968 * When components overlap, the first component is returned. The component
969 * that is closest to (x, y), containing that location, is returned.
970 * Heavyweight components take precedence of lightweight components.
972 * This function does not ignore invisible components. If there is an invisible
973 * component at (x,y), it will be returned.
975 * @param x The X coordinate of the point.
976 * @param y The Y coordinate of the point.
978 * @return The component containing the specified point, or
979 * <code>null</code> if there is no such point.
981 public Component getComponentAt(int x, int y)
983 return locate (x, y);
987 * Returns the component located at the specified point. This is done
988 * by checking whether or not a child component claims to contain this
989 * point. The first child component that does is returned. If no
990 * child component claims the point, the container itself is returned,
991 * unless the point does not exist within this container, in which
992 * case <code>null</code> is returned.
994 * When components overlap, the first component is returned. The component
995 * that is closest to (x, y), containing that location, is returned.
996 * Heavyweight components take precedence of lightweight components.
998 * This function does not ignore invisible components. If there is an invisible
999 * component at (x,y), it will be returned.
1001 * @param x The x position of the point to return the component at.
1002 * @param y The y position of the point to return the component at.
1004 * @return The component containing the specified point, or <code>null</code>
1005 * if there is no such point.
1007 * @deprecated use {@link #getComponentAt(int, int)} instead
1009 public Component locate(int x, int y)
1011 synchronized (getTreeLock ())
1013 if (!contains (x, y))
1014 return null;
1016 // First find the component closest to (x,y) that is a heavyweight.
1017 for (int i = 0; i < ncomponents; ++i)
1019 Component comp = component[i];
1020 int x2 = x - comp.x;
1021 int y2 = y - comp.y;
1022 if (comp.contains (x2, y2) && !comp.isLightweight())
1023 return comp;
1026 // if a heavyweight component is not found, look for a lightweight
1027 // closest to (x,y).
1028 for (int i = 0; i < ncomponents; ++i)
1030 Component comp = component[i];
1031 int x2 = x - comp.x;
1032 int y2 = y - comp.y;
1033 if (comp.contains (x2, y2) && comp.isLightweight())
1034 return comp;
1037 return this;
1042 * Returns the component located at the specified point. This is done
1043 * by checking whether or not a child component claims to contain this
1044 * point. The first child component that does is returned. If no
1045 * child component claims the point, the container itself is returned,
1046 * unless the point does not exist within this container, in which
1047 * case <code>null</code> is returned.
1049 * The top-most child component is returned in the case where components overlap.
1050 * This is determined by finding the component closest to (x,y) and contains
1051 * that location. Heavyweight components take precedence of lightweight components.
1053 * This function does not ignore invisible components. If there is an invisible
1054 * component at (x,y), it will be returned.
1056 * @param p The point to return the component at.
1057 * @return The component containing the specified point, or <code>null</code>
1058 * if there is no such point.
1060 public Component getComponentAt(Point p)
1062 return getComponentAt (p.x, p.y);
1066 * Locates the visible child component that contains the specified position.
1067 * The top-most child component is returned in the case where there is overlap
1068 * in the components. If the containing child component is a Container,
1069 * this method will continue searching for the deepest nested child
1070 * component. Components which are not visible are ignored during the search.
1072 * findComponentAt differs from getComponentAt, because it recursively
1073 * searches a Container's children.
1075 * @param x - x coordinate
1076 * @param y - y coordinate
1077 * @return null if the component does not contain the position.
1078 * If there is no child component at the requested point and the point is
1079 * within the bounds of the container the container itself is returned.
1081 public Component findComponentAt(int x, int y)
1083 synchronized (getTreeLock ())
1085 if (! contains(x, y))
1086 return null;
1088 for (int i = 0; i < ncomponents; ++i)
1090 // Ignore invisible children...
1091 if (!component[i].isVisible())
1092 continue;
1094 int x2 = x - component[i].x;
1095 int y2 = y - component[i].y;
1096 // We don't do the contains() check right away because
1097 // findComponentAt would redundantly do it first thing.
1098 if (component[i] instanceof Container)
1100 Container k = (Container) component[i];
1101 Component r = k.findComponentAt(x2, y2);
1102 if (r != null)
1103 return r;
1105 else if (component[i].contains(x2, y2))
1106 return component[i];
1109 return this;
1114 * Locates the visible child component that contains the specified position.
1115 * The top-most child component is returned in the case where there is overlap
1116 * in the components. If the containing child component is a Container,
1117 * this method will continue searching for the deepest nested child
1118 * component. Components which are not visible are ignored during the search.
1120 * findComponentAt differs from getComponentAt, because it recursively
1121 * searches a Container's children.
1123 * @param p - the component's location
1124 * @return null if the component does not contain the position.
1125 * If there is no child component at the requested point and the point is
1126 * within the bounds of the container the container itself is returned.
1128 public Component findComponentAt(Point p)
1130 return findComponentAt(p.x, p.y);
1134 * Called when this container is added to another container to inform it
1135 * to create its peer. Peers for any child components will also be
1136 * created.
1138 public void addNotify()
1140 super.addNotify();
1141 addNotifyContainerChildren();
1145 * Called when this container is removed from its parent container to
1146 * inform it to destroy its peer. This causes the peers of all child
1147 * component to be destroyed as well.
1149 public void removeNotify()
1151 synchronized (getTreeLock ())
1153 for (int i = 0; i < ncomponents; ++i)
1154 component[i].removeNotify();
1155 super.removeNotify();
1160 * Tests whether or not the specified component is contained within
1161 * this components subtree.
1163 * @param comp The component to test.
1165 * @return <code>true</code> if this container is an ancestor of the
1166 * specified component, <code>false</code> otherwise.
1168 public boolean isAncestorOf(Component comp)
1170 synchronized (getTreeLock ())
1172 while (true)
1174 if (comp == null)
1175 return false;
1176 if (comp == this)
1177 return true;
1178 comp = comp.getParent();
1184 * Returns a string representing the state of this container for
1185 * debugging purposes.
1187 * @return A string representing the state of this container.
1189 protected String paramString()
1191 if (layoutMgr == null)
1192 return super.paramString();
1194 StringBuffer sb = new StringBuffer();
1195 sb.append(super.paramString());
1196 sb.append(",layout=");
1197 sb.append(layoutMgr.getClass().getName());
1198 return sb.toString();
1202 * Writes a listing of this container to the specified stream starting
1203 * at the specified indentation point.
1205 * @param out The <code>PrintStream</code> to write to.
1206 * @param indent The indentation point.
1208 public void list(PrintStream out, int indent)
1210 synchronized (getTreeLock ())
1212 super.list(out, indent);
1213 for (int i = 0; i < ncomponents; ++i)
1214 component[i].list(out, indent + 2);
1219 * Writes a listing of this container to the specified stream starting
1220 * at the specified indentation point.
1222 * @param out The <code>PrintWriter</code> to write to.
1223 * @param indent The indentation point.
1225 public void list(PrintWriter out, int indent)
1227 synchronized (getTreeLock ())
1229 super.list(out, indent);
1230 for (int i = 0; i < ncomponents; ++i)
1231 component[i].list(out, indent + 2);
1236 * Sets the focus traversal keys for a given traversal operation for this
1237 * Container.
1239 * @exception IllegalArgumentException If id is not one of
1240 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1241 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1242 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
1243 * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS,
1244 * or if keystrokes contains null, or if any Object in keystrokes is not an
1245 * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event, or if any
1246 * keystroke already maps to another focus traversal operation for this
1247 * Container.
1249 * @since 1.4
1251 public void setFocusTraversalKeys(int id, Set keystrokes)
1253 if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1254 id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1255 id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1256 id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1257 throw new IllegalArgumentException ();
1259 if (keystrokes == null)
1261 Container parent = getParent ();
1263 while (parent != null)
1265 if (parent.areFocusTraversalKeysSet (id))
1267 keystrokes = parent.getFocusTraversalKeys (id);
1268 break;
1270 parent = parent.getParent ();
1273 if (keystrokes == null)
1274 keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager ().
1275 getDefaultFocusTraversalKeys (id);
1278 Set sa;
1279 Set sb;
1280 Set sc;
1281 String name;
1282 switch (id)
1284 case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
1285 sa = getFocusTraversalKeys
1286 (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
1287 sb = getFocusTraversalKeys
1288 (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
1289 sc = getFocusTraversalKeys
1290 (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1291 name = "forwardFocusTraversalKeys";
1292 break;
1293 case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
1294 sa = getFocusTraversalKeys
1295 (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
1296 sb = getFocusTraversalKeys
1297 (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
1298 sc = getFocusTraversalKeys
1299 (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1300 name = "backwardFocusTraversalKeys";
1301 break;
1302 case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS:
1303 sa = getFocusTraversalKeys
1304 (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
1305 sb = getFocusTraversalKeys
1306 (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
1307 sc = getFocusTraversalKeys
1308 (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1309 name = "upCycleFocusTraversalKeys";
1310 break;
1311 case KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS:
1312 sa = getFocusTraversalKeys
1313 (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
1314 sb = getFocusTraversalKeys
1315 (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
1316 sc = getFocusTraversalKeys
1317 (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
1318 name = "downCycleFocusTraversalKeys";
1319 break;
1320 default:
1321 throw new IllegalArgumentException ();
1324 int i = keystrokes.size ();
1325 Iterator iter = keystrokes.iterator ();
1327 while (--i >= 0)
1329 Object o = iter.next ();
1330 if (!(o instanceof AWTKeyStroke)
1331 || sa.contains (o) || sb.contains (o) || sc.contains (o)
1332 || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
1333 throw new IllegalArgumentException ();
1336 if (focusTraversalKeys == null)
1337 focusTraversalKeys = new Set[4];
1339 keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
1340 firePropertyChange (name, focusTraversalKeys[id], keystrokes);
1342 focusTraversalKeys[id] = keystrokes;
1346 * Returns the Set of focus traversal keys for a given traversal operation for
1347 * this Container.
1349 * @exception IllegalArgumentException If id is not one of
1350 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1351 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1352 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
1353 * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS.
1355 * @since 1.4
1357 public Set getFocusTraversalKeys (int id)
1359 if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1360 id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1361 id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1362 id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1363 throw new IllegalArgumentException ();
1365 Set s = null;
1367 if (focusTraversalKeys != null)
1368 s = focusTraversalKeys[id];
1370 if (s == null && parent != null)
1371 s = parent.getFocusTraversalKeys (id);
1373 return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager()
1374 .getDefaultFocusTraversalKeys(id)) : s;
1378 * Returns whether the Set of focus traversal keys for the given focus
1379 * traversal operation has been explicitly defined for this Container.
1380 * If this method returns false, this Container is inheriting the Set from
1381 * an ancestor, or from the current KeyboardFocusManager.
1383 * @exception IllegalArgumentException If id is not one of
1384 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1385 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1386 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
1387 * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS.
1389 * @since 1.4
1391 public boolean areFocusTraversalKeysSet (int id)
1393 if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1394 id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1395 id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1396 id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1397 throw new IllegalArgumentException ();
1399 return focusTraversalKeys != null && focusTraversalKeys[id] != null;
1403 * Check whether the given Container is the focus cycle root of this
1404 * Container's focus traversal cycle. If this Container is a focus
1405 * cycle root itself, then it will be in two different focus cycles
1406 * -- it's own, and that of its ancestor focus cycle root's. In
1407 * that case, if <code>c</code> is either of those containers, this
1408 * method will return true.
1410 * @param c the candidate Container
1412 * @return true if c is the focus cycle root of the focus traversal
1413 * cycle to which this Container belongs, false otherwise
1415 * @since 1.4
1417 public boolean isFocusCycleRoot (Container c)
1419 if (this == c
1420 && isFocusCycleRoot ())
1421 return true;
1423 Container ancestor = getFocusCycleRootAncestor ();
1425 if (c == ancestor)
1426 return true;
1428 return false;
1432 * If this Container is a focus cycle root, set the focus traversal
1433 * policy that determines the focus traversal order for its
1434 * children. If non-null, this policy will be inherited by all
1435 * inferior focus cycle roots. If <code>policy</code> is null, this
1436 * Container will inherit its policy from the closest ancestor focus
1437 * cycle root that's had its policy set.
1439 * @param policy the new focus traversal policy for this Container or null
1441 * @since 1.4
1443 public void setFocusTraversalPolicy (FocusTraversalPolicy policy)
1445 focusTraversalPolicy = policy;
1449 * Return the focus traversal policy that determines the focus
1450 * traversal order for this Container's children. This method
1451 * returns null if this Container is not a focus cycle root. If the
1452 * focus traversal policy has not been set explicitly, then this
1453 * method will return an ancestor focus cycle root's policy instead.
1455 * @return this Container's focus traversal policy or null
1457 * @since 1.4
1459 public FocusTraversalPolicy getFocusTraversalPolicy ()
1461 if (!isFocusCycleRoot ())
1462 return null;
1464 if (focusTraversalPolicy == null)
1466 Container ancestor = getFocusCycleRootAncestor ();
1468 if (ancestor != this && ancestor != null)
1469 return ancestor.getFocusTraversalPolicy ();
1470 else
1472 KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
1474 return manager.getDefaultFocusTraversalPolicy ();
1477 else
1478 return focusTraversalPolicy;
1482 * Check whether this Container's focus traversal policy has been
1483 * explicitly set. If it has not, then this Container will inherit
1484 * its focus traversal policy from one of its ancestor focus cycle
1485 * roots.
1487 * @return true if focus traversal policy is set, false otherwise
1489 public boolean isFocusTraversalPolicySet ()
1491 return focusTraversalPolicy == null;
1495 * Set whether or not this Container is the root of a focus
1496 * traversal cycle. This Container's focus traversal policy
1497 * determines the order of focus traversal. Some policies prevent
1498 * the focus from being transferred between two traversal cycles
1499 * until an up or down traversal operation is performed. In that
1500 * case, normal traversal (not up or down) is limited to this
1501 * Container and all of this Container's descendents that are not
1502 * descendents of inferior focus cycle roots. In the default case
1503 * however, ContainerOrderFocusTraversalPolicy is in effect, and it
1504 * supports implicit down-cycle traversal operations.
1506 * @param focusCycleRoot true if this is a focus cycle root, false otherwise
1508 * @since 1.4
1510 public void setFocusCycleRoot (boolean focusCycleRoot)
1512 this.focusCycleRoot = focusCycleRoot;
1516 * Check whether this Container is a focus cycle root.
1518 * @return true if this is a focus cycle root, false otherwise
1520 * @since 1.4
1522 public boolean isFocusCycleRoot ()
1524 return focusCycleRoot;
1528 * Transfer focus down one focus traversal cycle. If this Container
1529 * is a focus cycle root, then its default component becomes the
1530 * focus owner, and this Container becomes the current focus cycle
1531 * root. No traversal will occur if this Container is not a focus
1532 * cycle root.
1534 * @since 1.4
1536 public void transferFocusDownCycle ()
1538 if (isFocusCycleRoot())
1540 KeyboardFocusManager fm =
1541 KeyboardFocusManager.getCurrentKeyboardFocusManager();
1542 fm.setGlobalCurrentFocusCycleRoot(this);
1543 FocusTraversalPolicy policy = getFocusTraversalPolicy();
1544 Component defaultComponent = policy.getDefaultComponent(this);
1545 if (defaultComponent != null)
1546 defaultComponent.requestFocus();
1551 * Sets the ComponentOrientation property of this container and all components
1552 * contained within it.
1554 * @exception NullPointerException If orientation is null
1556 * @since 1.4
1558 public void applyComponentOrientation (ComponentOrientation orientation)
1560 if (orientation == null)
1561 throw new NullPointerException ();
1564 public void addPropertyChangeListener (PropertyChangeListener listener)
1566 // TODO: Why is this overridden?
1567 super.addPropertyChangeListener(listener);
1570 public void addPropertyChangeListener (String propertyName,
1571 PropertyChangeListener listener)
1573 // TODO: Why is this overridden?
1574 super.addPropertyChangeListener(propertyName, listener);
1579 * Sets the Z ordering for the component <code>comp</code> to
1580 * <code>index</code>. Components with lower Z order paint above components
1581 * with higher Z order.
1583 * @param comp the component for which to change the Z ordering
1584 * @param index the index to set
1586 * @throws NullPointerException if <code>comp == null</code>
1587 * @throws IllegalArgumentException if comp is an ancestor of this container
1588 * @throws IllegalArgumentException if <code>index</code> is not in
1589 * <code>[0, getComponentCount()]</code> for moving between
1590 * containers or <code>[0, getComponentCount() - 1]</code> for moving
1591 * inside this container
1592 * @throws IllegalArgumentException if <code>comp == this</code>
1593 * @throws IllegalArgumentException if <code>comp</code> is a
1594 * <code>Window</code>
1596 * @see #getComponentZOrder(Component)
1598 * @since 1.5
1600 public final void setComponentZOrder(Component comp, int index)
1602 if (comp == null)
1603 throw new NullPointerException("comp must not be null");
1604 if (comp instanceof Container && ((Container) comp).isAncestorOf(this))
1605 throw new IllegalArgumentException("comp must not be an ancestor of "
1606 + "this");
1607 if (comp instanceof Window)
1608 throw new IllegalArgumentException("comp must not be a Window");
1610 if (comp == this)
1611 throw new IllegalArgumentException("cannot add component to itself");
1613 // FIXME: Implement reparenting.
1614 if ( comp.getParent() != this)
1615 throw new AssertionError("Reparenting is not implemented yet");
1616 else
1618 // Find current component index.
1619 int currentIndex = getComponentZOrder(comp);
1620 if (currentIndex < index)
1622 System.arraycopy(component, currentIndex + 1, component,
1623 currentIndex, index - currentIndex);
1625 else
1627 System.arraycopy(component, index, component, index + 1,
1628 currentIndex - index);
1630 component[index] = comp;
1635 * Returns the Z ordering index of <code>comp</code>. If <code>comp</code>
1636 * is not a child component of this Container, this returns <code>-1</code>.
1638 * @param comp the component for which to query the Z ordering
1640 * @return the Z ordering index of <code>comp</code> or <code>-1</code> if
1641 * <code>comp</code> is not a child of this Container
1643 * @see #setComponentZOrder(Component, int)
1645 * @since 1.5
1647 public final int getComponentZOrder(Component comp)
1649 int index = -1;
1650 if (component != null)
1652 for (int i = 0; i < component.length; i++)
1654 if (component[i] == comp)
1656 index = i;
1657 break;
1661 return index;
1664 // Hidden helper methods.
1667 * Perform a graphics operation on the children of this container.
1668 * For each applicable child, the visitChild() method will be called
1669 * to perform the graphics operation.
1671 * @param gfx The graphics object that will be used to derive new
1672 * graphics objects for the children.
1674 * @param visitor Object encapsulating the graphics operation that
1675 * should be performed.
1677 * @param lightweightOnly If true, only lightweight components will
1678 * be visited.
1680 private void visitChildren(Graphics gfx, GfxVisitor visitor,
1681 boolean lightweightOnly)
1683 synchronized (getTreeLock())
1685 for (int i = ncomponents - 1; i >= 0; --i)
1687 Component comp = component[i];
1688 boolean applicable = comp.isVisible()
1689 && (comp.isLightweight() || ! lightweightOnly);
1691 if (applicable)
1692 visitChild(gfx, visitor, comp);
1698 * Perform a graphics operation on a child. A translated and clipped
1699 * graphics object will be created, and the visit() method of the
1700 * visitor will be called to perform the operation.
1702 * @param gfx The graphics object that will be used to derive new
1703 * graphics objects for the child.
1705 * @param visitor Object encapsulating the graphics operation that
1706 * should be performed.
1708 * @param comp The child component that should be visited.
1710 private void visitChild(Graphics gfx, GfxVisitor visitor,
1711 Component comp)
1713 Rectangle bounds = comp.getBounds();
1715 if(!gfx.hitClip(bounds.x,bounds.y, bounds.width, bounds.height))
1716 return;
1717 Graphics g2 = gfx.create(bounds.x, bounds.y, bounds.width,
1718 bounds.height);
1721 visitor.visit(comp, g2);
1723 finally
1725 g2.dispose();
1729 void dispatchEventImpl(AWTEvent e)
1731 boolean dispatched =
1732 LightweightDispatcher.getInstance().dispatchEvent(e);
1733 if (! dispatched)
1735 if ((e.id <= ContainerEvent.CONTAINER_LAST
1736 && e.id >= ContainerEvent.CONTAINER_FIRST)
1737 && (containerListener != null
1738 || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0))
1739 processEvent(e);
1740 else
1741 super.dispatchEventImpl(e);
1746 * Tests if this container has an interest in the given event id.
1748 * @param eventId The event id to check.
1750 * @return <code>true</code> if a listener for the event id exists or
1751 * if the eventMask is set for the event id.
1753 * @see java.awt.Component#eventTypeEnabled(int)
1755 boolean eventTypeEnabled(int eventId)
1757 if(eventId <= ContainerEvent.CONTAINER_LAST
1758 && eventId >= ContainerEvent.CONTAINER_FIRST)
1759 return containerListener != null
1760 || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0;
1761 else
1762 return super.eventTypeEnabled(eventId);
1765 // This is used to implement Component.transferFocus.
1766 Component findNextFocusComponent(Component child)
1768 synchronized (getTreeLock ())
1770 int start, end;
1771 if (child != null)
1773 for (start = 0; start < ncomponents; ++start)
1775 if (component[start] == child)
1776 break;
1778 end = start;
1779 // This special case lets us be sure to terminate.
1780 if (end == 0)
1781 end = ncomponents;
1782 ++start;
1784 else
1786 start = 0;
1787 end = ncomponents;
1790 for (int j = start; j != end; ++j)
1792 if (j >= ncomponents)
1794 // The JCL says that we should wrap here. However, that
1795 // seems wrong. To me it seems that focus order should be
1796 // global within in given window. So instead if we reach
1797 // the end we try to look in our parent, if we have one.
1798 if (parent != null)
1799 return parent.findNextFocusComponent(this);
1800 j -= ncomponents;
1802 if (component[j] instanceof Container)
1804 Component c = component[j];
1805 c = c.findNextFocusComponent(null);
1806 if (c != null)
1807 return c;
1809 else if (component[j].isFocusTraversable())
1810 return component[j];
1813 return null;
1817 private void addNotifyContainerChildren()
1819 synchronized (getTreeLock ())
1821 for (int i = ncomponents; --i >= 0; )
1823 component[i].addNotify();
1824 if (component[i].isLightweight ())
1826 enableEvents(component[i].eventMask);
1827 if (peer != null && !isLightweight ())
1828 enableEvents (AWTEvent.PAINT_EVENT_MASK);
1835 * Deserialize this Container:
1836 * <ol>
1837 * <li>Read from the stream the default serializable fields.</li>
1838 * <li>Read a list of serializable ContainerListeners as optional
1839 * data. If the list is null, no listeners will be registered.</li>
1840 * <li>Read this Container's FocusTraversalPolicy as optional data.
1841 * If this is null, then this Container will use a
1842 * DefaultFocusTraversalPolicy.</li>
1843 * </ol>
1845 * @param s the stream to read from
1846 * @throws ClassNotFoundException if deserialization fails
1847 * @throws IOException if the stream fails
1849 private void readObject (ObjectInputStream s)
1850 throws ClassNotFoundException, IOException
1852 s.defaultReadObject ();
1853 String key = (String) s.readObject ();
1854 while (key != null)
1856 Object object = s.readObject ();
1857 if ("containerL".equals (key))
1858 addContainerListener((ContainerListener) object);
1859 // FIXME: under what key is the focus traversal policy stored?
1860 else if ("focusTraversalPolicy".equals (key))
1861 setFocusTraversalPolicy ((FocusTraversalPolicy) object);
1863 key = (String) s.readObject();
1868 * Serialize this Container:
1869 * <ol>
1870 * <li>Write to the stream the default serializable fields.</li>
1871 * <li>Write the list of serializable ContainerListeners as optional
1872 * data.</li>
1873 * <li>Write this Container's FocusTraversalPolicy as optional data.</li>
1874 * </ol>
1876 * @param s the stream to write to
1877 * @throws IOException if the stream fails
1879 private void writeObject (ObjectOutputStream s) throws IOException
1881 s.defaultWriteObject ();
1882 AWTEventMulticaster.save (s, "containerL", containerListener);
1883 if (focusTraversalPolicy instanceof Serializable)
1884 s.writeObject (focusTraversalPolicy);
1885 else
1886 s.writeObject (null);
1889 // Nested classes.
1891 /* The following classes are used in concert with the
1892 visitChildren() method to implement all the graphics operations
1893 that requires traversal of the containment hierarchy. */
1895 abstract static class GfxVisitor
1897 public abstract void visit(Component c, Graphics gfx);
1900 static class GfxPaintVisitor extends GfxVisitor
1902 public static final GfxVisitor INSTANCE = new GfxPaintVisitor();
1904 public void visit(Component c, Graphics gfx)
1906 c.paint(gfx);
1910 static class GfxPrintVisitor extends GfxVisitor
1912 public static final GfxVisitor INSTANCE = new GfxPrintVisitor();
1914 public void visit(Component c, Graphics gfx)
1916 c.print(gfx);
1920 static class GfxPaintAllVisitor extends GfxVisitor
1922 public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor();
1924 public void visit(Component c, Graphics gfx)
1926 c.paintAll(gfx);
1930 static class GfxPrintAllVisitor extends GfxVisitor
1932 public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor();
1934 public void visit(Component c, Graphics gfx)
1936 c.printAll(gfx);
1941 * This class provides accessibility support for subclasses of container.
1943 * @author Eric Blake (ebb9@email.byu.edu)
1945 * @since 1.3
1947 protected class AccessibleAWTContainer extends AccessibleAWTComponent
1950 * Compatible with JDK 1.4+.
1952 private static final long serialVersionUID = 5081320404842566097L;
1955 * The handler to fire PropertyChange when children are added or removed.
1957 * @serial the handler for property changes
1959 protected ContainerListener accessibleContainerHandler
1960 = new AccessibleContainerHandler();
1963 * The default constructor.
1965 protected AccessibleAWTContainer()
1967 Container.this.addContainerListener(accessibleContainerHandler);
1971 * Return the number of accessible children of the containing accessible
1972 * object (at most the total number of its children).
1974 * @return the number of accessible children
1976 public int getAccessibleChildrenCount()
1978 synchronized (getTreeLock ())
1980 int count = 0;
1981 int i = component == null ? 0 : component.length;
1982 while (--i >= 0)
1983 if (component[i] instanceof Accessible)
1984 count++;
1985 return count;
1990 * Return the nth accessible child of the containing accessible object.
1992 * @param i the child to grab, zero-based
1993 * @return the accessible child, or null
1995 public Accessible getAccessibleChild(int i)
1997 synchronized (getTreeLock ())
1999 if (component == null)
2000 return null;
2001 int index = -1;
2002 while (i >= 0 && ++index < component.length)
2003 if (component[index] instanceof Accessible)
2004 i--;
2005 if (i < 0)
2006 return (Accessible) component[index];
2007 return null;
2012 * Return the accessible child located at point (in the parent's
2013 * coordinates), if one exists.
2015 * @param p the point to look at
2017 * @return an accessible object at that point, or null
2019 * @throws NullPointerException if p is null
2021 public Accessible getAccessibleAt(Point p)
2023 Component c = getComponentAt(p.x, p.y);
2024 return c != Container.this && c instanceof Accessible ? (Accessible) c
2025 : null;
2029 * This class fires a <code>PropertyChange</code> listener, if registered,
2030 * when children are added or removed from the enclosing accessible object.
2032 * @author Eric Blake (ebb9@email.byu.edu)
2034 * @since 1.3
2036 protected class AccessibleContainerHandler implements ContainerListener
2039 * Default constructor.
2041 protected AccessibleContainerHandler()
2043 // Nothing to do here.
2047 * Fired when a component is added; forwards to the PropertyChange
2048 * listener.
2050 * @param e the container event for adding
2052 public void componentAdded(ContainerEvent e)
2054 AccessibleAWTContainer.this.firePropertyChange
2055 (ACCESSIBLE_CHILD_PROPERTY, null, e.getChild());
2059 * Fired when a component is removed; forwards to the PropertyChange
2060 * listener.
2062 * @param e the container event for removing
2064 public void componentRemoved(ContainerEvent e)
2066 AccessibleAWTContainer.this.firePropertyChange
2067 (ACCESSIBLE_CHILD_PROPERTY, e.getChild(), null);
2069 } // class AccessibleContainerHandler
2070 } // class AccessibleAWTContainer
2071 } // class Container