source: trunk/gcc/libjava/java/awt/Container.java

Last change on this file was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 38.4 KB
Line 
1/* Container.java -- parent container class in AWT
2 Copyright (C) 1999, 2000, 2002 Free Software Foundation
3
4This file is part of GNU Classpath.
5
6GNU Classpath is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Classpath is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Classpath; see the file COPYING. If not, write to the
18Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
1902111-1307 USA.
20
21Linking this library statically or dynamically with other modules is
22making a combined work based on this library. Thus, the terms and
23conditions of the GNU General Public License cover the whole
24combination.
25
26As a special exception, the copyright holders of this library give you
27permission to link this library with independent modules to produce an
28executable, regardless of the license terms of these independent
29modules, and to copy and distribute the resulting executable under
30terms of your choice, provided that you also meet, for each linked
31independent module, the terms and conditions of the license of that
32module. An independent module is a module which is not derived from
33or based on this library. If you modify this library, you may extend
34this exception to your version of the library, but you are not
35obligated to do so. If you do not wish to do so, delete this
36exception statement from your version. */
37
38package java.awt;
39
40import java.awt.event.AWTEventListener;
41import java.awt.event.ContainerEvent;
42import java.awt.event.ContainerListener;
43import java.awt.event.MouseEvent;
44import java.awt.peer.ComponentPeer;
45import java.awt.peer.ContainerPeer;
46import java.awt.peer.LightweightPeer;
47import java.beans.PropertyChangeListener;
48import java.io.PrintStream;
49import java.io.PrintWriter;
50import java.io.Serializable;
51import java.util.EventListener;
52import java.util.Set;
53import javax.accessibility.Accessible;
54
55/**
56 * A generic window toolkit object that acts as a container for other objects.
57 * Components are tracked in a list, and new elements are at the end of the
58 * list or bottom of the stacking order.
59 *
60 * @author original author unknown
61 * @author Eric Blake <ebb9@email.byu.edu>
62 *
63 * @since 1.0
64 *
65 * @status still missing 1.4 support
66 */
67public class Container extends Component
68{
69 /**
70 * Compatible with JDK 1.0+.
71 */
72 private static final long serialVersionUID = 4613797578919906343L;
73
74 /* Serialized fields from the serialization spec. */
75 int ncomponents;
76 Component[] component;
77 LayoutManager layoutMgr;
78
79 LightweightDispatcher dispatcher;
80
81 Dimension maxSize;
82
83 /**
84 * @since 1.4
85 */
86 boolean focusCycleRoot;
87
88 int containerSerializedDataVersion;
89
90 /* Anything else is non-serializable, and should be declared "transient". */
91 transient ContainerListener containerListener;
92
93 /**
94 * Default constructor for subclasses.
95 */
96 public Container()
97 {
98 }
99
100 /**
101 * Returns the number of components in this container.
102 *
103 * @return The number of components in this container.
104 */
105 public int getComponentCount()
106 {
107 return ncomponents;
108 }
109
110 /**
111 * Returns the number of components in this container.
112 *
113 * @return The number of components in this container.
114 *
115 * @deprecated use {@link #getComponentCount()} instead
116 */
117 public int countComponents()
118 {
119 return getComponentCount();
120 }
121
122 /**
123 * Returns the component at the specified index.
124 *
125 * @param index The index of the component to retrieve.
126 *
127 * @return The requested component.
128 *
129 * @throws ArrayIndexOutOfBoundsException If the specified index is invalid
130 */
131 public Component getComponent(int n)
132 {
133 synchronized (getTreeLock ())
134 {
135 if (n < 0 || n >= ncomponents)
136 throw new ArrayIndexOutOfBoundsException("no such component");
137
138 return component[n];
139 }
140 }
141
142 /**
143 * Returns an array of the components in this container.
144 *
145 * @return The components in this container.
146 */
147 public Component[] getComponents()
148 {
149 synchronized (getTreeLock ())
150 {
151 Component[] result = new Component[ncomponents];
152
153 if (ncomponents > 0)
154 System.arraycopy(component, 0, result, 0, ncomponents);
155
156 return result;
157 }
158 }
159
160 /**
161 * Returns the insets for this container, which is the space used for
162 * borders, the margin, etc.
163 *
164 * @return The insets for this container.
165 */
166 public Insets getInsets()
167 {
168 if (peer == null)
169 return new Insets(0, 0, 0, 0);
170
171 return ((ContainerPeer) peer).getInsets();
172 }
173
174 /**
175 * Returns the insets for this container, which is the space used for
176 * borders, the margin, etc.
177 *
178 * @return The insets for this container.
179 * @deprecated use {@link #getInsets()} instead
180 */
181 public Insets insets()
182 {
183 return getInsets();
184 }
185
186 /**
187 * Adds the specified component to this container at the end of the
188 * component list.
189 *
190 * @param component The component to add to the container.
191 *
192 * @return The same component that was added.
193 */
194 public Component add(Component comp)
195 {
196 addImpl(comp, null, -1);
197 return comp;
198 }
199
200 /**
201 * Adds the specified component to the container at the end of the
202 * component list. This method should not be used. Instead, use
203 * <code>add(Component, Object</code>.
204 *
205 * @param name The name of the component to be added.
206 * @param component The component to be added.
207 *
208 * @return The same component that was added.
209 */
210 public Component add(String name, Component comp)
211 {
212 addImpl(comp, name, -1);
213 return comp;
214 }
215
216 /**
217 * Adds the specified component to this container at the specified index
218 * in the component list.
219 *
220 * @param component The component to be added.
221 * @param index The index in the component list to insert this child
222 * at, or -1 to add at the end of the list.
223 *
224 * @return The same component that was added.
225 *
226 * @throws ArrayIndexOutOfBounds If the specified index is invalid.
227 */
228 public Component add(Component comp, int index)
229 {
230 addImpl(comp, null, index);
231 return comp;
232 }
233
234 /**
235 * Adds the specified component to this container at the end of the
236 * component list. The layout manager will use the specified constraints
237 * when laying out this component.
238 *
239 * @param component The component to be added to this container.
240 * @param constraints The layout constraints for this component.
241 */
242 public void add(Component comp, Object constraints)
243 {
244 addImpl(comp, constraints, -1);
245 }
246
247 /**
248 * Adds the specified component to this container at the specified index
249 * in the component list. The layout manager will use the specified
250 * constraints when layout out this component.
251 *
252 * @param component The component to be added.
253 * @param constraints The layout constraints for this component.
254 * @param index The index in the component list to insert this child
255 * at, or -1 to add at the end of the list.
256 *
257 * @throws ArrayIndexOutOfBounds If the specified index is invalid.
258 */
259 public void add(Component comp, Object constraints, int index)
260 {
261 addImpl(comp, constraints, index);
262 }
263
264 /**
265 * This method is called by all the <code>add()</code> methods to perform
266 * the actual adding of the component. Subclasses who wish to perform
267 * their own processing when a component is added should override this
268 * method. Any subclass doing this must call the superclass version of
269 * this method in order to ensure proper functioning of the container.
270 *
271 * @param component The component to be added.
272 * @param constraints The layout constraints for this component, or
273 * <code>null</code> if there are no constraints.
274 * @param index The index in the component list to insert this child
275 * at, or -1 to add at the end of the list.
276 *
277 * @throws ArrayIndexOutOfBounds If the specified index is invalid.
278 */
279 protected void addImpl(Component comp, Object constraints, int index)
280 {
281 synchronized (getTreeLock ())
282 {
283 if (index > ncomponents
284 || (index < 0 && index != -1)
285 || comp instanceof Window
286 || (comp instanceof Container
287 && ((Container) comp).isAncestorOf(this)))
288 throw new IllegalArgumentException();
289
290 // Reparent component, and make sure component is instantiated if
291 // we are.
292 if (comp.parent != null)
293 comp.parent.remove(comp);
294 comp.parent = this;
295 if (peer != null)
296 {
297 comp.addNotify();
298
299 if (comp.isLightweight())
300 enableEvents(comp.eventMask);
301 }
302
303 invalidate();
304
305 if (component == null)
306 component = new Component[4]; // FIXME, better initial size?
307
308 // This isn't the most efficient implementation. We could do less
309 // copying when growing the array. It probably doesn't matter.
310 if (ncomponents >= component.length)
311 {
312 int nl = component.length * 2;
313 Component[] c = new Component[nl];
314 System.arraycopy(component, 0, c, 0, ncomponents);
315 component = c;
316 }
317
318 if (index == -1)
319 component[ncomponents++] = comp;
320 else
321 {
322 System.arraycopy(component, index, component, index + 1,
323 ncomponents - index);
324 component[index] = comp;
325 ++ncomponents;
326 }
327
328 // Notify the layout manager.
329 if (layoutMgr != null)
330 {
331 if (layoutMgr instanceof LayoutManager2)
332 {
333 LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
334 lm2.addLayoutComponent(comp, constraints);
335 }
336 else if (constraints instanceof String)
337 layoutMgr.addLayoutComponent((String) constraints, comp);
338 else
339 layoutMgr.addLayoutComponent(null, comp);
340 }
341
342 // Post event to notify of adding the container.
343 ContainerEvent ce = new ContainerEvent(this,
344 ContainerEvent.COMPONENT_ADDED,
345 comp);
346 getToolkit().getSystemEventQueue().postEvent(ce);
347 }
348 }
349
350 /**
351 * Removes the component at the specified index from this container.
352 *
353 * @param index The index of the component to remove.
354 */
355 public void remove(int index)
356 {
357 synchronized (getTreeLock ())
358 {
359 Component r = component[index];
360
361 r.removeNotify();
362
363 System.arraycopy(component, index + 1, component, index,
364 ncomponents - index - 1);
365 component[--ncomponents] = null;
366
367 invalidate();
368
369 if (layoutMgr != null)
370 layoutMgr.removeLayoutComponent(r);
371
372 // Post event to notify of adding the container.
373 ContainerEvent ce = new ContainerEvent(this,
374 ContainerEvent.COMPONENT_REMOVED,
375 r);
376 getToolkit().getSystemEventQueue().postEvent(ce);
377 }
378 }
379
380 /**
381 * Removes the specified component from this container.
382 *
383 * @return component The component to remove from this container.
384 */
385 public void remove(Component comp)
386 {
387 synchronized (getTreeLock ())
388 {
389 for (int i = 0; i < ncomponents; ++i)
390 {
391 if (component[i] == comp)
392 {
393 remove(i);
394 break;
395 }
396 }
397 }
398 }
399
400 /**
401 * Removes all components from this container.
402 */
403 public void removeAll()
404 {
405 synchronized (getTreeLock ())
406 {
407 while (ncomponents > 0)
408 remove(0);
409 }
410 }
411
412 /**
413 * Returns the current layout manager for this container.
414 *
415 * @return The layout manager for this container.
416 */
417 public LayoutManager getLayout()
418 {
419 return layoutMgr;
420 }
421
422 /**
423 * Sets the layout manager for this container to the specified layout
424 * manager.
425 *
426 * @param mgr The new layout manager for this container.
427 */
428 public void setLayout(LayoutManager mgr)
429 {
430 layoutMgr = mgr;
431 invalidate();
432 }
433
434 /**
435 * Layout the components in this container.
436 */
437 public void doLayout()
438 {
439 if (layoutMgr != null)
440 layoutMgr.layoutContainer(this);
441 }
442
443 /**
444 * Layout the components in this container.
445 *
446 * @deprecated use {@link #doLayout()} instead
447 */
448 public void layout()
449 {
450 doLayout();
451 }
452
453 /**
454 * Invalidates this container to indicate that it (and all parent
455 * containers) need to be laid out.
456 */
457 public void invalidate()
458 {
459 super.invalidate();
460 }
461
462 /**
463 * Re-lays out the components in this container.
464 */
465 public void validate()
466 {
467 synchronized (getTreeLock ())
468 {
469 if (! isValid())
470 {
471 validateTree();
472 }
473 }
474 }
475
476 /**
477 * Recursively validates the container tree, recomputing any invalid
478 * layouts.
479 */
480 protected void validateTree()
481 {
482 if (valid)
483 return;
484
485 ContainerPeer cPeer = null;
486 if (peer != null && ! (peer instanceof LightweightPeer))
487 {
488 cPeer = (ContainerPeer) peer;
489 cPeer.beginValidate();
490 }
491
492 doLayout();
493 for (int i = 0; i < ncomponents; ++i)
494 {
495 Component comp = component[i];
496 if (! comp.isValid())
497 {
498 if (comp instanceof Container)
499 {
500 ((Container) comp).validateTree();
501 }
502 else
503 {
504 component[i].validate();
505 }
506 }
507 }
508
509 /* children will call invalidate() when they are layed out. It
510 is therefore imporant that valid is not set to true
511 before after the children has been layed out. */
512 valid = true;
513
514 if (cPeer != null)
515 cPeer.endValidate();
516 }
517
518 public void setFont(Font f)
519 {
520 super.setFont(f);
521 // FIXME, should invalidate all children with font == null
522 }
523
524 /**
525 * Returns the preferred size of this container.
526 *
527 * @return The preferred size of this container.
528 */
529 public Dimension getPreferredSize()
530 {
531 if (layoutMgr != null)
532 return layoutMgr.preferredLayoutSize(this);
533 else
534 return super.getPreferredSize();
535 }
536
537 /**
538 * Returns the preferred size of this container.
539 *
540 * @return The preferred size of this container.
541 *
542 * @deprecated use {@link #getPreferredSize()} instead
543 */
544 public Dimension preferredSize()
545 {
546 return getPreferredSize();
547 }
548
549 /**
550 * Returns the minimum size of this container.
551 *
552 * @return The minimum size of this container.
553 */
554 public Dimension getMinimumSize()
555 {
556 if (layoutMgr != null)
557 return layoutMgr.minimumLayoutSize(this);
558 else
559 return super.getMinimumSize();
560 }
561
562 /**
563 * Returns the minimum size of this container.
564 *
565 * @return The minimum size of this container.
566 *
567 * @deprecated use {@link #getMinimumSize()} instead
568 */
569 public Dimension minimumSize()
570 {
571 return getMinimumSize();
572 }
573
574 /**
575 * Returns the maximum size of this container.
576 *
577 * @return The maximum size of this container.
578 */
579 public Dimension getMaximumSize()
580 {
581 if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
582 {
583 LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
584 return lm2.maximumLayoutSize(this);
585 }
586 else
587 return super.getMaximumSize();
588 }
589
590 /**
591 * Returns the preferred alignment along the X axis. This is a value
592 * between 0 and 1 where 0 represents alignment flush left and
593 * 1 means alignment flush right, and 0.5 means centered.
594 *
595 * @return The preferred alignment along the X axis.
596 */
597 public float getAlignmentX()
598 {
599 if (layoutMgr instanceof LayoutManager2)
600 {
601 LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
602 return lm2.getLayoutAlignmentX(this);
603 }
604 else
605 return super.getAlignmentX();
606 }
607
608 /**
609 * Returns the preferred alignment along the Y axis. This is a value
610 * between 0 and 1 where 0 represents alignment flush top and
611 * 1 means alignment flush bottom, and 0.5 means centered.
612 *
613 * @return The preferred alignment along the Y axis.
614 */
615 public float getAlignmentY()
616 {
617 if (layoutMgr instanceof LayoutManager2)
618 {
619 LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
620 return lm2.getLayoutAlignmentY(this);
621 }
622 else
623 return super.getAlignmentY();
624 }
625
626 /**
627 * Paints this container. The implementation of this method in this
628 * class forwards to any lightweight components in this container. If
629 * this method is subclassed, this method should still be invoked as
630 * a superclass method so that lightweight components are properly
631 * drawn.
632 *
633 * @param graphics The graphics context for this paint job.
634 */
635 public void paint(Graphics g)
636 {
637 if (!isShowing())
638 return;
639 super.paint(g);
640 visitChildren(g, GfxPaintVisitor.INSTANCE, true);
641 }
642
643 /**
644 * Updates this container. The implementation of this method in this
645 * class forwards to any lightweight components in this container. If
646 * this method is subclassed, this method should still be invoked as
647 * a superclass method so that lightweight components are properly
648 * drawn.
649 *
650 * @param graphics The graphics context for this update.
651 */
652 public void update(Graphics g)
653 {
654 super.update(g);
655 }
656
657 /**
658 * Prints this container. The implementation of this method in this
659 * class forwards to any lightweight components in this container. If
660 * this method is subclassed, this method should still be invoked as
661 * a superclass method so that lightweight components are properly
662 * drawn.
663 *
664 * @param graphics The graphics context for this print job.
665 */
666 public void print(Graphics g)
667 {
668 super.print(g);
669 visitChildren(g, GfxPrintVisitor.INSTANCE, true);
670 }
671
672 /**
673 * Paints all of the components in this container.
674 *
675 * @param graphics The graphics context for this paint job.
676 */
677 public void paintComponents(Graphics g)
678 {
679 super.paint(g);
680 visitChildren(g, GfxPaintAllVisitor.INSTANCE, true);
681 }
682
683 /**
684 * Prints all of the components in this container.
685 *
686 * @param graphics The graphics context for this print job.
687 */
688 public void printComponents(Graphics g)
689 {
690 super.paint(g);
691 visitChildren(g, GfxPrintAllVisitor.INSTANCE, true);
692 }
693
694 /**
695 * Adds the specified container listener to this object's list of
696 * container listeners.
697 *
698 * @param listener The listener to add.
699 */
700 public synchronized void addContainerListener(ContainerListener l)
701 {
702 containerListener = AWTEventMulticaster.add(containerListener, l);
703 }
704
705 /**
706 * Removes the specified container listener from this object's list of
707 * container listeners.
708 *
709 * @param listener The listener to remove.
710 */
711 public synchronized void removeContainerListener(ContainerListener l)
712 {
713 containerListener = AWTEventMulticaster.remove(containerListener, l);
714 }
715
716 /**
717 * @since 1.4
718 */
719 public synchronized ContainerListener[] getContainerListeners()
720 {
721 return (ContainerListener[])
722 AWTEventMulticaster.getListeners(containerListener,
723 ContainerListener.class);
724 }
725
726 /**
727 * Returns an array of all the objects currently registered as FooListeners
728 * upon this Container. FooListeners are registered using the addFooListener
729 * method.
730 *
731 * @since 1.3
732 */
733 public EventListener[] getListeners(Class listenerType)
734 {
735 if (listenerType == ContainerListener.class)
736 return getContainerListeners();
737 return super.getListeners(listenerType);
738 }
739
740 /**
741 * Processes the specified event. This method calls
742 * <code>processContainerEvent()</code> if this method is a
743 * <code>ContainerEvent</code>, otherwise it calls the superclass
744 * method.
745 *
746 * @param event The event to be processed.
747 */
748 protected void processEvent(AWTEvent e)
749 {
750 if (e instanceof ContainerEvent)
751 processContainerEvent((ContainerEvent) e);
752 else
753 super.processEvent(e);
754 }
755
756 /**
757 * Called when a container event occurs if container events are enabled.
758 * This method calls any registered listeners.
759 *
760 * @param event The event that occurred.
761 */
762 protected void processContainerEvent(ContainerEvent e)
763 {
764 if (containerListener == null)
765 return;
766 switch (e.id)
767 {
768 case ContainerEvent.COMPONENT_ADDED:
769 containerListener.componentAdded(e);
770 break;
771
772 case ContainerEvent.COMPONENT_REMOVED:
773 containerListener.componentRemoved(e);
774 break;
775 }
776 }
777
778 /**
779 * AWT 1.0 event processor.
780 *
781 * @param event The event that occurred.
782 *
783 * @deprecated use {@link #dispatchEvent(AWTEvent)} instead
784 */
785 public void deliverEvent(Event e)
786 {
787 }
788
789 /**
790 * Returns the component located at the specified point. This is done
791 * by checking whether or not a child component claims to contain this
792 * point. The first child component that does is returned. If no
793 * child component claims the point, the container itself is returned,
794 * unless the point does not exist within this container, in which
795 * case <code>null</code> is returned.
796 *
797 * @param x The X coordinate of the point.
798 * @param y The Y coordinate of the point.
799 *
800 * @return The component containing the specified point, or
801 * <code>null</code> if there is no such point.
802 */
803 public Component getComponentAt(int x, int y)
804 {
805 synchronized (getTreeLock ())
806 {
807 if (! contains(x, y))
808 return null;
809 for (int i = 0; i < ncomponents; ++i)
810 {
811 // Ignore invisible children...
812 if (!component[i].isVisible())
813 continue;
814
815 int x2 = x - component[i].x;
816 int y2 = y - component[i].y;
817 if (component[i].contains(x2, y2))
818 return component[i];
819 }
820 return this;
821 }
822 }
823
824 /**
825 * Returns the component located at the specified point. This is done
826 * by checking whether or not a child component claims to contain this
827 * point. The first child component that does is returned. If no
828 * child component claims the point, the container itself is returned,
829 * unless the point does not exist within this container, in which
830 * case <code>null</code> is returned.
831 *
832 * @param point The point to return the component at.
833 *
834 * @return The component containing the specified point, or <code>null</code>
835 * if there is no such point.
836 *
837 * @deprecated use {@link #getComponentAt(int, int)} instead
838 */
839 public Component locate(int x, int y)
840 {
841 return getComponentAt(x, y);
842 }
843
844 /**
845 * Returns the component located at the specified point. This is done
846 * by checking whether or not a child component claims to contain this
847 * point. The first child component that does is returned. If no
848 * child component claims the point, the container itself is returned,
849 * unless the point does not exist within this container, in which
850 * case <code>null</code> is returned.
851 *
852 * @param point The point to return the component at.
853 * @return The component containing the specified point, or <code>null</code>
854 * if there is no such point.
855 */
856 public Component getComponentAt(Point p)
857 {
858 return getComponentAt(p.x, p.y);
859 }
860
861 public Component findComponentAt(int x, int y)
862 {
863 synchronized (getTreeLock ())
864 {
865 if (! contains(x, y))
866 return null;
867
868 for (int i = 0; i < ncomponents; ++i)
869 {
870 // Ignore invisible children...
871 if (!component[i].isVisible())
872 continue;
873
874 int x2 = x - component[i].x;
875 int y2 = y - component[i].y;
876 // We don't do the contains() check right away because
877 // findComponentAt would redundantly do it first thing.
878 if (component[i] instanceof Container)
879 {
880 Container k = (Container) component[i];
881 Component r = k.findComponentAt(x2, y2);
882 if (r != null)
883 return r;
884 }
885 else if (component[i].contains(x2, y2))
886 return component[i];
887 }
888
889 return this;
890 }
891 }
892
893 public Component findComponentAt(Point p)
894 {
895 return findComponentAt(p.x, p.y);
896 }
897
898 /**
899 * Called when this container is added to another container to inform it
900 * to create its peer. Peers for any child components will also be
901 * created.
902 */
903 public void addNotify()
904 {
905 addNotifyContainerChildren();
906 super.addNotify();
907 }
908
909 /**
910 * Called when this container is removed from its parent container to
911 * inform it to destroy its peer. This causes the peers of all child
912 * component to be destroyed as well.
913 */
914 public void removeNotify()
915 {
916 synchronized (getTreeLock ())
917 {
918 for (int i = 0; i < ncomponents; ++i)
919 component[i].removeNotify();
920 super.removeNotify();
921 }
922 }
923
924 /**
925 * Tests whether or not the specified component is contained within
926 * this components subtree.
927 *
928 * @param component The component to test.
929 *
930 * @return <code>true</code> if this container is an ancestor of the
931 * specified component, <code>false</code> otherwise.
932 */
933 public boolean isAncestorOf(Component comp)
934 {
935 synchronized (getTreeLock ())
936 {
937 while (true)
938 {
939 if (comp == null)
940 return false;
941 if (comp == this)
942 return true;
943 comp = comp.getParent();
944 }
945 }
946 }
947
948 /**
949 * Returns a string representing the state of this container for
950 * debugging purposes.
951 *
952 * @return A string representing the state of this container.
953 */
954 protected String paramString()
955 {
956 String param = super.paramString();
957 if (layoutMgr != null)
958 param = param + "," + layoutMgr.getClass().getName();
959
960 return param;
961 }
962
963 /**
964 * Writes a listing of this container to the specified stream starting
965 * at the specified indentation point.
966 *
967 * @param stream The <code>PrintStream</code> to write to.
968 * @param indent The indentation point.
969 */
970 public void list(PrintStream out, int indent)
971 {
972 synchronized (getTreeLock ())
973 {
974 super.list(out, indent);
975 for (int i = 0; i < ncomponents; ++i)
976 component[i].list(out, indent + 2);
977 }
978 }
979
980 /**
981 * Writes a listing of this container to the specified stream starting
982 * at the specified indentation point.
983 *
984 * @param stream The <code>PrintWriter</code> to write to.
985 * @param indent The indentation point.
986 */
987 public void list(PrintWriter out, int indent)
988 {
989 synchronized (getTreeLock ())
990 {
991 super.list(out, indent);
992 for (int i = 0; i < ncomponents; ++i)
993 component[i].list(out, indent + 2);
994 }
995 }
996
997 public void setFocusTraversalKeys(int id, Set keys)
998 {
999 if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1000 id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1001 id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1002 id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1003 throw new IllegalArgumentException ();
1004 }
1005
1006 public Set getFocusTraversalKeys(int id)
1007 {
1008 if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1009 id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1010 id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1011 id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1012 throw new IllegalArgumentException ();
1013
1014 return null;
1015 }
1016
1017 public boolean areFocusTraversalKeysSet(int id)
1018 {
1019 if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1020 id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1021 id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1022 id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1023 throw new IllegalArgumentException ();
1024
1025 return false;
1026 }
1027
1028 public boolean isFocusCycleRoot(Container c)
1029 {
1030 return false;
1031 }
1032
1033 public void transferFocusBackward()
1034 {
1035 }
1036
1037 public void setFocusTraversalPolicy(FocusTraversalPolicy policy)
1038 {
1039 }
1040
1041 public FocusTraversalPolicy getFocusTraversalPolicy()
1042 {
1043 return null;
1044 }
1045
1046 public boolean isFocusTraversalPolicySet()
1047 {
1048 return false;
1049 }
1050
1051 public void setFocusCycleRoot(boolean focusCycleRoot)
1052 {
1053 }
1054
1055 public boolean isFocusCycleRoot()
1056 {
1057 return false;
1058 }
1059
1060 public void transferFocusDownCycle()
1061 {
1062 }
1063
1064 public void applyComponentOrientation(ComponentOrientation o)
1065 {
1066 if (orientation == null)
1067 throw new NullPointerException ();
1068 }
1069
1070 public void addPropertyChangeListener(PropertyChangeListener l)
1071 {
1072 }
1073
1074 public void addPropertyChangeListener(String name, PropertyChangeListener l)
1075 {
1076 }
1077
1078 // Hidden helper methods.
1079
1080 /**
1081 * Perform a graphics operation on the children of this container.
1082 * For each applicable child, the visitChild() method will be called
1083 * to perform the graphics operation.
1084 *
1085 * @param gfx The graphics object that will be used to derive new
1086 * graphics objects for the children.
1087 *
1088 * @param visitor Object encapsulating the graphics operation that
1089 * should be performed.
1090 *
1091 * @param lightweightOnly If true, only lightweight components will
1092 * be visited.
1093 */
1094 private void visitChildren(Graphics gfx, GfxVisitor visitor,
1095 boolean lightweightOnly)
1096 {
1097 synchronized (getTreeLock ())
1098 {
1099 for (int i = 0; i < ncomponents; ++i)
1100 {
1101 Component comp = component[i];
1102 boolean applicable = comp.isVisible()
1103 && (comp.isLightweight() || !lightweightOnly);
1104
1105 if (applicable)
1106 visitChild(gfx, visitor, comp);
1107 }
1108 }
1109 }
1110
1111 /**
1112 * Perform a graphics operation on a child. A translated and clipped
1113 * graphics object will be created, and the visit() method of the
1114 * visitor will be called to perform the operation.
1115 *
1116 * @param gfx The graphics object that will be used to derive new
1117 * graphics objects for the child.
1118 *
1119 * @param visitor Object encapsulating the graphics operation that
1120 * should be performed.
1121 *
1122 * @param comp The child component that should be visited.
1123 */
1124 private void visitChild(Graphics gfx, GfxVisitor visitor,
1125 Component comp)
1126 {
1127 Rectangle bounds = comp.getBounds();
1128 Rectangle clip = gfx.getClipBounds().intersection(bounds);
1129
1130 if (clip.isEmpty()) return;
1131
1132 Graphics gfx2 = gfx.create();
1133 gfx2.setClip(clip.x, clip.y, clip.width, clip.height);
1134 gfx2.translate(bounds.x, bounds.y);
1135
1136 visitor.visit(comp, gfx2);
1137 }
1138
1139 void dispatchEventImpl(AWTEvent e)
1140 {
1141 if ((e.id <= ContainerEvent.CONTAINER_LAST
1142 && e.id >= ContainerEvent.CONTAINER_FIRST)
1143 && (containerListener != null
1144 || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0))
1145 processEvent(e);
1146 else
1147 super.dispatchEventImpl(e);
1148 }
1149
1150 // This is used to implement Component.transferFocus.
1151 Component findNextFocusComponent(Component child)
1152 {
1153 synchronized (getTreeLock ())
1154 {
1155 int start, end;
1156 if (child != null)
1157 {
1158 for (start = 0; start < ncomponents; ++start)
1159 {
1160 if (component[start] == child)
1161 break;
1162 }
1163 end = start;
1164 // This special case lets us be sure to terminate.
1165 if (end == 0)
1166 end = ncomponents;
1167 ++start;
1168 }
1169 else
1170 {
1171 start = 0;
1172 end = ncomponents;
1173 }
1174
1175 for (int j = start; j != end; ++j)
1176 {
1177 if (j >= ncomponents)
1178 {
1179 // The JCL says that we should wrap here. However, that
1180 // seems wrong. To me it seems that focus order should be
1181 // global within in given window. So instead if we reach
1182 // the end we try to look in our parent, if we have one.
1183 if (parent != null)
1184 return parent.findNextFocusComponent(this);
1185 j -= ncomponents;
1186 }
1187 if (component[j] instanceof Container)
1188 {
1189 Component c = component[j];
1190 c = c.findNextFocusComponent(null);
1191 if (c != null)
1192 return c;
1193 }
1194 else if (component[j].isFocusTraversable())
1195 return component[j];
1196 }
1197
1198 return null;
1199 }
1200 }
1201
1202 private void addNotifyContainerChildren()
1203 {
1204 synchronized (getTreeLock ())
1205 {
1206 for (int i = ncomponents; --i >= 0; )
1207 {
1208 component[i].addNotify();
1209 if (component[i].isLightweight())
1210 enableEvents(component[i].eventMask);
1211 }
1212 }
1213 }
1214
1215 // Nested classes.
1216
1217 /* The following classes are used in concert with the
1218 visitChildren() method to implement all the graphics operations
1219 that requires traversal of the containment hierarchy. */
1220
1221 abstract static class GfxVisitor
1222 {
1223 public abstract void visit(Component c, Graphics gfx);
1224 }
1225
1226 static class GfxPaintVisitor extends GfxVisitor
1227 {
1228 public void visit(Component c, Graphics gfx) { c.paint(gfx); }
1229 public static final GfxVisitor INSTANCE = new GfxPaintVisitor();
1230 }
1231
1232 static class GfxPrintVisitor extends GfxVisitor
1233 {
1234 public void visit(Component c, Graphics gfx) { c.print(gfx); }
1235 public static final GfxVisitor INSTANCE = new GfxPrintVisitor();
1236 }
1237
1238 static class GfxPaintAllVisitor extends GfxVisitor
1239 {
1240 public void visit(Component c, Graphics gfx) { c.paintAll(gfx); }
1241 public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor();
1242 }
1243
1244 static class GfxPrintAllVisitor extends GfxVisitor
1245 {
1246 public void visit(Component c, Graphics gfx) { c.printAll(gfx); }
1247 public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor();
1248 }
1249
1250 /**
1251 * This class provides accessibility support for subclasses of container.
1252 *
1253 * @author Eric Blake <ebb9@email.byu.edu>
1254 *
1255 * @since 1.3
1256 */
1257 protected class AccessibleAWTContainer extends AccessibleAWTComponent
1258 {
1259 /**
1260 * Compatible with JDK 1.4+.
1261 */
1262 private static final long serialVersionUID = 5081320404842566097L;
1263
1264 /**
1265 * The handler to fire PropertyChange when children are added or removed.
1266 *
1267 * @serial the handler for property changes
1268 */
1269 protected ContainerListener accessibleContainerHandler
1270 = new AccessibleContainerHandler();
1271
1272 /**
1273 * The default constructor.
1274 */
1275 protected AccessibleAWTContainer()
1276 {
1277 Container.this.addContainerListener(accessibleContainerHandler);
1278 }
1279
1280 /**
1281 * Return the number of accessible children of the containing accessible
1282 * object (at most the total number of its children).
1283 *
1284 * @return the number of accessible children
1285 */
1286 public int getAccessibleChildrenCount()
1287 {
1288 synchronized (getTreeLock ())
1289 {
1290 int count = 0;
1291 int i = component == null ? 0 : component.length;
1292 while (--i >= 0)
1293 if (component[i] instanceof Accessible)
1294 count++;
1295 return count;
1296 }
1297 }
1298
1299 /**
1300 * Return the nth accessible child of the containing accessible object.
1301 *
1302 * @param i the child to grab, zero-based
1303 * @return the accessible child, or null
1304 */
1305 public Accessible getAccessibleChild(int i)
1306 {
1307 synchronized (getTreeLock ())
1308 {
1309 if (component == null)
1310 return null;
1311 int index = -1;
1312 while (i >= 0 && ++index < component.length)
1313 if (component[index] instanceof Accessible)
1314 i--;
1315 if (i < 0)
1316 return (Accessible) component[index];
1317 return null;
1318 }
1319 }
1320
1321 /**
1322 * Return the accessible child located at point (in the parent's
1323 * coordinates), if one exists.
1324 *
1325 * @param p the point to look at
1326 *
1327 * @return an accessible object at that point, or null
1328 *
1329 * @throws NullPointerException if p is null
1330 */
1331 public Accessible getAccessibleAt(Point p)
1332 {
1333 Component c = getComponentAt(p.x, p.y);
1334 return c != Container.this && c instanceof Accessible ? (Accessible) c
1335 : null;
1336 }
1337
1338 /**
1339 * This class fires a <code>PropertyChange</code> listener, if registered,
1340 * when children are added or removed from the enclosing accessible object.
1341 *
1342 * @author Eric Blake <ebb9@email.byu.edu>
1343 *
1344 * @since 1.3
1345 */
1346 protected class AccessibleContainerHandler implements ContainerListener
1347 {
1348 /**
1349 * Default constructor.
1350 */
1351 protected AccessibleContainerHandler()
1352 {
1353 }
1354
1355 /**
1356 * Fired when a component is added; forwards to the PropertyChange
1357 * listener.
1358 *
1359 * @param e the container event for adding
1360 */
1361 public void componentAdded(ContainerEvent e)
1362 {
1363 AccessibleAWTContainer.this.firePropertyChange
1364 (ACCESSIBLE_CHILD_PROPERTY, null, e.getChild());
1365 }
1366
1367 /**
1368 * Fired when a component is removed; forwards to the PropertyChange
1369 * listener.
1370 *
1371 * @param e the container event for removing
1372 */
1373 public void componentRemoved(ContainerEvent e)
1374 {
1375 AccessibleAWTContainer.this.firePropertyChange
1376 (ACCESSIBLE_CHILD_PROPERTY, e.getChild(), null);
1377 }
1378 } // class AccessibleContainerHandler
1379 } // class AccessibleAWTPanel
1380} // class Container
1381
1382/**
1383 * Undocumented helper class.
1384 * STUBBED
1385 */
1386class LightweightDispatcher implements Serializable, AWTEventListener
1387{
1388 private static final long serialVersionUID = 5184291520170872969L;
1389 private Container nativeContainer;
1390 private Component focus;
1391 private transient Component mouseEventTarget;
1392 private transient Component targetLastEntered;
1393 private transient boolean isMouseInNativeContainer;
1394 private Cursor nativeCursor;
1395 private long eventMask;
1396
1397 LightweightDispatcher(Container c)
1398 {
1399 }
1400
1401 void dispose()
1402 {
1403 }
1404
1405 void enableEvents(long l)
1406 {
1407 }
1408
1409 boolean dispatchEvent(AWTEvent e)
1410 {
1411 return true;
1412 }
1413
1414 boolean isMouseGrab(MouseEvent e)
1415 {
1416 return true;
1417 }
1418
1419 boolean processMouseEvent(MouseEvent e)
1420 {
1421 return true;
1422 }
1423
1424 void trackMouseEnterExit(Component c, MouseEvent e)
1425 {
1426 }
1427
1428 void startListeningForOtherDrags()
1429 {
1430 }
1431
1432 void stopListeningForOtherDrags()
1433 {
1434 }
1435
1436 public void eventDispatched(AWTEvent e)
1437 {
1438 }
1439
1440 void retargetMouseEvent(Component c, int i, MouseEvent e)
1441 {
1442 }
1443} // class LightweightDispatcher
Note: See TracBrowser for help on using the repository browser.