KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > izforge > izpack > gui > FlowLayout


1 /*
2  * IzPack - Copyright 2001-2007 Julien Ponge, All Rights Reserved.
3  *
4  * http://www.izforge.com/izpack/
5  * http://developer.berlios.de/projects/izpack/
6  *
7  * Copyright 2002 Elmar Grom
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */

21
22 package com.izforge.izpack.gui;
23
24 import java.awt.Component JavaDoc;
25 import java.awt.Container JavaDoc;
26 import java.awt.Dimension JavaDoc;
27 import java.awt.Insets JavaDoc;
28 import java.awt.LayoutManager JavaDoc;
29
30 /*---------------------------------------------------------------------------*/
31 /**
32  * A flow layout arranges components in a left-to-right flow, much like lines of text in a
33  * paragraph. Flow layouts are typically used to arrange buttons in a panel. It will arrange buttons
34  * left to right until no more buttons fit on the same line. Each line is centered.
35  * <p>
36  * For example, the following picture shows an applet using the flow layout manager (its default
37  * layout manager) to position three buttons:
38  * <p>
39  * <img SRC="doc-files/FlowLayout-1.gif" ALT="Graphic of Layout for Three Buttons" ALIGN=center
40  * HSPACE=10 VSPACE=7>
41  * <p>
42  * Here is the code for this applet:
43  * <p>
44  * <hr>
45  * <blockquote>
46  *
47  * <pre>
48  * import java.awt.*;
49  * import java.applet.Applet;
50  *
51  * public class myButtons extends Applet
52  * {
53  *
54  * Button button1, button2, button3;
55  *
56  * public void init()
57  * {
58  * button1 = new Button(&quot;Ok&quot;);
59  * button2 = new Button(&quot;Open&quot;);
60  * button3 = new Button(&quot;Close&quot;);
61  * add(button1);
62  * add(button2);
63  * add(button3);
64  * }
65  * }
66  *
67  * </pre>
68  *
69  * </blockquote>
70  * <hr>
71  * <p>
72  * A flow layout lets each component assume its natural (preferred) size.
73  *
74  * This class is a bit different from java.awt.FlowLayout. <blockquote> java.awt.FlowLayout has a
75  * minor problem that was bugging me when I wrote the UserInputPanel. FlowLayout puts some amount of
76  * space in between each component that it lays out. In addition it adds that same amount of space
77  * to the left and to the right of the entire group. Therefore items such as the RuleInputfield that
78  * are laid out with a FlowLayout would never line up properly with the other components (it would
79  * appear to be slightly indented). Because there is no way to circumvent this behavior in
80  * FlowLayout (it's hard coded) I copied the source and modified it so that it does not add the
81  * space to the left and to the right. Now my stuff lines up properly. (Elmar Grom)</blockquote>
82  *
83  * @version 1.39, 11/29/02
84  * @author Arthur van Hoff
85  * @author Sami Shaio
86  * @author Elmar Grom
87  */

88 /*---------------------------------------------------------------------------*/
89 public class FlowLayout implements LayoutManager JavaDoc
90 {
91
92     /**
93      * This value indicates that each row of components should be left-justified.
94      */

95     public static final int LEFT = 0;
96
97     /**
98      * This value indicates that each row of components should be centered.
99      */

100     public static final int CENTER = 1;
101
102     /**
103      * This value indicates that each row of components should be right-justified.
104      */

105     public static final int RIGHT = 2;
106
107     /**
108      * This value indicates that each row of components should be justified to the leading edge of
109      * the container's orientation, for example, to the left in left-to-right orientations.
110      *
111      * @see java.awt.Component#getComponentOrientation
112      * @see java.awt.ComponentOrientation
113      * @since 1.2 Package-private pending API change approval
114      */

115     public static final int LEADING = 3;
116
117     /**
118      * This value indicates that each row of components should be justified to the leading edge of
119      * the container's orientation, for example, to the right in left-to-right orientations.
120      *
121      * @see java.awt.Component#getComponentOrientation
122      * @see java.awt.ComponentOrientation
123      * @since 1.2 Package-private pending API change approval
124      */

125     public static final int TRAILING = 4;
126
127     /**
128      * <code>align</code> is the proprty that determines how each row distributes empty space. It
129      * can be one of the following three values : <code>LEFT</code>
130      * <code>RIGHT</code>
131      * <code>CENTER</code>
132      *
133      * @serial
134      * @see #getAlignment
135      * @see #setAlignment
136      */

137     int align; // This is for 1.1 serialization compatibilitys
138

139     /**
140      * <code>newAlign</code> is the property that determines how each row distributes empty space
141      * for the Java 2 platform, v1.2 and greater. It can be one of the following three values :
142      * <code>LEFT</code>
143      * <code>RIGHT</code>
144      * <code>CENTER</code>
145      *
146      * @serial
147      * @since 1.2
148      * @see #getAlignment
149      * @see #setAlignment
150      */

151     int newAlign; // This is the one we actually use
152

153     /**
154      * The flow layout manager allows a seperation of components with gaps. The horizontal gap will
155      * specify the space between components.
156      *
157      * @serial
158      * @see #getHgap
159      * @see #setHgap
160      */

161     int hgap;
162
163     /**
164      * The flow layout manager allows a seperation of components with gaps. The vertical gap will
165      * specify the space between rows.
166      *
167      * @serial
168      * @see #getVgap
169      * @see #setVgap
170      */

171     int vgap;
172
173     /*--------------------------------------------------------------------------*/
174     /**
175      * Constructs a new Flow Layout with a centered alignment and a default 5-unit horizontal and
176      * vertical gap.
177      */

178     /*--------------------------------------------------------------------------*/
179     public FlowLayout()
180     {
181         this(CENTER, 5, 5);
182     }
183
184     /*--------------------------------------------------------------------------*/
185     /**
186      * Constructs a new Flow Layout with the specified alignment and a default 5-unit horizontal and
187      * vertical gap. The value of the alignment argument must be one of <code>FlowLayout.LEFT</code>,
188      * <code>FlowLayout.RIGHT</code>, or <code>FlowLayout.CENTER</code>.
189      *
190      * @param align the alignment value
191      */

192     /*--------------------------------------------------------------------------*/
193     public FlowLayout(int align)
194     {
195         this(align, 5, 5);
196     }
197
198     /*--------------------------------------------------------------------------*/
199     /**
200      * Creates a new flow layout manager with the indicated alignment and the indicated horizontal
201      * and vertical gaps.
202      * <p>
203      * The value of the alignment argument must be one of <code>FlowLayout.LEFT</code>,
204      * <code>FlowLayout.RIGHT</code>, or <code>FlowLayout.CENTER</code>.
205      *
206      * @param align the alignment value.
207      * @param hgap the horizontal gap between components.
208      * @param vgap the vertical gap between components.
209      */

210     /*--------------------------------------------------------------------------*/
211     public FlowLayout(int align, int hgap, int vgap)
212     {
213         this.hgap = hgap;
214         this.vgap = vgap;
215         setAlignment(align);
216     }
217
218     /*--------------------------------------------------------------------------*/
219     /**
220      * Gets the alignment for this layout. Possible values are <code>FlowLayout.LEFT</code>,
221      * <code>FlowLayout.RIGHT</code>, or <code>FlowLayout.CENTER</code>.
222      *
223      * @return the alignment value for this layout.
224      *
225      * @see java.awt.FlowLayout#setAlignment
226      */

227     /*--------------------------------------------------------------------------*/
228     public int getAlignment()
229     {
230         return (newAlign);
231     }
232
233     /*--------------------------------------------------------------------------*/
234     /**
235      * Sets the alignment for this layout. Possible values are <code>FlowLayout.LEFT</code>,
236      * <code>FlowLayout.RIGHT</code>, and <code>FlowLayout.CENTER</code>.
237      *
238      * @param align the alignment value.
239      *
240      * @see #getAlignment()
241      */

242     /*--------------------------------------------------------------------------*/
243     public void setAlignment(int align)
244     {
245         this.newAlign = align;
246
247         // this.align is used only for serialization compatibility,
248
// so set it to a value compatible with the 1.1 version
249
// of the class
250

251         switch (align)
252         {
253         case LEADING:
254             this.align = LEFT;
255             break;
256         case TRAILING:
257             this.align = RIGHT;
258             break;
259         default:
260             this.align = align;
261             break;
262         }
263     }
264
265     /*--------------------------------------------------------------------------*/
266     /**
267      * Gets the horizontal gap between components.
268      *
269      * @return the horizontal gap between components.
270      *
271      * @see #setHgap(int)
272      */

273     /*--------------------------------------------------------------------------*/
274     public int getHgap()
275     {
276         return (hgap);
277     }
278
279     /*--------------------------------------------------------------------------*/
280     /**
281      * Sets the horizontal gap between components.
282      *
283      * @param hgap the horizontal gap between components
284      *
285      * @see #getHgap()
286      */

287     /*--------------------------------------------------------------------------*/
288     public void setHgap(int hgap)
289     {
290         this.hgap = hgap;
291     }
292
293     /*--------------------------------------------------------------------------*/
294     /**
295      * Gets the vertical gap between components.
296      *
297      * @return the vertical gap between components.\
298      *
299      * @see #setVgap(int)
300      */

301     /*--------------------------------------------------------------------------*/
302     public int getVgap()
303     {
304         return (vgap);
305     }
306
307     /*--------------------------------------------------------------------------*/
308     /**
309      * Sets the vertical gap between components.
310      *
311      * @param vgap the vertical gap between components
312      *
313      * @see #getVgap()
314      */

315     /*--------------------------------------------------------------------------*/
316     public void setVgap(int vgap)
317     {
318         this.vgap = vgap;
319     }
320
321     /*--------------------------------------------------------------------------*/
322     /**
323      * Adds the specified component to the layout. Not used by this class.
324      *
325      * @param name the name of the component
326      * @param comp the component to be added
327      */

328     /*--------------------------------------------------------------------------*/
329     public void addLayoutComponent(String JavaDoc name, Component JavaDoc comp)
330     {
331     }
332
333     /*--------------------------------------------------------------------------*/
334     /**
335      * Removes the specified component from the layout. Not used by this class.
336      *
337      * @param comp the component to remove
338      *
339      */

340     /*--------------------------------------------------------------------------*/
341     public void removeLayoutComponent(Component JavaDoc comp)
342     {
343     }
344
345     /*--------------------------------------------------------------------------*/
346     /**
347      * Returns the preferred dimensions for this layout given the components in the specified target
348      * container.
349      *
350      * @param target the component which needs to be laid out
351      *
352      * @return the preferred dimensions to lay out the subcomponents of the specified container.
353      * @see #minimumLayoutSize(Container)
354      */

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

402     /*--------------------------------------------------------------------------*/
403     public Dimension JavaDoc minimumLayoutSize(Container JavaDoc target)
404     {
405         synchronized (target.getTreeLock())
406         {
407             Dimension JavaDoc dim = new Dimension JavaDoc(0, 0);
408             int nmembers = target.getComponentCount();
409
410             for (int i = 0; i < nmembers; i++)
411             {
412                 Component JavaDoc m = target.getComponent(i);
413                 if (m.isVisible())
414                 {
415                     Dimension JavaDoc d = m.getMinimumSize();
416                     dim.height = Math.max(dim.height, d.height);
417                     if (i > 0)
418                     {
419                         dim.width += hgap;
420                     }
421                     dim.width += d.width;
422                 }
423             }
424
425             Insets JavaDoc insets = target.getInsets();
426             dim.width += insets.left + insets.right + hgap * 2;
427             dim.height += insets.top + insets.bottom + vgap * 2;
428
429             return (dim);
430         }
431     }
432
433     /*--------------------------------------------------------------------------*/
434     /**
435      * Centers the elements in the specified row, if there is any slack.
436      *
437      * @param target the component which needs to be moved
438      * @param x the x coordinate
439      * @param y the y coordinate
440      * @param width the width dimensions
441      * @param height the height dimensions
442      * @param rowStart the beginning of the row
443      * @param rowEnd the the ending of the row
444      */

445     /*--------------------------------------------------------------------------*/
446     private void moveComponents(Container JavaDoc target, int x, int y, int width, int height,
447             int rowStart, int rowEnd, boolean ltr)
448     {
449         synchronized (target.getTreeLock())
450         {
451             switch (newAlign)
452             {
453             case LEFT:
454                 x += ltr ? 0 : width;
455                 break;
456             case CENTER:
457                 x += width / 2;
458                 break;
459             case RIGHT:
460                 x += ltr ? width : 0;
461                 break;
462             case LEADING:
463                 break;
464             case TRAILING:
465                 x += width;
466                 break;
467             }
468
469             for (int i = rowStart; i < rowEnd; i++)
470             {
471                 Component JavaDoc m = target.getComponent(i);
472
473                 if (m.isVisible())
474                 {
475                     if (ltr)
476                     {
477                         m.setLocation(x, y + (height - m.getSize().height) / 2);
478                     }
479                     else
480                     {
481                         m.setLocation(target.getSize().width - x - m.getSize().width, y
482                                 + (height - m.getSize().height) / 2);
483                     }
484
485                     x += m.getSize().width + hgap;
486                 }
487             }
488         }
489     }
490
491     /*--------------------------------------------------------------------------*/
492     /**
493      * Lays out the container. This method lets each component take its preferred size by reshaping
494      * the components in the target container in order to satisfy the constraints of this
495      * <code>FlowLayout</code> object.
496      *
497      * @param target the specified component being laid out.
498      *
499      */

500     /*--------------------------------------------------------------------------*/
501     public void layoutContainer(Container JavaDoc target)
502     {
503         synchronized (target.getTreeLock())
504         {
505             Insets JavaDoc insets = target.getInsets();
506             int maxWidth = target.getSize().width - (insets.left + insets.right + hgap * 2);
507             int nMembers = target.getComponentCount();
508             int x = 0;
509             int y = insets.top + vgap;
510             int rowh = 0;
511             int start = 0;
512
513             boolean ltr = target.getComponentOrientation().isLeftToRight();
514
515             for (int i = 0; i < nMembers; i++)
516             {
517                 Component JavaDoc m = target.getComponent(i);
518
519                 if (m.isVisible())
520                 {
521                     Dimension JavaDoc d = m.getPreferredSize();
522                     m.setSize(d.width, d.height);
523
524                     if ((x == 0) || ((x + d.width) <= maxWidth))
525                     {
526                         if (x > 0)
527                         {
528                             x += hgap;
529                         }
530                         x += d.width;
531                         rowh = Math.max(rowh, d.height);
532                     }
533                     else
534                     {
535                         moveComponents(target, insets.left, y, maxWidth - x, rowh, start, i, ltr);
536                         x = d.width;
537                         y += vgap + rowh;
538                         rowh = d.height;
539                         start = i;
540                     }
541                 }
542             }
543
544             moveComponents(target, insets.left, y, maxWidth - x, rowh, start, nMembers, ltr);
545         }
546     }
547
548     /*--------------------------------------------------------------------------*/
549     /**
550      * Returns a string representation of this <code>FlowLayout</code> object and its values.
551      *
552      * @return a string representation of this layout.
553      */

554     /*--------------------------------------------------------------------------*/
555     public String JavaDoc toString()
556     {
557         String JavaDoc str = "";
558
559         switch (align)
560         {
561         case LEFT:
562             str = ",align=left";
563             break;
564         case CENTER:
565             str = ",align=center";
566             break;
567         case RIGHT:
568             str = ",align=right";
569             break;
570         case LEADING:
571             str = ",align=leading";
572             break;
573         case TRAILING:
574             str = ",align=trailing";
575             break;
576         }
577
578         return (getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + str + "]");
579     }
580 }
581 /*---------------------------------------------------------------------------*/
582
Popular Tags