Statistics
| Revision:

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
/*---------------------------------------------------------------------------*/