001: /*
002: * @(#)BorderLayout.java 1.9 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package java.awt;
029:
030: import java.util.Hashtable;
031:
032: /**
033: * A border layout lays out a container, arranging and resizing
034: * its components to fit in five regions:
035: * <code>North</code>, <code>South</code>, <code>East</code>,
036: * <code>West</code>, and <code>Center</code>. When adding a
037: * component to a container with a border layout, use one of these
038: * five names, for example:
039: * <pre>
040: * Panel p = new Panel();
041: * p.setLayout(new BorderLayout());
042: * p.add(new Button("Okay"), "South");
043: * </pre>
044: * As a convenience, BorderLayout interprets the absence of a string
045: * specification the same as "Center":
046: * <pre>
047: * Panel p2 = new Panel();
048: * p2.setLayout(new BorderLayout());
049: * p2.add(new TextArea()); // Same as p.add(new TextArea(), "Center");
050: * </pre>
051: * <p>
052: * The components are laid out according to their
053: * preferred sizes and the constraints of the container's size.
054: * The <code>North</code> and <code>South</code> components may
055: * be stretched horizontally; the <code>East</code> and
056: * <code>West</code> components may be stretched vertically;
057: * the <code>Center</code> component may stretch both horizontally
058: * and vertically to fill any space left over.
059: * <p>
060: * Here is an example of five buttons in an applet laid out using
061: * the <code>BorderLayout</code> layout manager:
062: * <p>
063: * <img src="images-awt/BorderLayout-1.gif"
064: * ALIGN=center HSPACE=10 VSPACE=7>
065: * <p>
066: * The code for this applet is as follows:
067: * <p>
068: * <hr><blockquote><pre>
069: * import java.awt.*;
070: * import java.applet.Applet;
071: *
072: * public class buttonDir extends Applet {
073: * public void init() {
074: * setLayout(new BorderLayout());
075: * add("North", new Button("North"));
076: * add("South", new Button("South"));
077: * add("East", new Button("East"));
078: * add("West", new Button("West"));
079: * add("Center", new Button("Center"));
080: * }
081: * }
082: * </pre></blockquote><hr>
083: * <p>
084: * @version 1.27 02/11/97
085: * @author Arthur van Hoff
086: * @see java.awt.Container#add(String, Component)
087: * @since JDK1.0
088: */
089: public class BorderLayout implements LayoutManager2,
090: java.io.Serializable {
091: int hgap;
092: int vgap;
093: Component north;
094: Component west;
095: Component east;
096: Component south;
097: Component center;
098: /**
099: * The north layout constraint (top of container).
100: */
101: public static final String NORTH = "North";
102: /**
103: * The south layout constraint (bottom of container).
104: */
105: public static final String SOUTH = "South";
106: /**
107: * The east layout constraint (left side of container).
108: */
109: public static final String EAST = "East";
110: /**
111: * The west layout constraint (right side of container).
112: */
113: public static final String WEST = "West";
114: /**
115: * The center layout constraint (middle of container).
116: */
117: public static final String CENTER = "Center";
118: /*
119: * JDK 1.1 serialVersionUID
120: */
121: private static final long serialVersionUID = -8658291919501921765L;
122:
123: /**
124: * Constructs a new border layout with
125: * no gaps between components.
126: * @since JDK1.0
127: */
128: public BorderLayout() {
129: this (0, 0);
130: }
131:
132: /**
133: * Constructs a border layout with the specified gaps
134: * between components.
135: * The horizontal gap is specified by <code>hgap</code>
136: * and the vertical gap is specified by <code>vgap</code>.
137: * @param hgap the horizontal gap.
138: * @param vgap the vertical gap.
139: * @since JDK1.0
140: */
141: public BorderLayout(int hgap, int vgap) {
142: this .hgap = hgap;
143: this .vgap = vgap;
144: }
145:
146: /**
147: * Returns the horizontal gap between components.
148: * @since JDK1.1
149: */
150: public int getHgap() {
151: return hgap;
152: }
153:
154: /**
155: * Sets the horizontal gap between components.
156: * @param hgap the horizontal gap between components
157: * @since JDK1.1
158: */
159: public void setHgap(int hgap) {
160: this .hgap = hgap;
161: }
162:
163: /**
164: * Returns the vertical gap between components.
165: * @since JDK1.1
166: */
167: public int getVgap() {
168: return vgap;
169: }
170:
171: /**
172: * Sets the vertical gap between components.
173: * @param vgap the vertical gap between components
174: * @since JDK1.1
175: */
176: public void setVgap(int vgap) {
177: this .vgap = vgap;
178: }
179:
180: /**
181: * Adds the specified component to the layout, using the specified
182: * constraint object. For border layouts, the constraint must be
183: * one of the following strings: <code>"North"</code>,
184: * <code>"South"</code>, <code>"East"</code>,
185: * <code>"West"</code>, or <code>"Center"</code>.
186: * <p>
187: * Most applications do not call this method directly. This method
188: * is called when a component is added to a container using the
189: * <code>Container.add</code> method with the same argument types.
190: * @param comp the component to be added.
191: * @param constraints an object that specifies how and where
192: * the component is added to the layout.
193: * @see java.awt.Container#add(java.awt.Component, java.lang.Object)
194: * @exception IllegalArgumentException if the constraint object is not
195: * a string, or if it not one of the five specified strings.
196: * @since JDK1.1
197: */
198: public void addLayoutComponent(Component comp, Object constraints) {
199: synchronized (comp.getTreeLock()) {
200: if ((constraints == null)
201: || (constraints instanceof String)) {
202: addLayoutComponent((String) constraints, comp);
203: } else {
204: throw new IllegalArgumentException(
205: "cannot add to layout: constraint must be a string (or null)");
206: }
207: }
208: }
209:
210: /**
211: * @deprecated replaced by <code>addLayoutComponent(Component, Object)</code>.
212: */
213: public void addLayoutComponent(String name, Component comp) {
214: synchronized (comp.getTreeLock()) {
215: /* Special case: treat null the same as "Center". */
216: if (name == null) {
217: name = "Center";
218: }
219: /* Assign the component to one of the known regions of the layout.
220: */
221: if ("Center".equals(name)) {
222: center = comp;
223: } else if ("North".equals(name)) {
224: north = comp;
225: } else if ("South".equals(name)) {
226: south = comp;
227: } else if ("East".equals(name)) {
228: east = comp;
229: } else if ("West".equals(name)) {
230: west = comp;
231: } else {
232: throw new IllegalArgumentException(
233: "cannot add to layout: unknown constraint: "
234: + name);
235: }
236: }
237: }
238:
239: /**
240: * Removes the specified component from this border layout. This
241: * method is called when a container calls its <code>remove</code> or
242: * <code>removeAll</code> methods. Most applications do not call this
243: * method directly.
244: * @param comp the component to be removed.
245: * @see java.awt.Container#remove(java.awt.Component)
246: * @see java.awt.Container#removeAll()
247: * @since JDK1.0
248: */
249: public void removeLayoutComponent(Component comp) {
250: synchronized (comp.getTreeLock()) {
251: if (comp == center) {
252: center = null;
253: } else if (comp == north) {
254: north = null;
255: } else if (comp == south) {
256: south = null;
257: } else if (comp == east) {
258: east = null;
259: } else if (comp == west) {
260: west = null;
261: }
262: }
263: }
264:
265: /**
266: * Determines the minimum size of the <code>target</code> container
267: * using this layout manager.
268: * <p>
269: * This method is called when a container calls its
270: * <code>getMinimumSize</code> method. Most applications do not call
271: * this method directly.
272: * @param target the container in which to do the layout.
273: * @return the minimum dimensions needed to lay out the subcomponents
274: * of the specified container.
275: * @see java.awt.Container
276: * @see java.awt.BorderLayout#preferredLayoutSize
277: * @see java.awt.Container#getMinimumSize()
278: * @since JDK1.0
279: */
280: public Dimension minimumLayoutSize(Container target) {
281: synchronized (target.getTreeLock()) {
282: Dimension dim = new Dimension(0, 0);
283: if ((east != null) && east.visible) {
284: Dimension d = east.getMinimumSize();
285: dim.width += d.width + hgap;
286: dim.height = Math.max(d.height, dim.height);
287: }
288: if ((west != null) && west.visible) {
289: Dimension d = west.getMinimumSize();
290: dim.width += d.width + hgap;
291: dim.height = Math.max(d.height, dim.height);
292: }
293: if ((center != null) && center.visible) {
294: Dimension d = center.getMinimumSize();
295: dim.width += d.width;
296: dim.height = Math.max(d.height, dim.height);
297: }
298: if ((north != null) && north.visible) {
299: Dimension d = north.getMinimumSize();
300: dim.width = Math.max(d.width, dim.width);
301: dim.height += d.height + vgap;
302: }
303: if ((south != null) && south.visible) {
304: Dimension d = south.getMinimumSize();
305: dim.width = Math.max(d.width, dim.width);
306: dim.height += d.height + vgap;
307: }
308: Insets insets = target.getInsets();
309: dim.width += insets.left + insets.right;
310: dim.height += insets.top + insets.bottom;
311: return dim;
312: }
313: }
314:
315: /**
316: * Determines the preferred size of the <code>target</code>
317: * container using this layout manager, based on the components
318: * in the container.
319: * <p>
320: * Most applications do not call this method directly. This method
321: * is called when a container calls its <code>getPreferredSize</code>
322: * method.
323: * @param target the container in which to do the layout.
324: * @return the preferred dimensions to lay out the subcomponents
325: * of the specified container.
326: * @see java.awt.Container
327: * @see java.awt.BorderLayout#minimumLayoutSize
328: * @see java.awt.Container#getPreferredSize()
329: * @since JDK1.0
330: */
331: public Dimension preferredLayoutSize(Container target) {
332: synchronized (target.getTreeLock()) {
333: Dimension dim = new Dimension(0, 0);
334: if ((east != null) && east.visible) {
335: Dimension d = east.getPreferredSize();
336: dim.width += d.width + hgap;
337: dim.height = Math.max(d.height, dim.height);
338: }
339: if ((west != null) && west.visible) {
340: Dimension d = west.getPreferredSize();
341: dim.width += d.width + hgap;
342: dim.height = Math.max(d.height, dim.height);
343: }
344: if ((center != null) && center.visible) {
345: Dimension d = center.getPreferredSize();
346: dim.width += d.width;
347: dim.height = Math.max(d.height, dim.height);
348: }
349: if ((north != null) && north.visible) {
350: Dimension d = north.getPreferredSize();
351: dim.width = Math.max(d.width, dim.width);
352: dim.height += d.height + vgap;
353: }
354: if ((south != null) && south.visible) {
355: Dimension d = south.getPreferredSize();
356: dim.width = Math.max(d.width, dim.width);
357: dim.height += d.height + vgap;
358: }
359: Insets insets = target.getInsets();
360: dim.width += insets.left + insets.right;
361: dim.height += insets.top + insets.bottom;
362: return dim;
363: }
364: }
365:
366: /**
367: * Returns the maximum dimensions for this layout given the components
368: * in the specified target container.
369: * @param target the component which needs to be laid out
370: * @see Container
371: * @see #minimumLayoutSize
372: * @see #preferredLayoutSize
373: */
374: public Dimension maximumLayoutSize(Container target) {
375: return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
376: }
377:
378: /**
379: * Returns the alignment along the x axis. This specifies how
380: * the component would like to be aligned relative to other
381: * components. The value should be a number between 0 and 1
382: * where 0 represents alignment along the origin, 1 is aligned
383: * the furthest away from the origin, 0.5 is centered, etc.
384: */
385: public float getLayoutAlignmentX(Container parent) {
386: return 0.5f;
387: }
388:
389: /**
390: * Returns the alignment along the y axis. This specifies how
391: * the component would like to be aligned relative to other
392: * components. The value should be a number between 0 and 1
393: * where 0 represents alignment along the origin, 1 is aligned
394: * the furthest away from the origin, 0.5 is centered, etc.
395: */
396: public float getLayoutAlignmentY(Container parent) {
397: return 0.5f;
398: }
399:
400: /**
401: * Invalidates the layout, indicating that if the layout manager
402: * has cached information it should be discarded.
403: */
404: public void invalidateLayout(Container target) {
405: }
406:
407: /**
408: * Lays out the container argument using this border layout.
409: * <p>
410: * This method actually reshapes the components in the specified
411: * container in order to satisfy the constraints of this
412: * <code>BorderLayout</code> object. The <code>North</code>
413: * and <code>South</code>components, if any, are placed at
414: * the top and bottom of the container, respectively. The
415: * <code>West</code> and <code>East</code> components are
416: * then placed on the left and right, respectively. Finally,
417: * the <code>Center</code> object is placed in any remaining
418: * space in the middle.
419: * <p>
420: * Most applications do not call this method directly. This method
421: * is called when a container calls its <code>doLayout</code> method.
422: * @param target the container in which to do the layout.
423: * @see java.awt.Container
424: * @see java.awt.Container#doLayout()
425: * @since JDK1.0
426: */
427: public void layoutContainer(Container target) {
428: synchronized (target.getTreeLock()) {
429: Insets insets = target.getInsets();
430: int top = insets.top;
431: int bottom = target.height - insets.bottom;
432: int left = insets.left;
433: int right = target.width - insets.right;
434: if ((north != null) && north.visible) {
435: north.setSize(right - left, north.height);
436: Dimension d = north.getPreferredSize();
437: north.setBounds(left, top, right - left, d.height);
438: top += d.height + vgap;
439: }
440: if ((south != null) && south.visible) {
441: south.setSize(right - left, south.height);
442: Dimension d = south.getPreferredSize();
443: south.setBounds(left, bottom - d.height, right - left,
444: d.height);
445: bottom -= d.height + vgap;
446: }
447: if ((east != null) && east.visible) {
448: east.setSize(east.width, bottom - top);
449: Dimension d = east.getPreferredSize();
450: east.setBounds(right - d.width, top, d.width, bottom
451: - top);
452: right -= d.width + hgap;
453: }
454: if ((west != null) && west.visible) {
455: west.setSize(west.width, bottom - top);
456: Dimension d = west.getPreferredSize();
457: west.setBounds(left, top, d.width, bottom - top);
458: left += d.width + hgap;
459: }
460: if ((center != null) && center.visible) {
461: center.setBounds(left, top, right - left, bottom - top);
462: }
463: }
464: }
465:
466: /**
467: * Returns a string representation of the state of this border layout.
468: * @return a string representation of this border layout.
469: * @since JDK1.0
470: */
471: public String toString() {
472: return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap
473: + "]";
474: }
475: }
|