KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > explorer > propertysheet > AutoGridLayout


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 /*
20 * AutoGridLayout.java
21 *
22 * Created on 04 October 2003, 16:01
23 */

24 package org.openide.explorer.propertysheet;
25
26 import java.awt.Component JavaDoc;
27 import java.awt.Container JavaDoc;
28 import java.awt.Dimension JavaDoc;
29 import java.awt.Insets JavaDoc;
30 import java.awt.LayoutManager JavaDoc;
31 import java.awt.Toolkit JavaDoc;
32
33 import java.util.Arrays JavaDoc;
34 import java.util.Comparator JavaDoc;
35
36
37 /**A layout manager which can layout like-heighted components in a grid
38  * pattern based on their preferred sizes. Can be used in packed or unpacked
39  * mode. Column positions are based on the preferred sizes of the first row
40  * of components.<p>
41  * When packed, the components are sorted from narrowest to widest;
42  * subsequent rows will use these columns, with components two wide for a
43  * single column spanning two or more columns.<p>
44  * When not packed, the components are sorted from widest to narrowest,
45  * resulting in more whitespace, but consistent rows of columns - no
46  * component will span more than one column.<p>
47  * Used by <code>RadioInplaceEditor</code> to manage the set of radio
48  * buttons representing property editor tags.
49  *
50  * @author Tim Boudreau
51  */

52 class AutoGridLayout implements LayoutManager JavaDoc {
53     int gapY = 5;
54     boolean pack;
55
56     public AutoGridLayout(boolean pack) {
57         this.pack = pack;
58     }
59
60     public void addLayoutComponent(String JavaDoc name, Component JavaDoc comp) {
61         //Do nothing
62
}
63
64     public void removeLayoutComponent(Component JavaDoc comp) {
65         //Do nothing
66
}
67
68     private Comparator JavaDoc<Component JavaDoc> comparator() {
69         return new PreferredSizeComparator(pack);
70     }
71
72     public void layoutContainer(Container JavaDoc parent) {
73         Component JavaDoc[] c = parent.getComponents();
74
75         if (c.length > 3) {
76             Arrays.sort(c, comparator());
77         }
78
79         if (c.length == 2) {
80             //we're probably a radio button editor in the property sheet -
81
//make sure that both buttons are displayed, even if some clipping
82
//would occur - we don't have another row to go to
83
Dimension JavaDoc d0 = c[0].getPreferredSize();
84             Dimension JavaDoc d1 = c[1].getPreferredSize();
85             c[0].setBounds(0, 0, d0.width, d0.height);
86             c[1].setBounds(d0.width, 0, d1.width, d1.height);
87
88             return;
89         }
90
91         Insets JavaDoc insets = parent.getInsets();
92
93         int w = parent.getWidth() - insets.right;
94         int h = parent.getHeight() - insets.bottom;
95         int currx = insets.left;
96         int curry = insets.top;
97         boolean done = false;
98         int cols = -1;
99
100         //Layout the first row of components according to their preferred
101
//sizes. Their positions will act as column positions. If sorted
102
//narrowest-first, results in a smaller, packedAutoGridLayout. If sorted
103
//widest-first, results in nice consistent columns, but uses more
104
//space to do it.
105
for (int i = 0; i < c.length; i++) {
106             Dimension JavaDoc d = c[i].getPreferredSize();
107
108             if ((d.width == 0) || (d.height == 0)) {
109                 //Can happen for foreign components that can't do
110
//a proper preferred size w/o a graphics context
111
d = PropUtils.getMinimumPanelSize();
112             }
113
114             if ((currx + d.width) > w) {
115                 curry += (d.height + gapY);
116                 currx = insets.left;
117
118                 if (cols == -1) {
119                     cols = i;
120
121                     break;
122                 }
123             }
124
125             c[i].setBounds(currx, curry, d.width, d.height);
126             currx += d.width;
127         }
128
129         if (cols == -1) {
130             cols = c.length;
131         }
132
133         int currCol = 0;
134
135         for (int i = cols; i < c.length; i++) {
136             Dimension JavaDoc d = c[i].getPreferredSize();
137
138             if ((currx + d.width) > w) {
139                 //will only happen with inverse sort - we're starting
140
//the loop with a position that won't fit, and should flip
141
//to the next line
142
curry += (d.height + gapY);
143                 currx = insets.left;
144                 currCol = 0;
145             }
146
147             //see if we're out of horizontal space and should punt
148
done = (curry + d.height) > h;
149
150             if (!done) {
151                 //fetch the width of this column, as the width of the first row component
152
int currColWidth = c[currCol].getWidth();
153
154                 //will we fit at all?
155
if (d.width <= w) {
156
157                     //loop until we know how many columns we need
158
while (currColWidth <= d.width) {
159                         currCol++;
160
161                         if (currCol > cols) {
162                             //out of columns? Flip to the next line
163
currCol = 0;
164                             curry += (d.height + gapY);
165                             currx = insets.left;
166                             currColWidth = 0;
167                         }
168
169                         //note the combined column width - it will be the
170
//next iteration's starting x position
171
currColWidth += c[currCol].getWidth();
172                     }
173
174                     c[i].setBounds(currx, curry, d.width, d.height);
175                     currx += currColWidth;
176                 } else {
177                     //Okay, we've got a component wider than its parent - give up
178
c[i].setBounds(currx, curry, d.width, d.height);
179                     currx += d.width;
180
181                     //just clip it if it's wider than max
182
}
183
184                 if (currx > w) {
185                     //see if we should flip to the next row or if there may
186
//still be space
187
currx = insets.left;
188                     curry += (d.height + gapY);
189                     currCol = 0;
190                 } else {
191                     currCol++;
192                 }
193             } else {
194                 //If we get here, we've run out of horizontal space - no
195
//point in trying to do something reasonable with the component
196
c[i].setBounds(0, 0, 0, 0);
197             }
198         }
199     }
200
201     public Dimension JavaDoc minimumLayoutSize(java.awt.Container JavaDoc parent) {
202         return preferredLayoutSize(parent);
203     }
204
205     public Dimension JavaDoc preferredLayoutSize(java.awt.Container JavaDoc parent) {
206         Component JavaDoc[] c = parent.getComponents();
207
208         if (c.length > 3) {
209             Arrays.sort(c, comparator());
210         }
211
212         Dimension JavaDoc max = Toolkit.getDefaultToolkit().getScreenSize();
213         max.width /= 2;
214         max.height /= 2;
215
216         Insets JavaDoc insets = parent.getInsets();
217
218         int w = max.width - insets.right;
219
220         int currx = insets.left;
221         int cols = -1;
222         int baseHeight = 0;
223         Dimension JavaDoc[] dims = new Dimension JavaDoc[c.length];
224         Dimension JavaDoc result = new Dimension JavaDoc();
225
226         //establish the base columns and populate the dimensions array
227
for (int i = 0; i < c.length; i++) {
228             dims[i] = c[i].getPreferredSize();
229
230             if ((dims[i].width == 0) || (dims[i].height == 0)) {
231                 //Can happen for foreign components that can't do
232
//a proper preferred size w/o a graphics context
233
dims[i] = PropUtils.getMinimumPanelSize();
234             }
235
236             baseHeight = Math.max(baseHeight, dims[i].height);
237
238             if (cols == -1) {
239                 if ((currx + dims[i].width) > w) {
240                     result.width = currx;
241                     cols = i;
242                 }
243             }
244
245             if (cols != -1) {
246                 //Make sure we don't have one element wider than all the
247
//column sizes
248
result.width = Math.max(result.width, dims[i].width + insets.left + insets.right);
249             }
250
251             currx += dims[i].width;
252         }
253
254         if (cols == -1) { //we didn't overstretch the available width
255
cols = c.length;
256             result.width = currx;
257         }
258
259         if (!pack && (c.length > 3)) {
260             //Then we can take a short cust - we know all will be 1 item per cell
261
int rows = (c.length / cols) + (((c.length % cols) != 0) ? 1 : 0);
262             result.height = (baseHeight * rows) + (gapY * rows) + insets.top + insets.bottom;
263             result.width += 6;
264             assert (result.width >= 0) && (result.height >= 0);
265
266             return result;
267         }
268
269         int currRow = 0;
270         int currCol = 0;
271         currx = insets.left;
272
273         //iterate the rest of the array, incrementing the row index
274
//when the content won't fit, to find out the total rows needed
275
for (int i = cols; i < c.length; i++) {
276             int colspan = 1;
277             int colwidth = dims[currCol].width;
278
279             while (dims[i].width > colwidth) {
280                 currCol++;
281                 colwidth += dims[currCol].width;
282                 colspan++;
283
284                 if ((colwidth + currx) > max.width) {
285                     currCol = 0;
286                     currRow++;
287                     colspan = 1;
288                     colwidth = dims[currCol].width;
289                 }
290             }
291
292             currCol += colspan;
293             currx += colwidth;
294
295             if ((currCol > cols) && (i != (c.length - 1))) {
296                 currCol = 0;
297                 currRow++;
298                 currx = insets.left;
299             }
300         }
301
302         result.height = (baseHeight * currRow) + insets.top + insets.bottom + (gapY * currRow);
303
304         return result;
305     }
306
307     private static final class PreferredSizeComparator implements Comparator JavaDoc<Component JavaDoc> {
308         boolean smallFirst;
309
310         public PreferredSizeComparator(boolean smallFirst) {
311             this.smallFirst = smallFirst;
312         }
313
314         public int compare(Component JavaDoc c1, Component JavaDoc c2) {
315             Dimension JavaDoc d1 = c1.getPreferredSize();
316             Dimension JavaDoc d2 = c2.getPreferredSize();
317
318             return smallFirst ? (d1.width - d2.width) : (d2.width - d1.width);
319         }
320     }
321 }
322
Popular Tags