View Javadoc
1   /*
2    * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  package javax.swing;
26  
27  import java.awt.Component;
28  import java.util.ArrayList;
29  import java.util.Hashtable;
30  import java.awt.Color;
31  import java.awt.Graphics;
32  import java.awt.Rectangle;
33  import sun.awt.SunToolkit;
34  
35  import javax.accessibility.*;
36  
37  /**
38   * <code>JLayeredPane</code> adds depth to a JFC/Swing container,
39   * allowing components to overlap each other when needed.
40   * An <code>Integer</code> object specifies each component's depth in the
41   * container, where higher-numbered components sit &quot;on top&quot; of other
42   * components.
43   * For task-oriented documentation and examples of using layered panes see
44   * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/layeredpane.html">How to Use a Layered Pane</a>,
45   * a section in <em>The Java Tutorial</em>.
46   *
47   * <TABLE STYLE="FLOAT:RIGHT" BORDER="0" SUMMARY="layout">
48   * <TR>
49   *   <TD ALIGN="CENTER">
50   *     <P STYLE="TEXT-ALIGN:CENTER"><IMG SRC="doc-files/JLayeredPane-1.gif"
51   *     alt="The following text describes this image."
52   *     WIDTH="269" HEIGHT="264" STYLE="FLOAT:BOTTOM; BORDER=0">
53   *   </TD>
54   * </TR>
55   * </TABLE>
56   * For convenience, <code>JLayeredPane</code> divides the depth-range
57   * into several different layers. Putting a component into one of those
58   * layers makes it easy to ensure that components overlap properly,
59   * without having to worry about specifying numbers for specific depths:
60   * <DL>
61   *    <DT><FONT SIZE="2">DEFAULT_LAYER</FONT></DT>
62   *         <DD>The standard layer, where most components go. This the bottommost
63   *         layer.
64   *    <DT><FONT SIZE="2">PALETTE_LAYER</FONT></DT>
65   *         <DD>The palette layer sits over the default layer. Useful for floating
66   *         toolbars and palettes, so they can be positioned above other components.
67   *    <DT><FONT SIZE="2">MODAL_LAYER</FONT></DT>
68   *         <DD>The layer used for modal dialogs. They will appear on top of any
69   *         toolbars, palettes, or standard components in the container.
70   *    <DT><FONT SIZE="2">POPUP_LAYER</FONT></DT>
71   *         <DD>The popup layer displays above dialogs. That way, the popup windows
72   *         associated with combo boxes, tooltips, and other help text will appear
73   *         above the component, palette, or dialog that generated them.
74   *    <DT><FONT SIZE="2">DRAG_LAYER</FONT></DT>
75   *         <DD>When dragging a component, reassigning it to the drag layer ensures
76   *         that it is positioned over every other component in the container. When
77   *         finished dragging, it can be reassigned to its normal layer.
78   * </DL>
79   * The <code>JLayeredPane</code> methods <code>moveToFront(Component)</code>,
80   * <code>moveToBack(Component)</code> and <code>setPosition</code> can be used
81   * to reposition a component within its layer. The <code>setLayer</code> method
82   * can also be used to change the component's current layer.
83   *
84   * <h2>Details</h2>
85   * <code>JLayeredPane</code> manages its list of children like
86   * <code>Container</code>, but allows for the definition of a several
87   * layers within itself. Children in the same layer are managed exactly
88   * like the normal <code>Container</code> object,
89   * with the added feature that when children components overlap, children
90   * in higher layers display above the children in lower layers.
91   * <p>
92   * Each layer is a distinct integer number. The layer attribute can be set
93   * on a <code>Component</code> by passing an <code>Integer</code>
94   * object during the add call.<br> For example:
95   * <PRE>
96   *     layeredPane.add(child, JLayeredPane.DEFAULT_LAYER);
97   * or
98   *     layeredPane.add(child, new Integer(10));
99   * </PRE>
100  * The layer attribute can also be set on a Component by calling<PRE>
101  *     layeredPaneParent.setLayer(child, 10)</PRE>
102  * on the <code>JLayeredPane</code> that is the parent of component. The layer
103  * should be set <i>before</i> adding the child to the parent.
104  * <p>
105  * Higher number layers display above lower number layers. So, using
106  * numbers for the layers and letters for individual components, a
107  * representative list order would look like this:<PRE>
108  *       5a, 5b, 5c, 2a, 2b, 2c, 1a </PRE>
109  * where the leftmost components are closest to the top of the display.
110  * <p>
111  * A component can be moved to the top or bottom position within its
112  * layer by calling <code>moveToFront</code> or <code>moveToBack</code>.
113  * <p>
114  * The position of a component within a layer can also be specified directly.
115  * Valid positions range from 0 up to one less than the number of
116  * components in that layer. A value of -1 indicates the bottommost
117  * position. A value of 0 indicates the topmost position. Unlike layer
118  * numbers, higher position values are <i>lower</i> in the display.
119  * <blockquote>
120  * <b>Note:</b> This sequence (defined by java.awt.Container) is the reverse
121  * of the layer numbering sequence. Usually though, you will use <code>moveToFront</code>,
122  * <code>moveToBack</code>, and <code>setLayer</code>.
123  * </blockquote>
124  * Here are some examples using the method add(Component, layer, position):
125  * Calling add(5x, 5, -1) results in:<PRE>
126  *       5a, 5b, 5c, 5x, 2a, 2b, 2c, 1a </PRE>
127  *
128  * Calling add(5z, 5, 2) results in:<PRE>
129  *       5a, 5b, 5z, 5c, 5x, 2a, 2b, 2c, 1a </PRE>
130  *
131  * Calling add(3a, 3, 7) results in:<PRE>
132  *       5a, 5b, 5z, 5c, 5x, 3a, 2a, 2b, 2c, 1a </PRE>
133  *
134  * Using normal paint/event mechanics results in 1a appearing at the bottom
135  * and 5a being above all other components.
136  * <p>
137  * <b>Note:</b> that these layers are simply a logical construct and LayoutManagers
138  * will affect all child components of this container without regard for
139  * layer settings.
140  * <p>
141  * <strong>Warning:</strong> Swing is not thread safe. For more
142  * information see <a
143  * href="package-summary.html#threading">Swing's Threading
144  * Policy</a>.
145  * <p>
146  * <strong>Warning:</strong>
147  * Serialized objects of this class will not be compatible with
148  * future Swing releases. The current serialization support is
149  * appropriate for short term storage or RMI between applications running
150  * the same version of Swing.  As of 1.4, support for long term storage
151  * of all JavaBeans&trade;
152  * has been added to the <code>java.beans</code> package.
153  * Please see {@link java.beans.XMLEncoder}.
154  *
155  * @author David Kloba
156  */
157 @SuppressWarnings("serial")
158 public class JLayeredPane extends JComponent implements Accessible {
159     /// Watch the values in getObjectForLayer()
160     /** Convenience object defining the Default layer. Equivalent to new Integer(0).*/
161     public final static Integer DEFAULT_LAYER = new Integer(0);
162     /** Convenience object defining the Palette layer. Equivalent to new Integer(100).*/
163     public final static Integer PALETTE_LAYER = new Integer(100);
164     /** Convenience object defining the Modal layer. Equivalent to new Integer(200).*/
165     public final static Integer MODAL_LAYER = new Integer(200);
166     /** Convenience object defining the Popup layer. Equivalent to new Integer(300).*/
167     public final static Integer POPUP_LAYER = new Integer(300);
168     /** Convenience object defining the Drag layer. Equivalent to new Integer(400).*/
169     public final static Integer DRAG_LAYER = new Integer(400);
170     /** Convenience object defining the Frame Content layer.
171       * This layer is normally only use to position the contentPane and menuBar
172       * components of JFrame.
173       * Equivalent to new Integer(-30000).
174       * @see JFrame
175       */
176     public final static Integer FRAME_CONTENT_LAYER = new Integer(-30000);
177 
178     /** Bound property */
179     public final static String LAYER_PROPERTY = "layeredContainerLayer";
180     // Hashtable to store layer values for non-JComponent components
181     private Hashtable<Component,Integer> componentToLayer;
182     private boolean optimizedDrawingPossible = true;
183 
184 
185 //////////////////////////////////////////////////////////////////////////////
186 //// Container Override methods
187 //////////////////////////////////////////////////////////////////////////////
188     /** Create a new JLayeredPane */
189     public JLayeredPane() {
190         setLayout(null);
191     }
192 
193     private void validateOptimizedDrawing() {
194         boolean layeredComponentFound = false;
195         synchronized(getTreeLock()) {
196             Integer layer;
197 
198             for (Component c : getComponents()) {
199                 layer = null;
200 
201                 if(SunToolkit.isInstanceOf(c, "javax.swing.JInternalFrame") ||
202                        (c instanceof JComponent &&
203                         (layer = (Integer)((JComponent)c).
204                                      getClientProperty(LAYER_PROPERTY)) != null))
205                 {
206                     if(layer != null && layer.equals(FRAME_CONTENT_LAYER))
207                         continue;
208                     layeredComponentFound = true;
209                     break;
210                 }
211             }
212         }
213 
214         if(layeredComponentFound)
215             optimizedDrawingPossible = false;
216         else
217             optimizedDrawingPossible = true;
218     }
219 
220     protected void addImpl(Component comp, Object constraints, int index) {
221         int layer;
222         int pos;
223 
224         if(constraints instanceof Integer) {
225             layer = ((Integer)constraints).intValue();
226             setLayer(comp, layer);
227         } else
228             layer = getLayer(comp);
229 
230         pos = insertIndexForLayer(layer, index);
231         super.addImpl(comp, constraints, pos);
232         comp.validate();
233         comp.repaint();
234         validateOptimizedDrawing();
235     }
236 
237     /**
238      * Remove the indexed component from this pane.
239      * This is the absolute index, ignoring layers.
240      *
241      * @param index  an int specifying the component to remove
242      * @see #getIndexOf
243      */
244     public void remove(int index) {
245         Component c = getComponent(index);
246         super.remove(index);
247         if (c != null && !(c instanceof JComponent)) {
248             getComponentToLayer().remove(c);
249         }
250         validateOptimizedDrawing();
251     }
252 
253     /**
254      * Removes all the components from this container.
255      *
256      * @since 1.5
257      */
258     public void removeAll() {
259         Component[] children = getComponents();
260         Hashtable<Component, Integer> cToL = getComponentToLayer();
261         for (int counter = children.length - 1; counter >= 0; counter--) {
262             Component c = children[counter];
263             if (c != null && !(c instanceof JComponent)) {
264                 cToL.remove(c);
265             }
266         }
267         super.removeAll();
268     }
269 
270     /**
271      * Returns false if components in the pane can overlap, which makes
272      * optimized drawing impossible. Otherwise, returns true.
273      *
274      * @return false if components can overlap, else true
275      * @see JComponent#isOptimizedDrawingEnabled
276      */
277     public boolean isOptimizedDrawingEnabled() {
278         return optimizedDrawingPossible;
279     }
280 
281 
282 //////////////////////////////////////////////////////////////////////////////
283 //// New methods for managing layers
284 //////////////////////////////////////////////////////////////////////////////
285     /** Sets the layer property on a JComponent. This method does not cause
286       * any side effects like setLayer() (painting, add/remove, etc).
287       * Normally you should use the instance method setLayer(), in order to
288       * get the desired side-effects (like repainting).
289       *
290       * @param c      the JComponent to move
291       * @param layer  an int specifying the layer to move it to
292       * @see #setLayer
293       */
294     public static void putLayer(JComponent c, int layer) {
295         /// MAKE SURE THIS AND setLayer(Component c, int layer, int position)  are SYNCED
296         Integer layerObj;
297 
298         layerObj = new Integer(layer);
299         c.putClientProperty(LAYER_PROPERTY, layerObj);
300     }
301 
302     /** Gets the layer property for a JComponent, it
303       * does not cause any side effects like setLayer(). (painting, add/remove, etc)
304       * Normally you should use the instance method getLayer().
305       *
306       * @param c  the JComponent to check
307       * @return   an int specifying the component's layer
308       */
309     public static int getLayer(JComponent c) {
310         Integer i;
311         if((i = (Integer)c.getClientProperty(LAYER_PROPERTY)) != null)
312             return i.intValue();
313         return DEFAULT_LAYER.intValue();
314     }
315 
316     /** Convenience method that returns the first JLayeredPane which
317       * contains the specified component. Note that all JFrames have a
318       * JLayeredPane at their root, so any component in a JFrame will
319       * have a JLayeredPane parent.
320       *
321       * @param c the Component to check
322       * @return the JLayeredPane that contains the component, or
323       *         null if no JLayeredPane is found in the component
324       *         hierarchy
325       * @see JFrame
326       * @see JRootPane
327       */
328     public static JLayeredPane getLayeredPaneAbove(Component c) {
329         if(c == null) return null;
330 
331         Component parent = c.getParent();
332         while(parent != null && !(parent instanceof JLayeredPane))
333             parent = parent.getParent();
334         return (JLayeredPane)parent;
335     }
336 
337     /** Sets the layer attribute on the specified component,
338       * making it the bottommost component in that layer.
339       * Should be called before adding to parent.
340       *
341       * @param c     the Component to set the layer for
342       * @param layer an int specifying the layer to set, where
343       *              lower numbers are closer to the bottom
344       */
345     public void setLayer(Component c, int layer)  {
346         setLayer(c, layer, -1);
347     }
348 
349     /** Sets the layer attribute for the specified component and
350       * also sets its position within that layer.
351       *
352       * @param c         the Component to set the layer for
353       * @param layer     an int specifying the layer to set, where
354       *                  lower numbers are closer to the bottom
355       * @param position  an int specifying the position within the
356       *                  layer, where 0 is the topmost position and -1
357       *                  is the bottommost position
358       */
359     public void setLayer(Component c, int layer, int position)  {
360         Integer layerObj;
361         layerObj = getObjectForLayer(layer);
362 
363         if(layer == getLayer(c) && position == getPosition(c)) {
364                 repaint(c.getBounds());
365             return;
366         }
367 
368         /// MAKE SURE THIS AND putLayer(JComponent c, int layer) are SYNCED
369         if(c instanceof JComponent)
370             ((JComponent)c).putClientProperty(LAYER_PROPERTY, layerObj);
371         else
372             getComponentToLayer().put(c, layerObj);
373 
374         if(c.getParent() == null || c.getParent() != this) {
375             repaint(c.getBounds());
376             return;
377         }
378 
379         int index = insertIndexForLayer(c, layer, position);
380 
381         setComponentZOrder(c, index);
382         repaint(c.getBounds());
383     }
384 
385     /**
386      * Returns the layer attribute for the specified Component.
387      *
388      * @param c  the Component to check
389      * @return an int specifying the component's current layer
390      */
391     public int getLayer(Component c) {
392         Integer i;
393         if(c instanceof JComponent)
394             i = (Integer)((JComponent)c).getClientProperty(LAYER_PROPERTY);
395         else
396             i = getComponentToLayer().get(c);
397 
398         if(i == null)
399             return DEFAULT_LAYER.intValue();
400         return i.intValue();
401     }
402 
403     /**
404      * Returns the index of the specified Component.
405      * This is the absolute index, ignoring layers.
406      * Index numbers, like position numbers, have the topmost component
407      * at index zero. Larger numbers are closer to the bottom.
408      *
409      * @param c  the Component to check
410      * @return an int specifying the component's index
411      */
412     public int getIndexOf(Component c) {
413         int i, count;
414 
415         count = getComponentCount();
416         for(i = 0; i < count; i++) {
417             if(c == getComponent(i))
418                 return i;
419         }
420         return -1;
421     }
422     /**
423      * Moves the component to the top of the components in its current layer
424      * (position 0).
425      *
426      * @param c the Component to move
427      * @see #setPosition(Component, int)
428      */
429     public void moveToFront(Component c) {
430         setPosition(c, 0);
431     }
432 
433     /**
434      * Moves the component to the bottom of the components in its current layer
435      * (position -1).
436      *
437      * @param c the Component to move
438      * @see #setPosition(Component, int)
439      */
440     public void moveToBack(Component c) {
441         setPosition(c, -1);
442     }
443 
444     /**
445      * Moves the component to <code>position</code> within its current layer,
446      * where 0 is the topmost position within the layer and -1 is the bottommost
447      * position.
448      * <p>
449      * <b>Note:</b> Position numbering is defined by java.awt.Container, and
450      * is the opposite of layer numbering. Lower position numbers are closer
451      * to the top (0 is topmost), and higher position numbers are closer to
452      * the bottom.
453      *
454      * @param c         the Component to move
455      * @param position  an int in the range -1..N-1, where N is the number of
456      *                  components in the component's current layer
457      */
458     public void setPosition(Component c, int position) {
459         setLayer(c, getLayer(c), position);
460     }
461 
462     /**
463      * Get the relative position of the component within its layer.
464      *
465      * @param c  the Component to check
466      * @return an int giving the component's position, where 0 is the
467      *         topmost position and the highest index value = the count
468      *         count of components at that layer, minus 1
469      *
470      * @see #getComponentCountInLayer
471      */
472     public int getPosition(Component c) {
473         int i, startLayer, curLayer, startLocation, pos = 0;
474 
475         getComponentCount();
476         startLocation = getIndexOf(c);
477 
478         if(startLocation == -1)
479             return -1;
480 
481         startLayer = getLayer(c);
482         for(i = startLocation - 1; i >= 0; i--) {
483             curLayer = getLayer(getComponent(i));
484             if(curLayer == startLayer)
485                 pos++;
486             else
487                 return pos;
488         }
489         return pos;
490     }
491 
492     /** Returns the highest layer value from all current children.
493       * Returns 0 if there are no children.
494       *
495       * @return an int indicating the layer of the topmost component in the
496       *         pane, or zero if there are no children
497       */
498     public int highestLayer() {
499         if(getComponentCount() > 0)
500             return getLayer(getComponent(0));
501         return 0;
502     }
503 
504     /** Returns the lowest layer value from all current children.
505       * Returns 0 if there are no children.
506       *
507       * @return an int indicating the layer of the bottommost component in the
508       *         pane, or zero if there are no children
509       */
510     public int lowestLayer() {
511         int count = getComponentCount();
512         if(count > 0)
513             return getLayer(getComponent(count-1));
514         return 0;
515     }
516 
517     /**
518      * Returns the number of children currently in the specified layer.
519      *
520      * @param layer  an int specifying the layer to check
521      * @return an int specifying the number of components in that layer
522      */
523     public int getComponentCountInLayer(int layer) {
524         int i, count, curLayer;
525         int layerCount = 0;
526 
527         count = getComponentCount();
528         for(i = 0; i < count; i++) {
529             curLayer = getLayer(getComponent(i));
530             if(curLayer == layer) {
531                 layerCount++;
532             /// Short circut the counting when we have them all
533             } else if(layerCount > 0 || curLayer < layer) {
534                 break;
535             }
536         }
537 
538         return layerCount;
539     }
540 
541     /**
542      * Returns an array of the components in the specified layer.
543      *
544      * @param layer  an int specifying the layer to check
545      * @return an array of Components contained in that layer
546      */
547     public Component[] getComponentsInLayer(int layer) {
548         int i, count, curLayer;
549         int layerCount = 0;
550         Component[] results;
551 
552         results = new Component[getComponentCountInLayer(layer)];
553         count = getComponentCount();
554         for(i = 0; i < count; i++) {
555             curLayer = getLayer(getComponent(i));
556             if(curLayer == layer) {
557                 results[layerCount++] = getComponent(i);
558             /// Short circut the counting when we have them all
559             } else if(layerCount > 0 || curLayer < layer) {
560                 break;
561             }
562         }
563 
564         return results;
565     }
566 
567     /**
568      * Paints this JLayeredPane within the specified graphics context.
569      *
570      * @param g  the Graphics context within which to paint
571      */
572     public void paint(Graphics g) {
573         if(isOpaque()) {
574             Rectangle r = g.getClipBounds();
575             Color c = getBackground();
576             if(c == null)
577                 c = Color.lightGray;
578             g.setColor(c);
579             if (r != null) {
580                 g.fillRect(r.x, r.y, r.width, r.height);
581             }
582             else {
583                 g.fillRect(0, 0, getWidth(), getHeight());
584             }
585         }
586         super.paint(g);
587     }
588 
589 //////////////////////////////////////////////////////////////////////////////
590 //// Implementation Details
591 //////////////////////////////////////////////////////////////////////////////
592 
593     /**
594      * Returns the hashtable that maps components to layers.
595      *
596      * @return the Hashtable used to map components to their layers
597      */
598     protected Hashtable<Component,Integer> getComponentToLayer() {
599         if(componentToLayer == null)
600             componentToLayer = new Hashtable<Component,Integer>(4);
601         return componentToLayer;
602     }
603 
604     /**
605      * Returns the Integer object associated with a specified layer.
606      *
607      * @param layer an int specifying the layer
608      * @return an Integer object for that layer
609      */
610     protected Integer getObjectForLayer(int layer) {
611         Integer layerObj;
612         switch(layer) {
613         case 0:
614             layerObj = DEFAULT_LAYER;
615             break;
616         case 100:
617             layerObj = PALETTE_LAYER;
618             break;
619         case 200:
620             layerObj = MODAL_LAYER;
621             break;
622         case 300:
623             layerObj = POPUP_LAYER;
624             break;
625         case 400:
626             layerObj = DRAG_LAYER;
627             break;
628         default:
629             layerObj = new Integer(layer);
630         }
631         return layerObj;
632     }
633 
634     /**
635      * Primitive method that determines the proper location to
636      * insert a new child based on layer and position requests.
637      *
638      * @param layer     an int specifying the layer
639      * @param position  an int specifying the position within the layer
640      * @return an int giving the (absolute) insertion-index
641      *
642      * @see #getIndexOf
643      */
644     protected int insertIndexForLayer(int layer, int position) {
645         return insertIndexForLayer(null, layer, position);
646     }
647 
648     /**
649      * This method is an extended version of insertIndexForLayer()
650      * to support setLayer which uses Container.setZOrder which does
651      * not remove the component from the containment hierarchy though
652      * we need to ignore it when calculating the insertion index.
653      *
654      * @param comp      component to ignore when determining index
655      * @param layer     an int specifying the layer
656      * @param position  an int specifying the position within the layer
657      * @return an int giving the (absolute) insertion-index
658      *
659      * @see #getIndexOf
660      */
661     private int insertIndexForLayer(Component comp, int layer, int position) {
662         int i, count, curLayer;
663         int layerStart = -1;
664         int layerEnd = -1;
665         int componentCount = getComponentCount();
666 
667         ArrayList<Component> compList =
668             new ArrayList<Component>(componentCount);
669         for (int index = 0; index < componentCount; index++) {
670             if (getComponent(index) != comp) {
671                 compList.add(getComponent(index));
672             }
673         }
674 
675         count = compList.size();
676         for (i = 0; i < count; i++) {
677             curLayer = getLayer(compList.get(i));
678             if (layerStart == -1 && curLayer == layer) {
679                 layerStart = i;
680             }
681             if (curLayer < layer) {
682                 if (i == 0) {
683                     // layer is greater than any current layer
684                     // [ ASSERT(layer > highestLayer()) ]
685                     layerStart = 0;
686                     layerEnd = 0;
687                 } else {
688                     layerEnd = i;
689                 }
690                 break;
691             }
692         }
693 
694         // layer requested is lower than any current layer
695         // [ ASSERT(layer < lowestLayer()) ]
696         // put it on the bottom of the stack
697         if (layerStart == -1 && layerEnd == -1)
698             return count;
699 
700         // In the case of a single layer entry handle the degenerative cases
701         if (layerStart != -1 && layerEnd == -1)
702             layerEnd = count;
703 
704         if (layerEnd != -1 && layerStart == -1)
705             layerStart = layerEnd;
706 
707         // If we are adding to the bottom, return the last element
708         if (position == -1)
709             return layerEnd;
710 
711         // Otherwise make sure the requested position falls in the
712         // proper range
713         if (position > -1 && layerStart + position <= layerEnd)
714             return layerStart + position;
715 
716         // Otherwise return the end of the layer
717         return layerEnd;
718     }
719 
720     /**
721      * Returns a string representation of this JLayeredPane. This method
722      * is intended to be used only for debugging purposes, and the
723      * content and format of the returned string may vary between
724      * implementations. The returned string may be empty but may not
725      * be <code>null</code>.
726      *
727      * @return  a string representation of this JLayeredPane.
728      */
729     protected String paramString() {
730         String optimizedDrawingPossibleString = (optimizedDrawingPossible ?
731                                                  "true" : "false");
732 
733         return super.paramString() +
734         ",optimizedDrawingPossible=" + optimizedDrawingPossibleString;
735     }
736 
737 /////////////////
738 // Accessibility support
739 ////////////////
740 
741     /**
742      * Gets the AccessibleContext associated with this JLayeredPane.
743      * For layered panes, the AccessibleContext takes the form of an
744      * AccessibleJLayeredPane.
745      * A new AccessibleJLayeredPane instance is created if necessary.
746      *
747      * @return an AccessibleJLayeredPane that serves as the
748      *         AccessibleContext of this JLayeredPane
749      */
750     public AccessibleContext getAccessibleContext() {
751         if (accessibleContext == null) {
752             accessibleContext = new AccessibleJLayeredPane();
753         }
754         return accessibleContext;
755     }
756 
757     /**
758      * This class implements accessibility support for the
759      * <code>JLayeredPane</code> class.  It provides an implementation of the
760      * Java Accessibility API appropriate to layered pane user-interface
761      * elements.
762      * <p>
763      * <strong>Warning:</strong>
764      * Serialized objects of this class will not be compatible with
765      * future Swing releases. The current serialization support is
766      * appropriate for short term storage or RMI between applications running
767      * the same version of Swing.  As of 1.4, support for long term storage
768      * of all JavaBeans&trade;
769      * has been added to the <code>java.beans</code> package.
770      * Please see {@link java.beans.XMLEncoder}.
771      */
772     @SuppressWarnings("serial")
773     protected class AccessibleJLayeredPane extends AccessibleJComponent {
774 
775         /**
776          * Get the role of this object.
777          *
778          * @return an instance of AccessibleRole describing the role of the
779          * object
780          * @see AccessibleRole
781          */
782         public AccessibleRole getAccessibleRole() {
783             return AccessibleRole.LAYERED_PANE;
784         }
785     }
786 }