KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > FlowLayout


1 /*
2  * @(#)FlowLayout.java 1.52 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package java.awt;
8
9 import java.io.ObjectInputStream JavaDoc;
10 import java.io.IOException JavaDoc;
11
12 /**
13  * A flow layout arranges components in a directional flow, much
14  * like lines of text in a paragraph. The flow direction is
15  * determined by the container's <code>componentOrientation</code>
16  * property and may be one of two values:
17  * <ul>
18  * <li><code>ComponentOrientation.LEFT_TO_RIGHT</code>
19  * <li><code>ComponentOrientation.RIGHT_TO_LEFT</code>
20  * </ul>
21  * Flow layouts are typically used
22  * to arrange buttons in a panel. It arranges buttons
23  * horizontally until no more buttons fit on the same line.
24  * The line alignment is determined by the <code>align</code>
25  * property. The possible values are:
26  * <ul>
27  * <li>{@link #LEFT LEFT}
28  * <li>{@link #RIGHT RIGHT}
29  * <li>{@link #CENTER CENTER}
30  * <li>{@link #LEADING LEADING}
31  * <li>{@link #TRAILING TRAILING}
32  * </ul>
33  * <p>
34  * For example, the following picture shows an applet using the flow
35  * layout manager (its default layout manager) to position three buttons:
36  * <p>
37  * <img SRC="doc-files/FlowLayout-1.gif"
38  * ALT="Graphic of Layout for Three Buttons"
39  * ALIGN=center HSPACE=10 VSPACE=7>
40  * <p>
41  * Here is the code for this applet:
42  * <p>
43  * <hr><blockquote><pre>
44  * import java.awt.*;
45  * import java.applet.Applet;
46  *
47  * public class myButtons extends Applet {
48  * Button button1, button2, button3;
49  * public void init() {
50  * button1 = new Button("Ok");
51  * button2 = new Button("Open");
52  * button3 = new Button("Close");
53  * add(button1);
54  * add(button2);
55  * add(button3);
56  * }
57  * }
58  * </pre></blockquote><hr>
59  * <p>
60  * A flow layout lets each component assume its natural (preferred) size.
61  *
62  * @version 1.52, 12/19/03
63  * @author Arthur van Hoff
64  * @author Sami Shaio
65  * @since JDK1.0
66  * @see ComponentOrientation
67  */

68 public class FlowLayout implements LayoutManager JavaDoc, java.io.Serializable JavaDoc {
69
70     /**
71      * This value indicates that each row of components
72      * should be left-justified.
73      */

74     public static final int LEFT = 0;
75
76     /**
77      * This value indicates that each row of components
78      * should be centered.
79      */

80     public static final int CENTER = 1;
81
82     /**
83      * This value indicates that each row of components
84      * should be right-justified.
85      */

86     public static final int RIGHT = 2;
87
88     /**
89      * This value indicates that each row of components
90      * should be justified to the leading edge of the container's
91      * orientation, for example, to the left in left-to-right orientations.
92      *
93      * @see java.awt.Component#getComponentOrientation
94      * @see java.awt.ComponentOrientation
95      * @since 1.2
96      * Package-private pending API change approval
97      */

98     public static final int LEADING = 3;
99
100     /**
101      * This value indicates that each row of components
102      * should be justified to the trailing edge of the container's
103      * orientation, for example, to the right in left-to-right orientations.
104      *
105      * @see java.awt.Component#getComponentOrientation
106      * @see java.awt.ComponentOrientation
107      * @since 1.2
108      * Package-private pending API change approval
109      */

110     public static final int TRAILING = 4;
111
112     /**
113      * <code>align</code> is the property that determines
114      * how each row distributes empty space.
115      * It can be one of the following values:
116      * <ul>
117      * <code>LEFT</code>
118      * <code>RIGHT</code>
119      * <code>CENTER</code>
120      * <code>LEADING</code>
121      * <code>TRAILING</code>
122      * </ul>
123      *
124      * @serial
125      * @see #getAlignment
126      * @see #setAlignment
127      */

128     int align; // This is for 1.1 serialization compatibility
129

130     /**
131      * <code>newAlign</code> is the property that determines
132      * how each row distributes empty space for the Java 2 platform,
133      * v1.2 and greater.
134      * It can be one of the following three values:
135      * <ul>
136      * <code>LEFT</code>
137      * <code>RIGHT</code>
138      * <code>CENTER</code>
139      * <code>LEADING</code>
140      * <code>TRAILING</code>
141      * </ul>
142      *
143      * @serial
144      * @since 1.2
145      * @see #getAlignment
146      * @see #setAlignment
147      */

148     int newAlign; // This is the one we actually use
149

150     /**
151      * The flow layout manager allows a seperation of
152      * components with gaps. The horizontal gap will
153      * specify the space between components and between
154      * the components and the borders of the
155      * <code>Container</code>.
156      *
157      * @serial
158      * @see #getHgap()
159      * @see #setHgap(int)
160      */

161     int hgap;
162
163     /**
164      * The flow layout manager allows a seperation of
165      * components with gaps. The vertical gap will
166      * specify the space between rows and between the
167      * the rows and the borders of the <code>Container</code>.
168      *
169      * @serial
170      * @see #getHgap()
171      * @see #setHgap(int)
172      */

173     int vgap;
174
175     /*
176      * JDK 1.1 serialVersionUID
177      */

178      private static final long serialVersionUID = -7262534875583282631L;
179
180     /**
181      * Constructs a new <code>FlowLayout</code> with a centered alignment and a
182      * default 5-unit horizontal and vertical gap.
183      */

184     public FlowLayout() {
185     this(CENTER, 5, 5);
186     }
187
188     /**
189      * Constructs a new <code>FlowLayout</code> with the specified
190      * alignment and a default 5-unit horizontal and vertical gap.
191      * The value of the alignment argument must be one of
192      * <code>FlowLayout.LEFT</code>, <code>FlowLayout.RIGHT</code>,
193      * <code>FlowLayout.CENTER</code>, <code>FlowLayout.LEADING</code>,
194      * or <code>FlowLayout.TRAILING</code>.
195      * @param align the alignment value
196      */

197     public FlowLayout(int align) {
198     this(align, 5, 5);
199     }
200
201     /**
202      * Creates a new flow layout manager with the indicated alignment
203      * and the indicated horizontal and vertical gaps.
204      * <p>
205      * The value of the alignment argument must be one of
206      * <code>FlowLayout.LEFT</code>, <code>FlowLayout.RIGHT</code>,
207      * <code>FlowLayout.CENTER</code>, <code>FlowLayout.LEADING</code>,
208      * or <code>FlowLayout.TRAILING</code>.
209      * @param align the alignment value
210      * @param hgap the horizontal gap between components
211      * and between the components and the
212      * borders of the <code>Container</code>
213      * @param vgap the vertical gap between components
214      * and between the components and the
215      * borders of the <code>Container</code>
216      */

217     public FlowLayout(int align, int hgap, int vgap) {
218     this.hgap = hgap;
219     this.vgap = vgap;
220         setAlignment(align);
221     }
222
223     /**
224      * Gets the alignment for this layout.
225      * Possible values are <code>FlowLayout.LEFT</code>,
226      * <code>FlowLayout.RIGHT</code>, <code>FlowLayout.CENTER</code>,
227      * <code>FlowLayout.LEADING</code>,
228      * or <code>FlowLayout.TRAILING</code>.
229      * @return the alignment value for this layout
230      * @see java.awt.FlowLayout#setAlignment
231      * @since JDK1.1
232      */

233     public int getAlignment() {
234     return newAlign;
235     }
236
237     /**
238      * Sets the alignment for this layout.
239      * Possible values are
240      * <ul>
241      * <li><code>FlowLayout.LEFT</code>
242      * <li><code>FlowLayout.RIGHT</code>
243      * <li><code>FlowLayout.CENTER</code>
244      * <li><code>FlowLayout.LEADING</code>
245      * <li><code>FlowLayout.TRAILING</code>
246      * </ul>
247      * @param align one of the alignment values shown above
248      * @see #getAlignment()
249      * @since JDK1.1
250      */

251     public void setAlignment(int align) {
252     this.newAlign = align;
253
254         // this.align is used only for serialization compatibility,
255
// so set it to a value compatible with the 1.1 version
256
// of the class
257

258         switch (align) {
259     case LEADING:
260             this.align = LEFT;
261         break;
262     case TRAILING:
263             this.align = RIGHT;
264         break;
265         default:
266             this.align = align;
267         break;
268         }
269     }
270
271     /**
272      * Gets the horizontal gap between components
273      * and between the components and the borders
274      * of the <code>Container</code>
275      *
276      * @return the horizontal gap between components
277      * and between the components and the borders
278      * of the <code>Container</code>
279      * @see java.awt.FlowLayout#setHgap
280      * @since JDK1.1
281      */

282     public int getHgap() {
283     return hgap;
284     }
285
286     /**
287      * Sets the horizontal gap between components and
288      * between the components and the borders of the
289      * <code>Container</code>.
290      *
291      * @param hgap the horizontal gap between components
292      * and between the components and the borders
293      * of the <code>Container</code>
294      * @see java.awt.FlowLayout#getHgap
295      * @since JDK1.1
296      */

297     public void setHgap(int hgap) {
298     this.hgap = hgap;
299     }
300
301     /**
302      * Gets the vertical gap between components and
303      * between the components and the borders of the
304      * <code>Container</code>.
305      *
306      * @return the vertical gap between components
307      * and between the components and the borders
308      * of the <code>Container</code>
309      * @see java.awt.FlowLayout#setVgap
310      * @since JDK1.1
311      */

312     public int getVgap() {
313     return vgap;
314     }
315
316     /**
317      * Sets the vertical gap between components and between
318      * the components and the borders of the <code>Container</code>.
319      *
320      * @param vgap the vertical gap between components
321      * and between the components and the borders
322      * of the <code>Container</code>
323      * @see java.awt.FlowLayout#getVgap
324      * @since JDK1.1
325      */

326     public void setVgap(int vgap) {
327     this.vgap = vgap;
328     }
329
330     /**
331      * Adds the specified component to the layout.
332      * Not used by this class.
333      * @param name the name of the component
334      * @param comp the component to be added
335      */

336     public void addLayoutComponent(String JavaDoc name, Component JavaDoc comp) {
337     }
338
339     /**
340      * Removes the specified component from the layout.
341      * Not used by this class.
342      * @param comp the component to remove
343      * @see java.awt.Container#removeAll
344      */

345     public void removeLayoutComponent(Component JavaDoc comp) {
346     }
347
348     /**
349      * Returns the preferred dimensions for this layout given the
350      * <i>visible</i> components in the specified target container.
351      *
352      * @param target the container that needs to be laid out
353      * @return the preferred dimensions to lay out the
354      * subcomponents of the specified container
355      * @see Container
356      * @see #minimumLayoutSize
357      * @see java.awt.Container#getPreferredSize
358      */

359     public Dimension JavaDoc preferredLayoutSize(Container JavaDoc target) {
360       synchronized (target.getTreeLock()) {
361     Dimension JavaDoc dim = new Dimension JavaDoc(0, 0);
362     int nmembers = target.getComponentCount();
363         boolean firstVisibleComponent = true;
364
365     for (int i = 0 ; i < nmembers ; i++) {
366         Component JavaDoc m = target.getComponent(i);
367         if (m.visible) {
368         Dimension JavaDoc d = m.getPreferredSize();
369         dim.height = Math.max(dim.height, d.height);
370                 if (firstVisibleComponent) {
371                     firstVisibleComponent = false;
372                 } else {
373                     dim.width += hgap;
374                 }
375         dim.width += d.width;
376         }
377     }
378     Insets JavaDoc insets = target.getInsets();
379     dim.width += insets.left + insets.right + hgap*2;
380     dim.height += insets.top + insets.bottom + vgap*2;
381     return dim;
382       }
383     }
384
385     /**
386      * Returns the minimum dimensions needed to layout the <i>visible</i>
387      * components contained in the specified target container.
388      * @param target the container that needs to be laid out
389      * @return the minimum dimensions to lay out the
390      * subcomponents of the specified container
391      * @see #preferredLayoutSize
392      * @see java.awt.Container
393      * @see java.awt.Container#doLayout
394      */

395     public Dimension JavaDoc minimumLayoutSize(Container JavaDoc target) {
396       synchronized (target.getTreeLock()) {
397     Dimension JavaDoc dim = new Dimension JavaDoc(0, 0);
398     int nmembers = target.getComponentCount();
399
400     for (int i = 0 ; i < nmembers ; i++) {
401         Component JavaDoc m = target.getComponent(i);
402         if (m.visible) {
403         Dimension JavaDoc d = m.getMinimumSize();
404         dim.height = Math.max(dim.height, d.height);
405         if (i > 0) {
406             dim.width += hgap;
407         }
408         dim.width += d.width;
409         }
410     }
411     Insets JavaDoc insets = target.getInsets();
412     dim.width += insets.left + insets.right + hgap*2;
413     dim.height += insets.top + insets.bottom + vgap*2;
414     return dim;
415       }
416     }
417
418     /**
419      * Centers the elements in the specified row, if there is any slack.
420      * @param target the component which needs to be moved
421      * @param x the x coordinate
422      * @param y the y coordinate
423      * @param width the width dimensions
424      * @param height the height dimensions
425      * @param rowStart the beginning of the row
426      * @param rowEnd the the ending of the row
427      */

428     private void moveComponents(Container JavaDoc target, int x, int y, int width, int height,
429                                 int rowStart, int rowEnd, boolean ltr) {
430       synchronized (target.getTreeLock()) {
431     switch (newAlign) {
432     case LEFT:
433         x += ltr ? 0 : width;
434         break;
435     case CENTER:
436         x += width / 2;
437         break;
438     case RIGHT:
439         x += ltr ? width : 0;
440         break;
441     case LEADING:
442         break;
443     case TRAILING:
444         x += width;
445         break;
446     }
447     for (int i = rowStart ; i < rowEnd ; i++) {
448         Component JavaDoc m = target.getComponent(i);
449         if (m.visible) {
450             if (ltr) {
451                 m.setLocation(x, y + (height - m.height) / 2);
452             } else {
453                 m.setLocation(target.width - x - m.width, y + (height - m.height) / 2);
454                 }
455                 x += m.width + hgap;
456         }
457     }
458       }
459     }
460
461     /**
462      * Lays out the container. This method lets each
463      * <i>visible</i> component take
464      * its preferred size by reshaping the components in the
465      * target container in order to satisfy the alignment of
466      * this <code>FlowLayout</code> object.
467      *
468      * @param target the specified component being laid out
469      * @see Container
470      * @see java.awt.Container#doLayout
471      */

472     public void layoutContainer(Container JavaDoc target) {
473       synchronized (target.getTreeLock()) {
474     Insets JavaDoc insets = target.getInsets();
475     int maxwidth = target.width - (insets.left + insets.right + hgap*2);
476     int nmembers = target.getComponentCount();
477     int x = 0, y = insets.top + vgap;
478     int rowh = 0, start = 0;
479
480         boolean ltr = target.getComponentOrientation().isLeftToRight();
481
482     for (int i = 0 ; i < nmembers ; i++) {
483         Component JavaDoc m = target.getComponent(i);
484         if (m.visible) {
485         Dimension JavaDoc d = m.getPreferredSize();
486         m.setSize(d.width, d.height);
487
488         if ((x == 0) || ((x + d.width) <= maxwidth)) {
489             if (x > 0) {
490             x += hgap;
491             }
492             x += d.width;
493             rowh = Math.max(rowh, d.height);
494         } else {
495             moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh, start, i, ltr);
496             x = d.width;
497             y += vgap + rowh;
498             rowh = d.height;
499             start = i;
500         }
501         }
502     }
503     moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh, start, nmembers, ltr);
504       }
505     }
506
507     //
508
// the internal serial version which says which version was written
509
// - 0 (default) for versions before the Java 2 platform, v1.2
510
// - 1 for version >= Java 2 platform v1.2, which includes "newAlign" field
511
//
512
private static final int currentSerialVersion = 1;
513     /**
514      * This represent the <code>currentSerialVersion</code>
515      * which is bein used. It will be one of two values :
516      * <code>0</code> versions before Java 2 platform v1.2..
517      * <code>1</code> versions after Java 2 platform v1.2..
518      *
519      * @serial
520      * @since 1.2
521      */

522     private int serialVersionOnStream = currentSerialVersion;
523
524     /**
525      * Reads this object out of a serialization stream, handling
526      * objects written by older versions of the class that didn't contain all
527      * of the fields we use now..
528      */

529     private void readObject(ObjectInputStream JavaDoc stream)
530          throws IOException JavaDoc, ClassNotFoundException JavaDoc
531     {
532         stream.defaultReadObject();
533
534         if (serialVersionOnStream < 1) {
535             // "newAlign" field wasn't present, so use the old "align" field.
536
setAlignment(this.align);
537         }
538         serialVersionOnStream = currentSerialVersion;
539     }
540
541     /**
542      * Returns a string representation of this <code>FlowLayout</code>
543      * object and its values.
544      * @return a string representation of this layout
545      */

546     public String JavaDoc toString() {
547     String JavaDoc str = "";
548     switch (align) {
549       case LEFT: str = ",align=left"; break;
550       case CENTER: str = ",align=center"; break;
551       case RIGHT: str = ",align=right"; break;
552       case LEADING: str = ",align=leading"; break;
553       case TRAILING: str = ",align=trailing"; break;
554     }
555     return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + str + "]";
556     }
557
558
559 }
560
Popular Tags