001: /*
002: * @(#)FlowLayout.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: package java.awt;
028:
029: /**
030: * A flow layout arranges components in a left-to-right flow, much
031: * like lines of text in a paragraph. Flow layouts are typically used
032: * to arrange buttons in a panel. It will arrange
033: * buttons left to right until no more buttons fit on the same line.
034: * Each line is centered.
035: * <p>
036: * For example, the following picture shows an applet using the flow
037: * layout manager (its default layout manager) to position three buttons:
038: * <p>
039: * <img src="images-awt/FlowLayout-1.gif"
040: * ALT="Graphic of Layout for Three Buttons"
041: * ALIGN=center HSPACE=10 VSPACE=7>
042: * <p>
043: * Here is the code for this applet:
044: * <p>
045: * <hr><blockquote><pre>
046: * import java.awt.*;
047: * import java.applet.Applet;
048: *
049: * public class myButtons extends Applet {
050: * Button button1, button2, button3;
051: * public void init() {
052: * button1 = new Button("Ok");
053: * button2 = new Button("Open");
054: * button3 = new Button("Close");
055: * add(button1);
056: * add(button2);
057: * add(button3);
058: * }
059: * }
060: * </pre></blockquote><hr>
061: * <p>
062: * A flow layout lets each component assume its natural (preferred) size.
063: *
064: * @version 1.27, 07/01/98
065: * @author Arthur van Hoff
066: * @author Sami Shaio
067: * @since JDK1.0
068: */
069: public class FlowLayout implements LayoutManager, java.io.Serializable {
070: /**
071: * This value indicates that each row of components
072: * should be left-justified.
073: * @since JDK1.0
074: */
075: public static final int LEFT = 0;
076: /**
077: * This value indicates that each row of components
078: * should be centered.
079: * @since JDK1.0
080: */
081: public static final int CENTER = 1;
082: /**
083: * This value indicates that each row of components
084: * should be right-justified.
085: * @since JDK1.0
086: */
087: public static final int RIGHT = 2;
088: int align;
089: int hgap;
090: int vgap;
091: /*
092: * JDK 1.1 serialVersionUID
093: */
094: private static final long serialVersionUID = -7262534875583282631L;
095:
096: /**
097: * Constructs a new Flow Layout with a centered alignment and a
098: * default 5-unit horizontal and vertical gap.
099: * @since JDK1.0
100: */
101: public FlowLayout() {
102: this (CENTER, 5, 5);
103: }
104:
105: /**
106: * Constructs a new Flow Layout with the specified alignment and a
107: * default 5-unit horizontal and vertical gap.
108: * The value of the alignment argument must be one of
109: * <code>FlowLayout.LEFT</code>, <code>FlowLayout.RIGHT</code>,
110: * or <code>FlowLayout.CENTER</code>.
111: * @param align the alignment value
112: * @since JDK1.0
113: */
114: public FlowLayout(int align) {
115: this (align, 5, 5);
116: }
117:
118: /**
119: * Creates a new flow layout manager with the indicated alignment
120: * and the indicated horizontal and vertical gaps.
121: * <p>
122: * The value of the alignment argument must be one of
123: * <code>FlowLayout.LEFT</code>, <code>FlowLayout.RIGHT</code>,
124: * or <code>FlowLayout.CENTER</code>.
125: * @param align the alignment value.
126: * @param hgap the horizontal gap between components.
127: * @param vgap the vertical gap between components.
128: * @since JDK1.0
129: */
130: public FlowLayout(int align, int hgap, int vgap) {
131: this .align = align;
132: this .hgap = hgap;
133: this .vgap = vgap;
134: }
135:
136: /**
137: * Gets the alignment for this layout.
138: * Possible values are <code>FlowLayout.LEFT</code>,
139: * <code>FlowLayout.RIGHT</code>, or <code>FlowLayout.CENTER</code>.
140: * @return the alignment value for this layout.
141: * @see java.awt.FlowLayout#setAlignment
142: * @since JDK1.1
143: */
144: public int getAlignment() {
145: return align;
146: }
147:
148: /**
149: * Sets the alignment for this layout.
150: * Possible values are <code>FlowLayout.LEFT</code>,
151: * <code>FlowLayout.RIGHT</code>, and <code>FlowLayout.CENTER</code>.
152: * @param align the alignment value.
153: * @see java.awt.FlowLayout#getAlignment
154: * @since JDK1.1
155: */
156: public void setAlignment(int align) {
157: this .align = align;
158: }
159:
160: /**
161: * Gets the horizontal gap between components.
162: * @return the horizontal gap between components.
163: * @see java.awt.FlowLayout#setHgap
164: * @since JDK1.1
165: */
166: public int getHgap() {
167: return hgap;
168: }
169:
170: /**
171: * Sets the horizontal gap between components.
172: * @param hgap the horizontal gap between components
173: * @see java.awt.FlowLayout#getHgap
174: * @since JDK1.1
175: */
176: public void setHgap(int hgap) {
177: this .hgap = hgap;
178: }
179:
180: /**
181: * Gets the vertical gap between components.
182: * @return the vertical gap between components.
183: * @see java.awt.FlowLayout#setVgap
184: * @since JDK1.1
185: */
186: public int getVgap() {
187: return vgap;
188: }
189:
190: /**
191: * Sets the vertical gap between components.
192: * @param vgap the vertical gap between components
193: * @see java.awt.FlowLayout#getVgap
194: * @since JDK1.1
195: */
196: public void setVgap(int vgap) {
197: this .vgap = vgap;
198: }
199:
200: /**
201: * Adds the specified component to the layout. Not used by this class.
202: * @param name the name of the component
203: * @param comp the component to be added
204: * @since JDK1.0
205: */
206: public void addLayoutComponent(String name, Component comp) {
207: }
208:
209: /**
210: * Removes the specified component from the layout. Not used by
211: * this class.
212: * @param comp the component to remove
213: * @see java.awt.Container#removeAll
214: * @since JDK1.0
215: */
216: public void removeLayoutComponent(Component comp) {
217: }
218:
219: /**
220: * Returns the preferred dimensions for this layout given the components
221: * in the specified target container.
222: * @param target the component which needs to be laid out
223: * @return the preferred dimensions to lay out the
224: * subcomponents of the specified container.
225: * @see Container
226: * @see #minimumLayoutSize
227: * @see java.awt.Container#getPreferredSize
228: * @since JDK1.0
229: */
230: public Dimension preferredLayoutSize(Container target) {
231: synchronized (target.getTreeLock()) {
232: Dimension dim = new Dimension(0, 0);
233: int nmembers = target.getComponentCount();
234: for (int i = 0; i < nmembers; i++) {
235: Component m = target.getComponent(i);
236: if (m.visible) {
237: Dimension d = m.getPreferredSize();
238: dim.height = Math.max(dim.height, d.height);
239: if (i > 0) {
240: dim.width += hgap;
241: }
242: dim.width += d.width;
243: }
244: }
245: Insets insets = target.getInsets();
246: dim.width += insets.left + insets.right + hgap * 2;
247: dim.height += insets.top + insets.bottom + vgap * 2;
248: return dim;
249: }
250: }
251:
252: /**
253: * Returns the minimum dimensions needed to layout the components
254: * contained in the specified target container.
255: * @param target the component which needs to be laid out
256: * @return the minimum dimensions to lay out the
257: * subcomponents of the specified container.
258: * @see #preferredLayoutSize
259: * @see java.awt.Container
260: * @see java.awt.Container#doLayout
261: * @since JDK1.0
262: */
263: public Dimension minimumLayoutSize(Container target) {
264: synchronized (target.getTreeLock()) {
265: Dimension dim = new Dimension(0, 0);
266: int nmembers = target.getComponentCount();
267: for (int i = 0; i < nmembers; i++) {
268: Component m = target.getComponent(i);
269: if (m.visible) {
270: Dimension d = m.getMinimumSize();
271: dim.height = Math.max(dim.height, d.height);
272: if (i > 0) {
273: dim.width += hgap;
274: }
275: dim.width += d.width;
276: }
277: }
278: Insets insets = target.getInsets();
279: dim.width += insets.left + insets.right + hgap * 2;
280: dim.height += insets.top + insets.bottom + vgap * 2;
281: return dim;
282: }
283: }
284:
285: /**
286: * Centers the elements in the specified row, if there is any slack.
287: * @param target the component which needs to be moved
288: * @param x the x coordinate
289: * @param y the y coordinate
290: * @param width the width dimensions
291: * @param height the height dimensions
292: * @param rowStart the beginning of the row
293: * @param rowEnd the the ending of the row
294: */
295: private void moveComponents(Container target, int x, int y,
296: int width, int height, int rowStart, int rowEnd) {
297: synchronized (target.getTreeLock()) {
298: switch (align) {
299: case LEFT:
300: break;
301:
302: case CENTER:
303: x += width / 2;
304: break;
305:
306: case RIGHT:
307: x += width;
308: break;
309: }
310: for (int i = rowStart; i < rowEnd; i++) {
311: Component m = target.getComponent(i);
312: if (m.visible) {
313: m.setLocation(x, y + (height - m.height) / 2);
314: x += hgap + m.width;
315: }
316: }
317: }
318: }
319:
320: /**
321: * Lays out the container. This method lets each component take
322: * its preferred size by reshaping the components in the
323: * target container in order to satisfy the constraints of
324: * this <code>FlowLayout</code> object.
325: * @param target the specified component being laid out.
326: * @see Container
327: * @see java.awt.Container#doLayout
328: * @since JDK1.0
329: */
330: public void layoutContainer(Container target) {
331: synchronized (target.getTreeLock()) {
332: Insets insets = target.getInsets();
333: int maxwidth = target.width
334: - (insets.left + insets.right + hgap * 2);
335: int nmembers = target.getComponentCount();
336: int x = 0, y = insets.top + vgap;
337: int rowh = 0, start = 0;
338: for (int i = 0; i < nmembers; i++) {
339: Component m = target.getComponent(i);
340: if (m.visible) {
341: Dimension d = m.getPreferredSize();
342: m.setSize(d.width, d.height);
343: if ((x == 0) || ((x + d.width) <= maxwidth)) {
344: if (x > 0) {
345: x += hgap;
346: }
347: x += d.width;
348: rowh = Math.max(rowh, d.height);
349: } else {
350: moveComponents(target, insets.left + hgap, y,
351: maxwidth - x, rowh, start, i);
352: x = d.width;
353: y += vgap + rowh;
354: rowh = d.height;
355: start = i;
356: }
357: }
358: }
359: moveComponents(target, insets.left + hgap, y, maxwidth - x,
360: rowh, start, nmembers);
361: }
362: }
363:
364: /**
365: * Returns a string representation of this <code>FlowLayout</code>
366: * object and its values.
367: * @return a string representation of this layout.
368: * @since JDK1.0
369: */
370: public String toString() {
371: String str = "";
372: switch (align) {
373: case LEFT:
374: str = ",align=left";
375: break;
376:
377: case CENTER:
378: str = ",align=center";
379: break;
380:
381: case RIGHT:
382: str = ",align=right";
383: break;
384: }
385: return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap
386: + str + "]";
387: }
388: }
|