1 /* FlowLayout.java -- Grid-based layout engine
2 Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation
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. */
41 import java
.io
.Serializable
;
43 /** This class implements a flow-based layout. Components are laid
44 * out in order from left to right. When a component cannot be placed
45 * without horizontal clipping, a new row is started. This class
46 * supports horizontal and vertical gaps. These are used for spacing
49 * @author Tom Tromey (tromey@redhat.com)
50 * @author Aaron M. Renn (arenn@urbanophile.com)
52 public class FlowLayout
implements LayoutManager
, Serializable
54 /** Constant that specifies left alignment. */
55 public static final int LEFT
= 0;
56 /** Constant that specifies center alignment. */
57 public static final int CENTER
= 1;
58 /** Constant that specifies right alignment. */
59 public static final int RIGHT
= 2;
61 /** Constant that specifies alignment to leading edge of container's
63 public static final int LEADING
= 3;
64 /** Constant that specifies alignment to trailing edge of container's
66 public static final int TRAILING
= 4;
68 // Serialization constant
69 private static final long serialVersionUID
= -7262534875583282631L;
72 * Add a new component to the layout. This particular implementation
75 * @param name the name
76 * @param comp the component
78 public void addLayoutComponent (String name
, Component comp
)
84 * Returns the current justification value for this object.
86 * @return The current justification value for this object.
88 public int getAlignment ()
94 * Returns the horizontal gap between components.
96 * @return The horizontal gap between components.
104 * Returns the vertical gap between lines of components.
106 * @return The vertical gap between lines of components.
108 public int getVgap ()
114 * Initializes a new instance of <code>FlowLayout</code> with a center
115 * justification and a default horizontal and vertical gap of 5.
123 * Initializes a new instance of <code>FlowLayout</code> with the specified
124 * justification and a default horizontal and vertical gap of 5.
126 * @param align The justification setting, which should be one of the
127 * contants in this class.
129 public FlowLayout (int align
)
135 * Initializes a new instance of <code>FlowLayout</code> with the specified
136 * justification and gap values
137 * @param align Alignment
138 * @param hgap The horizontal gap
139 * @param vgap The vertical gap
140 * @exception IllegalArgumentException If either gap is negative
142 public FlowLayout (int align
, int hgap
, int vgap
)
144 // Use methods to set fields so that we can have all the checking
148 setAlignment (align
);
151 /** Lay out the container's components based on current settings.
152 * @param parent The parent container
154 public void layoutContainer (Container parent
)
156 synchronized (parent
.getTreeLock ())
158 int num
= parent
.getComponentCount ();
159 // This is more efficient than calling getComponents().
160 Component
[] comps
= parent
.component
;
162 Dimension d
= parent
.getSize ();
163 Insets ins
= parent
.getInsets ();
165 ComponentOrientation orient
= parent
.getComponentOrientation ();
166 boolean left_to_right
= orient
.isLeftToRight ();
168 int y
= ins
.top
+ vgap
;
172 // Find the components which go in the current row.
173 int new_w
= ins
.left
+ hgap
+ ins
.right
;
176 boolean found_one
= false;
177 for (j
= i
; j
< num
; ++j
)
179 // Skip invisible items.
180 if (! comps
[j
].visible
)
183 Dimension c
= comps
[j
].getPreferredSize ();
185 int next_w
= new_w
+ hgap
+ c
.width
;
186 if (next_w
<= d
.width
|| ! found_one
)
189 new_h
= Math
.max (new_h
, c
.height
);
194 // Must start a new row, and we already found an item
199 // Set the location of each component for this row.
203 if (align
== LEADING
)
204 myalign
= left_to_right ? LEFT
: RIGHT
;
205 else if (align
== TRAILING
)
206 myalign
= left_to_right ? RIGHT
: LEFT
;
208 if (myalign
== RIGHT
)
209 x
= ins
.left
+ (d
.width
- new_w
) + hgap
;
210 else if (myalign
== CENTER
)
211 x
= ins
.left
+ (d
.width
- new_w
) / 2 + hgap
;
212 else // LEFT and all other values of align.
215 for (int k
= i
; k
< j
; ++k
)
217 if (comps
[k
].visible
)
219 Dimension c
= comps
[k
].getPreferredSize ();
220 comps
[k
].setBounds (x
, y
+ (new_h
- c
.height
) / 2,
226 // Advance to next row.
234 * Returns the minimum layout size for the specified container using
236 * @param cont The parent container
237 * @return The minimum layout size.
239 public Dimension
minimumLayoutSize (Container cont
)
241 return getSize (cont
, true);
245 * Returns the preferred layout size for the specified container using
247 * @param cont The parent container
248 * @return The preferred layout size.
250 public Dimension
preferredLayoutSize (Container cont
)
252 return getSize (cont
, false);
255 /** Remove the indicated component from this layout manager.
256 * This particular implementation does nothing.
257 * @param comp The component to remove
259 public void removeLayoutComponent (Component comp
)
265 * Sets the justification value for this object to the specified value.
267 * @param align The new justification value for this object, which must
268 * be one of the constants in this class.
270 public void setAlignment (int align
)
272 // The JDK accepts invalid values and treats them as
273 // LEFT during layout, so do we. The invalid value is even stored,
274 // getAlignment() returns the same invalid value.
279 * Sets the horizontal gap between components to the specified value.
281 * @param hgap The new horizontal gap between components.
283 public void setHgap (int hgap
)
286 throw new IllegalArgumentException ("horizontal gap must be nonnegative");
291 * Sets the vertical gap between lines of components to the specified value.
293 * @param vgap The new vertical gap.
295 public void setVgap (int vgap
)
298 throw new IllegalArgumentException ("vertical gap must be nonnegative");
302 /** Return String description of this object.
303 * @return A string representation of this object.
305 public String
toString ()
307 return ("[" + getClass ().getName () + ",hgap=" + hgap
+ ",vgap=" + vgap
308 + ",align=" + align
+ "]");
311 // This method is used to compute the various sizes.
312 private Dimension
getSize (Container parent
, boolean is_min
)
314 synchronized (parent
.getTreeLock ())
316 int w
, h
, num
= parent
.getComponentCount ();
317 // This is more efficient than calling getComponents().
318 Component
[] comps
= parent
.component
;
322 for (int i
= 0; i
< num
; ++i
)
324 if (! comps
[i
].visible
)
327 // FIXME: can we just directly read the fields in Component?
328 // Or will that not work with subclassing?
332 d
= comps
[i
].getMinimumSize ();
334 d
= comps
[i
].getPreferredSize ();
337 h
= Math
.max (d
.height
, h
);
340 Insets ins
= parent
.getInsets ();
342 w
+= (num
+ 1) * hgap
+ ins
.left
+ ins
.right
;
343 h
+= 2 * vgap
+ ins
.top
+ ins
.bottom
;
345 return new Dimension (w
, h
);
350 * @serial The justification alignment of the lines of components, which
351 * will be one of the constants defined in this class.
356 * @serial The horizontal gap between components.
361 * @serial The vertical gap between lines of components.