1/*
2 * Copyright (c) 1995, 2014, 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
26package java.awt;
27
28import 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 SOUTH}, {@code EAST},
37 * {@code WEST}, and {@code CENTER}.  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} interprets the
46 * absence of a string specification the same as the constant
47 * {@code CENTER}:
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} supports the relative
55 * positioning constants, {@code PAGE_START}, {@code PAGE_END},
56 * {@code LINE_START}, and {@code LINE_END}.
57 * In a container whose {@code ComponentOrientation} is set to
58 * {@code ComponentOrientation.LEFT_TO_RIGHT}, these constants map to
59 * {@code NORTH}, {@code SOUTH}, {@code WEST}, and
60 * {@code EAST}, respectively.
61 * <p>
62 * For compatibility with previous releases, {@code BorderLayout}
63 * also includes the relative positioning constants {@code BEFORE_FIRST_LINE},
64 * {@code AFTER_LAST_LINE}, {@code BEFORE_LINE_BEGINS} and
65 * {@code AFTER_LINE_ENDS}.  These are equivalent to
66 * {@code PAGE_START}, {@code PAGE_END}, {@code LINE_START}
67 * and {@code LINE_END} 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}
75 * and {@code PAGE_START} constants in a container whose
76 * orientation is {@code LEFT_TO_RIGHT}, only the
77 * {@code PAGE_START} will be laid out.
78 * <p>
79 * NOTE: Currently,
80 * {@code BorderLayout} does not support vertical
81 * orientations.  The {@code isVertical} setting on the container's
82 * {@code ComponentOrientation} 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} and {@code SOUTH} components may
87 * be stretched horizontally; the {@code EAST} and
88 * {@code WEST} components may be stretched vertically;
89 * the {@code CENTER} 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} 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 *
119 * @author      Arthur van Hoff
120 * @see         java.awt.Container#add(String, Component)
121 * @see         java.awt.ComponentOrientation
122 * @since       1.0
123 */
124public 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}.
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}.
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}
212     * and {@code BEFORE_FIRST_LINE} constants in a container whose
213     * orientation is {@code LEFT_TO_RIGHT}, only the
214     * {@code BEFORE_FIRST_LINE} will be laid 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}
359     * and the vertical gap is specified by {@code vgap}.
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     *
371     * @return the horizontal gap between components
372     * @since   1.1
373     */
374    public int getHgap() {
375        return hgap;
376    }
377
378    /**
379     * Sets the horizontal gap between components.
380     *
381     * @param hgap the horizontal gap between components
382     * @since   1.1
383     */
384    public void setHgap(int hgap) {
385        this.hgap = hgap;
386    }
387
388    /**
389     * Returns the vertical gap between components.
390     *
391     * @return the vertical gap between components
392     * @since   1.1
393     */
394    public int getVgap() {
395        return vgap;
396    }
397
398    /**
399     * Sets the vertical gap between components.
400     *
401     * @param vgap the vertical gap between components
402     * @since   1.1
403     */
404    public void setVgap(int vgap) {
405        this.vgap = vgap;
406    }
407
408    /**
409     * Adds the specified component to the layout, using the specified
410     * constraint object.  For border layouts, the constraint must be
411     * one of the following constants:  {@code NORTH},
412     * {@code SOUTH}, {@code EAST},
413     * {@code WEST}, or {@code CENTER}.
414     * <p>
415     * Most applications do not call this method directly. This method
416     * is called when a component is added to a container using the
417     * {@code Container.add} method with the same argument types.
418     * @param   comp         the component to be added.
419     * @param   constraints  an object that specifies how and where
420     *                       the component is added to the layout.
421     * @see     java.awt.Container#add(java.awt.Component, java.lang.Object)
422     * @exception   IllegalArgumentException  if the constraint object is not
423     *              a string, or if it not one of the five specified constants.
424     * @since   1.1
425     */
426    public void addLayoutComponent(Component comp, Object constraints) {
427      synchronized (comp.getTreeLock()) {
428        if ((constraints == null) || (constraints instanceof String)) {
429            addLayoutComponent((String)constraints, comp);
430        } else {
431            throw new IllegalArgumentException("cannot add to layout: constraint must be a string (or null)");
432        }
433      }
434    }
435
436    /**
437     * @deprecated  replaced by {@code addLayoutComponent(Component, Object)}.
438     */
439    @Deprecated
440    public void addLayoutComponent(String name, Component comp) {
441      synchronized (comp.getTreeLock()) {
442        /* Special case:  treat null the same as "Center". */
443        if (name == null) {
444            name = "Center";
445        }
446
447        /* Assign the component to one of the known regions of the layout.
448         */
449        if ("Center".equals(name)) {
450            center = comp;
451        } else if ("North".equals(name)) {
452            north = comp;
453        } else if ("South".equals(name)) {
454            south = comp;
455        } else if ("East".equals(name)) {
456            east = comp;
457        } else if ("West".equals(name)) {
458            west = comp;
459        } else if (BEFORE_FIRST_LINE.equals(name)) {
460            firstLine = comp;
461        } else if (AFTER_LAST_LINE.equals(name)) {
462            lastLine = comp;
463        } else if (BEFORE_LINE_BEGINS.equals(name)) {
464            firstItem = comp;
465        } else if (AFTER_LINE_ENDS.equals(name)) {
466            lastItem = comp;
467        } else {
468            throw new IllegalArgumentException("cannot add to layout: unknown constraint: " + name);
469        }
470      }
471    }
472
473    /**
474     * Removes the specified component from this border layout. This
475     * method is called when a container calls its {@code remove} or
476     * {@code removeAll} methods. Most applications do not call this
477     * method directly.
478     * @param   comp   the component to be removed.
479     * @see     java.awt.Container#remove(java.awt.Component)
480     * @see     java.awt.Container#removeAll()
481     */
482    public void removeLayoutComponent(Component comp) {
483      synchronized (comp.getTreeLock()) {
484        if (comp == center) {
485            center = null;
486        } else if (comp == north) {
487            north = null;
488        } else if (comp == south) {
489            south = null;
490        } else if (comp == east) {
491            east = null;
492        } else if (comp == west) {
493            west = null;
494        }
495        if (comp == firstLine) {
496            firstLine = null;
497        } else if (comp == lastLine) {
498            lastLine = null;
499        } else if (comp == firstItem) {
500            firstItem = null;
501        } else if (comp == lastItem) {
502            lastItem = null;
503        }
504      }
505    }
506
507    /**
508     * Gets the component that was added using the given constraint
509     *
510     * @param   constraints  the desired constraint, one of {@code CENTER},
511     *                       {@code NORTH}, {@code SOUTH},
512     *                       {@code WEST}, {@code EAST},
513     *                       {@code PAGE_START}, {@code PAGE_END},
514     *                       {@code LINE_START}, {@code LINE_END}
515     * @return  the component at the given location, or {@code null} if
516     *          the location is empty
517     * @exception   IllegalArgumentException  if the constraint object is
518     *              not one of the nine specified constants
519     * @see     #addLayoutComponent(java.awt.Component, java.lang.Object)
520     * @since 1.5
521     */
522    public Component getLayoutComponent(Object constraints) {
523        if (CENTER.equals(constraints)) {
524            return center;
525        } else if (NORTH.equals(constraints)) {
526            return north;
527        } else if (SOUTH.equals(constraints)) {
528            return south;
529        } else if (WEST.equals(constraints)) {
530            return west;
531        } else if (EAST.equals(constraints)) {
532            return east;
533        } else if (PAGE_START.equals(constraints)) {
534            return firstLine;
535        } else if (PAGE_END.equals(constraints)) {
536            return lastLine;
537        } else if (LINE_START.equals(constraints)) {
538            return firstItem;
539        } else if (LINE_END.equals(constraints)) {
540            return lastItem;
541        } else {
542            throw new IllegalArgumentException("cannot get component: unknown constraint: " + constraints);
543        }
544    }
545
546
547    /**
548     * Returns the component that corresponds to the given constraint location
549     * based on the target {@code Container}'s component orientation.
550     * Components added with the relative constraints {@code PAGE_START},
551     * {@code PAGE_END}, {@code LINE_START}, and {@code LINE_END}
552     * take precedence over components added with the explicit constraints
553     * {@code NORTH}, {@code SOUTH}, {@code WEST}, and {@code EAST}.
554     * The {@code Container}'s component orientation is used to determine the location of components
555     * added with {@code LINE_START} and {@code LINE_END}.
556     *
557     * @param   constraints     the desired absolute position, one of {@code CENTER},
558     *                          {@code NORTH}, {@code SOUTH},
559     *                          {@code EAST}, {@code WEST}
560     * @param   target     the {@code Container} used to obtain
561     *                     the constraint location based on the target
562     *                     {@code Container}'s component orientation.
563     * @return  the component at the given location, or {@code null} if
564     *          the location is empty
565     * @exception   IllegalArgumentException  if the constraint object is
566     *              not one of the five specified constants
567     * @exception   NullPointerException  if the target parameter is null
568     * @see     #addLayoutComponent(java.awt.Component, java.lang.Object)
569     * @since 1.5
570     */
571    public Component getLayoutComponent(Container target, Object constraints) {
572        boolean ltr = target.getComponentOrientation().isLeftToRight();
573        Component result = null;
574
575        if (NORTH.equals(constraints)) {
576            result = (firstLine != null) ? firstLine : north;
577        } else if (SOUTH.equals(constraints)) {
578            result = (lastLine != null) ? lastLine : south;
579        } else if (WEST.equals(constraints)) {
580            result = ltr ? firstItem : lastItem;
581            if (result == null) {
582                result = west;
583            }
584        } else if (EAST.equals(constraints)) {
585            result = ltr ? lastItem : firstItem;
586            if (result == null) {
587                result = east;
588            }
589        } else if (CENTER.equals(constraints)) {
590            result = center;
591        } else {
592            throw new IllegalArgumentException("cannot get component: invalid constraint: " + constraints);
593        }
594
595        return result;
596    }
597
598
599    /**
600     * Gets the constraints for the specified component
601     *
602     * @param   comp the component to be queried
603     * @return  the constraint for the specified component,
604     *          or null if component is null or is not present
605     *          in this layout
606     * @see #addLayoutComponent(java.awt.Component, java.lang.Object)
607     * @since 1.5
608     */
609    public Object getConstraints(Component comp) {
610        //fix for 6242148 : API method java.awt.BorderLayout.getConstraints(null) should return null
611        if (comp == null){
612            return null;
613        }
614        if (comp == center) {
615            return CENTER;
616        } else if (comp == north) {
617            return NORTH;
618        } else if (comp == south) {
619            return SOUTH;
620        } else if (comp == west) {
621            return WEST;
622        } else if (comp == east) {
623            return EAST;
624        } else if (comp == firstLine) {
625            return PAGE_START;
626        } else if (comp == lastLine) {
627            return PAGE_END;
628        } else if (comp == firstItem) {
629            return LINE_START;
630        } else if (comp == lastItem) {
631            return LINE_END;
632        }
633        return null;
634    }
635
636    /**
637     * Determines the minimum size of the {@code target} container
638     * using this layout manager.
639     * <p>
640     * This method is called when a container calls its
641     * {@code getMinimumSize} method. Most applications do not call
642     * this method directly.
643     * @param   target   the container in which to do the layout.
644     * @return  the minimum dimensions needed to lay out the subcomponents
645     *          of the specified container.
646     * @see     java.awt.Container
647     * @see     java.awt.BorderLayout#preferredLayoutSize
648     * @see     java.awt.Container#getMinimumSize()
649     */
650    public Dimension minimumLayoutSize(Container target) {
651      synchronized (target.getTreeLock()) {
652        Dimension dim = new Dimension(0, 0);
653
654        boolean ltr = target.getComponentOrientation().isLeftToRight();
655        Component c = null;
656
657        if ((c=getChild(EAST,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(WEST,ltr)) != null) {
663            Dimension d = c.getMinimumSize();
664            dim.width += d.width + hgap;
665            dim.height = Math.max(d.height, dim.height);
666        }
667        if ((c=getChild(CENTER,ltr)) != null) {
668            Dimension d = c.getMinimumSize();
669            dim.width += d.width;
670            dim.height = Math.max(d.height, dim.height);
671        }
672        if ((c=getChild(NORTH,ltr)) != null) {
673            Dimension d = c.getMinimumSize();
674            dim.width = Math.max(d.width, dim.width);
675            dim.height += d.height + vgap;
676        }
677        if ((c=getChild(SOUTH,ltr)) != null) {
678            Dimension d = c.getMinimumSize();
679            dim.width = Math.max(d.width, dim.width);
680            dim.height += d.height + vgap;
681        }
682
683        Insets insets = target.getInsets();
684        dim.width += insets.left + insets.right;
685        dim.height += insets.top + insets.bottom;
686
687        return dim;
688      }
689    }
690
691    /**
692     * Determines the preferred size of the {@code target}
693     * container using this layout manager, based on the components
694     * in the container.
695     * <p>
696     * Most applications do not call this method directly. This method
697     * is called when a container calls its {@code getPreferredSize}
698     * method.
699     * @param   target   the container in which to do the layout.
700     * @return  the preferred dimensions to lay out the subcomponents
701     *          of the specified container.
702     * @see     java.awt.Container
703     * @see     java.awt.BorderLayout#minimumLayoutSize
704     * @see     java.awt.Container#getPreferredSize()
705     */
706    public Dimension preferredLayoutSize(Container target) {
707      synchronized (target.getTreeLock()) {
708        Dimension dim = new Dimension(0, 0);
709
710        boolean ltr = target.getComponentOrientation().isLeftToRight();
711        Component c = null;
712
713        if ((c=getChild(EAST,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(WEST,ltr)) != null) {
719            Dimension d = c.getPreferredSize();
720            dim.width += d.width + hgap;
721            dim.height = Math.max(d.height, dim.height);
722        }
723        if ((c=getChild(CENTER,ltr)) != null) {
724            Dimension d = c.getPreferredSize();
725            dim.width += d.width;
726            dim.height = Math.max(d.height, dim.height);
727        }
728        if ((c=getChild(NORTH,ltr)) != null) {
729            Dimension d = c.getPreferredSize();
730            dim.width = Math.max(d.width, dim.width);
731            dim.height += d.height + vgap;
732        }
733        if ((c=getChild(SOUTH,ltr)) != null) {
734            Dimension d = c.getPreferredSize();
735            dim.width = Math.max(d.width, dim.width);
736            dim.height += d.height + vgap;
737        }
738
739        Insets insets = target.getInsets();
740        dim.width += insets.left + insets.right;
741        dim.height += insets.top + insets.bottom;
742
743        return dim;
744      }
745    }
746
747    /**
748     * Returns the maximum dimensions for this layout given the components
749     * in the specified target container.
750     * @param target the component which needs to be laid out
751     * @see Container
752     * @see #minimumLayoutSize
753     * @see #preferredLayoutSize
754     */
755    public Dimension maximumLayoutSize(Container target) {
756        return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
757    }
758
759    /**
760     * Returns the alignment along the x axis.  This specifies how
761     * the component would like to be aligned relative to other
762     * components.  The value should be a number between 0 and 1
763     * where 0 represents alignment along the origin, 1 is aligned
764     * the furthest away from the origin, 0.5 is centered, etc.
765     */
766    public float getLayoutAlignmentX(Container parent) {
767        return 0.5f;
768    }
769
770    /**
771     * Returns the alignment along the y axis.  This specifies how
772     * the component would like to be aligned relative to other
773     * components.  The value should be a number between 0 and 1
774     * where 0 represents alignment along the origin, 1 is aligned
775     * the furthest away from the origin, 0.5 is centered, etc.
776     */
777    public float getLayoutAlignmentY(Container parent) {
778        return 0.5f;
779    }
780
781    /**
782     * Invalidates the layout, indicating that if the layout manager
783     * has cached information it should be discarded.
784     */
785    public void invalidateLayout(Container target) {
786    }
787
788    /**
789     * Lays out the container argument using this border layout.
790     * <p>
791     * This method actually reshapes the components in the specified
792     * container in order to satisfy the constraints of this
793     * {@code BorderLayout} object. The {@code NORTH}
794     * and {@code SOUTH} components, if any, are placed at
795     * the top and bottom of the container, respectively. The
796     * {@code WEST} and {@code EAST} components are
797     * then placed on the left and right, respectively. Finally,
798     * the {@code CENTER} object is placed in any remaining
799     * space in the middle.
800     * <p>
801     * Most applications do not call this method directly. This method
802     * is called when a container calls its {@code doLayout} method.
803     * @param   target   the container in which to do the layout.
804     * @see     java.awt.Container
805     * @see     java.awt.Container#doLayout()
806     */
807    public void layoutContainer(Container target) {
808      synchronized (target.getTreeLock()) {
809        Insets insets = target.getInsets();
810        int top = insets.top;
811        int bottom = target.height - insets.bottom;
812        int left = insets.left;
813        int right = target.width - insets.right;
814
815        boolean ltr = target.getComponentOrientation().isLeftToRight();
816        Component c = null;
817
818        if ((c=getChild(NORTH,ltr)) != null) {
819            c.setSize(right - left, c.height);
820            Dimension d = c.getPreferredSize();
821            c.setBounds(left, top, right - left, d.height);
822            top += d.height + vgap;
823        }
824        if ((c=getChild(SOUTH,ltr)) != null) {
825            c.setSize(right - left, c.height);
826            Dimension d = c.getPreferredSize();
827            c.setBounds(left, bottom - d.height, right - left, d.height);
828            bottom -= d.height + vgap;
829        }
830        if ((c=getChild(EAST,ltr)) != null) {
831            c.setSize(c.width, bottom - top);
832            Dimension d = c.getPreferredSize();
833            c.setBounds(right - d.width, top, d.width, bottom - top);
834            right -= d.width + hgap;
835        }
836        if ((c=getChild(WEST,ltr)) != null) {
837            c.setSize(c.width, bottom - top);
838            Dimension d = c.getPreferredSize();
839            c.setBounds(left, top, d.width, bottom - top);
840            left += d.width + hgap;
841        }
842        if ((c=getChild(CENTER,ltr)) != null) {
843            c.setBounds(left, top, right - left, bottom - top);
844        }
845      }
846    }
847
848    /**
849     * Get the component that corresponds to the given constraint location
850     *
851     * @param   key     The desired absolute position,
852     *                  either NORTH, SOUTH, EAST, or WEST.
853     * @param   ltr     Is the component line direction left-to-right?
854     */
855    private Component getChild(String key, boolean ltr) {
856        Component result = null;
857
858        if (key == NORTH) {
859            result = (firstLine != null) ? firstLine : north;
860        }
861        else if (key == SOUTH) {
862            result = (lastLine != null) ? lastLine : south;
863        }
864        else if (key == WEST) {
865            result = ltr ? firstItem : lastItem;
866            if (result == null) {
867                result = west;
868            }
869        }
870        else if (key == EAST) {
871            result = ltr ? lastItem : firstItem;
872            if (result == null) {
873                result = east;
874            }
875        }
876        else if (key == CENTER) {
877            result = center;
878        }
879        if (result != null && !result.visible) {
880            result = null;
881        }
882        return result;
883    }
884
885    /**
886     * Returns a string representation of the state of this border layout.
887     * @return    a string representation of this border layout.
888     */
889    public String toString() {
890        return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]";
891    }
892}
893