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