source: trunk/src/gcc/libjava/java/awt/Container.java@ 1389

Last change on this file since 1389 was 2, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 28.5 KB
Line 
1/* Copyright (C) 1999, 2000, 2002 Free Software Foundation
2
3This file is part of GNU Classpath.
4
5GNU Classpath is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 2, or (at your option)
8any later version.
9
10GNU Classpath is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with GNU Classpath; see the file COPYING. If not, write to the
17Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
1802111-1307 USA.
19
20Linking this library statically or dynamically with other modules is
21making a combined work based on this library. Thus, the terms and
22conditions of the GNU General Public License cover the whole
23combination.
24
25As a special exception, the copyright holders of this library give you
26permission to link this library with independent modules to produce an
27executable, regardless of the license terms of these independent
28modules, and to copy and distribute the resulting executable under
29terms of your choice, provided that you also meet, for each linked
30independent module, the terms and conditions of the license of that
31module. An independent module is a module which is not derived from
32or based on this library. If you modify this library, you may extend
33this exception to your version of the library, but you are not
34obligated to do so. If you do not wish to do so, delete this
35exception statement from your version. */
36
37package java.awt;
38
39import java.awt.event.*;
40import java.io.PrintStream;
41import java.io.PrintWriter;
42import java.util.EventListener;
43import java.awt.peer.ComponentPeer;
44import java.awt.peer.ContainerPeer;
45import java.awt.peer.LightweightPeer;
46
47/* A somewhat incomplete class. */
48
49public class Container extends Component
50{
51 /* Serialized fields from the serialization spec. */
52 int ncomponents;
53 Component[] component;
54 LayoutManager layoutMgr;
55 /* LightweightDispatcher dispatcher; */ // wtf?
56 Dimension maxSize;
57 int containerSerializedDataVersion;
58
59 /* Anything else is non-serializable, and should be declared "transient". */
60 transient ContainerListener containerListener;
61
62 /**
63 * Default constructor for subclasses.
64 */
65 public Container()
66 {
67 }
68
69 /**
70 * Returns the number of components in this container.
71 *
72 * @return The number of components in this container.
73 */
74 public int getComponentCount()
75 {
76 return ncomponents;
77 }
78
79 /**
80 * Returns the number of components in this container.
81 *
82 * @return The number of components in this container.
83 *
84 * @deprecated This method is deprecated in favor of
85 * <code>getComponentCount()</code>.
86 */
87 public int countComponents()
88 {
89 return ncomponents;
90 }
91
92 /**
93 * Returns the component at the specified index.
94 *
95 * @param index The index of the component to retrieve.
96 *
97 * @return The requested component.
98 *
99 * @exception ArrayIndexOutOfBoundsException If the specified index is not
100 * valid.
101 */
102 public Component getComponent (int n)
103 {
104 if (n < 0 || n >= ncomponents)
105 throw new ArrayIndexOutOfBoundsException("no such component");
106 return component[n];
107 }
108
109 /**
110 * Returns an array of the components in this container.
111 *
112 * @return The components in this container.
113 */
114 public Component[] getComponents()
115 {
116 Component[] result = new Component[ncomponents];
117 if (ncomponents > 0)
118 System.arraycopy(component, 0, result, 0, ncomponents);
119 return result;
120 }
121
122 /**
123 * Returns the insets for this container, which is the space used for
124 * borders, the margin, etc.
125 *
126 * @return The insets for this container.
127 */
128 public Insets getInsets()
129 {
130 if (peer == null)
131 return new Insets(0, 0, 0, 0);
132 return ((ContainerPeer) peer).getInsets();
133 }
134
135 /**
136 * Returns the insets for this container, which is the space used for
137 * borders, the margin, etc.
138 *
139 * @return The insets for this container.
140 *
141 * @deprecated This method is deprecated in favor of
142 * <code>getInsets()</code>.
143 */
144 public Insets insets()
145 {
146 return getInsets();
147 }
148
149 /**
150 * Adds the specified component to this container at the end of the
151 * component list.
152 *
153 * @param component The component to add to the container.
154 *
155 * @return The same component that was added.
156 */
157 public Component add (Component comp)
158 {
159 addImpl (comp, null, -1);
160 return comp;
161 }
162
163 /**
164 * Adds the specified component to the container at the end of the
165 * component list. This method should not be used. Instead, use
166 * <code>add(Component, Object</code>.
167 *
168 * @param name FIXME
169 * @param component The component to be added.
170 *
171 * @return The same component that was added.
172 */
173 public Component add (String name, Component comp)
174 {
175 addImpl (comp, name, -1);
176 return comp;
177 }
178
179 /**
180 * Adds the specified component to this container at the specified index
181 * in the component list.
182 *
183 * @param component The component to be added.
184 * @param index The index in the component list to insert this child
185 * at, or -1 to add at the end of the list.
186 *
187 * @return The same component that was added.
188 *
189 * @param throws ArrayIndexOutOfBounds If the specified index is invalid.
190 */
191 public Component add (Component comp, int index)
192 {
193 addImpl (comp, null, index);
194 return comp;
195 }
196
197 /**
198 * Adds the specified component to this container at the end of the
199 * component list. The layout manager will use the specified constraints
200 * when laying out this component.
201 *
202 * @param component The component to be added to this container.
203 * @param constraints The layout constraints for this component.
204 */
205 public void add (Component comp, Object constraints)
206 {
207 addImpl (comp, constraints, -1);
208 }
209
210 /**
211 * Adds the specified component to this container at the specified index
212 * in the component list. The layout manager will use the specified
213 * constraints when layout out this component.
214 *
215 * @param component The component to be added.
216 * @param constraints The layout constraints for this component.
217 * @param index The index in the component list to insert this child
218 * at, or -1 to add at the end of the list.
219 *
220 * @param throws ArrayIndexOutOfBounds If the specified index is invalid.
221 */
222 public void add (Component comp, Object constraints, int index)
223 {
224 addImpl (comp, constraints, index);
225 }
226
227 /**
228 * This method is called by all the <code>add()</code> methods to perform
229 * the actual adding of the component. Subclasses who wish to perform
230 * their own processing when a component is added should override this
231 * method. Any subclass doing this must call the superclass version of
232 * this method in order to ensure proper functioning of the container.
233 *
234 * @param component The component to be added.
235 * @param constraints The layout constraints for this component, or
236 * <code>null</code> if there are no constraints.
237 * @param index The index in the component list to insert this child
238 * at, or -1 to add at the end of the list.
239 *
240 * @param throws ArrayIndexOutOfBounds If the specified index is invalid.
241 */
242 protected void addImpl (Component comp, Object constraints, int index)
243 {
244 if (index > ncomponents
245 || (index < 0 && index != -1)
246 || comp instanceof Window
247 || (comp instanceof Container
248 && ((Container) comp).isAncestorOf (this)))
249 throw new IllegalArgumentException ();
250
251 // Reparent component, and make sure component is instantiated if
252 // we are.
253 if (comp.parent != null)
254 comp.parent.remove (comp);
255 comp.parent = this;
256 if (peer != null)
257 {
258 comp.addNotify ();
259
260 if (comp.isLightweight())
261 enableEvents(comp.eventMask);
262 }
263
264 invalidate ();
265
266 if (component == null)
267 component = new Component[4]; // FIXME, better initial size?
268
269 // This isn't the most efficient implementation. We could do less
270 // copying when growing the array. It probably doesn't matter.
271 if (ncomponents >= component.length)
272 {
273 int nl = component.length * 2;
274 Component[] c = new Component[nl];
275 System.arraycopy (component, 0, c, 0, ncomponents);
276 component = c;
277 }
278 if (index == -1)
279 component[ncomponents++] = comp;
280 else
281 {
282 System.arraycopy (component, index, component, index + 1,
283 ncomponents - index);
284 component[index] = comp;
285 ++ncomponents;
286 }
287
288 // Notify the layout manager.
289 if (layoutMgr != null)
290 {
291 if (layoutMgr instanceof LayoutManager2)
292 {
293 LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
294 lm2.addLayoutComponent (comp, constraints);
295 }
296 else if (constraints instanceof String)
297 layoutMgr.addLayoutComponent ((String) constraints, comp);
298 else
299 layoutMgr.addLayoutComponent (null, comp);
300 }
301
302 // Post event to notify of adding the container.
303 ContainerEvent ce = new ContainerEvent (this,
304 ContainerEvent.COMPONENT_ADDED,
305 comp);
306 getToolkit().getSystemEventQueue().postEvent(ce);
307 }
308
309 /**
310 * Removes the component at the specified index from this container.
311 *
312 * @param index The index of the component to remove.
313 */
314 public void remove (int index)
315 {
316 Component r = component[index];
317
318 r.removeNotify ();
319
320 System.arraycopy (component, index + 1, component, index,
321 ncomponents - index - 1);
322 component[--ncomponents] = null;
323
324 invalidate ();
325
326 if (layoutMgr != null)
327 layoutMgr.removeLayoutComponent (r);
328
329 // Post event to notify of adding the container.
330 ContainerEvent ce = new ContainerEvent (this,
331 ContainerEvent.COMPONENT_REMOVED,
332 r);
333 getToolkit().getSystemEventQueue().postEvent(ce);
334 }
335
336 /**
337 * Removes the specified component from this container.
338 *
339 * @return component The component to remove from this container.
340 */
341 public void remove (Component comp)
342 {
343 for (int i = 0; i < ncomponents; ++i)
344 {
345 if (component[i] == comp)
346 {
347 remove (i);
348 break;
349 }
350 }
351 }
352
353 /**
354 * Removes all components from this container.
355 */
356 public void removeAll()
357 {
358 while (ncomponents > 0)
359 remove (0);
360 }
361
362 /**
363 * Returns the current layout manager for this container.
364 *
365 * @return The layout manager for this container.
366 */
367 public LayoutManager getLayout()
368 {
369 return layoutMgr;
370 }
371
372 /**
373 * Sets the layout manager for this container to the specified layout
374 * manager.
375 *
376 * @param mgr The new layout manager for this container.
377 */
378 public void setLayout(LayoutManager mgr)
379 {
380 layoutMgr = mgr;
381 invalidate ();
382 }
383
384 /**
385 * Layout the components in this container.
386 */
387 public void doLayout()
388 {
389 if (layoutMgr != null)
390 layoutMgr.layoutContainer (this);
391 }
392
393 /**
394 * Layout the components in this container.
395 *
396 * @deprecated This method is deprecated in favor of
397 * <code>doLayout()</code>.
398 */
399 public void layout()
400 {
401 doLayout();
402 }
403
404 /**
405 * Invalidates this container to indicate that it (and all parent
406 * containers) need to be laid out.
407 */
408 public void invalidate()
409 {
410 super.invalidate ();
411 }
412
413 /**
414 * Re-lays out the components in this container.
415 */
416 public void validate()
417 {
418 // FIXME: use the tree lock?
419 synchronized (this)
420 {
421 if (! isValid ())
422 {
423 validateTree ();
424 }
425 }
426 }
427
428 /**
429 * Recursively validates the container tree, recomputing any invalid
430 * layouts.
431 */
432 protected void validateTree()
433 {
434 if (valid)
435 return;
436
437 ContainerPeer cPeer = null;
438 if ((peer != null) && !(peer instanceof LightweightPeer))
439 {
440 cPeer = (ContainerPeer) peer;
441 cPeer.beginValidate();
442 }
443
444 doLayout ();
445 for (int i = 0; i < ncomponents; ++i)
446 {
447 Component comp = component[i];
448 if (! comp.isValid ())
449 {
450 if (comp instanceof Container)
451 {
452 ((Container) comp).validateTree();
453 }
454 else
455 {
456 component[i].validate();
457 }
458 }
459 }
460
461 /* children will call invalidate() when they are layed out. It
462 is therefore imporant that valid is not set to true
463 before after the children has been layed out. */
464 valid = true;
465
466 if (cPeer != null)
467 cPeer.endValidate();
468 }
469
470 public void setFont(Font f)
471 {
472 super.setFont(f);
473 // FIXME, should invalidate all children with font == null
474 }
475
476 /**
477 * Returns the preferred size of this container.
478 *
479 * @return The preferred size of this container.
480 */
481 public Dimension getPreferredSize()
482 {
483 if (layoutMgr != null)
484 return layoutMgr.preferredLayoutSize (this);
485 else
486 return super.getPreferredSize ();
487 }
488
489 /**
490 * Returns the preferred size of this container.
491 *
492 * @return The preferred size of this container.
493 *
494 * @deprecated This method is deprecated in favor of
495 * <code>getPreferredSize()</code>.
496 */
497 public Dimension preferredSize()
498 {
499 return getPreferredSize();
500 }
501
502 /**
503 * Returns the minimum size of this container.
504 *
505 * @return The minimum size of this container.
506 */
507 public Dimension getMinimumSize()
508 {
509 if (layoutMgr != null)
510 return layoutMgr.minimumLayoutSize (this);
511 else
512 return super.getMinimumSize ();
513 }
514
515 /**
516 * Returns the minimum size of this container.
517 *
518 * @return The minimum size of this container.
519 *
520 * @deprecated This method is deprecated in favor of
521 * <code>getMinimumSize()</code>.
522 */
523 public Dimension minimumSize()
524 {
525 return getMinimumSize();
526 }
527
528 /**
529 * Returns the maximum size of this container.
530 *
531 * @return The maximum size of this container.
532 */
533 public Dimension getMaximumSize()
534 {
535 if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
536 {
537 LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
538 return lm2.maximumLayoutSize (this);
539 }
540 else
541 return super.getMaximumSize ();
542 }
543
544 /**
545 * Returns the preferred alignment along the X axis. This is a value
546 * between 0 and 1 where 0 represents alignment flush left and
547 * 1 means alignment flush right, and 0.5 means centered.
548 *
549 * @return The preferred alignment along the X axis.
550 */
551 public float getAlignmentX()
552 {
553 if (layoutMgr instanceof LayoutManager2)
554 {
555 LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
556 return lm2.getLayoutAlignmentX (this);
557 }
558 else
559 return super.getAlignmentX();
560 }
561
562 /**
563 * Returns the preferred alignment along the Y axis. This is a value
564 * between 0 and 1 where 0 represents alignment flush top and
565 * 1 means alignment flush bottom, and 0.5 means centered.
566 *
567 * @return The preferred alignment along the Y axis.
568 */
569 public float getAlignmentY()
570 {
571 if (layoutMgr instanceof LayoutManager2)
572 {
573 LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
574 return lm2.getLayoutAlignmentY (this);
575 }
576 else
577 return super.getAlignmentY();
578 }
579
580 /**
581 * Paints this container. The implementation of this method in this
582 * class forwards to any lightweight components in this container. If
583 * this method is subclassed, this method should still be invoked as
584 * a superclass method so that lightweight components are properly
585 * drawn.
586 *
587 * @param graphics The graphics context for this paint job.
588 */
589 public void paint(Graphics g)
590 {
591 if (!isShowing())
592 return;
593 super.paint(g);
594 visitChildren(g, GfxPaintVisitor.INSTANCE, true);
595 }
596
597 /**
598 * Perform a graphics operation on the children of this container.
599 * For each applicable child, the visitChild() method will be called
600 * to perform the graphics operation.
601 *
602 * @param gfx The graphics object that will be used to derive new
603 * graphics objects for the children.
604 *
605 * @param visitor Object encapsulating the graphics operation that
606 * should be performed.
607 *
608 * @param lightweightOnly If true, only lightweight components will
609 * be visited.
610 */
611 private void visitChildren(Graphics gfx, GfxVisitor visitor,
612 boolean lightweightOnly)
613 {
614 // FIXME: do locking
615
616 for (int i = 0; i < ncomponents; ++i)
617 {
618 Component comp = component[i];
619 boolean applicable = comp.isVisible()
620 && (comp.isLightweight() || !lightweightOnly);
621
622 if (applicable)
623 visitChild(gfx, visitor, comp);
624 }
625 }
626
627 /**
628 * Perform a graphics operation on a child. A translated and clipped
629 * graphics object will be created, and the visit() method of the
630 * visitor will be called to perform the operation.
631 *
632 * @param gfx The graphics object that will be used to derive new
633 * graphics objects for the child.
634 *
635 * @param visitor Object encapsulating the graphics operation that
636 * should be performed.
637 *
638 * @param comp The child component that should be visited.
639 */
640 private void visitChild(Graphics gfx, GfxVisitor visitor,
641 Component comp)
642 {
643 Rectangle bounds = comp.getBounds();
644 Rectangle clip = gfx.getClipBounds().intersection(bounds);
645
646 if (clip.isEmpty()) return;
647
648 Graphics gfx2 = gfx.create();
649 gfx2.setClip(clip.x, clip.y, clip.width, clip.height);
650 gfx2.translate(bounds.x, bounds.y);
651
652 visitor.visit(comp, gfx2);
653 }
654
655 /**
656 * Updates this container. The implementation of this method in this
657 * class forwards to any lightweight components in this container. If
658 * this method is subclassed, this method should still be invoked as
659 * a superclass method so that lightweight components are properly
660 * drawn.
661 *
662 * @param graphics The graphics context for this update.
663 */
664 public void update(Graphics g)
665 {
666 super.update(g);
667 }
668
669 /**
670 * Prints this container. The implementation of this method in this
671 * class forwards to any lightweight components in this container. If
672 * this method is subclassed, this method should still be invoked as
673 * a superclass method so that lightweight components are properly
674 * drawn.
675 *
676 * @param graphics The graphics context for this print job.
677 */
678 public void print(Graphics g)
679 {
680 super.print(g);
681 visitChildren(g, GfxPrintVisitor.INSTANCE, true);
682 }
683
684 /**
685 * Paints all of the components in this container.
686 *
687 * @param graphics The graphics context for this paint job.
688 */
689 public void paintComponents(Graphics g)
690 {
691 super.paint(g);
692 visitChildren(g, GfxPaintAllVisitor.INSTANCE, true);
693 }
694
695 /**
696 * Prints all of the components in this container.
697 *
698 * @param graphics The graphics context for this print job.
699 */
700 public void printComponents(Graphics g)
701 {
702 super.paint(g);
703 visitChildren(g, GfxPrintAllVisitor.INSTANCE, true);
704 }
705
706 void dispatchEventImpl(AWTEvent e)
707 {
708 if ((e.id <= ContainerEvent.CONTAINER_LAST
709 && e.id >= ContainerEvent.CONTAINER_FIRST)
710 && (containerListener != null
711 || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0))
712 processEvent(e);
713 else
714 super.dispatchEventImpl(e);
715 }
716
717 /**
718 * Adds the specified container listener to this object's list of
719 * container listeners.
720 *
721 * @param listener The listener to add.
722 */
723 public synchronized void addContainerListener(ContainerListener l)
724 {
725 containerListener = AWTEventMulticaster.add (containerListener, l);
726 }
727
728 /**
729 * Removes the specified container listener from this object's list of
730 * container listeners.
731 *
732 * @param listener The listener to remove.
733 */
734 public synchronized void removeContainerListener(ContainerListener l)
735 {
736 containerListener = AWTEventMulticaster.remove(containerListener, l);
737 }
738
739 /** @since 1.3 */
740 public EventListener[] getListeners(Class listenerType)
741 {
742 if (listenerType == ContainerListener.class)
743 return getListenersImpl(listenerType, containerListener);
744 else return super.getListeners(listenerType);
745 }
746
747 /**
748 * Processes the specified event. This method calls
749 * <code>processContainerEvent()</code> if this method is a
750 * <code>ContainerEvent</code>, otherwise it calls the superclass
751 * method.
752 *
753 * @param event The event to be processed.
754 */
755 protected void processEvent(AWTEvent e)
756 {
757 if (e instanceof ContainerEvent)
758 processContainerEvent((ContainerEvent) e);
759 else super.processEvent(e);
760 }
761
762 /**
763 * Called when a container event occurs if container events are enabled.
764 * This method calls any registered listeners.
765 *
766 * @param event The event that occurred.
767 */
768 protected void processContainerEvent(ContainerEvent e)
769 {
770 if (containerListener == null)
771 return;
772 switch (e.id)
773 {
774 case ContainerEvent.COMPONENT_ADDED:
775 containerListener.componentAdded(e);
776 break;
777
778 case ContainerEvent.COMPONENT_REMOVED:
779 containerListener.componentRemoved(e);
780 break;
781 }
782 }
783
784 /**
785 * AWT 1.0 event processor.
786 *
787 * @param event The event that occurred.
788 *
789 * @deprecated This method is deprecated in favor of
790 * <code>dispatchEvent()</code>.
791 */
792 public void deliverEvent(Event e)
793 {
794 }
795
796 /**
797 * Returns the component located at the specified point. This is done
798 * by checking whether or not a child component claims to contain this
799 * point. The first child component that does is returned. If no
800 * child component claims the point, the container itself is returned,
801 * unless the point does not exist within this container, in which
802 * case <code>null</code> is returned.
803 *
804 * @param x The X coordinate of the point.
805 * @param y The Y coordinate of the point.
806 *
807 * @return The component containing the specified point, or
808 * <code>null</code> if there is no such point.
809 */
810 public Component getComponentAt (int x, int y)
811 {
812 if (! contains (x, y))
813 return null;
814 for (int i = 0; i < ncomponents; ++i)
815 {
816 // Ignore invisible children...
817 if (!component[i].isVisible())
818 continue;
819
820 int x2 = x - component[i].x;
821 int y2 = y - component[i].y;
822 if (component[i].contains (x2, y2))
823 return component[i];
824 }
825 return this;
826 }
827
828 /**
829 * Returns the component located at the specified point. This is done
830 * by checking whether or not a child component claims to contain this
831 * point. The first child component that does is returned. If no
832 * child component claims the point, the container itself is returned,
833 * unless the point does not exist within this container, in which
834 * case <code>null</code> is returned.
835 *
836 * @param point The point to return the component at.
837 *
838 * @return The component containing the specified point, or <code>null</code>
839 * if there is no such point.
840 *
841 * @deprecated This method is deprecated in favor of
842 * <code>getComponentAt(int, int)</code>.
843 */
844 public Component locate(int x, int y)
845 {
846 return getComponentAt(x, y);
847 }
848
849 /**
850 * Returns the component located at the specified point. This is done
851 * by checking whether or not a child component claims to contain this
852 * point. The first child component that does is returned. If no
853 * child component claims the point, the container itself is returned,
854 * unless the point does not exist within this container, in which
855 * case <code>null</code> is returned.
856 *
857 * @param point The point to return the component at.
858 *
859 * @return The component containing the specified point, or <code>null</code>
860 * if there is no such point.
861 */
862 public Component getComponentAt(Point p)
863 {
864 return getComponentAt(p.x, p.y);
865 }
866
867 public Component findComponentAt (int x, int y)
868 {
869 if (! contains (x, y))
870 return null;
871
872 for (int i = 0; i < ncomponents; ++i)
873 {
874 // Ignore invisible children...
875 if (!component[i].isVisible())
876 continue;
877
878 int x2 = x - component[i].x;
879 int y2 = y - component[i].y;
880 // We don't do the contains() check right away because
881 // findComponentAt would redundantly do it first thing.
882 if (component[i] instanceof Container)
883 {
884 Container k = (Container) component[i];
885 Component r = k.findComponentAt (x2, y2);
886 if (r != null)
887 return r;
888 }
889 else if (component[i].contains (x2, y2))
890 return component[i];
891 }
892
893 return this;
894 }
895
896 public Component findComponentAt(Point p)
897 {
898 return findComponentAt(p.x, p.y);
899 }
900
901 /**
902 * Called when this container is added to another container to inform it
903 * to create its peer. Peers for any child components will also be
904 * created.
905 */
906 public void addNotify ()
907 {
908 addNotifyContainerChildren ();
909 super.addNotify();
910 }
911
912 private void addNotifyContainerChildren()
913 {
914 for (int i = ncomponents; --i >= 0; )
915 {
916 component[i].addNotify();
917 if (component[i].isLightweight())
918 enableEvents(component[i].eventMask);
919 }
920 }
921
922 /**
923 * Called when this container is removed from its parent container to
924 * inform it to destroy its peer. This causes the peers of all child
925 * component to be destroyed as well.
926 */
927 public void removeNotify()
928 {
929 for (int i = 0; i < ncomponents; ++i)
930 component[i].removeNotify ();
931 super.removeNotify();
932 }
933
934 /**
935 * Tests whether or not the specified component is contained within
936 * this components subtree.
937 *
938 * @param component The component to test.
939 *
940 * @return <code>true</code> if this container is an ancestor of the
941 * specified component, <code>false</code>.
942 */
943 public boolean isAncestorOf (Component comp)
944 {
945 for (;;)
946 {
947 if (comp == null)
948 return false;
949 if (comp == this)
950 return true;
951 comp = comp.getParent();
952 }
953 }
954
955 /**
956 * Returns a string representing the state of this container for
957 * debugging purposes.
958 *
959 * @return A string representing the state of this container.
960 */
961 protected String paramString()
962 {
963 String param = super.paramString();
964 if (layoutMgr != null)
965 param = param + "," + layoutMgr.getClass().getName();
966
967 return param;
968 }
969
970 /**
971 * Writes a listing of this container to the specified stream starting
972 * at the specified indentation point.
973 *
974 * @param stream The <code>PrintStream</code> to write to.
975 * @param indent The indentation point.
976 */
977 public void list (PrintStream out, int indent)
978 {
979 super.list (out, indent);
980 for (int i = 0; i < ncomponents; ++i)
981 component[i].list (out, indent + 2);
982 }
983
984 /**
985 * Writes a listing of this container to the specified stream starting
986 * at the specified indentation point.
987 *
988 * @param stream The <code>PrintWriter</code> to write to.
989 * @param indent The indentation point.
990 */
991 public void list(PrintWriter out, int indent)
992 {
993 super.list (out, indent);
994 for (int i = 0; i < ncomponents; ++i)
995 component[i].list (out, indent + 2);
996 }
997
998
999 /* The following classes are used in concert with the
1000 visitChildren() method to implement all the graphics operations
1001 that requires traversal of the containment hierarchy. */
1002
1003 abstract static class GfxVisitor
1004 {
1005 public abstract void visit(Component c, Graphics gfx);
1006 }
1007
1008 static class GfxPaintVisitor extends GfxVisitor
1009 {
1010 public void visit(Component c, Graphics gfx) { c.paint(gfx); }
1011 public static final GfxVisitor INSTANCE = new GfxPaintVisitor();
1012 }
1013
1014 static class GfxPrintVisitor extends GfxVisitor
1015 {
1016 public void visit(Component c, Graphics gfx) { c.print(gfx); }
1017 public static final GfxVisitor INSTANCE = new GfxPrintVisitor();
1018 }
1019
1020 static class GfxPaintAllVisitor extends GfxVisitor
1021 {
1022 public void visit(Component c, Graphics gfx) { c.paintAll(gfx); }
1023 public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor();
1024 }
1025
1026 static class GfxPrintAllVisitor extends GfxVisitor
1027 {
1028 public void visit(Component c, Graphics gfx) { c.printAll(gfx); }
1029 public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor();
1030 }
1031
1032 // This is used to implement Component.transferFocus.
1033 Component findNextFocusComponent (Component child)
1034 {
1035 int start, end;
1036 if (child != null)
1037 {
1038 for (start = 0; start < ncomponents; ++start)
1039 {
1040 if (component[start] == child)
1041 break;
1042 }
1043 end = start;
1044 // This special case lets us be sure to terminate.
1045 if (end == 0)
1046 end = ncomponents;
1047 ++start;
1048 }
1049 else
1050 {
1051 start = 0;
1052 end = ncomponents;
1053 }
1054
1055 for (int j = start; j != end; ++j)
1056 {
1057 if (j >= ncomponents)
1058 {
1059 // The JCL says that we should wrap here. However, that
1060 // seems wrong. To me it seems that focus order should be
1061 // global within in given window. So instead if we reach
1062 // the end we try to look in our parent, if we have one.
1063 if (parent != null)
1064 return parent.findNextFocusComponent (this);
1065 j -= ncomponents;
1066 }
1067 if (component[j] instanceof Container)
1068 {
1069 Component c = component[j];
1070 c = c.findNextFocusComponent (null);
1071 if (c != null)
1072 return c;
1073 }
1074 else if (component[j].isFocusTraversable ())
1075 return component[j];
1076 }
1077
1078 return null;
1079 }
1080}
Note: See TracBrowser for help on using the repository browser.