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)
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
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
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. */
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
;
63 import javax
.accessibility
.Accessible
;
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)
76 * @status still missing 1.4 support, some generics from 1.5
78 public class Container
extends Component
81 * Compatible with JDK 1.0+.
83 private static final long serialVersionUID
= 4613797578919906343L;
85 /* Serialized fields from the serialization spec. */
87 Component
[] component
;
88 LayoutManager layoutMgr
;
93 boolean focusCycleRoot
;
96 * Indicates if this container provides a focus traversal policy.
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)
120 transient Set
[] focusTraversalKeys
;
123 * Default constructor for subclasses.
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()
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");
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
];
184 System
.arraycopy(component
, 0, result
, 0, ncomponents
);
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()
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()
211 if (peer
== null || peer
instanceof LightweightPeer
)
212 i
= new Insets (0, 0, 0, 0);
214 i
= ((ContainerPeer
) peer
).getInsets ();
219 * Adds the specified component to this container at the end of the
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);
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);
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
);
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
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
);
343 component
[ncomponents
++] = comp
;
346 System
.arraycopy(component
, index
, component
, index
+ 1,
347 ncomponents
- index
);
348 component
[index
] = comp
;
352 // Give the new component a parent.
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.
369 // Create the peer _after_ the component has been added, so that
370 // the peer gets to know about the component hierarchy.
373 // Notify the component that it has a new parent.
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
);
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
,
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
];
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
);
443 System
.arraycopy(component
, index
+ 1, component
, index
,
444 ncomponents
- index
- 1);
445 component
[--ncomponents
] = null;
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
,
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
)
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)
504 Component r
= component
[ncomponents
];
505 component
[ncomponents
] = null;
510 if (layoutMgr
!= null)
511 layoutMgr
.removeLayoutComponent(r
);
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.
521 = new ContainerEvent(this,
522 ContainerEvent
.COMPONENT_REMOVED
,
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
);
550 * Returns the current layout manager for this container.
552 * @return The layout manager for this container.
554 public LayoutManager
getLayout()
560 * Sets the layout manager for this container to the specified layout
563 * @param mgr The new layout manager for this container.
565 public void setLayout(LayoutManager mgr
)
573 * Layout the components in this container.
575 public void doLayout()
581 * Layout the components in this container.
583 * @deprecated use {@link #doLayout()} instead
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()
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 ())
619 cPeer
.beginValidate();
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();
649 * Recursively validates the container tree, recomputing any invalid
652 protected void validateTree()
656 ContainerPeer cPeer
= null;
657 if (peer
instanceof ContainerPeer
)
659 cPeer
= (ContainerPeer
) peer
;
664 for (int i
= 0; i
< ncomponents
; ++i
)
666 Component comp
= component
[i
];
668 if (comp
instanceof Container
&& ! (comp
instanceof Window
)
671 ((Container
) comp
).validateTree();
681 cPeer
= (ContainerPeer
) peer
;
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. */
693 public void setFont(Font f
)
695 Font oldFont
= getFont();
697 Font newFont
= getFont();
698 if (newFont
!= oldFont
&& (oldFont
== null || ! oldFont
.equals(newFont
)))
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
;
732 prefSize
= l
.preferredLayoutSize(this);
734 prefSize
= super.preferredSizeImpl();
739 return new Dimension(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
;
772 minSize
= l
.minimumLayoutSize(this);
774 minSize
= super.minimumSizeImpl();
779 return new Dimension(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);
802 maxSize
= super.maximumSizeImpl();
808 return new Dimension(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);
833 alignmentX
= super.getAlignmentX();
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);
857 alignmentY
= super.getAlignmentY();
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
868 * @param g - The graphics context for this paint job.
870 public void paint(Graphics g
)
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
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
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)
907 ComponentPeer p
= peer
;
908 if (! (p
instanceof LightweightPeer
))
910 g
.clearRect(0, 0, getWidth(), getHeight());
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
923 * @param g The graphics context for this print job.
925 public void print(Graphics 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
)
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
)
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
,
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
);
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>
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()
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
1021 * @param e The event to be processed.
1023 protected void processEvent(AWTEvent e
)
1025 if (e
instanceof ContainerEvent
)
1026 processContainerEvent((ContainerEvent
) e
);
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)
1043 case ContainerEvent
.COMPONENT_ADDED
:
1044 containerListener
.componentAdded(e
);
1047 case ContainerEvent
.COMPONENT_REMOVED
:
1048 containerListener
.componentRemoved(e
);
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 ();
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
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
)
1122 return isAncestorOf(component
);
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
))
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())
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())
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
))
1229 for (int i
= 0; i
< ncomponents
; ++i
)
1231 // Ignore invisible children...
1232 if (!component
[i
].isVisible())
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
);
1246 else if (component
[i
].contains(x2
, y2
))
1247 return component
[i
];
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
1279 public void addNotify()
1281 synchronized (getTreeLock())
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
];
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 ())
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
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
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
);
1421 parent
= parent
.getParent ();
1424 if (keystrokes
== null)
1425 keystrokes
= KeyboardFocusManager
.getCurrentKeyboardFocusManager ().
1426 getDefaultFocusTraversalKeys (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";
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";
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";
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";
1472 throw new IllegalArgumentException ();
1475 int i
= keystrokes
.size ();
1476 Iterator iter
= keystrokes
.iterator ();
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];
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
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.
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 ();
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.
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
1569 public boolean isFocusCycleRoot (Container c
)
1572 && isFocusCycleRoot ())
1575 Container ancestor
= getFocusCycleRootAncestor ();
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
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
1611 public FocusTraversalPolicy
getFocusTraversalPolicy ()
1613 if (!isFocusCycleRoot ())
1616 if (focusTraversalPolicy
== null)
1618 Container ancestor
= getFocusCycleRootAncestor ();
1620 if (ancestor
!= this && ancestor
!= null)
1621 return ancestor
.getFocusTraversalPolicy ();
1624 KeyboardFocusManager manager
= KeyboardFocusManager
.getCurrentKeyboardFocusManager ();
1626 return manager
.getDefaultFocusTraversalPolicy ();
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
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
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)
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()
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
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
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
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
);
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)
1797 public final void setComponentZOrder(Component comp
, int index
)
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 "
1804 if (comp
instanceof Window
)
1805 throw new IllegalArgumentException("comp must not be a Window");
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");
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
);
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)
1847 public final int getComponentZOrder(Component comp
)
1849 synchronized (getTreeLock())
1852 if (component
!= null)
1854 for (int i
= 0; i
< ncomponents
; i
++)
1856 if (component
[i
] == comp
)
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
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
);
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
,
1916 Rectangle bounds
= comp
.getBounds();
1918 if(!gfx
.hitClip(bounds
.x
,bounds
.y
, bounds
.width
, bounds
.height
))
1920 Graphics g2
= gfx
.create(bounds
.x
, bounds
.y
, bounds
.width
,
1924 g2
.setFont(comp
.getFont());
1925 visitor
.visit(comp
, g2
);
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.
1946 ComponentPeer p
= peer
;
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;
1986 return super.eventTypeEnabled(eventId
);
1989 // This is used to implement Component.transferFocus.
1990 Component
findNextFocusComponent(Component child
)
1992 synchronized (getTreeLock ())
1997 for (start
= 0; start
< ncomponents
; ++start
)
1999 if (component
[start
] == child
)
2003 // This special case lets us be sure to terminate.
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.
2023 return parent
.findNextFocusComponent(this);
2026 if (component
[j
] instanceof Container
)
2028 Component c
= component
[j
];
2029 c
= c
.findNextFocusComponent(null);
2033 else if (component
[j
].isFocusTraversable())
2034 return component
[j
];
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
,
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
;
2077 assert false : "Should not reach here";
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.
2101 for (int i
= 0; i
< getComponentCount(); i
++)
2103 Component child
= getComponent(i
);
2104 child
.fireHierarchyEvent(HierarchyEvent
.ANCESTOR_RESIZED
,
2110 for (int i
= 0; i
< getComponentCount(); i
++)
2112 Component child
= getComponent(i
);
2113 child
.fireHierarchyEvent(HierarchyEvent
.ANCESTOR_MOVED
,
2120 private void addNotifyContainerChildren()
2122 synchronized (getTreeLock ())
2124 for (int i
= ncomponents
; --i
>= 0; )
2126 component
[i
].addNotify();
2132 * Deserialize this Container:
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>
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 ();
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:
2167 * <li>Write to the stream the default serializable fields.</li>
2168 * <li>Write the list of serializable ContainerListeners as optional
2170 * <li>Write this Container's FocusTraversalPolicy as optional data.</li>
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
);
2183 s
.writeObject (null);
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
)
2207 static class GfxPrintVisitor
extends GfxVisitor
2209 public static final GfxVisitor INSTANCE
= new GfxPrintVisitor();
2211 public void visit(Component c
, Graphics gfx
)
2217 static class GfxPaintAllVisitor
extends GfxVisitor
2219 public static final GfxVisitor INSTANCE
= new GfxPaintAllVisitor();
2221 public void visit(Component c
, Graphics gfx
)
2227 static class GfxPrintAllVisitor
extends GfxVisitor
2229 public static final GfxVisitor INSTANCE
= new GfxPrintAllVisitor();
2231 public void visit(Component c
, Graphics gfx
)
2238 * This class provides accessibility support for subclasses of container.
2240 * @author Eric Blake (ebb9@email.byu.edu)
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 ())
2278 int i
= component
== null ?
0 : component
.length
;
2280 if (component
[i
] instanceof Accessible
)
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)
2299 while (i
>= 0 && ++index
< component
.length
)
2300 if (component
[index
] instanceof Accessible
)
2303 return (Accessible
) component
[index
];
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
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)
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
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
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