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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [javax/] [swing/] [JLayeredPane.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* JLayeredPane.java --
2
   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package javax.swing;
40
 
41
import java.awt.Color;
42
import java.awt.Component;
43
import java.awt.Container;
44
import java.awt.Graphics;
45
import java.awt.Rectangle;
46
import java.awt.Shape;
47
import java.util.Hashtable;
48
import java.util.Iterator;
49
import java.util.Map;
50
import java.util.TreeMap;
51
 
52
import javax.accessibility.Accessible;
53
import javax.accessibility.AccessibleContext;
54
import javax.accessibility.AccessibleRole;
55
 
56
/**
57
 * A container that adds depth to the usual <code>Container</code> semantics.
58
 * Each child component of a <code>Layered Pane</code> is placed within one
59
 * of several layers. <code>JLayeredPane</code> defines a set of standard
60
 * layers. The pre-defined sets are (in the order from button to top):
61
 *
62
 *  <dl>
63
 *    <dt>{@link #DEFAULT_LAYER}</dt>
64
 *    <dd>The layer where most of the normal components are placed. This
65
 *      is the bottommost layer.</dd>
66
 *
67
 *    <dt>{@link #PALETTE_LAYER}</dt>
68
 *    <dd>Palette windows are placed in this layer.</dd>
69
 *
70
 *    <dt>{@link #MODAL_LAYER}</dt>
71
 *    <dd>The layer where internal modal dialog windows are placed.</dd>
72
 *
73
 *    <dt>{@link #POPUP_LAYER}</dt>
74
 *    <dd>The layer for popup menus</dd>
75
 *
76
 *    <dt>{@link #DRAG_LAYER}</dt>
77
 *    <dd>Components that are beeing dragged are temporarily placed in
78
 *       this layer.</dd>
79
 *  </dl>
80
 *
81
 * <p>A child is in exactly one of these layers at any time, though there may
82
 * be other layers if someone creates them.</p>
83
 *
84
 * <p>You can add a component to a specific layer using the
85
 * {@link Container#add(Component, Object)} method. I.e.
86
 * <code>layeredPane.add(comp, JLayeredPane.MODAL_LAYER)</code> will add the
87
 * component <code>comp</code> to the modal layer of <code>layeredPane</code>.
88
 * </p>
89
 *
90
 * <p>To change the layer of a component that is already a child of
91
 * a <code>JLayeredPane</code>, use the {@link #setLayer(Component, int)}
92
 * method.</p>
93
 *
94
 * <p>The purpose of this class is to translate this view of "layers" into a
95
 * contiguous array of components: the one held in our ancestor,
96
 * {@link java.awt.Container}.</p>
97
 *
98
 * <p>There is a precise set of words we will use to refer to numbers within
99
 * this class:</p>
100
 *
101
 * <dl>
102
 * <dt>Component Index:</dt>
103
 * <dd>An offset into the <code>component</code> array held in our ancestor,
104
 * {@link java.awt.Container}, from <code>[0 .. component.length)</code>. The drawing
105
 * rule with indices is that 0 is drawn last.</dd>
106
 *
107
 * <dt>Layer Number:</dt>
108
 * <dd>A general <code>int</code> specifying a layer within this component.  Negative
109
 * numbers are drawn first, then layer 0, then positive numbered layers, in
110
 * ascending order.</dd>
111
 *
112
 * <dt>Position:</dt>
113
 * <dd>An offset into a layer's "logical drawing order". Layer position 0
114
 * is drawn last. Layer position -1 is a synonym for the first layer
115
 * position (the logical "bottom").</dd>
116
 * </dl>
117
 *
118
 * <p><b>Note:</b> the layer numbering order is the <em>reverse</em> of the
119
 * component indexing and position order</p>
120
 *
121
 * @author Graydon Hoare (graydon@redhat.com)
122
 */
123
public class JLayeredPane extends JComponent implements Accessible
124
{
125
 
126
  /**
127
   * Provides accessibility support for <code>JLayeredPane</code>.
128
   */
129
  protected class AccessibleJLayeredPane extends AccessibleJComponent
130
  {
131
    /**
132
     * Creates a new instance of <code>AccessibleJLayeredPane</code>.
133
     */
134
    public AccessibleJLayeredPane()
135
    {
136
      // Nothing to do here.
137
    }
138
 
139
    /**
140
     * Returns the accessble role of <code>JLayeredPane</code>,
141
     * {@link AccessibleRole#LAYERED_PANE}.
142
     */
143
    public AccessibleRole getAccessibleRole()
144
    {
145
      return AccessibleRole.LAYERED_PANE;
146
    }
147
  }
148
 
149
  private static final long serialVersionUID = 5534920399324590459L;
150
 
151
  public static final String LAYER_PROPERTY = "layeredContainerLayer";
152
 
153
  public static Integer FRAME_CONTENT_LAYER = new Integer (-30000);
154
 
155
  public static Integer DEFAULT_LAYER = new Integer (0);
156
  public static Integer PALETTE_LAYER = new Integer (100);
157
  public static Integer MODAL_LAYER   = new Integer (200);
158
  public static Integer POPUP_LAYER   = new Integer (300);
159
  public static Integer DRAG_LAYER    = new Integer (400);
160
 
161
  TreeMap layers;               // Layer Number (Integer) -> Layer Size (Integer)
162
  Hashtable componentToLayer;   // Component -> Layer Number (Integer)
163
 
164
  private transient Rectangle rectCache;
165
 
166
  public JLayeredPane()
167
  {
168
    layers = new TreeMap ();
169
    componentToLayer = new Hashtable ();
170
    setLayout(null);
171
  }
172
 
173
  /**
174
   * Looks up the layer a child component is currently assigned to.
175
   *
176
   * @param c the component to look up.
177
   * @return the layer the component is currently assigned to, in this container.
178
   * @throws IllegalArgumentException if the component is not a child of this container.
179
   */
180
  public int getLayer(Component c)
181
  {
182
    Component myComp = c;
183
    while(! componentToLayer.containsKey(myComp))
184
      {
185
        myComp = myComp.getParent();
186
        if (myComp == null)
187
          break;
188
      }
189
    if (myComp == null)
190
      throw new IllegalArgumentException
191
        ("component is not in this JLayeredPane");
192
    Integer layerObj = (Integer) componentToLayer.get(myComp);
193
    return layerObj.intValue();
194
  }
195
 
196
  /**
197
   * Looks up the layer of <code>comp</code> in the component's nearest
198
   * JLayeredPane ancestor. If <code>comp</code> is not contained
199
   * in a JLayeredPane, the value 0 (default layer) is returned.
200
   *
201
   * @param comp the component for which the layer is looked up
202
   *
203
   * @return the layer of <code>comp</code> in its nearest JLayeredPane
204
   *     ancestor
205
   */
206
  public static int getLayer(JComponent comp)
207
  {
208
    JLayeredPane lp = (JLayeredPane) SwingUtilities.getAncestorOfClass
209
      (JLayeredPane.class, comp);
210
    if (lp == null)
211
      return 0;
212
    else
213
      // The cast here forces the call to the instance method getLayer()
214
      // instead of the static method (this would lead to infinite
215
      // recursion).
216
      return lp.getLayer((Component) comp);
217
  }
218
 
219
  /**
220
   * Returns the first JLayeredPane that contains the Component
221
   * <code>comp</code> or <code>null</code> if <code>comp</code> is
222
   * not contained in a JLayeredPane.
223
   *
224
   * @param comp the component for which we are searching the JLayeredPane
225
   *     ancestor
226
   *
227
   * @return the first JLayeredPane that contains the Component
228
   *     <code>comp</code> or <code>null</code> if <code>comp</code> is
229
   *     not contained in a JLayeredPane
230
   */
231
  public static JLayeredPane getLayeredPaneAbove(Component comp)
232
  {
233
    JLayeredPane lp = (JLayeredPane) SwingUtilities.getAncestorOfClass
234
      (JLayeredPane.class, comp);
235
    return lp;
236
  }
237
 
238
  /**
239
   * <p>Returns a pair of ints representing a half-open interval
240
   * <code>[top, bottom)</code>, which is the range of component indices
241
   * the provided layer number corresponds to.</p>
242
   *
243
   * <p>Note that "bottom" is <em>not</em> included in the interval of
244
   * component indices in this layer: a layer with 0 elements in it has
245
   * <code>ret[0] == ret[1]</code>.</p>
246
   *
247
   * @param layer the layer to look up.
248
   * @return the half-open range of indices this layer spans.
249
   * @throws IllegalArgumentException if layer does not refer to an active layer
250
   * in this container.
251
   */
252
  private int[] layerToRange (Integer layer)
253
  {
254
    int[] ret = new int[2];
255
    ret[1] = getComponents ().length;
256
    Iterator i = layers.entrySet ().iterator ();
257
    while (i.hasNext())
258
      {
259
        Map.Entry pair = (Map.Entry) i.next();
260
        Integer layerNum = (Integer) pair.getKey ();
261
        Integer layerSz = (Integer) pair.getValue ();
262
        int layerInt = layerNum.intValue();
263
        if (layerInt == layer.intValue())
264
          {
265
            ret[0] = ret[1] - layerSz.intValue ();
266
            break;
267
          }
268
        // In the following case there exists no layer with the specified
269
        // number, so we return an empty interval here with the index at which
270
        // such a layer would be inserted
271
        else if (layerInt > layer.intValue())
272
          {
273
            ret[1] = ret[0];
274
            break;
275
          }
276
        else
277
          {
278
            ret[1] -= layerSz.intValue ();
279
          }
280
      }
281
    return ret;
282
  }
283
 
284
  /**
285
   * Increments the recorded size of a given layer.
286
   *
287
   * @param layer the layer number to increment.
288
   * @see #incrLayer
289
   */
290
  private void incrLayer(Integer layer)
291
  {
292
    int sz = 1;
293
    if (layers.containsKey (layer))
294
            sz += ((Integer)(layers.get (layer))).intValue ();
295
    layers.put (layer, new Integer(sz));
296
  }
297
 
298
  /**
299
   * Decrements the recorded size of a given layer.
300
   *
301
   * @param layer the layer number to decrement.
302
   * @see #incrLayer
303
   */
304
  private void decrLayer(Integer layer)
305
  {
306
    int sz = 0;
307
    if (layers.containsKey (layer))
308
            sz = ((Integer)(layers.get (layer))).intValue () - 1;
309
    layers.put (layer, new Integer(sz));
310
  }
311
 
312
  /**
313
   * Return the greatest layer number currently in use, in this container.
314
   * This number may legally be positive <em>or</em> negative.
315
   *
316
   * @return the least layer number.
317
   * @see #lowestLayer()
318
   */
319
  public int highestLayer()
320
  {
321
    if (layers.size() == 0)
322
            return 0;
323
    return ((Integer)(layers.lastKey ())).intValue ();
324
  }
325
 
326
  /**
327
   * Return the least layer number currently in use, in this container.
328
   * This number may legally be positive <em>or</em> negative.
329
   *
330
   * @return the least layer number.
331
   * @see #highestLayer()
332
   */
333
  public int lowestLayer()
334
  {
335
    if (layers.size() == 0)
336
            return 0;
337
    return ((Integer)(layers.firstKey ())).intValue ();
338
  }
339
 
340
  /**
341
   * Moves a component to the "front" of its layer. The "front" is a
342
   * synonym for position 0, which is also the last position drawn in each
343
   * layer, so is usually the component which occludes the most other
344
   * components in its layer.
345
   *
346
   * @param c the component to move to the front of its layer.
347
   * @throws IllegalArgumentException if the component is not a child of
348
   * this container.
349
   * @see #moveToBack
350
   */
351
  public void moveToFront(Component c)
352
  {
353
    setPosition (c, 0);
354
  }
355
 
356
  /**
357
   * <p>Moves a component to the "back" of its layer. The "back" is a
358
   * synonym for position N-1 (also known as position -1), where N is the
359
   * size of the layer.</p>
360
   *
361
   * <p>The "back" of a layer is the first position drawn, so the component at
362
   * the "back" is usually the component which is occluded by the most
363
   * other components in its layer.</p>
364
   *
365
   * @param c the component to move to the back of its layer.
366
   * @throws IllegalArgumentException if the component is not a child of
367
   * this container.
368
   * @see #moveToFront
369
   */
370
  public void moveToBack(Component c)
371
  {
372
    setPosition (c, -1);
373
  }
374
 
375
  /**
376
   * Return the position of a component within its layer. Positions are assigned
377
   * from the "front" (position 0) to the "back" (position N-1), and drawn from
378
   * the back towards the front.
379
   *
380
   * @param c the component to get the position of.
381
   * @throws IllegalArgumentException if the component is not a child of
382
   * this container.
383
   * @see #setPosition
384
   */
385
  public int getPosition(Component c)
386
  {
387
    int layer = getLayer (c);
388
    int[] range = layerToRange(new Integer(layer));
389
    int top = range[0];
390
    int bot = range[1];
391
    Component[] comps = getComponents ();
392
    for (int i = top; i < bot; ++i)
393
            {
394
        if (comps[i] == c)
395
          return i - top;
396
            }
397
    // should have found it
398
    throw new IllegalArgumentException ();
399
  }
400
 
401
  /**
402
   * Change the position of a component within its layer. Positions are assigned
403
   * from the "front" (position 0) to the "back" (position N-1), and drawn from
404
   * the back towards the front.
405
   *
406
   * @param c the component to change the position of.
407
   * @param position the position to assign the component to.
408
   * @throws IllegalArgumentException if the component is not a child of
409
   * this container.
410
   * @see #getPosition
411
   */
412
  public void setPosition(Component c, int position)
413
  {
414
    int layer = getLayer (c);
415
    int[] range = layerToRange(new Integer(layer));
416
    if (range[0] == range[1])
417
      throw new IllegalArgumentException ();
418
 
419
    int top = range[0];
420
    int bot = range[1];
421
    if (position == -1)
422
      position = (bot - top) - 1;
423
    int targ = Math.min(top + position, bot-1);
424
    int curr = -1;
425
 
426
    Component[] comps = getComponents();
427
    for (int i = top; i < bot; ++i)
428
      {
429
        if (comps[i] == c)
430
          {
431
            curr = i;
432
            break;
433
          }
434
      }
435
    if (curr == -1)
436
      // should have found it
437
      throw new IllegalArgumentException();
438
 
439
    super.swapComponents (curr, targ);
440
    revalidate();
441
    repaint();
442
  }
443
 
444
  /**
445
   * Return an array of all components within a layer of this
446
   * container. Components are ordered front-to-back, with the "front"
447
   * element (which draws last) at position 0 of the returned array.
448
   *
449
   * @param layer the layer to return components from.
450
   * @return the components in the layer.
451
   */
452
  public Component[] getComponentsInLayer(int layer)
453
  {
454
    int[] range = layerToRange (getObjectForLayer (layer));
455
    if (range[0] == range[1])
456
            return new Component[0];
457
    else
458
            {
459
        Component[] comps = getComponents ();
460
        int sz = range[1] - range[0];
461
        Component[] nc = new Component[sz];
462
        for (int i = 0; i < sz; ++i)
463
          nc[i] = comps[range[0] + i];
464
        return nc;
465
            }
466
  }
467
 
468
  /**
469
   * Return the number of components within a layer of this
470
   * container.
471
   *
472
   * @param layer the layer count components in.
473
   * @return the number of components in the layer.
474
   */
475
  public int getComponentCountInLayer(int layer)
476
  {
477
    int[] range = layerToRange (getObjectForLayer (layer));
478
    if (range[0] == range[1])
479
            return 0;
480
    else
481
            return (range[1] - range[0]);
482
  }
483
 
484
  /**
485
   * Return a hashtable mapping child components of this container to
486
   * Integer objects representing the component's layer assignments.
487
   */
488
  protected Hashtable getComponentToLayer()
489
  {
490
    return componentToLayer;
491
  }
492
 
493
  /**
494
   * Return the index of a component within the underlying (contiguous)
495
   * array of children. This is a "raw" number which does not represent the
496
   * child's position in a layer, but rather its position in the logical
497
   * drawing order of all children of the container.
498
   *
499
   * @param c the component to look up.
500
   * @return the external index of the component.
501
   * @throws IllegalArgumentException if the component is not a child of
502
   * this container.
503
   */
504
  public int getIndexOf(Component c)
505
  {
506
    int layer = getLayer (c);
507
    int[] range = layerToRange(new Integer(layer));
508
    Component[] comps = getComponents();
509
    for (int i = range[0]; i < range[1]; ++i)
510
            {
511
        if (comps[i] == c)
512
          return i;
513
            }
514
    // should have found the component during iteration
515
    throw new IllegalArgumentException ();
516
  }
517
 
518
  /**
519
   * Return an Integer object which holds the same int value as the
520
   * parameter. This is strictly an optimization to minimize the number of
521
   * identical Integer objects which we allocate.
522
   *
523
   * @param layer the layer number as an int.
524
   * @return the layer number as an Integer, possibly shared.
525
   */
526
  protected Integer getObjectForLayer(int layer)
527
  {
528
    switch (layer)
529
            {
530
            case -30000:
531
        return FRAME_CONTENT_LAYER;
532
 
533
            case 0:
534
        return DEFAULT_LAYER;
535
 
536
            case 100:
537
        return PALETTE_LAYER;
538
 
539
            case 200:
540
        return MODAL_LAYER;
541
 
542
            case 300:
543
        return POPUP_LAYER;
544
 
545
            case 400:
546
        return DRAG_LAYER;
547
 
548
            default:
549
        break;
550
            }
551
 
552
    return new Integer(layer);
553
  }
554
 
555
  /**
556
   * Computes an index at which to request the superclass {@link
557
   * java.awt.Container} inserts a component, given an abstract layer and
558
   * position number.
559
   *
560
   * @param layer the layer in which to insert a component.
561
   * @param position the position in the layer at which to insert a component.
562
   * @return the index at which to insert the component.
563
   */
564
  protected int insertIndexForLayer(int layer, int position)
565
  {
566
 
567
    Integer lobj = getObjectForLayer (layer);
568
    if (! layers.containsKey(lobj))
569
      layers.put (lobj, new Integer (0));
570
    int[] range = layerToRange (lobj);
571
    if (range[0] == range[1])
572
        return range[0];
573
 
574
    int top = range[0];
575
    int bot = range[1];
576
 
577
    if (position == -1 || position > (bot - top))
578
        return bot;
579
    else
580
        return top + position;
581
  }
582
 
583
  /**
584
   * Removes a child from this container. The child is specified by
585
   * index. After removal, the child no longer occupies a layer.
586
   *
587
   * @param index the index of the child component to remove.
588
   */
589
  public void remove(int index)
590
  {
591
    Component c = getComponent(index);
592
    int layer = getLayer(c);
593
    decrLayer(new Integer(layer));
594
    componentToLayer.remove(c);
595
    super.remove(index);
596
    // FIXME: Figure out if this call is correct.
597
    revalidate();
598
  }
599
 
600
  /**
601
   * <p>Set the layer property for a component, within this container. The
602
   * component will be implicitly mapped to the bottom-most position in the
603
   * layer, but only if added <em>after</em> calling this method.</p>
604
   *
605
   * <p>Read that carefully: this method should be called <em>before</em> the
606
   * component is added to the container.</p>
607
   *
608
   * @param c the component to set the layer property for.
609
   * @param layer the layer number to assign to the component.
610
   */
611
  public void setLayer(Component c, int layer)
612
  {
613
    componentToLayer.put (c, getObjectForLayer (layer));
614
  }
615
 
616
  /**
617
   * Set the layer and position of a component, within this container.
618
   *
619
   * @param c the child component to set the layer property for.
620
   * @param layer the layer number to assign to the component.
621
   * @param position the position number to assign to the component.
622
   */
623
  public void setLayer(Component c,
624
                       int layer,
625
                       int position)
626
  {
627
    remove(c);
628
    add(c, getObjectForLayer (layer));
629
    setPosition(c, position);
630
    revalidate();
631
    repaint();
632
  }
633
 
634
  /**
635
   * Overrides the default implementation from {@link java.awt.Container}
636
   * such that <code>layerConstraint</code> is interpreted as an {@link
637
   * Integer}, specifying the layer to which the component will be added
638
   * (at the bottom position).
639
   *
640
   * @param comp the component to add.
641
   * @param layerConstraint an integer specifying the layer to add the component to.
642
   * @param index an ignored parameter, for compatibility.
643
   */
644
  protected void addImpl(Component comp, Object layerConstraint, int index)
645
  {
646
    Integer layer;
647
    if (layerConstraint != null && layerConstraint instanceof Integer)
648
      layer = (Integer) layerConstraint;
649
    else if (componentToLayer.containsKey (comp))
650
            layer = (Integer) componentToLayer.remove (comp);
651
    else
652
            layer = DEFAULT_LAYER;
653
 
654
    int newIdx = insertIndexForLayer(layer.intValue (), index);
655
 
656
    componentToLayer.put (comp, layer);
657
    incrLayer (layer);
658
 
659
    super.addImpl(comp, null, newIdx);
660
  }
661
 
662
  /**
663
   * Sets the layer property for a JComponent.
664
   *
665
   * @param component the component for which to set the layer
666
   * @param layer the layer property to set
667
   */
668
  public static void putLayer(JComponent component, int layer)
669
  {
670
    getLayeredPaneAbove(component).setLayer(component, layer);
671
  }
672
 
673
  /**
674
   * Returns the accessible context for this <code>JLayeredPane</code>.
675
   *
676
   * @return the accessible context for this <code>JLayeredPane</code>
677
   */
678
  public AccessibleContext getAccessibleContext()
679
  {
680
    if (accessibleContext == null)
681
      accessibleContext = new AccessibleJLayeredPane();
682
    return accessibleContext;
683
  }
684
 
685
  /**
686
   * This method is overridden order to provide a reasonable painting
687
   * mechanism for <code>JLayeredPane</code>. This is necessary since
688
   * <code>JLayeredPane</code>'s do not have an own UI delegate.
689
   *
690
   * Basically this method clears the background for the
691
   * <code>JLayeredPane</code> and then calls <code>super.paint(g)</code>.
692
   *
693
   * @param g the graphics context to use
694
   */
695
  public void paint(Graphics g)
696
  {
697
    if (isOpaque())
698
      {
699
        Color oldColor = g.getColor();
700
        Rectangle clip = g.getClipBounds();
701
        g.setColor(getBackground());
702
        g.fillRect(clip.x, clip.y, clip.width, clip.height);
703
        g.setColor(oldColor);
704
      }
705
    super.paint(g);
706
  }
707
 
708
  /**
709
   * Overridden to return <code>false</code>, since <code>JLayeredPane</code>
710
   * cannot guarantee that its children don't overlap.
711
   *
712
   * @return <code>false</code>
713
   */
714
  public boolean isOptimizedDrawingEnabled()
715
  {
716
    return false;
717
  }
718
}

powered by: WebSVN 2.1.0

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