root / import / ext3D / trunk / install-extension3d / IzPack / src / lib / com / izforge / izpack / gui / FlowLayout.java @ 15280
History | View | Annotate | Download (18.8 KB)
1 |
/*
|
---|---|
2 |
* $Id: FlowLayout.java,v 1.1 2006/06/14 07:29:07 cesar Exp $
|
3 |
* IzPack
|
4 |
* Copyright (C) 2002 Elmar Grom
|
5 |
*
|
6 |
* File : FlowLayout.java
|
7 |
* Description : A special layout manger designed for the RuleInputField
|
8 |
* Author's email : elmar@grom.net
|
9 |
* Author's Website : http://www.izforge.com
|
10 |
*
|
11 |
* This program is free software; you can redistribute it and/or
|
12 |
* modify it under the terms of the GNU General Public License
|
13 |
* as published by the Free Software Foundation; either version 2
|
14 |
* of the License, or any later version.
|
15 |
*
|
16 |
* This program is distributed in the hope that it will be useful,
|
17 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19 |
* GNU General Public License for more details.
|
20 |
*
|
21 |
* You should have received a copy of the GNU General Public License
|
22 |
* along with this program; if not, write to the Free Software
|
23 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
24 |
*/
|
25 |
|
26 |
package com.izforge.izpack.gui; |
27 |
|
28 |
import java.awt.Component; |
29 |
import java.awt.Container; |
30 |
import java.awt.Dimension; |
31 |
import java.awt.Insets; |
32 |
import java.awt.LayoutManager; |
33 |
|
34 |
/*---------------------------------------------------------------------------*/
|
35 |
/**
|
36 |
* A flow layout arranges components in a left-to-right flow, much
|
37 |
* like lines of text in a paragraph. Flow layouts are typically used
|
38 |
* to arrange buttons in a panel. It will arrange
|
39 |
* buttons left to right until no more buttons fit on the same line.
|
40 |
* Each line is centered.
|
41 |
* <p>
|
42 |
* For example, the following picture shows an applet using the flow
|
43 |
* layout manager (its default layout manager) to position three buttons:
|
44 |
* <p>
|
45 |
* <img src="doc-files/FlowLayout-1.gif"
|
46 |
* ALT="Graphic of Layout for Three Buttons"
|
47 |
* ALIGN=center HSPACE=10 VSPACE=7>
|
48 |
* <p>
|
49 |
* Here is the code for this applet:
|
50 |
* <p>
|
51 |
* <hr><blockquote><pre>
|
52 |
* import java.awt.*;
|
53 |
* import java.applet.Applet;
|
54 |
*
|
55 |
* public class myButtons extends Applet {
|
56 |
* Button button1, button2, button3;
|
57 |
* public void init() {
|
58 |
* button1 = new Button("Ok");
|
59 |
* button2 = new Button("Open");
|
60 |
* button3 = new Button("Close");
|
61 |
* add(button1);
|
62 |
* add(button2);
|
63 |
* add(button3);
|
64 |
* }
|
65 |
* }
|
66 |
* </pre></blockquote><hr>
|
67 |
* <p>
|
68 |
* A flow layout lets each component assume its natural (preferred) size.
|
69 |
*
|
70 |
* This class is a bit different from java.awt.FlowLayout.
|
71 |
* <blockquote>
|
72 |
* java.awt.FlowLayout has a minor problem that was
|
73 |
* bugging me when I wrote the UserInputPanel. FlowLayout puts some amount of
|
74 |
* space in between each component that it lays out. In addition it adds that
|
75 |
* same amount of space to the left and to the right of the entire group.
|
76 |
* Therefore items such as the RuleInputfield that are laid out with a
|
77 |
* FlowLayout would never line up properly with the other components (it would
|
78 |
* appear to be slightly indented). Because there is no way to circumvent this
|
79 |
* behavior in FlowLayout (it's hard coded) I copied the source and modified it
|
80 |
* so that it does not add the space to the left and to the right. Now my stuff
|
81 |
* lines up properly.
|
82 |
* (Elmar Grom)</blockquote>
|
83 |
*
|
84 |
* @version 1.39, 11/29/02
|
85 |
* @author Arthur van Hoff
|
86 |
* @author Sami Shaio
|
87 |
* @author Elmar Grom
|
88 |
*/
|
89 |
/*---------------------------------------------------------------------------*/
|
90 |
public class FlowLayout implements LayoutManager |
91 |
{ |
92 |
|
93 |
/**
|
94 |
* This value indicates that each row of components
|
95 |
* should be left-justified.
|
96 |
*/
|
97 |
public static final int LEFT = 0; |
98 |
|
99 |
/**
|
100 |
* This value indicates that each row of components
|
101 |
* should be centered.
|
102 |
*/
|
103 |
public static final int CENTER = 1; |
104 |
|
105 |
/**
|
106 |
* This value indicates that each row of components
|
107 |
* should be right-justified.
|
108 |
*/
|
109 |
public static final int RIGHT = 2; |
110 |
|
111 |
/**
|
112 |
* This value indicates that each row of components
|
113 |
* should be justified to the leading edge of the container's
|
114 |
* orientation, for example, to the left in left-to-right orientations.
|
115 |
*
|
116 |
* @see java.awt.Component#getComponentOrientation
|
117 |
* @see java.awt.ComponentOrientation
|
118 |
* @since 1.2
|
119 |
* Package-private pending API change approval
|
120 |
*/
|
121 |
public static final int LEADING = 3; |
122 |
|
123 |
/**
|
124 |
* This value indicates that each row of components
|
125 |
* should be justified to the leading edge of the container's
|
126 |
* orientation, for example, to the right in left-to-right orientations.
|
127 |
*
|
128 |
* @see java.awt.Component#getComponentOrientation
|
129 |
* @see java.awt.ComponentOrientation
|
130 |
* @since 1.2
|
131 |
* Package-private pending API change approval
|
132 |
*/
|
133 |
public static final int TRAILING = 4; |
134 |
|
135 |
/**
|
136 |
* <code>align</code> is the proprty that determines
|
137 |
* how each row distributes empty space.
|
138 |
* It can be one of the following three values :
|
139 |
* <code>LEFT</code>
|
140 |
* <code>RIGHT</code>
|
141 |
* <code>CENTER</code>
|
142 |
*
|
143 |
* @serial
|
144 |
* @see #getAlignment
|
145 |
* @see #setAlignment
|
146 |
*/
|
147 |
int align; // This is for 1.1 serialization compatibilitys |
148 |
/**
|
149 |
* <code>newAlign</code> is the property that determines
|
150 |
* how each row distributes empty space for the Java 2 platform, v1.2 and greater.
|
151 |
* It can be one of the following three values :
|
152 |
* <code>LEFT</code>
|
153 |
* <code>RIGHT</code>
|
154 |
* <code>CENTER</code>
|
155 |
*
|
156 |
* @serial
|
157 |
* @since 1.2
|
158 |
* @see #getAlignment
|
159 |
* @see #setAlignment
|
160 |
*/
|
161 |
int newAlign; // This is the one we actually use |
162 |
/**
|
163 |
* The flow layout manager allows a seperation of
|
164 |
* components with gaps. The horizontal gap will
|
165 |
* specify the space between components.
|
166 |
*
|
167 |
* @serial
|
168 |
* @see #getHgap
|
169 |
* @see #setHgap
|
170 |
*/
|
171 |
int hgap;
|
172 |
/**
|
173 |
* The flow layout manager allows a seperation of
|
174 |
* components with gaps. The vertical gap will
|
175 |
* specify the space between rows.
|
176 |
*
|
177 |
* @serial
|
178 |
* @see #getVgap
|
179 |
* @see #setVgap
|
180 |
*/
|
181 |
int vgap;
|
182 |
|
183 |
|
184 |
/*--------------------------------------------------------------------------*/
|
185 |
/**
|
186 |
* Constructs a new Flow Layout with a centered alignment and a
|
187 |
* default 5-unit horizontal and vertical gap.
|
188 |
*/
|
189 |
/*--------------------------------------------------------------------------*/
|
190 |
public FlowLayout () |
191 |
{ |
192 |
this (CENTER, 5, 5); |
193 |
} |
194 |
/*--------------------------------------------------------------------------*/
|
195 |
/**
|
196 |
* Constructs a new Flow Layout with the specified alignment and a
|
197 |
* default 5-unit horizontal and vertical gap.
|
198 |
* The value of the alignment argument must be one of
|
199 |
* <code>FlowLayout.LEFT</code>, <code>FlowLayout.RIGHT</code>,
|
200 |
* or <code>FlowLayout.CENTER</code>.
|
201 |
*
|
202 |
* @param align the alignment value
|
203 |
*/
|
204 |
/*--------------------------------------------------------------------------*/
|
205 |
public FlowLayout (int align) |
206 |
{ |
207 |
this (align, 5, 5); |
208 |
} |
209 |
/*--------------------------------------------------------------------------*/
|
210 |
/**
|
211 |
* Creates a new flow layout manager with the indicated alignment
|
212 |
* and the indicated horizontal and vertical gaps.
|
213 |
* <p>
|
214 |
* The value of the alignment argument must be one of
|
215 |
* <code>FlowLayout.LEFT</code>, <code>FlowLayout.RIGHT</code>,
|
216 |
* or <code>FlowLayout.CENTER</code>.
|
217 |
*
|
218 |
* @param align the alignment value.
|
219 |
* @param hgap the horizontal gap between components.
|
220 |
* @param vgap the vertical gap between components.
|
221 |
*/
|
222 |
/*--------------------------------------------------------------------------*/
|
223 |
public FlowLayout (int align, |
224 |
int hgap,
|
225 |
int vgap)
|
226 |
{ |
227 |
this.hgap = hgap;
|
228 |
this.vgap = vgap;
|
229 |
setAlignment (align); |
230 |
} |
231 |
/*--------------------------------------------------------------------------*/
|
232 |
/**
|
233 |
* Gets the alignment for this layout.
|
234 |
* Possible values are <code>FlowLayout.LEFT</code>,
|
235 |
* <code>FlowLayout.RIGHT</code>, or <code>FlowLayout.CENTER</code>.
|
236 |
*
|
237 |
* @return the alignment value for this layout.
|
238 |
*
|
239 |
* @see java.awt.FlowLayout#setAlignment
|
240 |
*/
|
241 |
/*--------------------------------------------------------------------------*/
|
242 |
public int getAlignment () |
243 |
{ |
244 |
return (newAlign);
|
245 |
} |
246 |
/*--------------------------------------------------------------------------*/
|
247 |
/**
|
248 |
* Sets the alignment for this layout.
|
249 |
* Possible values are <code>FlowLayout.LEFT</code>,
|
250 |
* <code>FlowLayout.RIGHT</code>, and <code>FlowLayout.CENTER</code>.
|
251 |
*
|
252 |
* @param align the alignment value.
|
253 |
*
|
254 |
* @see #getAlignment()
|
255 |
*/
|
256 |
/*--------------------------------------------------------------------------*/
|
257 |
public void setAlignment (int align) |
258 |
{ |
259 |
this.newAlign = align;
|
260 |
|
261 |
// this.align is used only for serialization compatibility,
|
262 |
// so set it to a value compatible with the 1.1 version
|
263 |
// of the class
|
264 |
|
265 |
switch (align)
|
266 |
{ |
267 |
case LEADING : this.align = LEFT; |
268 |
break;
|
269 |
case TRAILING : this.align = RIGHT; |
270 |
break;
|
271 |
default : this.align = align; |
272 |
break;
|
273 |
} |
274 |
} |
275 |
/*--------------------------------------------------------------------------*/
|
276 |
/**
|
277 |
* Gets the horizontal gap between components.
|
278 |
*
|
279 |
* @return the horizontal gap between components.
|
280 |
*
|
281 |
* @see #setHgap(int)
|
282 |
*/
|
283 |
/*--------------------------------------------------------------------------*/
|
284 |
public int getHgap () |
285 |
{ |
286 |
return (hgap);
|
287 |
} |
288 |
/*--------------------------------------------------------------------------*/
|
289 |
/**
|
290 |
* Sets the horizontal gap between components.
|
291 |
*
|
292 |
* @param hgap the horizontal gap between components
|
293 |
*
|
294 |
* @see #getHgap()
|
295 |
*/
|
296 |
/*--------------------------------------------------------------------------*/
|
297 |
public void setHgap (int hgap) |
298 |
{ |
299 |
this.hgap = hgap;
|
300 |
} |
301 |
/*--------------------------------------------------------------------------*/
|
302 |
/**
|
303 |
* Gets the vertical gap between components.
|
304 |
*
|
305 |
* @return the vertical gap between components.\
|
306 |
*
|
307 |
* @see #setVgap(int)
|
308 |
*/
|
309 |
/*--------------------------------------------------------------------------*/
|
310 |
public int getVgap () |
311 |
{ |
312 |
return (vgap);
|
313 |
} |
314 |
/*--------------------------------------------------------------------------*/
|
315 |
/**
|
316 |
* Sets the vertical gap between components.
|
317 |
*
|
318 |
* @param vgap the vertical gap between components
|
319 |
*
|
320 |
* @see #getVgap()
|
321 |
*/
|
322 |
/*--------------------------------------------------------------------------*/
|
323 |
public void setVgap (int vgap) |
324 |
{ |
325 |
this.vgap = vgap;
|
326 |
} |
327 |
/*--------------------------------------------------------------------------*/
|
328 |
/**
|
329 |
* Adds the specified component to the layout. Not used by this class.
|
330 |
*
|
331 |
* @param name the name of the component
|
332 |
* @param comp the component to be added
|
333 |
*/
|
334 |
/*--------------------------------------------------------------------------*/
|
335 |
public void addLayoutComponent (String name, |
336 |
Component comp)
|
337 |
{} |
338 |
/*--------------------------------------------------------------------------*/
|
339 |
/**
|
340 |
* Removes the specified component from the layout. Not used by
|
341 |
* this class.
|
342 |
*
|
343 |
* @param comp the component to remove
|
344 |
*
|
345 |
*/
|
346 |
/*--------------------------------------------------------------------------*/
|
347 |
public void removeLayoutComponent (Component comp) |
348 |
{} |
349 |
/*--------------------------------------------------------------------------*/
|
350 |
/**
|
351 |
* Returns the preferred dimensions for this layout given the components
|
352 |
* in the specified target container.
|
353 |
*
|
354 |
* @param target the component which needs to be laid out
|
355 |
*
|
356 |
* @return the preferred dimensions to lay out the
|
357 |
* subcomponents of the specified container.
|
358 |
* @see #minimumLayoutSize(Container)
|
359 |
*/
|
360 |
/*--------------------------------------------------------------------------*/
|
361 |
public Dimension preferredLayoutSize (Container target) |
362 |
{ |
363 |
synchronized (target.getTreeLock ())
|
364 |
{ |
365 |
Dimension dim = new Dimension (0, 0); |
366 |
int nmembers = target.getComponentCount ();
|
367 |
boolean firstVisibleComponent = true; |
368 |
|
369 |
for (int i = 0 ; i < nmembers ; i++) |
370 |
{ |
371 |
Component m = target.getComponent (i);
|
372 |
if (m.isVisible ())
|
373 |
{ |
374 |
Dimension d = m.getPreferredSize ();
|
375 |
dim.height = Math.max (dim.height, d.height);
|
376 |
if (firstVisibleComponent)
|
377 |
{ |
378 |
firstVisibleComponent = false;
|
379 |
} |
380 |
else
|
381 |
{ |
382 |
dim.width += hgap; |
383 |
} |
384 |
dim.width += d.width; |
385 |
} |
386 |
} |
387 |
|
388 |
Insets insets = target.getInsets ();
|
389 |
dim.width += insets.left + insets.right + hgap*2;
|
390 |
dim.height += insets.top + insets.bottom + vgap*2;
|
391 |
|
392 |
return (dim);
|
393 |
} |
394 |
} |
395 |
/*--------------------------------------------------------------------------*/
|
396 |
/**
|
397 |
* Returns the minimum dimensions needed to layout the components
|
398 |
* contained in the specified target container.
|
399 |
*
|
400 |
* @param target the component which needs to be laid out
|
401 |
*
|
402 |
* @return the minimum dimensions to lay out the
|
403 |
* subcomponents of the specified container.
|
404 |
*
|
405 |
* @see #preferredLayoutSize(Container)
|
406 |
*/
|
407 |
/*--------------------------------------------------------------------------*/
|
408 |
public Dimension minimumLayoutSize (Container target) |
409 |
{ |
410 |
synchronized (target.getTreeLock ())
|
411 |
{ |
412 |
Dimension dim = new Dimension (0, 0); |
413 |
int nmembers = target.getComponentCount ();
|
414 |
|
415 |
for (int i = 0 ; i < nmembers ; i++) |
416 |
{ |
417 |
Component m = target.getComponent (i);
|
418 |
if (m.isVisible ())
|
419 |
{ |
420 |
Dimension d = m.getMinimumSize ();
|
421 |
dim.height = Math.max (dim.height, d.height);
|
422 |
if (i > 0) |
423 |
{ |
424 |
dim.width += hgap; |
425 |
} |
426 |
dim.width += d.width; |
427 |
} |
428 |
} |
429 |
|
430 |
Insets insets = target.getInsets ();
|
431 |
dim.width += insets.left + insets.right + hgap*2;
|
432 |
dim.height += insets.top + insets.bottom + vgap*2;
|
433 |
|
434 |
return (dim);
|
435 |
} |
436 |
} |
437 |
/*--------------------------------------------------------------------------*/
|
438 |
/**
|
439 |
* Centers the elements in the specified row, if there is any slack.
|
440 |
*
|
441 |
* @param target the component which needs to be moved
|
442 |
* @param x the x coordinate
|
443 |
* @param y the y coordinate
|
444 |
* @param width the width dimensions
|
445 |
* @param height the height dimensions
|
446 |
* @param rowStart the beginning of the row
|
447 |
* @param rowEnd the the ending of the row
|
448 |
*/
|
449 |
/*--------------------------------------------------------------------------*/
|
450 |
private void moveComponents (Container target, |
451 |
int x,
|
452 |
int y,
|
453 |
int width,
|
454 |
int height,
|
455 |
int rowStart,
|
456 |
int rowEnd,
|
457 |
boolean ltr)
|
458 |
{ |
459 |
synchronized (target.getTreeLock())
|
460 |
{ |
461 |
switch (newAlign)
|
462 |
{ |
463 |
case LEFT : x += ltr ? 0 : width; |
464 |
break;
|
465 |
case CENTER : x += width / 2; |
466 |
break;
|
467 |
case RIGHT : x += ltr ? width : 0; |
468 |
break;
|
469 |
case LEADING : break; |
470 |
case TRAILING : x += width;
|
471 |
break;
|
472 |
} |
473 |
|
474 |
for (int i = rowStart ; i < rowEnd ; i++) |
475 |
{ |
476 |
Component m = target.getComponent(i);
|
477 |
|
478 |
if (m.isVisible ())
|
479 |
{ |
480 |
if (ltr)
|
481 |
{ |
482 |
m.setLocation (x, y + (height - m.getSize ().height) / 2);
|
483 |
} |
484 |
else
|
485 |
{ |
486 |
m.setLocation (target.getSize ().width - x - m.getSize ().width, y + (height - m.getSize ().height) / 2);
|
487 |
} |
488 |
|
489 |
x += m.getSize ().width + hgap; |
490 |
} |
491 |
} |
492 |
} |
493 |
} |
494 |
/*--------------------------------------------------------------------------*/
|
495 |
/**
|
496 |
* Lays out the container. This method lets each component take
|
497 |
* its preferred size by reshaping the components in the
|
498 |
* target container in order to satisfy the constraints of
|
499 |
* this <code>FlowLayout</code> object.
|
500 |
*
|
501 |
* @param target the specified component being laid out.
|
502 |
*
|
503 |
*/
|
504 |
/*--------------------------------------------------------------------------*/
|
505 |
public void layoutContainer (Container target) |
506 |
{ |
507 |
synchronized (target.getTreeLock ())
|
508 |
{ |
509 |
Insets insets = target.getInsets ();
|
510 |
int maxWidth = target.getSize ().width - (insets.left + insets.right + hgap * 2); |
511 |
int nMembers = target.getComponentCount ();
|
512 |
int x = 0; |
513 |
int y = insets.top + vgap;
|
514 |
int rowh = 0; |
515 |
int start = 0; |
516 |
|
517 |
boolean ltr = target.getComponentOrientation ().isLeftToRight ();
|
518 |
|
519 |
for (int i = 0 ; i < nMembers ; i++) |
520 |
{ |
521 |
Component m = target.getComponent (i);
|
522 |
|
523 |
if (m.isVisible ())
|
524 |
{ |
525 |
Dimension d = m.getPreferredSize ();
|
526 |
m.setSize (d.width, d.height); |
527 |
|
528 |
if ((x == 0) || ((x + d.width) <= maxWidth)) |
529 |
{ |
530 |
if (x > 0) |
531 |
{ |
532 |
x += hgap; |
533 |
} |
534 |
x += d.width; |
535 |
rowh = Math.max (rowh, d.height);
|
536 |
} |
537 |
else
|
538 |
{ |
539 |
moveComponents (target, insets.left, y, maxWidth - x, rowh, start, i, ltr); |
540 |
x = d.width; |
541 |
y += vgap + rowh; |
542 |
rowh = d.height; |
543 |
start = i; |
544 |
} |
545 |
} |
546 |
} |
547 |
|
548 |
moveComponents (target, insets.left, y, maxWidth - x, rowh, start, nMembers, ltr); |
549 |
} |
550 |
} |
551 |
/*--------------------------------------------------------------------------*/
|
552 |
/**
|
553 |
* Returns a string representation of this <code>FlowLayout</code>
|
554 |
* object and its values.
|
555 |
*
|
556 |
* @return a string representation of this layout.
|
557 |
*/
|
558 |
/*--------------------------------------------------------------------------*/
|
559 |
public String toString() |
560 |
{ |
561 |
String str = ""; |
562 |
|
563 |
switch (align)
|
564 |
{ |
565 |
case LEFT : str = ",align=left"; |
566 |
break;
|
567 |
case CENTER : str = ",align=center"; |
568 |
break;
|
569 |
case RIGHT : str = ",align=right"; |
570 |
break;
|
571 |
case LEADING : str = ",align=leading"; |
572 |
break;
|
573 |
case TRAILING : str = ",align=trailing"; |
574 |
break;
|
575 |
} |
576 |
|
577 |
return (getClass ().getName () + "[hgap=" + hgap + ",vgap=" + vgap + str + "]"); |
578 |
} |
579 |
} |
580 |
/*---------------------------------------------------------------------------*/
|