1 /* BorderLayout.java -- A layout manager class
2 Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
42 * This class implements a layout manager that positions components
43 * in certain sectors of the parent container.
45 * @author Aaron M. Renn (arenn@urbanophile.com)
46 * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
48 public class BorderLayout implements LayoutManager2, java.io.Serializable
52 * Constant indicating the top of the container
54 public static final String NORTH = "North";
57 * Constant indicating the bottom of the container
59 public static final String SOUTH = "South";
62 * Constant indicating the right side of the container
64 public static final String EAST = "East";
67 * Constant indicating the left side of the container
69 public static final String WEST = "West";
72 * Constant indicating the center of the container
74 public static final String CENTER = "Center";
78 * The constant indicating the position before the first line of the
79 * layout. The exact position depends on the writing system: For a
80 * top-to-bottom orientation, it is the same as {@link #NORTH}, for
81 * a bottom-to-top orientation, it is the same as {@link #SOUTH}.
83 * <p>This constant is an older name for {@link #PAGE_START} which
84 * has exactly the same value.
88 public static final String BEFORE_FIRST_LINE = "First";
91 * The constant indicating the position after the last line of the
92 * layout. The exact position depends on the writing system: For a
93 * top-to-bottom orientation, it is the same as {@link #SOUTH}, for
94 * a bottom-to-top orientation, it is the same as {@link #NORTH}.
96 * <p>This constant is an older name for {@link #PAGE_END} which
97 * has exactly the same value.
101 public static final String AFTER_LAST_LINE = "Last";
104 * The constant indicating the position before the first item of the
105 * layout. The exact position depends on the writing system: For a
106 * left-to-right orientation, it is the same as {@link #WEST}, for
107 * a right-to-left orientation, it is the same as {@link #EAST}.
109 * <p>This constant is an older name for {@link #LINE_START} which
110 * has exactly the same value.
114 public static final String BEFORE_LINE_BEGINS = "Before";
117 * The constant indicating the position after the last item of the
118 * layout. The exact position depends on the writing system: For a
119 * left-to-right orientation, it is the same as {@link #EAST}, for
120 * a right-to-left orientation, it is the same as {@link #WEST}.
122 * <p>This constant is an older name for {@link #LINE_END} which
123 * has exactly the same value.
127 public static final String AFTER_LINE_ENDS = "After";
130 * The constant indicating the position before the first line of the
131 * layout. The exact position depends on the writing system: For a
132 * top-to-bottom orientation, it is the same as {@link #NORTH}, for
133 * a bottom-to-top orientation, it is the same as {@link #SOUTH}.
137 public static final String PAGE_START = BEFORE_FIRST_LINE;
140 * The constant indicating the position after the last line of the
141 * layout. The exact position depends on the writing system: For a
142 * top-to-bottom orientation, it is the same as {@link #SOUTH}, for
143 * a bottom-to-top orientation, it is the same as {@link #NORTH}.
147 public static final String PAGE_END = AFTER_LAST_LINE;
150 * The constant indicating the position before the first item of the
151 * layout. The exact position depends on the writing system: For a
152 * left-to-right orientation, it is the same as {@link #WEST}, for
153 * a right-to-left orientation, it is the same as {@link #EAST}.
157 public static final String LINE_START = BEFORE_LINE_BEGINS;
160 * The constant indicating the position after the last item of the
161 * layout. The exact position depends on the writing system: For a
162 * left-to-right orientation, it is the same as {@link #EAST}, for
163 * a right-to-left orientation, it is the same as {@link #WEST}.
167 public static final String LINE_END = AFTER_LINE_ENDS;
171 * Serialization constant.
173 private static final long serialVersionUID = -8658291919501921765L;
179 private Component north;
184 private Component south;
189 private Component east;
194 private Component west;
199 private Component center;
204 private Component firstLine;
209 private Component lastLine;
214 private Component firstItem;
219 private Component lastItem;
222 * @serial The horizontal gap between components
227 * @serial The vertical gap between components
233 * Initializes a new instance of <code>BorderLayout</code> with no
234 * horiztonal or vertical gaps between components.
236 public BorderLayout()
242 * Initializes a new instance of <code>BorderLayout</code> with the
243 * specified horiztonal and vertical gaps between components.
245 * @param hgap The horizontal gap between components.
246 * @param vgap The vertical gap between components.
248 public BorderLayout(int hgap, int vgap)
255 * Returns the horitzontal gap value.
257 * @return The horitzontal gap value.
265 * Sets the horizontal gap to the specified value.
267 * @param hgap The new horizontal gap.
269 public void setHgap(int hgap)
275 * Returns the vertical gap value.
277 * @return The vertical gap value.
285 * Sets the vertical gap to the specified value.
287 * @param vgap The new vertical gap value.
289 public void setVgap(int vgap)
295 * Adds a component to the layout in the specified constraint position,
296 * which must be one of the string constants defined in this class.
298 * @param component The component to add.
299 * @param constraints The constraint string.
301 * @exception IllegalArgumentException If the constraint object is not
302 * a string, or is not one of the specified constants in this class.
304 public void addLayoutComponent(Component component, Object constraints)
306 if (constraints != null && ! (constraints instanceof String))
307 throw new IllegalArgumentException("Constraint must be a string");
309 addLayoutComponent((String) constraints, component);
313 * Adds a component to the layout in the specified constraint position,
314 * which must be one of the string constants defined in this class.
316 * @param constraints The constraint string.
317 * @param component The component to add.
319 * @exception IllegalArgumentException If the constraint object is not
320 * one of the specified constants in this class.
322 * @deprecated This method is deprecated in favor of
323 * <code>addLayoutComponent(Component, Object)</code>.
325 public void addLayoutComponent(String constraints, Component component)
327 String str = constraints;
329 if (str == null || str.equals(CENTER))
331 else if (str.equals(NORTH))
333 else if (str.equals(SOUTH))
335 else if (str.equals(EAST))
337 else if (str.equals(WEST))
339 else if (str.equals(BEFORE_FIRST_LINE))
340 firstLine = component;
341 else if (str.equals(AFTER_LAST_LINE))
342 lastLine = component;
343 else if (str.equals(BEFORE_LINE_BEGINS))
344 firstItem = component;
345 else if (str.equals(AFTER_LINE_ENDS))
346 lastItem = component;
348 throw new IllegalArgumentException("Constraint value not valid: " + str);
352 * Removes the specified component from the layout.
354 * @param component The component to remove from the layout.
356 public void removeLayoutComponent(Component component)
358 if (north == component)
360 if (south == component)
362 if (east == component)
364 if (west == component)
366 if (center == component)
368 if (firstItem == component)
370 if (lastItem == component)
372 if (firstLine == component)
374 if (lastLine == component)
379 * Returns the minimum size of the specified container using this layout.
381 * @param target The container to calculate the minimum size for.
383 * @return The minimum size of the container
385 public Dimension minimumLayoutSize(Container target)
387 return calcSize(target, MIN);
391 * Returns the preferred size of the specified container using this layout.
393 * @param target The container to calculate the preferred size for.
395 * @return The preferred size of the container
397 public Dimension preferredLayoutSize(Container target)
399 return calcSize(target, PREF);
403 * Returns the maximum size of the specified container using this layout.
405 * @param target The container to calculate the maximum size for.
407 * @return The maximum size of the container
409 public Dimension maximumLayoutSize(Container target)
411 return calcSize(target, MAX);
415 * Returns the X axis alignment, which is a <code>float</code> indicating
416 * where along the X axis this container wishs to position its layout.
417 * 0 indicates align to the left, 1 indicates align to the right, and 0.5
418 * indicates align to the center.
420 * @param parent The parent container.
422 * @return The X alignment value.
424 public float getLayoutAlignmentX(Container parent)
426 return(parent.getAlignmentX());
430 * Returns the Y axis alignment, which is a <code>float</code> indicating
431 * where along the Y axis this container wishs to position its layout.
432 * 0 indicates align to the top, 1 indicates align to the bottom, and 0.5
433 * indicates align to the center.
435 * @param parent The parent container.
437 * @return The Y alignment value.
439 public float getLayoutAlignmentY(Container parent)
441 return(parent.getAlignmentY());
445 * Instructs this object to discard any layout information it might
448 * @param parent The parent container.
450 public void invalidateLayout(Container parent)
452 // FIXME: Implement this properly!
456 * Lays out the specified container according to the constraints
459 * @param target The container to lay out.
461 public void layoutContainer(Container target)
463 synchronized (target.getTreeLock ())
465 Insets i = target.getInsets();
467 ComponentOrientation orient = target.getComponentOrientation ();
468 boolean left_to_right = orient.isLeftToRight ();
470 Component my_north = north;
471 Component my_east = east;
472 Component my_south = south;
473 Component my_west = west;
475 // Note that we currently don't handle vertical layouts. Neither
477 if (firstLine != null)
478 my_north = firstLine;
479 if (lastLine != null)
481 if (firstItem != null)
488 if (lastItem != null)
496 Dimension c = calcCompSize(center, PREF);
497 Dimension n = calcCompSize(my_north, PREF);
498 Dimension s = calcCompSize(my_south, PREF);
499 Dimension e = calcCompSize(my_east, PREF);
500 Dimension w = calcCompSize(my_west, PREF);
501 int targetWidth = target.getWidth();
502 int targetHeight = target.getHeight();
506 +----------------------------+ }
508 | +----------------------+ | --- y1 }
510 | +----------------------+ | } vgap
511 | +---+ +----------+ +---+ | --- y2 } }
512 | |w | |c | |e | | } hh
513 | +---+ +----------+ +---+ | } vgap }
514 | +----------------------+ | --- y3 }
516 | +----------------------+ | }
518 +----------------------------+ }
520 <---------------------->
526 int x2 = x1 + w.width + (w.width == 0 ? 0 : hgap);
528 if (targetWidth <= i.right + e.width)
529 x3 = x2 + w.width + (w.width == 0 ? 0 : hgap);
531 x3 = targetWidth - i.right - e.width;
532 int ww = targetWidth - i.right - i.left;
535 int y2 = y1 + n.height + (n.height == 0 ? 0 : vgap);
536 int midh = Math.max(e.height, Math.max(w.height, c.height));
538 if (targetHeight <= i.bottom + s.height)
539 y3 = y2 + midh + vgap;
541 y3 = targetHeight - i.bottom - s.height;
542 int hh = y3-y2-(s.height == 0 ? 0 : vgap);
544 setBounds(center, x2, y2, x3-x2-(w.width == 0 ? 0 : hgap), hh);
545 setBounds(my_north, x1, y1, ww, n.height);
546 setBounds(my_south, x1, y3, ww, s.height);
547 setBounds(my_west, x1, y2, w.width, hh);
548 setBounds(my_east, x3, y2, e.width, hh);
553 * Returns a string representation of this layout manager.
555 * @return A string representation of this object.
557 public String toString()
559 return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]";
563 * FIXME: Document me!
565 private void setBounds(Component comp, int x, int y, int w, int h)
569 comp.setBounds(x, y, w, h);
572 // FIXME: Maybe move to top of file.
573 // Some constants for use with calcSize().
574 private static final int MIN = 0;
575 private static final int MAX = 1;
576 private static final int PREF = 2;
578 private Dimension calcCompSize(Component comp, int what)
580 if (comp == null || !comp.isVisible())
581 return new Dimension(0, 0);
583 return comp.getMinimumSize();
584 else if (what == MAX)
585 return comp.getMaximumSize();
586 return comp.getPreferredSize();
590 * This is a helper function used to compute the various sizes for
593 private Dimension calcSize(Container target, int what)
595 synchronized (target.getTreeLock ())
597 Insets ins = target.getInsets();
599 ComponentOrientation orient = target.getComponentOrientation ();
600 boolean left_to_right = orient.isLeftToRight ();
602 Component my_north = north;
603 Component my_east = east;
604 Component my_south = south;
605 Component my_west = west;
607 // Note that we currently don't handle vertical layouts. Neither
609 if (firstLine != null)
610 my_north = firstLine;
611 if (lastLine != null)
613 if (firstItem != null)
620 if (lastItem != null)
628 Dimension ndim = calcCompSize(my_north, what);
629 Dimension sdim = calcCompSize(my_south, what);
630 Dimension edim = calcCompSize(my_east, what);
631 Dimension wdim = calcCompSize(my_west, what);
632 Dimension cdim = calcCompSize(center, what);
634 int width = edim.width + cdim.width + wdim.width + (hgap * 2);
635 // Check for overflow.
636 if (width < edim.width || width < cdim.width || width < cdim.width)
637 width = Integer.MAX_VALUE;
639 if (ndim.width > width)
641 if (sdim.width > width)
644 width += (ins.left + ins.right);
646 int height = edim.height;
647 if (cdim.height > height)
648 height = cdim.height;
649 if (wdim.height > height)
650 height = wdim.height;
652 int addedHeight = height + (ndim.height + sdim.height + (vgap * 2)
653 + ins.top + ins.bottom);
654 // Check for overflow.
655 if (addedHeight < height)
656 height = Integer.MAX_VALUE;
658 height = addedHeight;
660 return(new Dimension(width, height));