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 
  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       1.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      *
 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</code>,
 412      * <code>SOUTH</code>, <code>EAST</code>,
 413      * <code>WEST</code>, or <code>CENTER</code>.
 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</code> 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)</code>.
 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</code> or
 476      * <code>removeAll</code> 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</code>,
 511      *                       <code>NORTH</code>, <code>SOUTH</code>,
 512      *                       <code>WEST</code>, <code>EAST</code>,
 513      *                       <code>PAGE_START</code>, <code>PAGE_END</code>,
 514      *                       <code>LINE_START</code>, <code>LINE_END</code>
 515      * @return  the component at the given location, or <code>null</code> 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</code>'s component orientation.
 550      * Components added with the relative constraints <code>PAGE_START</code>,
 551      * <code>PAGE_END</code>, <code>LINE_START</code>, and <code>LINE_END</code>
 552      * take precedence over components added with the explicit constraints
 553      * <code>NORTH</code>, <code>SOUTH</code>, <code>WEST</code>, and <code>EAST</code>.
 554      * The <code>Container</code>'s component orientation is used to determine the location of components
 555      * added with <code>LINE_START</code> and <code>LINE_END</code>.
 556      *
 557      * @param   constraints     the desired absolute position, one of <code>CENTER</code>,
 558      *                          <code>NORTH</code>, <code>SOUTH</code>,
 559      *                          <code>EAST</code>, <code>WEST</code>
 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</code> 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</code> container
 638      * using this layout manager.
 639      * <p>
 640      * This method is called when a container calls its
 641      * <code>getMinimumSize</code> 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</code>
 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</code>
 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</code> object. The <code>NORTH</code>
 794      * and <code>SOUTH</code> components, if any, are placed at
 795      * the top and bottom of the container, respectively. The
 796      * <code>WEST</code> and <code>EAST</code> components are
 797      * then placed on the left and right, respectively. Finally,
 798      * the <code>CENTER</code> 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</code> 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 }