View Javadoc
1   /*
2    * Copyright (c) 1995, 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  
26  package java.awt;
27  
28  import java.util.Hashtable;
29  
30  /**
31   * A border layout lays out a container, arranging and resizing
32   * its components to fit in five regions:
33   * north, south, east, west, and center.
34   * Each region may contain no more than one component, and
35   * is identified by a corresponding constant:
36   * <code>NORTH</code>, <code>SOUTH</code>, <code>EAST</code>,
37   * <code>WEST</code>, and <code>CENTER</code>.  When adding a
38   * component to a container with a border layout, use one of these
39   * five constants, for example:
40   * <pre>
41   *    Panel p = new Panel();
42   *    p.setLayout(new BorderLayout());
43   *    p.add(new Button("Okay"), BorderLayout.SOUTH);
44   * </pre>
45   * As a convenience, <code>BorderLayout</code> interprets the
46   * absence of a string specification the same as the constant
47   * <code>CENTER</code>:
48   * <pre>
49   *    Panel p2 = new Panel();
50   *    p2.setLayout(new BorderLayout());
51   *    p2.add(new TextArea());  // Same as p.add(new TextArea(), BorderLayout.CENTER);
52   * </pre>
53   * <p>
54   * In addition, <code>BorderLayout</code> supports the relative
55   * positioning constants, <code>PAGE_START</code>, <code>PAGE_END</code>,
56   * <code>LINE_START</code>, and <code>LINE_END</code>.
57   * In a container whose <code>ComponentOrientation</code> is set to
58   * <code>ComponentOrientation.LEFT_TO_RIGHT</code>, these constants map to
59   * <code>NORTH</code>, <code>SOUTH</code>, <code>WEST</code>, and
60   * <code>EAST</code>, respectively.
61   * <p>
62   * For compatibility with previous releases, <code>BorderLayout</code>
63   * also includes the relative positioning constants <code>BEFORE_FIRST_LINE</code>,
64   * <code>AFTER_LAST_LINE</code>, <code>BEFORE_LINE_BEGINS</code> and
65   * <code>AFTER_LINE_ENDS</code>.  These are equivalent to
66   * <code>PAGE_START</code>, <code>PAGE_END</code>, <code>LINE_START</code>
67   * and <code>LINE_END</code> respectively.  For
68   * consistency with the relative positioning constants used by other
69   * components, the latter constants are preferred.
70   * <p>
71   * Mixing both absolute and relative positioning constants can lead to
72   * unpredictable results.  If
73   * you use both types, the relative constants will take precedence.
74   * For example, if you add components using both the <code>NORTH</code>
75   * and <code>PAGE_START</code> constants in a container whose
76   * orientation is <code>LEFT_TO_RIGHT</code>, only the
77   * <code>PAGE_START</code> will be layed out.
78   * <p>
79   * NOTE: Currently (in the Java 2 platform v1.2),
80   * <code>BorderLayout</code> does not support vertical
81   * orientations.  The <code>isVertical</code> setting on the container's
82   * <code>ComponentOrientation</code> is not respected.
83   * <p>
84   * The components are laid out according to their
85   * preferred sizes and the constraints of the container's size.
86   * The <code>NORTH</code> and <code>SOUTH</code> components may
87   * be stretched horizontally; the <code>EAST</code> and
88   * <code>WEST</code> components may be stretched vertically;
89   * the <code>CENTER</code> component may stretch both horizontally
90   * and vertically to fill any space left over.
91   * <p>
92   * Here is an example of five buttons in an applet laid out using
93   * the <code>BorderLayout</code> layout manager:
94   * <p>
95   * <img src="doc-files/BorderLayout-1.gif"
96   * alt="Diagram of an applet demonstrating BorderLayout.
97   *      Each section of the BorderLayout contains a Button corresponding to its position in the layout, one of:
98   *      North, West, Center, East, or South."
99   * style="float:center; margin: 7px 10px;">
100  * <p>
101  * The code for this applet is as follows:
102  *
103  * <hr><blockquote><pre>
104  * import java.awt.*;
105  * import java.applet.Applet;
106  *
107  * public class buttonDir extends Applet {
108  *   public void init() {
109  *     setLayout(new BorderLayout());
110  *     add(new Button("North"), BorderLayout.NORTH);
111  *     add(new Button("South"), BorderLayout.SOUTH);
112  *     add(new Button("East"), BorderLayout.EAST);
113  *     add(new Button("West"), BorderLayout.WEST);
114  *     add(new Button("Center"), BorderLayout.CENTER);
115  *   }
116  * }
117  * </pre></blockquote><hr>
118  * <p>
119  * @author      Arthur van Hoff
120  * @see         java.awt.Container#add(String, Component)
121  * @see         java.awt.ComponentOrientation
122  * @since       JDK1.0
123  */
124 public class BorderLayout implements LayoutManager2,
125                                      java.io.Serializable {
126     /**
127      * Constructs a border layout with the horizontal gaps
128      * between components.
129      * The horizontal gap is specified by <code>hgap</code>.
130      *
131      * @see #getHgap()
132      * @see #setHgap(int)
133      *
134      * @serial
135      */
136         int hgap;
137 
138     /**
139      * Constructs a border layout with the vertical gaps
140      * between components.
141      * The vertical gap is specified by <code>vgap</code>.
142      *
143      * @see #getVgap()
144      * @see #setVgap(int)
145      * @serial
146      */
147         int vgap;
148 
149     /**
150      * Constant to specify components location to be the
151      *      north portion of the border layout.
152      * @serial
153      * @see #getChild(String, boolean)
154      * @see #addLayoutComponent
155      * @see #getLayoutAlignmentX
156      * @see #getLayoutAlignmentY
157      * @see #removeLayoutComponent
158      */
159         Component north;
160      /**
161      * Constant to specify components location to be the
162      *      west portion of the border layout.
163      * @serial
164      * @see #getChild(String, boolean)
165      * @see #addLayoutComponent
166      * @see #getLayoutAlignmentX
167      * @see #getLayoutAlignmentY
168      * @see #removeLayoutComponent
169      */
170         Component west;
171     /**
172      * Constant to specify components location to be the
173      *      east portion of the border layout.
174      * @serial
175      * @see #getChild(String, boolean)
176      * @see #addLayoutComponent
177      * @see #getLayoutAlignmentX
178      * @see #getLayoutAlignmentY
179      * @see #removeLayoutComponent
180      */
181         Component east;
182     /**
183      * Constant to specify components location to be the
184      *      south portion of the border layout.
185      * @serial
186      * @see #getChild(String, boolean)
187      * @see #addLayoutComponent
188      * @see #getLayoutAlignmentX
189      * @see #getLayoutAlignmentY
190      * @see #removeLayoutComponent
191      */
192     Component south;
193     /**
194      * Constant to specify components location to be the
195      *      center portion of the border layout.
196      * @serial
197      * @see #getChild(String, boolean)
198      * @see #addLayoutComponent
199      * @see #getLayoutAlignmentX
200      * @see #getLayoutAlignmentY
201      * @see #removeLayoutComponent
202      */
203         Component center;
204 
205     /**
206      *
207      * A relative positioning constant, that can be used instead of
208      * north, south, east, west or center.
209      * mixing the two types of constants can lead to unpredictable results.  If
210      * you use both types, the relative constants will take precedence.
211      * For example, if you add components using both the <code>NORTH</code>
212      * and <code>BEFORE_FIRST_LINE</code> constants in a container whose
213      * orientation is <code>LEFT_TO_RIGHT</code>, only the
214      * <code>BEFORE_FIRST_LINE</code> will be layed out.
215      * This will be the same for lastLine, firstItem, lastItem.
216      * @serial
217      */
218     Component firstLine;
219      /**
220      * A relative positioning constant, that can be used instead of
221      * north, south, east, west or center.
222      * Please read Description for firstLine.
223      * @serial
224      */
225         Component lastLine;
226      /**
227      * A relative positioning constant, that can be used instead of
228      * north, south, east, west or center.
229      * Please read Description for firstLine.
230      * @serial
231      */
232         Component firstItem;
233     /**
234      * A relative positioning constant, that can be used instead of
235      * north, south, east, west or center.
236      * Please read Description for firstLine.
237      * @serial
238      */
239         Component lastItem;
240 
241     /**
242      * The north layout constraint (top of container).
243      */
244     public static final String NORTH  = "North";
245 
246     /**
247      * The south layout constraint (bottom of container).
248      */
249     public static final String SOUTH  = "South";
250 
251     /**
252      * The east layout constraint (right side of container).
253      */
254     public static final String EAST   = "East";
255 
256     /**
257      * The west layout constraint (left side of container).
258      */
259     public static final String WEST   = "West";
260 
261     /**
262      * The center layout constraint (middle of container).
263      */
264     public static final String CENTER = "Center";
265 
266     /**
267      * Synonym for PAGE_START.  Exists for compatibility with previous
268      * versions.  PAGE_START is preferred.
269      *
270      * @see #PAGE_START
271      * @since 1.2
272      */
273     public static final String BEFORE_FIRST_LINE = "First";
274 
275     /**
276      * Synonym for PAGE_END.  Exists for compatibility with previous
277      * versions.  PAGE_END is preferred.
278      *
279      * @see #PAGE_END
280      * @since 1.2
281      */
282     public static final String AFTER_LAST_LINE = "Last";
283 
284     /**
285      * Synonym for LINE_START.  Exists for compatibility with previous
286      * versions.  LINE_START is preferred.
287      *
288      * @see #LINE_START
289      * @since 1.2
290      */
291     public static final String BEFORE_LINE_BEGINS = "Before";
292 
293     /**
294      * Synonym for LINE_END.  Exists for compatibility with previous
295      * versions.  LINE_END is preferred.
296      *
297      * @see #LINE_END
298      * @since 1.2
299      */
300     public static final String AFTER_LINE_ENDS = "After";
301 
302     /**
303      * The component comes before the first line of the layout's content.
304      * For Western, left-to-right and top-to-bottom orientations, this is
305      * equivalent to NORTH.
306      *
307      * @see java.awt.Component#getComponentOrientation
308      * @since 1.4
309      */
310     public static final String PAGE_START = BEFORE_FIRST_LINE;
311 
312     /**
313      * The component comes after the last line of the layout's content.
314      * For Western, left-to-right and top-to-bottom orientations, this is
315      * equivalent to SOUTH.
316      *
317      * @see java.awt.Component#getComponentOrientation
318      * @since 1.4
319      */
320     public static final String PAGE_END = AFTER_LAST_LINE;
321 
322     /**
323      * The component goes at the beginning of the line direction for the
324      * layout. For Western, left-to-right and top-to-bottom orientations,
325      * this is equivalent to WEST.
326      *
327      * @see java.awt.Component#getComponentOrientation
328      * @since 1.4
329      */
330     public static final String LINE_START = BEFORE_LINE_BEGINS;
331 
332     /**
333      * The component goes at the end of the line direction for the
334      * layout. For Western, left-to-right and top-to-bottom orientations,
335      * this is equivalent to EAST.
336      *
337      * @see java.awt.Component#getComponentOrientation
338      * @since 1.4
339      */
340     public static final String LINE_END = AFTER_LINE_ENDS;
341 
342     /*
343      * JDK 1.1 serialVersionUID
344      */
345      private static final long serialVersionUID = -8658291919501921765L;
346 
347     /**
348      * Constructs a new border layout with
349      * no gaps between components.
350      */
351     public BorderLayout() {
352         this(0, 0);
353     }
354 
355     /**
356      * Constructs a border layout with the specified gaps
357      * between components.
358      * The horizontal gap is specified by <code>hgap</code>
359      * and the vertical gap is specified by <code>vgap</code>.
360      * @param   hgap   the horizontal gap.
361      * @param   vgap   the vertical gap.
362      */
363     public BorderLayout(int hgap, int vgap) {
364         this.hgap = hgap;
365         this.vgap = vgap;
366     }
367 
368     /**
369      * Returns the horizontal gap between components.
370      * @since   JDK1.1
371      */
372     public int getHgap() {
373         return hgap;
374     }
375 
376     /**
377      * Sets the horizontal gap between components.
378      * @param hgap the horizontal gap between components
379      * @since   JDK1.1
380      */
381     public void setHgap(int hgap) {
382         this.hgap = hgap;
383     }
384 
385     /**
386      * Returns the vertical gap between components.
387      * @since   JDK1.1
388      */
389     public int getVgap() {
390         return vgap;
391     }
392 
393     /**
394      * Sets the vertical gap between components.
395      * @param vgap the vertical gap between components
396      * @since   JDK1.1
397      */
398     public void setVgap(int vgap) {
399         this.vgap = vgap;
400     }
401 
402     /**
403      * Adds the specified component to the layout, using the specified
404      * constraint object.  For border layouts, the constraint must be
405      * one of the following constants:  <code>NORTH</code>,
406      * <code>SOUTH</code>, <code>EAST</code>,
407      * <code>WEST</code>, or <code>CENTER</code>.
408      * <p>
409      * Most applications do not call this method directly. This method
410      * is called when a component is added to a container using the
411      * <code>Container.add</code> method with the same argument types.
412      * @param   comp         the component to be added.
413      * @param   constraints  an object that specifies how and where
414      *                       the component is added to the layout.
415      * @see     java.awt.Container#add(java.awt.Component, java.lang.Object)
416      * @exception   IllegalArgumentException  if the constraint object is not
417      *                 a string, or if it not one of the five specified
418          *              constants.
419      * @since   JDK1.1
420      */
421     public void addLayoutComponent(Component comp, Object constraints) {
422       synchronized (comp.getTreeLock()) {
423         if ((constraints == null) || (constraints instanceof String)) {
424             addLayoutComponent((String)constraints, comp);
425         } else {
426             throw new IllegalArgumentException("cannot add to layout: constraint must be a string (or null)");
427         }
428       }
429     }
430 
431     /**
432      * @deprecated  replaced by <code>addLayoutComponent(Component, Object)</code>.
433      */
434     @Deprecated
435     public void addLayoutComponent(String name, Component comp) {
436       synchronized (comp.getTreeLock()) {
437         /* Special case:  treat null the same as "Center". */
438         if (name == null) {
439             name = "Center";
440         }
441 
442         /* Assign the component to one of the known regions of the layout.
443          */
444         if ("Center".equals(name)) {
445             center = comp;
446         } else if ("North".equals(name)) {
447             north = comp;
448         } else if ("South".equals(name)) {
449             south = comp;
450         } else if ("East".equals(name)) {
451             east = comp;
452         } else if ("West".equals(name)) {
453             west = comp;
454         } else if (BEFORE_FIRST_LINE.equals(name)) {
455             firstLine = comp;
456         } else if (AFTER_LAST_LINE.equals(name)) {
457             lastLine = comp;
458         } else if (BEFORE_LINE_BEGINS.equals(name)) {
459             firstItem = comp;
460         } else if (AFTER_LINE_ENDS.equals(name)) {
461             lastItem = comp;
462         } else {
463             throw new IllegalArgumentException("cannot add to layout: unknown constraint: " + name);
464         }
465       }
466     }
467 
468     /**
469      * Removes the specified component from this border layout. This
470      * method is called when a container calls its <code>remove</code> or
471      * <code>removeAll</code> methods. Most applications do not call this
472      * method directly.
473      * @param   comp   the component to be removed.
474      * @see     java.awt.Container#remove(java.awt.Component)
475      * @see     java.awt.Container#removeAll()
476      */
477     public void removeLayoutComponent(Component comp) {
478       synchronized (comp.getTreeLock()) {
479         if (comp == center) {
480             center = null;
481         } else if (comp == north) {
482             north = null;
483         } else if (comp == south) {
484             south = null;
485         } else if (comp == east) {
486             east = null;
487         } else if (comp == west) {
488             west = null;
489         }
490         if (comp == firstLine) {
491             firstLine = null;
492         } else if (comp == lastLine) {
493             lastLine = null;
494         } else if (comp == firstItem) {
495             firstItem = null;
496         } else if (comp == lastItem) {
497             lastItem = null;
498         }
499       }
500     }
501 
502     /**
503      * Gets the component that was added using the given constraint
504      *
505      * @param   constraints  the desired constraint, one of <code>CENTER</code>,
506      *                       <code>NORTH</code>, <code>SOUTH</code>,
507      *                       <code>WEST</code>, <code>EAST</code>,
508      *                       <code>PAGE_START</code>, <code>PAGE_END</code>,
509      *                       <code>LINE_START</code>, <code>LINE_END</code>
510      * @return  the component at the given location, or <code>null</code> if
511      *          the location is empty
512      * @exception   IllegalArgumentException  if the constraint object is
513      *              not one of the nine specified constants
514      * @see     #addLayoutComponent(java.awt.Component, java.lang.Object)
515      * @since 1.5
516      */
517     public Component getLayoutComponent(Object constraints) {
518         if (CENTER.equals(constraints)) {
519             return center;
520         } else if (NORTH.equals(constraints)) {
521             return north;
522         } else if (SOUTH.equals(constraints)) {
523             return south;
524         } else if (WEST.equals(constraints)) {
525             return west;
526         } else if (EAST.equals(constraints)) {
527             return east;
528         } else if (PAGE_START.equals(constraints)) {
529             return firstLine;
530         } else if (PAGE_END.equals(constraints)) {
531             return lastLine;
532         } else if (LINE_START.equals(constraints)) {
533             return firstItem;
534         } else if (LINE_END.equals(constraints)) {
535             return lastItem;
536         } else {
537             throw new IllegalArgumentException("cannot get component: unknown constraint: " + constraints);
538         }
539     }
540 
541 
542     /**
543      * Returns the component that corresponds to the given constraint location
544      * based on the target <code>Container</code>'s component orientation.
545      * Components added with the relative constraints <code>PAGE_START</code>,
546      * <code>PAGE_END</code>, <code>LINE_START</code>, and <code>LINE_END</code>
547      * take precedence over components added with the explicit constraints
548      * <code>NORTH</code>, <code>SOUTH</code>, <code>WEST</code>, and <code>EAST</code>.
549      * The <code>Container</code>'s component orientation is used to determine the location of components
550      * added with <code>LINE_START</code> and <code>LINE_END</code>.
551      *
552      * @param   constraints     the desired absolute position, one of <code>CENTER</code>,
553      *                          <code>NORTH</code>, <code>SOUTH</code>,
554      *                          <code>EAST</code>, <code>WEST</code>
555      * @param   target     the {@code Container} used to obtain
556      *                     the constraint location based on the target
557      *                     {@code Container}'s component orientation.
558      * @return  the component at the given location, or <code>null</code> if
559      *          the location is empty
560      * @exception   IllegalArgumentException  if the constraint object is
561      *              not one of the five specified constants
562      * @exception   NullPointerException  if the target parameter is null
563      * @see     #addLayoutComponent(java.awt.Component, java.lang.Object)
564      * @since 1.5
565      */
566     public Component getLayoutComponent(Container target, Object constraints) {
567         boolean ltr = target.getComponentOrientation().isLeftToRight();
568         Component result = null;
569 
570         if (NORTH.equals(constraints)) {
571             result = (firstLine != null) ? firstLine : north;
572         } else if (SOUTH.equals(constraints)) {
573             result = (lastLine != null) ? lastLine : south;
574         } else if (WEST.equals(constraints)) {
575             result = ltr ? firstItem : lastItem;
576             if (result == null) {
577                 result = west;
578             }
579         } else if (EAST.equals(constraints)) {
580             result = ltr ? lastItem : firstItem;
581             if (result == null) {
582                 result = east;
583             }
584         } else if (CENTER.equals(constraints)) {
585             result = center;
586         } else {
587             throw new IllegalArgumentException("cannot get component: invalid constraint: " + constraints);
588         }
589 
590         return result;
591     }
592 
593 
594     /**
595      * Gets the constraints for the specified component
596      *
597      * @param   comp the component to be queried
598      * @return  the constraint for the specified component,
599      *          or null if component is null or is not present
600      *          in this layout
601      * @see #addLayoutComponent(java.awt.Component, java.lang.Object)
602      * @since 1.5
603      */
604     public Object getConstraints(Component comp) {
605         //fix for 6242148 : API method java.awt.BorderLayout.getConstraints(null) should return null
606         if (comp == null){
607             return null;
608         }
609         if (comp == center) {
610             return CENTER;
611         } else if (comp == north) {
612             return NORTH;
613         } else if (comp == south) {
614             return SOUTH;
615         } else if (comp == west) {
616             return WEST;
617         } else if (comp == east) {
618             return EAST;
619         } else if (comp == firstLine) {
620             return PAGE_START;
621         } else if (comp == lastLine) {
622             return PAGE_END;
623         } else if (comp == firstItem) {
624             return LINE_START;
625         } else if (comp == lastItem) {
626             return LINE_END;
627         }
628         return null;
629     }
630 
631     /**
632      * Determines the minimum size of the <code>target</code> container
633      * using this layout manager.
634      * <p>
635      * This method is called when a container calls its
636      * <code>getMinimumSize</code> method. Most applications do not call
637      * this method directly.
638      * @param   target   the container in which to do the layout.
639      * @return  the minimum dimensions needed to lay out the subcomponents
640      *          of the specified container.
641      * @see     java.awt.Container
642      * @see     java.awt.BorderLayout#preferredLayoutSize
643      * @see     java.awt.Container#getMinimumSize()
644      */
645     public Dimension minimumLayoutSize(Container target) {
646       synchronized (target.getTreeLock()) {
647         Dimension dim = new Dimension(0, 0);
648 
649         boolean ltr = target.getComponentOrientation().isLeftToRight();
650         Component c = null;
651 
652         if ((c=getChild(EAST,ltr)) != null) {
653             Dimension d = c.getMinimumSize();
654             dim.width += d.width + hgap;
655             dim.height = Math.max(d.height, dim.height);
656         }
657         if ((c=getChild(WEST,ltr)) != null) {
658             Dimension d = c.getMinimumSize();
659             dim.width += d.width + hgap;
660             dim.height = Math.max(d.height, dim.height);
661         }
662         if ((c=getChild(CENTER,ltr)) != null) {
663             Dimension d = c.getMinimumSize();
664             dim.width += d.width;
665             dim.height = Math.max(d.height, dim.height);
666         }
667         if ((c=getChild(NORTH,ltr)) != null) {
668             Dimension d = c.getMinimumSize();
669             dim.width = Math.max(d.width, dim.width);
670             dim.height += d.height + vgap;
671         }
672         if ((c=getChild(SOUTH,ltr)) != null) {
673             Dimension d = c.getMinimumSize();
674             dim.width = Math.max(d.width, dim.width);
675             dim.height += d.height + vgap;
676         }
677 
678         Insets insets = target.getInsets();
679         dim.width += insets.left + insets.right;
680         dim.height += insets.top + insets.bottom;
681 
682         return dim;
683       }
684     }
685 
686     /**
687      * Determines the preferred size of the <code>target</code>
688      * container using this layout manager, based on the components
689      * in the container.
690      * <p>
691      * Most applications do not call this method directly. This method
692      * is called when a container calls its <code>getPreferredSize</code>
693      * method.
694      * @param   target   the container in which to do the layout.
695      * @return  the preferred dimensions to lay out the subcomponents
696      *          of the specified container.
697      * @see     java.awt.Container
698      * @see     java.awt.BorderLayout#minimumLayoutSize
699      * @see     java.awt.Container#getPreferredSize()
700      */
701     public Dimension preferredLayoutSize(Container target) {
702       synchronized (target.getTreeLock()) {
703         Dimension dim = new Dimension(0, 0);
704 
705         boolean ltr = target.getComponentOrientation().isLeftToRight();
706         Component c = null;
707 
708         if ((c=getChild(EAST,ltr)) != null) {
709             Dimension d = c.getPreferredSize();
710             dim.width += d.width + hgap;
711             dim.height = Math.max(d.height, dim.height);
712         }
713         if ((c=getChild(WEST,ltr)) != null) {
714             Dimension d = c.getPreferredSize();
715             dim.width += d.width + hgap;
716             dim.height = Math.max(d.height, dim.height);
717         }
718         if ((c=getChild(CENTER,ltr)) != null) {
719             Dimension d = c.getPreferredSize();
720             dim.width += d.width;
721             dim.height = Math.max(d.height, dim.height);
722         }
723         if ((c=getChild(NORTH,ltr)) != null) {
724             Dimension d = c.getPreferredSize();
725             dim.width = Math.max(d.width, dim.width);
726             dim.height += d.height + vgap;
727         }
728         if ((c=getChild(SOUTH,ltr)) != null) {
729             Dimension d = c.getPreferredSize();
730             dim.width = Math.max(d.width, dim.width);
731             dim.height += d.height + vgap;
732         }
733 
734         Insets insets = target.getInsets();
735         dim.width += insets.left + insets.right;
736         dim.height += insets.top + insets.bottom;
737 
738         return dim;
739       }
740     }
741 
742     /**
743      * Returns the maximum dimensions for this layout given the components
744      * in the specified target container.
745      * @param target the component which needs to be laid out
746      * @see Container
747      * @see #minimumLayoutSize
748      * @see #preferredLayoutSize
749      */
750     public Dimension maximumLayoutSize(Container target) {
751         return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
752     }
753 
754     /**
755      * Returns the alignment along the x axis.  This specifies how
756      * the component would like to be aligned relative to other
757      * components.  The value should be a number between 0 and 1
758      * where 0 represents alignment along the origin, 1 is aligned
759      * the furthest away from the origin, 0.5 is centered, etc.
760      */
761     public float getLayoutAlignmentX(Container parent) {
762         return 0.5f;
763     }
764 
765     /**
766      * Returns the alignment along the y axis.  This specifies how
767      * the component would like to be aligned relative to other
768      * components.  The value should be a number between 0 and 1
769      * where 0 represents alignment along the origin, 1 is aligned
770      * the furthest away from the origin, 0.5 is centered, etc.
771      */
772     public float getLayoutAlignmentY(Container parent) {
773         return 0.5f;
774     }
775 
776     /**
777      * Invalidates the layout, indicating that if the layout manager
778      * has cached information it should be discarded.
779      */
780     public void invalidateLayout(Container target) {
781     }
782 
783     /**
784      * Lays out the container argument using this border layout.
785      * <p>
786      * This method actually reshapes the components in the specified
787      * container in order to satisfy the constraints of this
788      * <code>BorderLayout</code> object. The <code>NORTH</code>
789      * and <code>SOUTH</code> components, if any, are placed at
790      * the top and bottom of the container, respectively. The
791      * <code>WEST</code> and <code>EAST</code> components are
792      * then placed on the left and right, respectively. Finally,
793      * the <code>CENTER</code> object is placed in any remaining
794      * space in the middle.
795      * <p>
796      * Most applications do not call this method directly. This method
797      * is called when a container calls its <code>doLayout</code> method.
798      * @param   target   the container in which to do the layout.
799      * @see     java.awt.Container
800      * @see     java.awt.Container#doLayout()
801      */
802     public void layoutContainer(Container target) {
803       synchronized (target.getTreeLock()) {
804         Insets insets = target.getInsets();
805         int top = insets.top;
806         int bottom = target.height - insets.bottom;
807         int left = insets.left;
808         int right = target.width - insets.right;
809 
810         boolean ltr = target.getComponentOrientation().isLeftToRight();
811         Component c = null;
812 
813         if ((c=getChild(NORTH,ltr)) != null) {
814             c.setSize(right - left, c.height);
815             Dimension d = c.getPreferredSize();
816             c.setBounds(left, top, right - left, d.height);
817             top += d.height + vgap;
818         }
819         if ((c=getChild(SOUTH,ltr)) != null) {
820             c.setSize(right - left, c.height);
821             Dimension d = c.getPreferredSize();
822             c.setBounds(left, bottom - d.height, right - left, d.height);
823             bottom -= d.height + vgap;
824         }
825         if ((c=getChild(EAST,ltr)) != null) {
826             c.setSize(c.width, bottom - top);
827             Dimension d = c.getPreferredSize();
828             c.setBounds(right - d.width, top, d.width, bottom - top);
829             right -= d.width + hgap;
830         }
831         if ((c=getChild(WEST,ltr)) != null) {
832             c.setSize(c.width, bottom - top);
833             Dimension d = c.getPreferredSize();
834             c.setBounds(left, top, d.width, bottom - top);
835             left += d.width + hgap;
836         }
837         if ((c=getChild(CENTER,ltr)) != null) {
838             c.setBounds(left, top, right - left, bottom - top);
839         }
840       }
841     }
842 
843     /**
844      * Get the component that corresponds to the given constraint location
845      *
846      * @param   key     The desired absolute position,
847      *                  either NORTH, SOUTH, EAST, or WEST.
848      * @param   ltr     Is the component line direction left-to-right?
849      */
850     private Component getChild(String key, boolean ltr) {
851         Component result = null;
852 
853         if (key == NORTH) {
854             result = (firstLine != null) ? firstLine : north;
855         }
856         else if (key == SOUTH) {
857             result = (lastLine != null) ? lastLine : south;
858         }
859         else if (key == WEST) {
860             result = ltr ? firstItem : lastItem;
861             if (result == null) {
862                 result = west;
863             }
864         }
865         else if (key == EAST) {
866             result = ltr ? lastItem : firstItem;
867             if (result == null) {
868                 result = east;
869             }
870         }
871         else if (key == CENTER) {
872             result = center;
873         }
874         if (result != null && !result.visible) {
875             result = null;
876         }
877         return result;
878     }
879 
880     /**
881      * Returns a string representation of the state of this border layout.
882      * @return    a string representation of this border layout.
883      */
884     public String toString() {
885         return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]";
886     }
887 }