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