KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > installer > VariableGridLayout


1 /*
2  * VariableGridLayout.java - a grid layout manager with variable cell sizes
3  *
4  * Originally written by Dirk Moebius for the jEdit project. This work has been
5  * placed into the public domain. You may use this work in any way and for any
6  * purpose you wish.
7  *
8  * THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, NOT EVEN THE
9  * IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, ASSUMES
10  * _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE RESULTING FROM THE USE, MODIFICATION,
11  * OR REDISTRIBUTION OF THIS SOFTWARE.
12  */

13
14 package installer;
15
16
17 import java.awt.*;
18
19 // This is copied from jEdit's org.gjt.sp.jedit.gui package.
20

21 /**
22  * The <code>VariableGridLayout</code> class is a layout manager
23  * that lays out a container's components in a rectangular grid
24  * with variable cell sizes.<p>
25  *
26  * The container is divided into rectangles, and one component is placed
27  * in each rectangle. Each row is as large as the largest component in
28  * that row, and each column is as wide as the widest component in
29  * that column.<p>
30  *
31  * This behavior is basically the same as in
32  * <code>java.awt.GridLayout</code>, but with different row heights and
33  * column widths for each row/column.<p>
34  *
35  * For example, the following is an applet that lays out six buttons
36  * into three rows and two columns:<p>
37  *
38  * <blockquote><pre>
39  * import java.awt.*;
40  * import java.applet.Applet;
41  * public class ButtonGrid extends Applet {
42  * public void init() {
43  * setLayout(new VariableGridLayout(VariableGridLayout.FIXED_NUM_COLUMNS, 2));
44  * add(new Button("1"));
45  * add(new Button("2"));
46  * add(new Button("3"));
47  * add(new Button("4"));
48  * add(new Button("5"));
49  * add(new Button("6"));
50  * }
51  * }
52  * </pre></blockquote><p>
53  *
54  * <b>Programmer's remark:</b> VariableGridLayout could be faster, if it would
55  * reside in the package java.awt, because then it could access some
56  * package private fields of <code>Container</code> or
57  * <code>Component</code>. Instead, it has to call
58  * <code>Component.getSize()</code>,
59  * which allocates memory on the heap.<p>
60  *
61  * <b>Todo:</b>
62  * <ul>
63  * <li>Use alignmentX/Y property if the grid cell is larger than the preferred size of the component.
64  * <li>Ability to span components over more than one cell horizontally
65  * </ul>
66  *
67  * @author Dirk Moebius
68  * @version 1.0
69  * @see java.awt.GridLayout
70  */

71 public class VariableGridLayout implements LayoutManager2, java.io.Serializable JavaDoc
72 {
73
74     public static final int FIXED_NUM_ROWS = 1;
75     public static final int FIXED_NUM_COLUMNS = 2;
76
77
78     public VariableGridLayout(int mode, int size, int hgap, int vgap) {
79         if (mode != FIXED_NUM_ROWS && mode != FIXED_NUM_COLUMNS) {
80             throw new IllegalArgumentException JavaDoc("illegal mode; value is " + mode);
81         }
82         if (size <= 0) {
83             throw new IllegalArgumentException JavaDoc("size cannot be zero or less; value is " + size);
84         }
85         if (hgap < 0) {
86             throw new IllegalArgumentException JavaDoc("hgap cannot be negative; value is " + hgap);
87         }
88         if (vgap < 0) {
89             throw new IllegalArgumentException JavaDoc("vgap cannot be negative; value is " + vgap);
90         }
91         this.mode = mode;
92         this.size = size;
93         this.hgap = hgap;
94         this.vgap = vgap;
95     }
96
97
98     /**
99      * Creates a variable grid layout manager with the specified mode
100      * and zero horizontal and vertical gap.
101      */

102     public VariableGridLayout(int mode, int size) {
103         this(mode, size, 0, 0);
104     }
105
106
107     /**
108      * Creates a variable grid layout manager with mode FIXED_NUM_ROWS,
109      * number of rows == 1 and zero horizontal and vertical gap.
110      */

111     public VariableGridLayout() {
112         this(FIXED_NUM_ROWS, 1, 0, 0);
113     }
114
115
116     /**
117      * Not used in this class.
118      */

119     public void addLayoutComponent(String JavaDoc name, Component component) { }
120
121
122     /**
123      * Not used in this class.
124      */

125     public void addLayoutComponent(Component component, Object JavaDoc constraints) { }
126
127
128     /**
129      * Not used in this class.
130      */

131     public void removeLayoutComponent(Component component) { }
132
133
134     /**
135      * Always returns 0.5.
136      */

137     public float getLayoutAlignmentX(Container container) {
138         return 0.5f;
139     }
140
141
142     /**
143      * Always returns 0.5.
144      */

145     public float getLayoutAlignmentY(Container container) {
146         return 0.5f;
147     }
148
149
150     public Dimension preferredLayoutSize(Container parent) {
151         return getLayoutSize(parent, 2);
152     }
153
154
155     public Dimension minimumLayoutSize(Container parent) {
156         return getLayoutSize(parent, 0);
157     }
158
159
160     public Dimension maximumLayoutSize(Container parent) {
161         return getLayoutSize(parent, 1);
162     }
163
164
165     public void layoutContainer(Container parent) {
166         synchronized (parent.getTreeLock()) {
167             update(parent);
168
169             int ncomponents = parent.getComponentCount();
170
171             if (ncomponents == 0) {
172                 return;
173             }
174
175             // Pass 1: compute preferred row heights / column widths
176
int total_height = 0;
177             for (int r = 0, i = 0; r < nrows; r++) {
178                 for (int c = 0; c < ncols; c++, i++) {
179                     if (i < ncomponents) {
180                         Dimension d = parent.getComponent(i).getPreferredSize();
181                         row_heights[r] = Math.max(row_heights[r], d.height);
182                         col_widths[c] = Math.max(col_widths[c], d.width);
183                     } else {
184                         break;
185                     }
186                 }
187                 total_height += row_heights[r];
188             }
189
190             int total_width = 0;
191             for (int c = 0; c < ncols; c++) {
192                 total_width += col_widths[c];
193             }
194
195             // Pass 2: redistribute free space
196
Dimension parent_size = parent.getSize();
197             Insets insets = parent.getInsets();
198             int free_height = parent_size.height - insets.top - insets.bottom - (nrows - 1) * vgap;
199             int free_width = parent_size.width - insets.left - insets.right - (ncols - 1) * hgap;
200
201             if (total_height != free_height) {
202                 double dy = (double)free_height / (double)total_height;
203                 for (int r = 0; r < nrows; r++) {
204                     row_heights[r] = (int) ((double)row_heights[r] * dy);
205                 }
206             }
207
208             if (total_width != free_width) {
209                 double dx = ((double)free_width) / ((double)total_width);
210                 for (int c = 0; c < ncols; c++) {
211                     col_widths[c] = (int) ((double)col_widths[c] * dx);
212                 }
213             }
214
215             // Pass 3: layout components
216
for (int r = 0, y = insets.top, i = 0; r < nrows; y += row_heights[r] + vgap, r++) {
217                 for (int c = 0, x = insets.left; c < ncols; x += col_widths[c] + hgap, c++, i++) {
218                     if (i < ncomponents) {
219                         parent.getComponent(i).setBounds(x, y, col_widths[c], row_heights[r]);
220                     }
221                 }
222             }
223
224         } // synchronized
225
}
226
227
228     public void invalidateLayout(Container container) {}
229
230
231     /**
232      * Returns the string representation of this variable grid layout's values.
233      * @return a string representation of this variable grid layout.
234      */

235     public String JavaDoc toString() {
236         return getClass().getName() + "[mode=" + mode + ",size=" + size
237                + ",hgap=" + hgap + ",vgap=" + vgap + "]";
238     }
239
240
241     /**
242      * @param which if 0 compute minimum layout size,
243      * if 1 compute maximum layout size,
244      * otherwise compute preferred layout size.
245      */

246     private Dimension getLayoutSize(Container parent, int which) {
247         synchronized (parent.getTreeLock()){
248             update(parent);
249
250             int ncomponents = parent.getComponentCount();
251             int h = 0;
252             int w = 0;
253
254             for (int r = 0, i = 0; r < nrows; r++) {
255                 int row_height = 0;
256                 for (int c = 0; c < ncols; c++, i++) {
257                     if (i < ncomponents) {
258                         switch (which) {
259                             case 0:
260                                 row_height = Math.max(row_height, parent.getComponent(i).getMinimumSize().height);
261                                 break;
262                             case 1:
263                                 row_height = Math.max(row_height, parent.getComponent(i).getMaximumSize().height);
264                                 break;
265                             default:
266                                 row_height = Math.max(row_height, parent.getComponent(i).getPreferredSize().height);
267                                 break;
268                         }
269                     } else {
270                         break;
271                     }
272                 }
273                 h += row_height;
274             }
275
276             for (int c = 0; c < ncols; c++) {
277                 int col_width = 0;
278                 for (int r = 0; r < nrows; r++) {
279                     int i = r * ncols + c;
280                     if (i < ncomponents) {
281                         switch (which) {
282                             case 0:
283                                 col_width = Math.max(col_width, parent.getComponent(i).getMinimumSize().width);
284                                 break;
285                             case 1:
286                                 col_width = Math.max(col_width, parent.getComponent(i).getMaximumSize().width);
287                                 break;
288                             default:
289                                 col_width = Math.max(col_width, parent.getComponent(i).getPreferredSize().width);
290                                 break;
291                         }
292                     } else {
293                         break;
294                     }
295                 }
296                 w += col_width;
297             }
298
299             Insets insets = parent.getInsets();
300             return new Dimension(w + insets.left + insets.right + ((ncols - 1) * hgap),
301                                  h + insets.top + insets.bottom + ((nrows - 1) * vgap));
302         }
303     }
304
305
306     private void update(Container container) {
307         int ncomponents = container.getComponentCount();
308         int old_nrows = nrows;
309         int old_ncols = ncols;
310         if (this.mode == FIXED_NUM_ROWS) {
311             nrows = this.size;
312             ncols = (ncomponents + nrows - 1) / nrows;
313         } else {
314             ncols = this.size;
315             nrows = (ncomponents + ncols - 1) / ncols;
316         }
317         if (old_nrows != nrows) {
318             row_heights = new int[nrows];
319         }
320         if (old_ncols != ncols) {
321             col_widths = new int[ncols];
322         }
323     }
324
325
326     private int mode;
327     private int size;
328     private int hgap;
329     private int vgap;
330     private transient int nrows = -1;
331     private transient int ncols = -1;
332     private transient int[] row_heights = null;
333     private transient int[] col_widths = null;
334 }
335
Popular Tags