OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [java/] [awt/] [Container.java] - Blame information for rev 791

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 771 jeremybenn
/* Container.java -- parent container class in AWT
2
   Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006
3
   Free Software Foundation
4
 
5
This file is part of GNU Classpath.
6
 
7
GNU Classpath is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
10
any later version.
11
 
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.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GNU Classpath; see the file COPYING.  If not, write to the
19
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
02110-1301 USA.
21
 
22
Linking this library statically or dynamically with other modules is
23
making a combined work based on this library.  Thus, the terms and
24
conditions of the GNU General Public License cover the whole
25
combination.
26
 
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. */
38
 
39
 
40
package java.awt;
41
 
42
import gnu.java.lang.CPStringBuilder;
43
 
44
import java.awt.event.ContainerEvent;
45
import java.awt.event.ContainerListener;
46
import java.awt.event.HierarchyEvent;
47
import java.awt.event.KeyEvent;
48
import java.awt.event.MouseEvent;
49
import java.awt.peer.ComponentPeer;
50
import java.awt.peer.ContainerPeer;
51
import java.awt.peer.LightweightPeer;
52
import java.beans.PropertyChangeListener;
53
import java.io.IOException;
54
import java.io.ObjectInputStream;
55
import java.io.ObjectOutputStream;
56
import java.io.PrintStream;
57
import java.io.PrintWriter;
58
import java.io.Serializable;
59
import java.util.Collections;
60
import java.util.EventListener;
61
import java.util.HashSet;
62
import java.util.Iterator;
63
import java.util.Set;
64
 
65
import javax.accessibility.Accessible;
66
 
67
/**
68
 * A generic window toolkit object that acts as a container for other objects.
69
 * Components are tracked in a list, and new elements are at the end of the
70
 * list or bottom of the stacking order.
71
 *
72
 * @author original author unknown
73
 * @author Eric Blake (ebb9@email.byu.edu)
74
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
75
 *
76
 * @since 1.0
77
 *
78
 * @status still missing 1.4 support, some generics from 1.5
79
 */
80
public class Container extends Component
81
{
82
  /**
83
   * Compatible with JDK 1.0+.
84
   */
85
  private static final long serialVersionUID = 4613797578919906343L;
86
 
87
  /* Serialized fields from the serialization spec. */
88
  int ncomponents;
89
  Component[] component;
90
  LayoutManager layoutMgr;
91
 
92
  /**
93
   * @since 1.4
94
   */
95
  boolean focusCycleRoot;
96
 
97
  /**
98
   * Indicates if this container provides a focus traversal policy.
99
   *
100
   * @since 1.5
101
   */
102
  private boolean focusTraversalPolicyProvider;
103
 
104
  int containerSerializedDataVersion;
105
 
106
  /* Anything else is non-serializable, and should be declared "transient". */
107
  transient ContainerListener containerListener;
108
 
109
  /** The focus traversal policy that determines how focus is
110
      transferred between this Container and its children. */
111
  private FocusTraversalPolicy focusTraversalPolicy;
112
 
113
  /**
114
   * The focus traversal keys, if not inherited from the parent or default
115
   * keyboard manager. These sets will contain only AWTKeyStrokes that
116
   * represent press and release events to use as focus control.
117
   *
118
   * @see #getFocusTraversalKeys(int)
119
   * @see #setFocusTraversalKeys(int, Set)
120
   * @since 1.4
121
   */
122
  transient Set[] focusTraversalKeys;
123
 
124
  /**
125
   * Default constructor for subclasses.
126
   */
127
  public Container()
128
  {
129
    // Nothing to do here.
130
  }
131
 
132
  /**
133
   * Returns the number of components in this container.
134
   *
135
   * @return The number of components in this container.
136
   */
137
  public int getComponentCount()
138
  {
139
    return countComponents ();
140
  }
141
 
142
  /**
143
   * Returns the number of components in this container.
144
   *
145
   * @return The number of components in this container.
146
   *
147
   * @deprecated use {@link #getComponentCount()} instead
148
   */
149
  public int countComponents()
150
  {
151
    return ncomponents;
152
  }
153
 
154
  /**
155
   * Returns the component at the specified index.
156
   *
157
   * @param n The index of the component to retrieve.
158
   *
159
   * @return The requested component.
160
   *
161
   * @throws ArrayIndexOutOfBoundsException If the specified index is invalid
162
   */
163
  public Component getComponent(int n)
164
  {
165
    synchronized (getTreeLock ())
166
      {
167
        if (n < 0 || n >= ncomponents)
168
          throw new ArrayIndexOutOfBoundsException("no such component");
169
 
170
        return component[n];
171
      }
172
  }
173
 
174
  /**
175
   * Returns an array of the components in this container.
176
   *
177
   * @return The components in this container.
178
   */
179
  public Component[] getComponents()
180
  {
181
    synchronized (getTreeLock ())
182
      {
183
        Component[] result = new Component[ncomponents];
184
 
185
        if (ncomponents > 0)
186
          System.arraycopy(component, 0, result, 0, ncomponents);
187
 
188
        return result;
189
      }
190
  }
191
 
192
  /**
193
   * Returns the insets for this container, which is the space used for
194
   * borders, the margin, etc.
195
   *
196
   * @return The insets for this container.
197
   */
198
  public Insets getInsets()
199
  {
200
    return insets ();
201
  }
202
 
203
  /**
204
   * Returns the insets for this container, which is the space used for
205
   * borders, the margin, etc.
206
   *
207
   * @return The insets for this container.
208
   * @deprecated use {@link #getInsets()} instead
209
   */
210
  public Insets insets()
211
  {
212
    Insets i;
213
    if (peer == null || peer instanceof LightweightPeer)
214
      i = new Insets (0, 0, 0, 0);
215
    else
216
      i = ((ContainerPeer) peer).getInsets ();
217
    return i;
218
  }
219
 
220
  /**
221
   * Adds the specified component to this container at the end of the
222
   * component list.
223
   *
224
   * @param comp The component to add to the container.
225
   *
226
   * @return The same component that was added.
227
   */
228
  public Component add(Component comp)
229
  {
230
    addImpl(comp, null, -1);
231
    return comp;
232
  }
233
 
234
  /**
235
   * Adds the specified component to the container at the end of the
236
   * component list.  This method should not be used. Instead, use
237
   * <code>add(Component, Object)</code>.
238
   *
239
   * @param name The name of the component to be added.
240
   * @param comp The component to be added.
241
   *
242
   * @return The same component that was added.
243
   *
244
   * @see #add(Component,Object)
245
   */
246
  public Component add(String name, Component comp)
247
  {
248
    addImpl(comp, name, -1);
249
    return comp;
250
  }
251
 
252
  /**
253
   * Adds the specified component to this container at the specified index
254
   * in the component list.
255
   *
256
   * @param comp The component to be added.
257
   * @param index The index in the component list to insert this child
258
   * at, or -1 to add at the end of the list.
259
   *
260
   * @return The same component that was added.
261
   *
262
   * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
263
   */
264
  public Component add(Component comp, int index)
265
  {
266
    addImpl(comp, null, index);
267
    return comp;
268
  }
269
 
270
  /**
271
   * Adds the specified component to this container at the end of the
272
   * component list.  The layout manager will use the specified constraints
273
   * when laying out this component.
274
   *
275
   * @param comp The component to be added to this container.
276
   * @param constraints The layout constraints for this component.
277
   */
278
  public void add(Component comp, Object constraints)
279
  {
280
    addImpl(comp, constraints, -1);
281
  }
282
 
283
  /**
284
   * Adds the specified component to this container at the specified index
285
   * in the component list.  The layout manager will use the specified
286
   * constraints when layout out this component.
287
   *
288
   * @param comp The component to be added.
289
   * @param constraints The layout constraints for this component.
290
   * @param index The index in the component list to insert this child
291
   * at, or -1 to add at the end of the list.
292
   *
293
   * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
294
   */
295
  public void add(Component comp, Object constraints, int index)
296
  {
297
    addImpl(comp, constraints, index);
298
  }
299
 
300
  /**
301
   * This method is called by all the <code>add()</code> methods to perform
302
   * the actual adding of the component.  Subclasses who wish to perform
303
   * their own processing when a component is added should override this
304
   * method.  Any subclass doing this must call the superclass version of
305
   * this method in order to ensure proper functioning of the container.
306
   *
307
   * @param comp The component to be added.
308
   * @param constraints The layout constraints for this component, or
309
   * <code>null</code> if there are no constraints.
310
   * @param index The index in the component list to insert this child
311
   * at, or -1 to add at the end of the list.
312
   *
313
   * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
314
   */
315
  protected void addImpl(Component comp, Object constraints, int index)
316
  {
317
    synchronized (getTreeLock ())
318
      {
319
        if (index > ncomponents
320
            || (index < 0 && index != -1)
321
            || comp instanceof Window
322
            || (comp instanceof Container
323
                && ((Container) comp).isAncestorOf(this)))
324
          throw new IllegalArgumentException();
325
 
326
        // Reparent component, and make sure component is instantiated if
327
        // we are.
328
        if (comp.parent != null)
329
          comp.parent.remove(comp);
330
 
331
        if (component == null)
332
          component = new Component[4]; // FIXME, better initial size?
333
 
334
        // This isn't the most efficient implementation.  We could do less
335
        // copying when growing the array.  It probably doesn't matter.
336
        if (ncomponents >= component.length)
337
          {
338
            int nl = component.length * 2;
339
            Component[] c = new Component[nl];
340
            System.arraycopy(component, 0, c, 0, ncomponents);
341
            component = c;
342
          }
343
 
344
        if (index == -1)
345
          component[ncomponents++] = comp;
346
        else
347
          {
348
            System.arraycopy(component, index, component, index + 1,
349
                             ncomponents - index);
350
            component[index] = comp;
351
            ++ncomponents;
352
          }
353
 
354
        // Give the new component a parent.
355
        comp.parent = this;
356
 
357
        // Update the counter for Hierarchy(Bounds)Listeners.
358
        int childHierarchyListeners = comp.numHierarchyListeners;
359
        if (childHierarchyListeners > 0)
360
          updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
361
                                       childHierarchyListeners);
362
        int childHierarchyBoundsListeners = comp.numHierarchyBoundsListeners;
363
        if (childHierarchyBoundsListeners > 0)
364
          updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
365
                                       childHierarchyListeners);
366
 
367
        // Invalidate the layout of this container.
368
        if (valid)
369
          invalidate();
370
 
371
        // Create the peer _after_ the component has been added, so that
372
        // the peer gets to know about the component hierarchy.
373
        if (peer != null)
374
          {
375
            // Notify the component that it has a new parent.
376
            comp.addNotify();
377
          }
378
 
379
        // Notify the layout manager.
380
        if (layoutMgr != null)
381
          {
382
            // If we have a LayoutManager2 the constraints are "real",
383
            // otherwise they are the "name" of the Component to add.
384
            if (layoutMgr instanceof LayoutManager2)
385
              {
386
                LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
387
                lm2.addLayoutComponent(comp, constraints);
388
              }
389
            else if (constraints instanceof String)
390
              layoutMgr.addLayoutComponent((String) constraints, comp);
391
            else
392
              layoutMgr.addLayoutComponent("", comp);
393
          }
394
 
395
        // We previously only sent an event when this container is showing.
396
        // Also, the event was posted to the event queue. A Mauve test shows
397
        // that this event is not delivered using the event queue and it is
398
        // also sent when the container is not showing.
399
        if (containerListener != null
400
            || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
401
          {
402
            ContainerEvent ce = new ContainerEvent(this,
403
                                                ContainerEvent.COMPONENT_ADDED,
404
                                                comp);
405
            dispatchEvent(ce);
406
          }
407
 
408
        // Notify hierarchy listeners.
409
        comp.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, comp,
410
                                this, HierarchyEvent.PARENT_CHANGED);
411
      }
412
  }
413
 
414
  /**
415
   * Removes the component at the specified index from this container.
416
   *
417
   * @param index The index of the component to remove.
418
   */
419
  public void remove(int index)
420
  {
421
    synchronized (getTreeLock ())
422
      {
423
        if (index < 0 || index >= ncomponents)
424
          throw new ArrayIndexOutOfBoundsException();
425
 
426
        Component r = component[index];
427
        if (peer != null)
428
          r.removeNotify();
429
 
430
        if (layoutMgr != null)
431
          layoutMgr.removeLayoutComponent(r);
432
 
433
        // Update the counter for Hierarchy(Bounds)Listeners.
434
        int childHierarchyListeners = r.numHierarchyListeners;
435
        if (childHierarchyListeners > 0)
436
          updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
437
                                       -childHierarchyListeners);
438
        int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners;
439
        if (childHierarchyBoundsListeners > 0)
440
          updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
441
                                       -childHierarchyListeners);
442
 
443
        r.parent = null;
444
 
445
        System.arraycopy(component, index + 1, component, index,
446
                         ncomponents - index - 1);
447
        component[--ncomponents] = null;
448
 
449
        if (valid)
450
          invalidate();
451
 
452
        if (containerListener != null
453
            || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
454
          {
455
            // Post event to notify of removing the component.
456
            ContainerEvent ce = new ContainerEvent(this,
457
                                              ContainerEvent.COMPONENT_REMOVED,
458
                                              r);
459
            dispatchEvent(ce);
460
          }
461
 
462
        // Notify hierarchy listeners.
463
        r.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r,
464
                             this, HierarchyEvent.PARENT_CHANGED);
465
      }
466
  }
467
 
468
  /**
469
   * Removes the specified component from this container.
470
   *
471
   * @param comp The component to remove from this container.
472
   */
473
  public void remove(Component comp)
474
  {
475
    synchronized (getTreeLock ())
476
      {
477
        for (int i = 0; i < ncomponents; ++i)
478
          {
479
            if (component[i] == comp)
480
              {
481
                remove(i);
482
                break;
483
              }
484
          }
485
      }
486
  }
487
 
488
  /**
489
   * Removes all components from this container.
490
   */
491
  public void removeAll()
492
  {
493
    synchronized (getTreeLock ())
494
      {
495
        // In order to allow the same bad tricks to be used as in RI
496
        // this code has to stay exactly that way: In a real-life app
497
        // a Container subclass implemented its own vector for
498
        // subcomponents, supplied additional addXYZ() methods
499
        // and overrode remove(int) and removeAll (the latter calling
500
        // super.removeAll() ).
501
        // By doing it this way, user code cannot prevent the correct
502
        // removal of components.
503
        while (ncomponents > 0)
504
          {
505
            ncomponents--;
506
            Component r = component[ncomponents];
507
            component[ncomponents] = null;
508
 
509
            if (peer != null)
510
              r.removeNotify();
511
 
512
            if (layoutMgr != null)
513
              layoutMgr.removeLayoutComponent(r);
514
 
515
            r.parent = null;
516
 
517
            // Send ContainerEvent if necessary.
518
            if (containerListener != null
519
                || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
520
              {
521
                // Post event to notify of removing the component.
522
                ContainerEvent ce
523
                  = new ContainerEvent(this,
524
                                       ContainerEvent.COMPONENT_REMOVED,
525
                                       r);
526
                dispatchEvent(ce);
527
              }
528
 
529
            // Update the counter for Hierarchy(Bounds)Listeners.
530
            int childHierarchyListeners = r.numHierarchyListeners;
531
            if (childHierarchyListeners > 0)
532
              updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
533
                                           -childHierarchyListeners);
534
            int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners;
535
            if (childHierarchyBoundsListeners > 0)
536
              updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
537
                                           -childHierarchyListeners);
538
 
539
 
540
            // Send HierarchyEvent if necessary.
541
            fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, this,
542
                               HierarchyEvent.PARENT_CHANGED);
543
 
544
          }
545
 
546
        if (valid)
547
          invalidate();
548
      }
549
  }
550
 
551
  /**
552
   * Returns the current layout manager for this container.
553
   *
554
   * @return The layout manager for this container.
555
   */
556
  public LayoutManager getLayout()
557
  {
558
    return layoutMgr;
559
  }
560
 
561
  /**
562
   * Sets the layout manager for this container to the specified layout
563
   * manager.
564
   *
565
   * @param mgr The new layout manager for this container.
566
   */
567
  public void setLayout(LayoutManager mgr)
568
  {
569
    layoutMgr = mgr;
570
    if (valid)
571
      invalidate();
572
  }
573
 
574
  /**
575
   * Layout the components in this container.
576
   */
577
  public void doLayout()
578
  {
579
    layout ();
580
  }
581
 
582
  /**
583
   * Layout the components in this container.
584
   *
585
   * @deprecated use {@link #doLayout()} instead
586
   */
587
  public void layout()
588
  {
589
    if (layoutMgr != null)
590
      layoutMgr.layoutContainer (this);
591
  }
592
 
593
  /**
594
   * Invalidates this container to indicate that it (and all parent
595
   * containers) need to be laid out.
596
   */
597
  public void invalidate()
598
  {
599
    super.invalidate();
600
    if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
601
      {
602
        LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
603
        lm2.invalidateLayout(this);
604
      }
605
  }
606
 
607
  /**
608
   * Re-lays out the components in this container.
609
   */
610
  public void validate()
611
  {
612
    ComponentPeer p = peer;
613
    if (! valid && p != null)
614
      {
615
        ContainerPeer cPeer = null;
616
        if (p instanceof ContainerPeer)
617
          cPeer = (ContainerPeer) peer;
618
        synchronized (getTreeLock ())
619
          {
620
            if (cPeer != null)
621
              cPeer.beginValidate();
622
            validateTree();
623
            valid = true;
624
            if (cPeer != null)
625
              cPeer.endValidate();
626
          }
627
      }
628
  }
629
 
630
  /**
631
   * Recursively invalidates the container tree.
632
   */
633
  private final void invalidateTree()
634
  {
635
    synchronized (getTreeLock())
636
      {
637
        for (int i = 0; i < ncomponents; i++)
638
          {
639
            Component comp = component[i];
640
            if (comp instanceof Container)
641
              ((Container) comp).invalidateTree();
642
            else if (comp.valid)
643
              comp.invalidate();
644
          }
645
        if (valid)
646
          invalidate();
647
      }
648
  }
649
 
650
  /**
651
   * Recursively validates the container tree, recomputing any invalid
652
   * layouts.
653
   */
654
  protected void validateTree()
655
  {
656
    if (!valid)
657
      {
658
        ContainerPeer cPeer = null;
659
        if (peer instanceof ContainerPeer)
660
          {
661
            cPeer = (ContainerPeer) peer;
662
            cPeer.beginLayout();
663
          }
664
 
665
        doLayout ();
666
        for (int i = 0; i < ncomponents; ++i)
667
          {
668
            Component comp = component[i];
669
 
670
            if (comp instanceof Container && ! (comp instanceof Window)
671
                && ! comp.valid)
672
              {
673
                ((Container) comp).validateTree();
674
              }
675
            else
676
              {
677
                comp.validate();
678
              }
679
          }
680
 
681
        if (cPeer != null)
682
          {
683
            cPeer = (ContainerPeer) peer;
684
            cPeer.endLayout();
685
          }
686
      }
687
 
688
    /* children will call invalidate() when they are layed out. It
689
       is therefore important that valid is not set to true
690
       until after the children have been layed out. */
691
    valid = true;
692
 
693
  }
694
 
695
  public void setFont(Font f)
696
  {
697
    Font oldFont = getFont();
698
    super.setFont(f);
699
    Font newFont = getFont();
700
    if (newFont != oldFont && (oldFont == null || ! oldFont.equals(newFont)))
701
      {
702
        invalidateTree();
703
      }
704
  }
705
 
706
  /**
707
   * Returns the preferred size of this container.
708
   *
709
   * @return The preferred size of this container.
710
   */
711
  public Dimension getPreferredSize()
712
  {
713
    return preferredSize ();
714
  }
715
 
716
  /**
717
   * Returns the preferred size of this container.
718
   *
719
   * @return The preferred size of this container.
720
   *
721
   * @deprecated use {@link #getPreferredSize()} instead
722
   */
723
  public Dimension preferredSize()
724
  {
725
    Dimension size = prefSize;
726
    // Try to return cached value if possible.
727
    if (size == null || !(prefSizeSet || valid))
728
      {
729
        // Need to lock here.
730
        synchronized (getTreeLock())
731
          {
732
            LayoutManager l = layoutMgr;
733
            if (l != null)
734
              prefSize = l.preferredLayoutSize(this);
735
            else
736
              prefSize = super.preferredSizeImpl();
737
            size = prefSize;
738
          }
739
      }
740
    if (size != null)
741
      return new Dimension(size);
742
    else
743
      return size;
744
  }
745
 
746
  /**
747
   * Returns the minimum size of this container.
748
   *
749
   * @return The minimum size of this container.
750
   */
751
  public Dimension getMinimumSize()
752
  {
753
    return minimumSize ();
754
  }
755
 
756
  /**
757
   * Returns the minimum size of this container.
758
   *
759
   * @return The minimum size of this container.
760
   *
761
   * @deprecated use {@link #getMinimumSize()} instead
762
   */
763
  public Dimension minimumSize()
764
  {
765
    Dimension size = minSize;
766
    // Try to return cached value if possible.
767
    if (size == null || !(minSizeSet || valid))
768
      {
769
        // Need to lock here.
770
        synchronized (getTreeLock())
771
          {
772
            LayoutManager l = layoutMgr;
773
            if (l != null)
774
              minSize = l.minimumLayoutSize(this);
775
            else
776
              minSize = super.minimumSizeImpl();
777
            size = minSize;
778
          }
779
      }
780
    if (size != null)
781
      return new Dimension(size);
782
    else
783
      return size;
784
  }
785
 
786
  /**
787
   * Returns the maximum size of this container.
788
   *
789
   * @return The maximum size of this container.
790
   */
791
  public Dimension getMaximumSize()
792
  {
793
    Dimension size = maxSize;
794
    // Try to return cached value if possible.
795
    if (size == null || !(maxSizeSet || valid))
796
      {
797
        // Need to lock here.
798
        synchronized (getTreeLock())
799
          {
800
            LayoutManager l = layoutMgr;
801
            if (l instanceof LayoutManager2)
802
              maxSize = ((LayoutManager2) l).maximumLayoutSize(this);
803
            else {
804
              maxSize = super.maximumSizeImpl();
805
            }
806
            size = maxSize;
807
          }
808
      }
809
    if (size != null)
810
      return new Dimension(size);
811
    else
812
      return size;
813
  }
814
 
815
  /**
816
   * Returns the preferred alignment along the X axis.  This is a value
817
   * between 0 and 1 where 0 represents alignment flush left and
818
   * 1 means alignment flush right, and 0.5 means centered.
819
   *
820
   * @return The preferred alignment along the X axis.
821
   */
822
  public float getAlignmentX()
823
  {
824
    LayoutManager layout = getLayout();
825
    float alignmentX = 0.0F;
826
    if (layout != null && layout instanceof LayoutManager2)
827
      {
828
        synchronized (getTreeLock())
829
          {
830
            LayoutManager2 lm2 = (LayoutManager2) layout;
831
            alignmentX = lm2.getLayoutAlignmentX(this);
832
          }
833
      }
834
    else
835
      alignmentX = super.getAlignmentX();
836
    return alignmentX;
837
  }
838
 
839
  /**
840
   * Returns the preferred alignment along the Y axis.  This is a value
841
   * between 0 and 1 where 0 represents alignment flush top and
842
   * 1 means alignment flush bottom, and 0.5 means centered.
843
   *
844
   * @return The preferred alignment along the Y axis.
845
   */
846
  public float getAlignmentY()
847
  {
848
    LayoutManager layout = getLayout();
849
    float alignmentY = 0.0F;
850
    if (layout != null && layout instanceof LayoutManager2)
851
      {
852
        synchronized (getTreeLock())
853
          {
854
            LayoutManager2 lm2 = (LayoutManager2) layout;
855
            alignmentY = lm2.getLayoutAlignmentY(this);
856
          }
857
      }
858
    else
859
      alignmentY = super.getAlignmentY();
860
    return alignmentY;
861
  }
862
 
863
  /**
864
   * Paints this container.  The implementation of this method in this
865
   * class forwards to any lightweight components in this container.  If
866
   * this method is subclassed, this method should still be invoked as
867
   * a superclass method so that lightweight components are properly
868
   * drawn.
869
   *
870
   * @param g - The graphics context for this paint job.
871
   */
872
  public void paint(Graphics g)
873
  {
874
    if (isShowing())
875
      {
876
        visitChildren(g, GfxPaintVisitor.INSTANCE, true);
877
      }
878
  }
879
 
880
  /**
881
   * Updates this container.  The implementation of this method in this
882
   * class forwards to any lightweight components in this container.  If
883
   * this method is subclassed, this method should still be invoked as
884
   * a superclass method so that lightweight components are properly
885
   * drawn.
886
   *
887
   * @param g The graphics context for this update.
888
   *
889
   * @specnote The specification suggests that this method forwards the
890
   *           update() call to all its lightweight children. Tests show
891
   *           that this is not done either in the JDK. The exact behaviour
892
   *           seems to be that the background is cleared in heavyweight
893
   *           Containers, and all other containers
894
   *           directly call paint(), causing the (lightweight) children to
895
   *           be painted.
896
   */
897
  public void update(Graphics g)
898
  {
899
    // It seems that the JDK clears the background of containers like Panel
900
    // and Window (within this method) but not of 'plain' Containers or
901
    // JComponents. This could
902
    // lead to the assumption that it only clears heavyweight containers.
903
    // However that is not quite true. In a test with a custom Container
904
    // that overrides isLightweight() to return false, the background is
905
    // also not cleared. So we do a check on !(peer instanceof LightweightPeer)
906
    // instead.
907
    if (isShowing())
908
      {
909
        ComponentPeer p = peer;
910
        if (! (p instanceof LightweightPeer))
911
          {
912
            g.clearRect(0, 0, getWidth(), getHeight());
913
          }
914
        paint(g);
915
      }
916
  }
917
 
918
  /**
919
   * Prints this container.  The implementation of this method in this
920
   * class forwards to any lightweight components in this container.  If
921
   * this method is subclassed, this method should still be invoked as
922
   * a superclass method so that lightweight components are properly
923
   * drawn.
924
   *
925
   * @param g The graphics context for this print job.
926
   */
927
  public void print(Graphics g)
928
  {
929
    super.print(g);
930
    visitChildren(g, GfxPrintVisitor.INSTANCE, true);
931
  }
932
 
933
  /**
934
   * Paints all of the components in this container.
935
   *
936
   * @param g The graphics context for this paint job.
937
   */
938
  public void paintComponents(Graphics g)
939
  {
940
    if (isShowing())
941
      visitChildren(g, GfxPaintAllVisitor.INSTANCE, false);
942
  }
943
 
944
  /**
945
   * Prints all of the components in this container.
946
   *
947
   * @param g The graphics context for this print job.
948
   */
949
  public void printComponents(Graphics g)
950
  {
951
    super.paint(g);
952
    visitChildren(g, GfxPrintAllVisitor.INSTANCE, true);
953
  }
954
 
955
  /**
956
   * Adds the specified container listener to this object's list of
957
   * container listeners.
958
   *
959
   * @param listener The listener to add.
960
   */
961
  public synchronized void addContainerListener(ContainerListener listener)
962
  {
963
    if (listener != null)
964
      {
965
        containerListener = AWTEventMulticaster.add(containerListener,
966
                                                    listener);
967
        newEventsOnly = true;
968
      }
969
  }
970
 
971
  /**
972
   * Removes the specified container listener from this object's list of
973
   * container listeners.
974
   *
975
   * @param listener The listener to remove.
976
   */
977
  public synchronized void removeContainerListener(ContainerListener listener)
978
  {
979
    containerListener = AWTEventMulticaster.remove(containerListener, listener);
980
  }
981
 
982
  /**
983
   * @since 1.4
984
   */
985
  public synchronized ContainerListener[] getContainerListeners()
986
  {
987
    return (ContainerListener[])
988
      AWTEventMulticaster.getListeners(containerListener,
989
                                       ContainerListener.class);
990
  }
991
 
992
  /**
993
   * Returns all registered {@link EventListener}s of the given
994
   * <code>listenerType</code>.
995
   *
996
   * @param listenerType the class of listeners to filter (<code>null</code>
997
   *                     not permitted).
998
   *
999
   * @return An array of registered listeners.
1000
   *
1001
   * @throws ClassCastException if <code>listenerType</code> does not implement
1002
   *                            the {@link EventListener} interface.
1003
   * @throws NullPointerException if <code>listenerType</code> is
1004
   *                              <code>null</code>.
1005
   *
1006
   * @see #getContainerListeners()
1007
   *
1008
   * @since 1.3
1009
   */
1010
  public <T extends EventListener> T[] getListeners(Class<T> listenerType)
1011
  {
1012
    if (listenerType == ContainerListener.class)
1013
      return (T[]) getContainerListeners();
1014
    return super.getListeners(listenerType);
1015
  }
1016
 
1017
  /**
1018
   * Processes the specified event.  This method calls
1019
   * <code>processContainerEvent()</code> if this method is a
1020
   * <code>ContainerEvent</code>, otherwise it calls the superclass
1021
   * method.
1022
   *
1023
   * @param e The event to be processed.
1024
   */
1025
  protected void processEvent(AWTEvent e)
1026
  {
1027
    if (e instanceof ContainerEvent)
1028
      processContainerEvent((ContainerEvent) e);
1029
    else
1030
      super.processEvent(e);
1031
  }
1032
 
1033
  /**
1034
   * Called when a container event occurs if container events are enabled.
1035
   * This method calls any registered listeners.
1036
   *
1037
   * @param e The event that occurred.
1038
   */
1039
  protected void processContainerEvent(ContainerEvent e)
1040
  {
1041
    if (containerListener == null)
1042
      return;
1043
    switch (e.id)
1044
      {
1045
      case ContainerEvent.COMPONENT_ADDED:
1046
        containerListener.componentAdded(e);
1047
        break;
1048
 
1049
      case ContainerEvent.COMPONENT_REMOVED:
1050
        containerListener.componentRemoved(e);
1051
        break;
1052
      }
1053
  }
1054
 
1055
  /**
1056
   * AWT 1.0 event processor.
1057
   *
1058
   * @param e The event that occurred.
1059
   *
1060
   * @deprecated use {@link #dispatchEvent(AWTEvent)} instead
1061
   */
1062
  public void deliverEvent(Event e)
1063
  {
1064
    if (!handleEvent (e))
1065
      {
1066
        synchronized (getTreeLock ())
1067
          {
1068
            Component parent = getParent ();
1069
 
1070
            if (parent != null)
1071
              parent.deliverEvent (e);
1072
          }
1073
      }
1074
  }
1075
 
1076
  /**
1077
   * Returns the component located at the specified point.  This is done
1078
   * by checking whether or not a child component claims to contain this
1079
   * point.  The first child component that does is returned.  If no
1080
   * child component claims the point, the container itself is returned,
1081
   * unless the point does not exist within this container, in which
1082
   * case <code>null</code> is returned.
1083
   *
1084
   * When components overlap, the first component is returned. The component
1085
   * that is closest to (x, y), containing that location, is returned.
1086
   * Heavyweight components take precedence of lightweight components.
1087
   *
1088
   * This function does not ignore invisible components. If there is an invisible
1089
   * component at (x,y), it will be returned.
1090
   *
1091
   * @param x The X coordinate of the point.
1092
   * @param y The Y coordinate of the point.
1093
   *
1094
   * @return The component containing the specified point, or
1095
   * <code>null</code> if there is no such point.
1096
   */
1097
  public Component getComponentAt(int x, int y)
1098
  {
1099
    return locate (x, y);
1100
  }
1101
 
1102
  /**
1103
   * Returns the mouse pointer position relative to this Container's
1104
   * top-left corner.  If allowChildren is false, the mouse pointer
1105
   * must be directly over this container.  If allowChildren is true,
1106
   * the mouse pointer may be over this container or any of its
1107
   * descendents.
1108
   *
1109
   * @param allowChildren true to allow descendents, false if pointer
1110
   * must be directly over Container.
1111
   *
1112
   * @return relative mouse pointer position
1113
   *
1114
   * @throws HeadlessException if in a headless environment
1115
   */
1116
  public Point getMousePosition(boolean allowChildren) throws HeadlessException
1117
  {
1118
    return super.getMousePositionHelper(allowChildren);
1119
  }
1120
 
1121
  boolean mouseOverComponent(Component component, boolean allowChildren)
1122
  {
1123
    if (allowChildren)
1124
      return isAncestorOf(component);
1125
    else
1126
      return component == this;
1127
  }
1128
 
1129
  /**
1130
   * Returns the component located at the specified point.  This is done
1131
   * by checking whether or not a child component claims to contain this
1132
   * point.  The first child component that does is returned.  If no
1133
   * child component claims the point, the container itself is returned,
1134
   * unless the point does not exist within this container, in which
1135
   * case <code>null</code> is returned.
1136
   *
1137
   * When components overlap, the first component is returned. The component
1138
   * that is closest to (x, y), containing that location, is returned.
1139
   * Heavyweight components take precedence of lightweight components.
1140
   *
1141
   * This function does not ignore invisible components. If there is an invisible
1142
   * component at (x,y), it will be returned.
1143
   *
1144
   * @param x The x position of the point to return the component at.
1145
   * @param y The y position of the point to return the component at.
1146
   *
1147
   * @return The component containing the specified point, or <code>null</code>
1148
   * if there is no such point.
1149
   *
1150
   * @deprecated use {@link #getComponentAt(int, int)} instead
1151
   */
1152
  public Component locate(int x, int y)
1153
  {
1154
    synchronized (getTreeLock ())
1155
      {
1156
        if (!contains (x, y))
1157
          return null;
1158
 
1159
        // First find the component closest to (x,y) that is a heavyweight.
1160
        for (int i = 0; i < ncomponents; ++i)
1161
          {
1162
            Component comp = component[i];
1163
            int x2 = x - comp.x;
1164
            int y2 = y - comp.y;
1165
            if (comp.contains (x2, y2) && !comp.isLightweight())
1166
              return comp;
1167
          }
1168
 
1169
        // if a heavyweight component is not found, look for a lightweight
1170
        // closest to (x,y).
1171
        for (int i = 0; i < ncomponents; ++i)
1172
          {
1173
            Component comp = component[i];
1174
            int x2 = x - comp.x;
1175
            int y2 = y - comp.y;
1176
            if (comp.contains (x2, y2) && comp.isLightweight())
1177
              return comp;
1178
          }
1179
 
1180
        return this;
1181
      }
1182
  }
1183
 
1184
  /**
1185
   * Returns the component located at the specified point.  This is done
1186
   * by checking whether or not a child component claims to contain this
1187
   * point.  The first child component that does is returned.  If no
1188
   * child component claims the point, the container itself is returned,
1189
   * unless the point does not exist within this container, in which
1190
   * case <code>null</code> is returned.
1191
   *
1192
   * The top-most child component is returned in the case where components overlap.
1193
   * This is determined by finding the component closest to (x,y) and contains
1194
   * that location. Heavyweight components take precedence of lightweight components.
1195
   *
1196
   * This function does not ignore invisible components. If there is an invisible
1197
   * component at (x,y), it will be returned.
1198
   *
1199
   * @param p The point to return the component at.
1200
   * @return The component containing the specified point, or <code>null</code>
1201
   * if there is no such point.
1202
   */
1203
  public Component getComponentAt(Point p)
1204
  {
1205
    return getComponentAt (p.x, p.y);
1206
  }
1207
 
1208
  /**
1209
   * Locates the visible child component that contains the specified position.
1210
   * The top-most child component is returned in the case where there is overlap
1211
   * in the components. If the containing child component is a Container,
1212
   * this method will continue searching for the deepest nested child
1213
   * component. Components which are not visible are ignored during the search.
1214
   *
1215
   * findComponentAt differs from getComponentAt, because it recursively
1216
   * searches a Container's children.
1217
   *
1218
   * @param x - x coordinate
1219
   * @param y - y coordinate
1220
   * @return null if the component does not contain the position.
1221
   * If there is no child component at the requested point and the point is
1222
   * within the bounds of the container the container itself is returned.
1223
   */
1224
  public Component findComponentAt(int x, int y)
1225
  {
1226
    synchronized (getTreeLock ())
1227
      {
1228
        if (! contains(x, y))
1229
          return null;
1230
 
1231
        for (int i = 0; i < ncomponents; ++i)
1232
          {
1233
            // Ignore invisible children...
1234
            if (!component[i].isVisible())
1235
              continue;
1236
 
1237
            int x2 = x - component[i].x;
1238
            int y2 = y - component[i].y;
1239
            // We don't do the contains() check right away because
1240
            // findComponentAt would redundantly do it first thing.
1241
            if (component[i] instanceof Container)
1242
              {
1243
                Container k = (Container) component[i];
1244
                Component r = k.findComponentAt(x2, y2);
1245
                if (r != null)
1246
                  return r;
1247
              }
1248
            else if (component[i].contains(x2, y2))
1249
              return component[i];
1250
          }
1251
 
1252
        return this;
1253
      }
1254
  }
1255
 
1256
  /**
1257
   * Locates the visible child component that contains the specified position.
1258
   * The top-most child component is returned in the case where there is overlap
1259
   * in the components. If the containing child component is a Container,
1260
   * this method will continue searching for the deepest nested child
1261
   * component. Components which are not visible are ignored during the search.
1262
   *
1263
   * findComponentAt differs from getComponentAt, because it recursively
1264
   * searches a Container's children.
1265
   *
1266
   * @param p - the component's location
1267
   * @return null if the component does not contain the position.
1268
   * If there is no child component at the requested point and the point is
1269
   * within the bounds of the container the container itself is returned.
1270
   */
1271
  public Component findComponentAt(Point p)
1272
  {
1273
    return findComponentAt(p.x, p.y);
1274
  }
1275
 
1276
  /**
1277
   * Called when this container is added to another container to inform it
1278
   * to create its peer.  Peers for any child components will also be
1279
   * created.
1280
   */
1281
  public void addNotify()
1282
  {
1283
    synchronized (getTreeLock())
1284
      {
1285
        super.addNotify();
1286
        addNotifyContainerChildren();
1287
      }
1288
  }
1289
 
1290
  /**
1291
   * Called when this container is removed from its parent container to
1292
   * inform it to destroy its peer.  This causes the peers of all child
1293
   * component to be destroyed as well.
1294
   */
1295
  public void removeNotify()
1296
  {
1297
    synchronized (getTreeLock ())
1298
      {
1299
        int ncomps = ncomponents;
1300
        Component[] comps = component;
1301
        for (int i = ncomps - 1; i >= 0; --i)
1302
          {
1303
            Component comp = comps[i];
1304
            if (comp != null)
1305
              comp.removeNotify();
1306
          }
1307
        super.removeNotify();
1308
      }
1309
  }
1310
 
1311
  /**
1312
   * Tests whether or not the specified component is contained within
1313
   * this components subtree.
1314
   *
1315
   * @param comp The component to test.
1316
   *
1317
   * @return <code>true</code> if this container is an ancestor of the
1318
   * specified component, <code>false</code> otherwise.
1319
   */
1320
  public boolean isAncestorOf(Component comp)
1321
  {
1322
    synchronized (getTreeLock ())
1323
      {
1324
        while (true)
1325
          {
1326
            if (comp == null)
1327
              return false;
1328
            comp = comp.getParent();
1329
            if (comp == this)
1330
              return true;
1331
          }
1332
      }
1333
  }
1334
 
1335
  /**
1336
   * Returns a string representing the state of this container for
1337
   * debugging purposes.
1338
   *
1339
   * @return A string representing the state of this container.
1340
   */
1341
  protected String paramString()
1342
  {
1343
    if (layoutMgr == null)
1344
      return super.paramString();
1345
 
1346
    CPStringBuilder sb = new CPStringBuilder();
1347
    sb.append(super.paramString());
1348
    sb.append(",layout=");
1349
    sb.append(layoutMgr.getClass().getName());
1350
    return sb.toString();
1351
  }
1352
 
1353
  /**
1354
   * Writes a listing of this container to the specified stream starting
1355
   * at the specified indentation point.
1356
   *
1357
   * @param out The <code>PrintStream</code> to write to.
1358
   * @param indent The indentation point.
1359
   */
1360
  public void list(PrintStream out, int indent)
1361
  {
1362
    synchronized (getTreeLock ())
1363
      {
1364
        super.list(out, indent);
1365
        for (int i = 0; i < ncomponents; ++i)
1366
          component[i].list(out, indent + 2);
1367
      }
1368
  }
1369
 
1370
  /**
1371
   * Writes a listing of this container to the specified stream starting
1372
   * at the specified indentation point.
1373
   *
1374
   * @param out The <code>PrintWriter</code> to write to.
1375
   * @param indent The indentation point.
1376
   */
1377
  public void list(PrintWriter out, int indent)
1378
  {
1379
    synchronized (getTreeLock ())
1380
      {
1381
        super.list(out, indent);
1382
        for (int i = 0; i < ncomponents; ++i)
1383
          component[i].list(out, indent + 2);
1384
      }
1385
  }
1386
 
1387
  /**
1388
   * Sets the focus traversal keys for a given traversal operation for this
1389
   * Container.
1390
   *
1391
   * @exception IllegalArgumentException If id is not one of
1392
   * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1393
   * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1394
   * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
1395
   * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS,
1396
   * or if keystrokes contains null, or if any Object in keystrokes is not an
1397
   * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event, or if any
1398
   * keystroke already maps to another focus traversal operation for this
1399
   * Container.
1400
   *
1401
   * @since 1.4
1402
   */
1403
  public void setFocusTraversalKeys(int id,
1404
                                    Set<? extends AWTKeyStroke> keystrokes)
1405
  {
1406
    if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1407
        id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1408
        id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1409
        id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1410
      throw new IllegalArgumentException ();
1411
 
1412
    if (keystrokes == null)
1413
      {
1414
        Container parent = getParent ();
1415
 
1416
        while (parent != null)
1417
          {
1418
            if (parent.areFocusTraversalKeysSet (id))
1419
              {
1420
                keystrokes = parent.getFocusTraversalKeys (id);
1421
                break;
1422
              }
1423
            parent = parent.getParent ();
1424
          }
1425
 
1426
        if (keystrokes == null)
1427
          keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager ().
1428
            getDefaultFocusTraversalKeys (id);
1429
      }
1430
 
1431
    Set sa;
1432
    Set sb;
1433
    Set sc;
1434
    String name;
1435
    switch (id)
1436
      {
1437
      case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
1438
        sa = getFocusTraversalKeys
1439
          (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
1440
        sb = getFocusTraversalKeys
1441
          (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
1442
        sc = getFocusTraversalKeys
1443
          (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1444
        name = "forwardFocusTraversalKeys";
1445
        break;
1446
      case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
1447
        sa = getFocusTraversalKeys
1448
          (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
1449
        sb = getFocusTraversalKeys
1450
          (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
1451
        sc = getFocusTraversalKeys
1452
          (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1453
        name = "backwardFocusTraversalKeys";
1454
        break;
1455
      case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS:
1456
        sa = getFocusTraversalKeys
1457
          (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
1458
        sb = getFocusTraversalKeys
1459
          (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
1460
        sc = getFocusTraversalKeys
1461
          (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1462
        name = "upCycleFocusTraversalKeys";
1463
        break;
1464
      case KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS:
1465
        sa = getFocusTraversalKeys
1466
          (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
1467
        sb = getFocusTraversalKeys
1468
          (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
1469
        sc = getFocusTraversalKeys
1470
          (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
1471
        name = "downCycleFocusTraversalKeys";
1472
        break;
1473
      default:
1474
        throw new IllegalArgumentException ();
1475
      }
1476
 
1477
    int i = keystrokes.size ();
1478
    Iterator iter = keystrokes.iterator ();
1479
 
1480
    while (--i >= 0)
1481
      {
1482
        Object o = iter.next ();
1483
        if (!(o instanceof AWTKeyStroke)
1484
            || sa.contains (o) || sb.contains (o) || sc.contains (o)
1485
            || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
1486
          throw new IllegalArgumentException ();
1487
      }
1488
 
1489
    if (focusTraversalKeys == null)
1490
      focusTraversalKeys = new Set[4];
1491
 
1492
    keystrokes =
1493
      Collections.unmodifiableSet(new HashSet<AWTKeyStroke>(keystrokes));
1494
    firePropertyChange (name, focusTraversalKeys[id], keystrokes);
1495
 
1496
    focusTraversalKeys[id] = keystrokes;
1497
  }
1498
 
1499
  /**
1500
   * Returns the Set of focus traversal keys for a given traversal operation for
1501
   * this Container.
1502
   *
1503
   * @exception IllegalArgumentException If id is not one of
1504
   * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1505
   * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1506
   * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
1507
   * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS.
1508
   *
1509
   * @since 1.4
1510
   */
1511
  public Set<AWTKeyStroke> getFocusTraversalKeys (int id)
1512
  {
1513
    if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1514
        id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1515
        id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1516
        id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1517
      throw new IllegalArgumentException ();
1518
 
1519
    Set s = null;
1520
 
1521
    if (focusTraversalKeys != null)
1522
      s = focusTraversalKeys[id];
1523
 
1524
    if (s == null && parent != null)
1525
      s = parent.getFocusTraversalKeys (id);
1526
 
1527
    return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager()
1528
                        .getDefaultFocusTraversalKeys(id)) : s;
1529
  }
1530
 
1531
  /**
1532
   * Returns whether the Set of focus traversal keys for the given focus
1533
   * traversal operation has been explicitly defined for this Container.
1534
   * If this method returns false, this Container is inheriting the Set from
1535
   * an ancestor, or from the current KeyboardFocusManager.
1536
   *
1537
   * @exception IllegalArgumentException If id is not one of
1538
   * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1539
   * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1540
   * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
1541
   * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS.
1542
   *
1543
   * @since 1.4
1544
   */
1545
  public boolean areFocusTraversalKeysSet (int id)
1546
  {
1547
    if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1548
        id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1549
        id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1550
        id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1551
      throw new IllegalArgumentException ();
1552
 
1553
    return focusTraversalKeys != null && focusTraversalKeys[id] != null;
1554
  }
1555
 
1556
  /**
1557
   * Check whether the given Container is the focus cycle root of this
1558
   * Container's focus traversal cycle.  If this Container is a focus
1559
   * cycle root itself, then it will be in two different focus cycles
1560
   * -- it's own, and that of its ancestor focus cycle root's.  In
1561
   * that case, if <code>c</code> is either of those containers, this
1562
   * method will return true.
1563
   *
1564
   * @param c the candidate Container
1565
   *
1566
   * @return true if c is the focus cycle root of the focus traversal
1567
   * cycle to which this Container belongs, false otherwise
1568
   *
1569
   * @since 1.4
1570
   */
1571
  public boolean isFocusCycleRoot (Container c)
1572
  {
1573
    if (this == c
1574
        && isFocusCycleRoot ())
1575
      return true;
1576
 
1577
    Container ancestor = getFocusCycleRootAncestor ();
1578
 
1579
    if (c == ancestor)
1580
      return true;
1581
 
1582
    return false;
1583
  }
1584
 
1585
  /**
1586
   * If this Container is a focus cycle root, set the focus traversal
1587
   * policy that determines the focus traversal order for its
1588
   * children.  If non-null, this policy will be inherited by all
1589
   * inferior focus cycle roots.  If <code>policy</code> is null, this
1590
   * Container will inherit its policy from the closest ancestor focus
1591
   * cycle root that's had its policy set.
1592
   *
1593
   * @param policy the new focus traversal policy for this Container or null
1594
   *
1595
   * @since 1.4
1596
   */
1597
  public void setFocusTraversalPolicy (FocusTraversalPolicy policy)
1598
  {
1599
    focusTraversalPolicy = policy;
1600
  }
1601
 
1602
  /**
1603
   * Return the focus traversal policy that determines the focus
1604
   * traversal order for this Container's children.  This method
1605
   * returns null if this Container is not a focus cycle root.  If the
1606
   * focus traversal policy has not been set explicitly, then this
1607
   * method will return an ancestor focus cycle root's policy instead.
1608
   *
1609
   * @return this Container's focus traversal policy or null
1610
   *
1611
   * @since 1.4
1612
   */
1613
  public FocusTraversalPolicy getFocusTraversalPolicy ()
1614
  {
1615
    if (!isFocusCycleRoot ())
1616
      return null;
1617
 
1618
    if (focusTraversalPolicy == null)
1619
      {
1620
        Container ancestor = getFocusCycleRootAncestor ();
1621
 
1622
        if (ancestor != this && ancestor !=  null)
1623
          return ancestor.getFocusTraversalPolicy ();
1624
        else
1625
          {
1626
            KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
1627
 
1628
            return manager.getDefaultFocusTraversalPolicy ();
1629
          }
1630
      }
1631
    else
1632
      return focusTraversalPolicy;
1633
  }
1634
 
1635
  /**
1636
   * Check whether this Container's focus traversal policy has been
1637
   * explicitly set.  If it has not, then this Container will inherit
1638
   * its focus traversal policy from one of its ancestor focus cycle
1639
   * roots.
1640
   *
1641
   * @return true if focus traversal policy is set, false otherwise
1642
  */
1643
  public boolean isFocusTraversalPolicySet ()
1644
  {
1645
    return focusTraversalPolicy == null;
1646
  }
1647
 
1648
  /**
1649
   * Set whether or not this Container is the root of a focus
1650
   * traversal cycle.  This Container's focus traversal policy
1651
   * determines the order of focus traversal.  Some policies prevent
1652
   * the focus from being transferred between two traversal cycles
1653
   * until an up or down traversal operation is performed.  In that
1654
   * case, normal traversal (not up or down) is limited to this
1655
   * Container and all of this Container's descendents that are not
1656
   * descendents of inferior focus cycle roots.  In the default case
1657
   * however, ContainerOrderFocusTraversalPolicy is in effect, and it
1658
   * supports implicit down-cycle traversal operations.
1659
   *
1660
   * @param focusCycleRoot true if this is a focus cycle root, false otherwise
1661
   *
1662
   * @since 1.4
1663
   */
1664
  public void setFocusCycleRoot (boolean focusCycleRoot)
1665
  {
1666
    this.focusCycleRoot = focusCycleRoot;
1667
  }
1668
 
1669
  /**
1670
   * Set to <code>true</code> if this container provides a focus traversal
1671
   * policy, <code>false</code> when the root container's focus
1672
   * traversal policy should be used.
1673
   *
1674
   * @return <code>true</code> if this container provides a focus traversal
1675
   *        policy, <code>false</code> when the root container's focus
1676
   *        traversal policy should be used
1677
   *
1678
   * @see #setFocusTraversalPolicyProvider(boolean)
1679
   *
1680
   * @since 1.5
1681
   */
1682
  public final boolean isFocusTraversalPolicyProvider()
1683
  {
1684
    return focusTraversalPolicyProvider;
1685
  }
1686
 
1687
  /**
1688
   * Set to <code>true</code> if this container provides a focus traversal
1689
   * policy, <code>false</code> when the root container's focus
1690
   * traversal policy should be used.
1691
   *
1692
   * @param b <code>true</code> if this container provides a focus traversal
1693
   *        policy, <code>false</code> when the root container's focus
1694
   *        traversal policy should be used
1695
   *
1696
   * @see #isFocusTraversalPolicyProvider()
1697
   *
1698
   * @since 1.5
1699
   */
1700
  public final void setFocusTraversalPolicyProvider(boolean b)
1701
  {
1702
    focusTraversalPolicyProvider = b;
1703
  }
1704
 
1705
  /**
1706
   * Check whether this Container is a focus cycle root.
1707
   *
1708
   * @return true if this is a focus cycle root, false otherwise
1709
   *
1710
   * @since 1.4
1711
   */
1712
  public boolean isFocusCycleRoot ()
1713
  {
1714
    return focusCycleRoot;
1715
  }
1716
 
1717
  /**
1718
   * Transfer focus down one focus traversal cycle.  If this Container
1719
   * is a focus cycle root, then its default component becomes the
1720
   * focus owner, and this Container becomes the current focus cycle
1721
   * root.  No traversal will occur if this Container is not a focus
1722
   * cycle root.
1723
   *
1724
   * @since 1.4
1725
   */
1726
  public void transferFocusDownCycle ()
1727
  {
1728
    if (isFocusCycleRoot())
1729
      {
1730
        KeyboardFocusManager fm =
1731
          KeyboardFocusManager.getCurrentKeyboardFocusManager();
1732
        fm.setGlobalCurrentFocusCycleRoot(this);
1733
        FocusTraversalPolicy policy = getFocusTraversalPolicy();
1734
        Component defaultComponent = policy.getDefaultComponent(this);
1735
        if (defaultComponent != null)
1736
          defaultComponent.requestFocus();
1737
      }
1738
  }
1739
 
1740
  /**
1741
   * Sets the ComponentOrientation property of this container and all components
1742
   * contained within it.
1743
   *
1744
   * @exception NullPointerException If orientation is null
1745
   *
1746
   * @since 1.4
1747
   */
1748
  public void applyComponentOrientation (ComponentOrientation orientation)
1749
  {
1750
    if (orientation == null)
1751
      throw new NullPointerException();
1752
 
1753
    setComponentOrientation(orientation);
1754
    for (int i = 0; i < ncomponents; i++)
1755
      {
1756
        if (component[i] instanceof Container)
1757
             ((Container) component[i]).applyComponentOrientation(orientation);
1758
          else
1759
             component[i].setComponentOrientation(orientation);
1760
      }
1761
  }
1762
 
1763
  public void addPropertyChangeListener (PropertyChangeListener listener)
1764
  {
1765
    // TODO: Why is this overridden?
1766
    super.addPropertyChangeListener(listener);
1767
  }
1768
 
1769
  public void addPropertyChangeListener (String propertyName,
1770
                                         PropertyChangeListener listener)
1771
  {
1772
    // TODO: Why is this overridden?
1773
    super.addPropertyChangeListener(propertyName, listener);
1774
  }
1775
 
1776
 
1777
  /**
1778
   * Sets the Z ordering for the component <code>comp</code> to
1779
   * <code>index</code>. Components with lower Z order paint above components
1780
   * with higher Z order.
1781
   *
1782
   * @param comp the component for which to change the Z ordering
1783
   * @param index the index to set
1784
   *
1785
   * @throws NullPointerException if <code>comp == null</code>
1786
   * @throws IllegalArgumentException if comp is an ancestor of this container
1787
   * @throws IllegalArgumentException if <code>index</code> is not in
1788
   *         <code>[0, getComponentCount()]</code> for moving between
1789
   *         containers or <code>[0, getComponentCount() - 1]</code> for moving
1790
   *         inside this container
1791
   * @throws IllegalArgumentException if <code>comp == this</code>
1792
   * @throws IllegalArgumentException if <code>comp</code> is a
1793
   *         <code>Window</code>
1794
   *
1795
   * @see #getComponentZOrder(Component)
1796
   *
1797
   * @since 1.5
1798
   */
1799
  public final void setComponentZOrder(Component comp, int index)
1800
  {
1801
    if (comp == null)
1802
      throw new NullPointerException("comp must not be null");
1803
    if (comp instanceof Container && ((Container) comp).isAncestorOf(this))
1804
      throw new IllegalArgumentException("comp must not be an ancestor of "
1805
                                         + "this");
1806
    if (comp instanceof Window)
1807
      throw new IllegalArgumentException("comp must not be a Window");
1808
 
1809
    if (comp == this)
1810
      throw new IllegalArgumentException("cannot add component to itself");
1811
 
1812
    synchronized (getTreeLock())
1813
      {
1814
        // FIXME: Implement reparenting.
1815
        if ( comp.getParent() != this)
1816
          throw new AssertionError("Reparenting is not implemented yet");
1817
        else
1818
          {
1819
            // Find current component index.
1820
            int currentIndex = getComponentZOrder(comp);
1821
            if (currentIndex < index)
1822
              {
1823
                System.arraycopy(component, currentIndex + 1, component,
1824
                                 currentIndex, index - currentIndex);
1825
              }
1826
            else
1827
              {
1828
                System.arraycopy(component, index, component, index + 1,
1829
                                 currentIndex - index);
1830
              }
1831
            component[index] = comp;
1832
          }
1833
      }
1834
  }
1835
 
1836
  /**
1837
   * Returns the Z ordering index of <code>comp</code>. If <code>comp</code>
1838
   * is not a child component of this Container, this returns <code>-1</code>.
1839
   *
1840
   * @param comp the component for which to query the Z ordering
1841
   *
1842
   * @return the Z ordering index of <code>comp</code> or <code>-1</code> if
1843
   *         <code>comp</code> is not a child of this Container
1844
   *
1845
   * @see #setComponentZOrder(Component, int)
1846
   *
1847
   * @since 1.5
1848
   */
1849
  public final int getComponentZOrder(Component comp)
1850
  {
1851
    synchronized (getTreeLock())
1852
      {
1853
        int index = -1;
1854
        if (component != null)
1855
          {
1856
            for (int i = 0; i < ncomponents; i++)
1857
              {
1858
                if (component[i] == comp)
1859
                  {
1860
                    index = i;
1861
                    break;
1862
                  }
1863
              }
1864
          }
1865
        return index;
1866
      }
1867
  }
1868
 
1869
  // Hidden helper methods.
1870
 
1871
  /**
1872
   * Perform a graphics operation on the children of this container.
1873
   * For each applicable child, the visitChild() method will be called
1874
   * to perform the graphics operation.
1875
   *
1876
   * @param gfx The graphics object that will be used to derive new
1877
   * graphics objects for the children.
1878
   *
1879
   * @param visitor Object encapsulating the graphics operation that
1880
   * should be performed.
1881
   *
1882
   * @param lightweightOnly If true, only lightweight components will
1883
   * be visited.
1884
   */
1885
  private void visitChildren(Graphics gfx, GfxVisitor visitor,
1886
                             boolean lightweightOnly)
1887
  {
1888
    synchronized (getTreeLock())
1889
      {
1890
        for (int i = ncomponents - 1; i >= 0; --i)
1891
          {
1892
            Component comp = component[i];
1893
            boolean applicable = comp.isVisible()
1894
                                 && (comp.isLightweight() || ! lightweightOnly);
1895
 
1896
            if (applicable)
1897
              visitChild(gfx, visitor, comp);
1898
          }
1899
      }
1900
  }
1901
 
1902
  /**
1903
   * Perform a graphics operation on a child. A translated and clipped
1904
   * graphics object will be created, and the visit() method of the
1905
   * visitor will be called to perform the operation.
1906
   *
1907
   * @param gfx The graphics object that will be used to derive new
1908
   * graphics objects for the child.
1909
   *
1910
   * @param visitor Object encapsulating the graphics operation that
1911
   * should be performed.
1912
   *
1913
   * @param comp The child component that should be visited.
1914
   */
1915
  private void visitChild(Graphics gfx, GfxVisitor visitor,
1916
                          Component comp)
1917
  {
1918
    Rectangle bounds = comp.getBounds();
1919
 
1920
    if(!gfx.hitClip(bounds.x,bounds.y, bounds.width, bounds.height))
1921
      return;
1922
    Graphics g2 = gfx.create(bounds.x, bounds.y, bounds.width,
1923
                             bounds.height);
1924
    try
1925
      {
1926
        g2.setFont(comp.getFont());
1927
        visitor.visit(comp, g2);
1928
      }
1929
    finally
1930
      {
1931
        g2.dispose();
1932
      }
1933
  }
1934
 
1935
  /**
1936
   * Overridden to dispatch events to lightweight descendents.
1937
   *
1938
   * @param e the event to dispatch.
1939
   */
1940
  void dispatchEventImpl(AWTEvent e)
1941
  {
1942
    LightweightDispatcher dispatcher = LightweightDispatcher.getInstance();
1943
    if (! isLightweight() && dispatcher.dispatchEvent(e))
1944
      {
1945
        // Some lightweight descendent got this event dispatched. Consume
1946
        // it and let the peer handle it.
1947
        e.consume();
1948
        ComponentPeer p = peer;
1949
        if (p != null)
1950
          p.handleEvent(e);
1951
      }
1952
    else
1953
      {
1954
        super.dispatchEventImpl(e);
1955
      }
1956
  }
1957
 
1958
  /**
1959
   * This is called by the lightweight dispatcher to avoid recursivly
1960
   * calling into the lightweight dispatcher.
1961
   *
1962
   * @param e the event to dispatch
1963
   *
1964
   * @see LightweightDispatcher#redispatch(MouseEvent, Component, int)
1965
   */
1966
  void dispatchNoLightweight(AWTEvent e)
1967
  {
1968
    super.dispatchEventImpl(e);
1969
  }
1970
 
1971
  /**
1972
   * Tests if this container has an interest in the given event id.
1973
   *
1974
   * @param eventId The event id to check.
1975
   *
1976
   * @return <code>true</code> if a listener for the event id exists or
1977
   *         if the eventMask is set for the event id.
1978
   *
1979
   * @see java.awt.Component#eventTypeEnabled(int)
1980
   */
1981
  boolean eventTypeEnabled(int eventId)
1982
  {
1983
    if(eventId <= ContainerEvent.CONTAINER_LAST
1984
       && eventId >= ContainerEvent.CONTAINER_FIRST)
1985
      return containerListener != null
1986
        || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0;
1987
      else
1988
        return super.eventTypeEnabled(eventId);
1989
  }
1990
 
1991
  // This is used to implement Component.transferFocus.
1992
  Component findNextFocusComponent(Component child)
1993
  {
1994
    synchronized (getTreeLock ())
1995
      {
1996
        int start, end;
1997
        if (child != null)
1998
          {
1999
            for (start = 0; start < ncomponents; ++start)
2000
              {
2001
                if (component[start] == child)
2002
                  break;
2003
              }
2004
            end = start;
2005
            // This special case lets us be sure to terminate.
2006
            if (end == 0)
2007
              end = ncomponents;
2008
            ++start;
2009
          }
2010
        else
2011
          {
2012
            start = 0;
2013
            end = ncomponents;
2014
          }
2015
 
2016
        for (int j = start; j != end; ++j)
2017
          {
2018
            if (j >= ncomponents)
2019
              {
2020
                // The JCL says that we should wrap here.  However, that
2021
                // seems wrong.  To me it seems that focus order should be
2022
                // global within in given window.  So instead if we reach
2023
                // the end we try to look in our parent, if we have one.
2024
                if (parent != null)
2025
                  return parent.findNextFocusComponent(this);
2026
                j -= ncomponents;
2027
              }
2028
            if (component[j] instanceof Container)
2029
              {
2030
                Component c = component[j];
2031
                c = c.findNextFocusComponent(null);
2032
                if (c != null)
2033
                  return c;
2034
              }
2035
            else if (component[j].isFocusTraversable())
2036
              return component[j];
2037
          }
2038
 
2039
        return null;
2040
      }
2041
  }
2042
 
2043
  /**
2044
   * Fires hierarchy events to the children of this container and this
2045
   * container itself. This overrides {@link Component#fireHierarchyEvent}
2046
   * in order to forward this event to all children.
2047
   */
2048
  void fireHierarchyEvent(int id, Component changed, Container parent,
2049
                          long flags)
2050
  {
2051
    // Only propagate event if there is actually a listener waiting for it.
2052
    if ((id == HierarchyEvent.HIERARCHY_CHANGED && numHierarchyListeners > 0)
2053
        || ((id == HierarchyEvent.ANCESTOR_MOVED
2054
             || id == HierarchyEvent.ANCESTOR_RESIZED)
2055
            && numHierarchyBoundsListeners > 0))
2056
      {
2057
        for (int i = 0; i < ncomponents; i++)
2058
          component[i].fireHierarchyEvent(id, changed, parent, flags);
2059
        super.fireHierarchyEvent(id, changed, parent, flags);
2060
      }
2061
  }
2062
 
2063
  /**
2064
   * Adjusts the number of hierarchy listeners of this container and all of
2065
   * its parents. This is called by the add/remove listener methods and
2066
   * structure changing methods in Container.
2067
   *
2068
   * @param type the type, either {@link AWTEvent#HIERARCHY_BOUNDS_EVENT_MASK}
2069
   *        or {@link AWTEvent#HIERARCHY_EVENT_MASK}
2070
   * @param delta the number of listeners added or removed
2071
   */
2072
  void updateHierarchyListenerCount(long type, int delta)
2073
  {
2074
    if (type == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)
2075
      numHierarchyBoundsListeners += delta;
2076
    else if (type == AWTEvent.HIERARCHY_EVENT_MASK)
2077
      numHierarchyListeners += delta;
2078
    else
2079
      assert false : "Should not reach here";
2080
 
2081
    if (parent != null)
2082
      parent.updateHierarchyListenerCount(type, delta);
2083
  }
2084
 
2085
  /**
2086
   * Notifies interested listeners about resizing or moving the container.
2087
   * This performs the super behaviour (sending component events) and
2088
   * additionally notifies any hierarchy bounds listeners on child components.
2089
   *
2090
   * @param resized true if the component has been resized, false otherwise
2091
   * @param moved true if the component has been moved, false otherwise
2092
   */
2093
  void notifyReshape(boolean resized, boolean moved)
2094
  {
2095
    // Notify component listeners.
2096
    super.notifyReshape(resized, moved);
2097
 
2098
    if (ncomponents > 0)
2099
      {
2100
        // Notify hierarchy bounds listeners.
2101
        if (resized)
2102
          {
2103
            for (int i = 0; i < getComponentCount(); i++)
2104
              {
2105
                Component child = getComponent(i);
2106
                child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_RESIZED,
2107
                                         this, parent, 0);
2108
              }
2109
          }
2110
        if (moved)
2111
          {
2112
            for (int i = 0; i < getComponentCount(); i++)
2113
              {
2114
                Component child = getComponent(i);
2115
                child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED,
2116
                                         this, parent, 0);
2117
              }
2118
          }
2119
      }
2120
  }
2121
 
2122
  private void addNotifyContainerChildren()
2123
  {
2124
    synchronized (getTreeLock ())
2125
      {
2126
        for (int i = ncomponents;  --i >= 0; )
2127
          {
2128
            component[i].addNotify();
2129
          }
2130
      }
2131
  }
2132
 
2133
  /**
2134
   * Deserialize this Container:
2135
   * <ol>
2136
   * <li>Read from the stream the default serializable fields.</li>
2137
   * <li>Read a list of serializable ContainerListeners as optional
2138
   * data.  If the list is null, no listeners will be registered.</li>
2139
   * <li>Read this Container's FocusTraversalPolicy as optional data.
2140
   * If this is null, then this Container will use a
2141
   * DefaultFocusTraversalPolicy.</li>
2142
   * </ol>
2143
   *
2144
   * @param s the stream to read from
2145
   * @throws ClassNotFoundException if deserialization fails
2146
   * @throws IOException if the stream fails
2147
   */
2148
  private void readObject (ObjectInputStream s)
2149
    throws ClassNotFoundException, IOException
2150
  {
2151
    s.defaultReadObject ();
2152
    String key = (String) s.readObject ();
2153
    while (key != null)
2154
      {
2155
        Object object = s.readObject ();
2156
        if ("containerL".equals (key))
2157
          addContainerListener((ContainerListener) object);
2158
        // FIXME: under what key is the focus traversal policy stored?
2159
        else if ("focusTraversalPolicy".equals (key))
2160
          setFocusTraversalPolicy ((FocusTraversalPolicy) object);
2161
 
2162
        key = (String) s.readObject();
2163
      }
2164
  }
2165
 
2166
  /**
2167
   * Serialize this Container:
2168
   * <ol>
2169
   * <li>Write to the stream the default serializable fields.</li>
2170
   * <li>Write the list of serializable ContainerListeners as optional
2171
   * data.</li>
2172
   * <li>Write this Container's FocusTraversalPolicy as optional data.</li>
2173
   * </ol>
2174
   *
2175
   * @param s the stream to write to
2176
   * @throws IOException if the stream fails
2177
   */
2178
  private void writeObject (ObjectOutputStream s) throws IOException
2179
  {
2180
    s.defaultWriteObject ();
2181
    AWTEventMulticaster.save (s, "containerL", containerListener);
2182
    if (focusTraversalPolicy instanceof Serializable)
2183
      s.writeObject (focusTraversalPolicy);
2184
    else
2185
      s.writeObject (null);
2186
  }
2187
 
2188
  // Nested classes.
2189
 
2190
  /* The following classes are used in concert with the
2191
     visitChildren() method to implement all the graphics operations
2192
     that requires traversal of the containment hierarchy. */
2193
 
2194
  abstract static class GfxVisitor
2195
  {
2196
    public abstract void visit(Component c, Graphics gfx);
2197
  }
2198
 
2199
  static class GfxPaintVisitor extends GfxVisitor
2200
  {
2201
    public static final GfxVisitor INSTANCE = new GfxPaintVisitor();
2202
 
2203
    public void visit(Component c, Graphics gfx)
2204
    {
2205
      c.paint(gfx);
2206
    }
2207
  }
2208
 
2209
  static class GfxPrintVisitor extends GfxVisitor
2210
  {
2211
    public static final GfxVisitor INSTANCE = new GfxPrintVisitor();
2212
 
2213
    public void visit(Component c, Graphics gfx)
2214
    {
2215
      c.print(gfx);
2216
    }
2217
  }
2218
 
2219
  static class GfxPaintAllVisitor extends GfxVisitor
2220
  {
2221
    public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor();
2222
 
2223
    public void visit(Component c, Graphics gfx)
2224
    {
2225
      c.paintAll(gfx);
2226
    }
2227
  }
2228
 
2229
  static class GfxPrintAllVisitor extends GfxVisitor
2230
  {
2231
    public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor();
2232
 
2233
    public void visit(Component c, Graphics gfx)
2234
    {
2235
      c.printAll(gfx);
2236
    }
2237
  }
2238
 
2239
  /**
2240
   * This class provides accessibility support for subclasses of container.
2241
   *
2242
   * @author Eric Blake (ebb9@email.byu.edu)
2243
   *
2244
   * @since 1.3
2245
   */
2246
  protected class AccessibleAWTContainer extends AccessibleAWTComponent
2247
  {
2248
    /**
2249
     * Compatible with JDK 1.4+.
2250
     */
2251
    private static final long serialVersionUID = 5081320404842566097L;
2252
 
2253
    /**
2254
     * The handler to fire PropertyChange when children are added or removed.
2255
     *
2256
     * @serial the handler for property changes
2257
     */
2258
    protected ContainerListener accessibleContainerHandler
2259
      = new AccessibleContainerHandler();
2260
 
2261
    /**
2262
     * The default constructor.
2263
     */
2264
    protected AccessibleAWTContainer()
2265
    {
2266
      Container.this.addContainerListener(accessibleContainerHandler);
2267
    }
2268
 
2269
    /**
2270
     * Return the number of accessible children of the containing accessible
2271
     * object (at most the total number of its children).
2272
     *
2273
     * @return the number of accessible children
2274
     */
2275
    public int getAccessibleChildrenCount()
2276
    {
2277
      synchronized (getTreeLock ())
2278
        {
2279
          int count = 0;
2280
          int i = component == null ? 0 : component.length;
2281
          while (--i >= 0)
2282
            if (component[i] instanceof Accessible)
2283
              count++;
2284
          return count;
2285
        }
2286
    }
2287
 
2288
    /**
2289
     * Return the nth accessible child of the containing accessible object.
2290
     *
2291
     * @param i the child to grab, zero-based
2292
     * @return the accessible child, or null
2293
     */
2294
    public Accessible getAccessibleChild(int i)
2295
    {
2296
      synchronized (getTreeLock ())
2297
        {
2298
          if (component == null)
2299
            return null;
2300
          int index = -1;
2301
          while (i >= 0 && ++index < component.length)
2302
            if (component[index] instanceof Accessible)
2303
              i--;
2304
          if (i < 0)
2305
            return (Accessible) component[index];
2306
          return null;
2307
        }
2308
    }
2309
 
2310
    /**
2311
     * Return the accessible child located at point (in the parent's
2312
     * coordinates), if one exists.
2313
     *
2314
     * @param p the point to look at
2315
     *
2316
     * @return an accessible object at that point, or null
2317
     *
2318
     * @throws NullPointerException if p is null
2319
     */
2320
    public Accessible getAccessibleAt(Point p)
2321
    {
2322
      Component c = getComponentAt(p.x, p.y);
2323
      return c != Container.this && c instanceof Accessible ? (Accessible) c
2324
        : null;
2325
    }
2326
 
2327
    /**
2328
     * This class fires a <code>PropertyChange</code> listener, if registered,
2329
     * when children are added or removed from the enclosing accessible object.
2330
     *
2331
     * @author Eric Blake (ebb9@email.byu.edu)
2332
     *
2333
     * @since 1.3
2334
     */
2335
    protected class AccessibleContainerHandler implements ContainerListener
2336
    {
2337
      /**
2338
       * Default constructor.
2339
       */
2340
      protected AccessibleContainerHandler()
2341
      {
2342
        // Nothing to do here.
2343
      }
2344
 
2345
      /**
2346
       * Fired when a component is added; forwards to the PropertyChange
2347
       * listener.
2348
       *
2349
       * @param e the container event for adding
2350
       */
2351
      public void componentAdded(ContainerEvent e)
2352
      {
2353
        AccessibleAWTContainer.this.firePropertyChange
2354
          (ACCESSIBLE_CHILD_PROPERTY, null, e.getChild());
2355
      }
2356
 
2357
      /**
2358
       * Fired when a component is removed; forwards to the PropertyChange
2359
       * listener.
2360
       *
2361
       * @param e the container event for removing
2362
       */
2363
      public void componentRemoved(ContainerEvent e)
2364
      {
2365
        AccessibleAWTContainer.this.firePropertyChange
2366
          (ACCESSIBLE_CHILD_PROPERTY, e.getChild(), null);
2367
      }
2368
    } // class AccessibleContainerHandler
2369
  } // class AccessibleAWTContainer
2370
} // class Container

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.