KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > layout > RowLayout


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.swt.layout;
12
13 import org.eclipse.swt.*;
14 import org.eclipse.swt.graphics.*;
15 import org.eclipse.swt.widgets.*;
16
17 /**
18  * Instances of this class determine the size and position of the
19  * children of a <code>Composite</code> by placing them either in
20  * horizontal rows or vertical columns within the parent <code>Composite</code>.
21  * <p>
22  * <code>RowLayout</code> aligns all controls in one row if the
23  * <code>type</code> is set to horizontal, and one column if it is
24  * set to vertical. It has the ability to wrap, and provides configurable
25  * margins and spacing. <code>RowLayout</code> has a number of configuration
26  * fields. In addition, the height and width of each control in a
27  * <code>RowLayout</code> can be specified by setting a <code>RowData</code>
28  * object into the control using <code>setLayoutData ()</code>.
29  * </p>
30  * <p>
31  * The following example code creates a <code>RowLayout</code>, sets all
32  * of its fields to non-default values, and then sets it into a
33  * <code>Shell</code>.
34  * <pre>
35  * RowLayout rowLayout = new RowLayout();
36  * rowLayout.wrap = false;
37  * rowLayout.pack = false;
38  * rowLayout.justify = true;
39  * rowLayout.type = SWT.VERTICAL;
40  * rowLayout.marginLeft = 5;
41  * rowLayout.marginTop = 5;
42  * rowLayout.marginRight = 5;
43  * rowLayout.marginBottom = 5;
44  * rowLayout.spacing = 0;
45  * shell.setLayout(rowLayout);
46  * </pre>
47  * If you are using the default field values, you only need one line of code:
48  * <pre>
49  * shell.setLayout(new RowLayout());
50  * </pre>
51  * </p>
52  *
53  * @see RowData
54  */

55 public final class RowLayout extends Layout {
56     
57     /**
58      * type specifies whether the layout places controls in rows or
59      * columns.
60      *
61      * The default value is HORIZONTAL.
62      *
63      * Possible values are: <ul>
64      * <li>HORIZONTAL: Position the controls horizontally from left to right</li>
65      * <li>VERTICAL: Position the controls vertically from top to bottom</li>
66      * </ul>
67      *
68      * @since 2.0
69      */

70     public int type = SWT.HORIZONTAL;
71     
72     /**
73      * marginWidth specifies the number of pixels of horizontal margin
74      * that will be placed along the left and right edges of the layout.
75      *
76      * The default value is 0.
77      *
78      * @since 3.0
79      */

80     public int marginWidth = 0;
81     
82     /**
83      * marginHeight specifies the number of pixels of vertical margin
84      * that will be placed along the top and bottom edges of the layout.
85      *
86      * The default value is 0.
87      *
88      * @since 3.0
89      */

90     public int marginHeight = 0;
91
92     /**
93      * spacing specifies the number of pixels between the edge of one cell
94      * and the edge of its neighbouring cell.
95      *
96      * The default value is 3.
97      */

98     public int spacing = 3;
99             
100     /**
101      * wrap specifies whether a control will be wrapped to the next
102      * row if there is insufficient space on the current row.
103      *
104      * The default value is true.
105      */

106     public boolean wrap = true;
107
108     /**
109      * pack specifies whether all controls in the layout take
110      * their preferred size. If pack is false, all controls will
111      * have the same size which is the size required to accommodate the
112      * largest preferred height and the largest preferred width of all
113      * the controls in the layout.
114      *
115      * The default value is true.
116      */

117     public boolean pack = true;
118     
119     /**
120      * fill specifies whether the controls in a row should be
121      * all the same height for horizontal layouts, or the same
122      * width for vertical layouts.
123      *
124      * The default value is false.
125      *
126      * @since 3.0
127      */

128     public boolean fill = false;
129
130     /**
131      * justify specifies whether the controls in a row should be
132      * fully justified, with any extra space placed between the controls.
133      *
134      * The default value is false.
135      */

136     public boolean justify = false;
137
138     /**
139      * marginLeft specifies the number of pixels of horizontal margin
140      * that will be placed along the left edge of the layout.
141      *
142      * The default value is 3.
143      */

144     public int marginLeft = 3;
145
146     /**
147      * marginTop specifies the number of pixels of vertical margin
148      * that will be placed along the top edge of the layout.
149      *
150      * The default value is 3.
151      */

152     public int marginTop = 3;
153
154     /**
155      * marginRight specifies the number of pixels of horizontal margin
156      * that will be placed along the right edge of the layout.
157      *
158      * The default value is 3.
159      */

160     public int marginRight = 3;
161
162     /**
163      * marginBottom specifies the number of pixels of vertical margin
164      * that will be placed along the bottom edge of the layout.
165      *
166      * The default value is 3.
167      */

168     public int marginBottom = 3;
169
170 /**
171  * Constructs a new instance of this class.
172  */

173 public RowLayout () {
174 }
175
176 /**
177  * Constructs a new instance of this class given the type.
178  *
179  * @param type the type of row layout
180  *
181  * @since 2.0
182  */

183 public RowLayout (int type) {
184     this.type = type;
185 }
186
187 protected Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache) {
188     Point extent;
189     if (type == SWT.HORIZONTAL) {
190         extent = layoutHorizontal (composite, false, (wHint != SWT.DEFAULT) && wrap, wHint, flushCache);
191     } else {
192         extent = layoutVertical (composite, false, (hHint != SWT.DEFAULT) && wrap, hHint, flushCache);
193     }
194     if (wHint != SWT.DEFAULT) extent.x = wHint;
195     if (hHint != SWT.DEFAULT) extent.y = hHint;
196     return extent;
197 }
198
199 Point computeSize (Control control, boolean flushCache) {
200     int wHint = SWT.DEFAULT, hHint = SWT.DEFAULT;
201     RowData data = (RowData) control.getLayoutData ();
202     if (data != null) {
203         wHint = data.width;
204         hHint = data.height;
205     }
206     return control.computeSize (wHint, hHint, flushCache);
207 }
208
209 protected boolean flushCache (Control control) {
210     return true;
211 }
212
213 String JavaDoc getName () {
214     String JavaDoc string = getClass ().getName ();
215     int index = string.lastIndexOf ('.');
216     if (index == -1) return string;
217     return string.substring (index + 1, string.length ());
218 }
219
220 protected void layout (Composite composite, boolean flushCache) {
221     Rectangle clientArea = composite.getClientArea ();
222     if (type == SWT.HORIZONTAL) {
223         layoutHorizontal (composite, true, wrap, clientArea.width, flushCache);
224     } else {
225         layoutVertical (composite, true, wrap, clientArea.height, flushCache);
226     }
227 }
228
229 Point layoutHorizontal (Composite composite, boolean move, boolean wrap, int width, boolean flushCache) {
230     Control [] children = composite.getChildren ();
231     int count = 0;
232     for (int i=0; i<children.length; i++) {
233         Control control = children [i];
234         RowData data = (RowData) control.getLayoutData ();
235         if (data == null || !data.exclude) {
236             children [count++] = children [i];
237         }
238     }
239     if (count == 0) {
240         return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom);
241     }
242     int childWidth = 0, childHeight = 0, maxHeight = 0;
243     if (!pack) {
244         for (int i=0; i<count; i++) {
245             Control child = children [i];
246             Point size = computeSize (child, flushCache);
247             childWidth = Math.max (childWidth, size.x);
248             childHeight = Math.max (childHeight, size.y);
249         }
250         maxHeight = childHeight;
251     }
252     int clientX = 0, clientY = 0;
253     if (move) {
254         Rectangle rect = composite.getClientArea ();
255         clientX = rect.x;
256         clientY = rect.y;
257     }
258     int [] wraps = null;
259     boolean wrapped = false;
260     Rectangle [] bounds = null;
261     if (move && (justify || fill)) {
262         bounds = new Rectangle [count];
263         wraps = new int [count];
264     }
265     int maxX = 0, x = marginLeft + marginWidth, y = marginTop + marginHeight;
266     for (int i=0; i<count; i++) {
267         Control child = children [i];
268         if (pack) {
269             Point size = computeSize (child, flushCache);
270             childWidth = size.x;
271             childHeight = size.y;
272         }
273         if (wrap && (i != 0) && (x + childWidth > width)) {
274             wrapped = true;
275             if (move && (justify || fill)) wraps [i - 1] = maxHeight;
276             x = marginLeft + marginWidth;
277             y += spacing + maxHeight;
278             if (pack) maxHeight = 0;
279         }
280         if (pack || fill) {
281             maxHeight = Math.max (maxHeight, childHeight);
282         }
283         if (move) {
284             int childX = x + clientX, childY = y + clientY;
285             if (justify || fill) {
286                 bounds [i] = new Rectangle (childX, childY, childWidth, childHeight);
287             } else {
288                 child.setBounds (childX, childY, childWidth, childHeight);
289             }
290         }
291         x += spacing + childWidth;
292         maxX = Math.max (maxX, x);
293     }
294     maxX = Math.max (clientX + marginLeft + marginWidth, maxX - spacing);
295     if (!wrapped) maxX += marginRight + marginWidth;
296     if (move && (justify || fill)) {
297         int space = 0, margin = 0;
298         if (!wrapped) {
299             space = Math.max (0, (width - maxX) / (count + 1));
300             margin = Math.max (0, ((width - maxX) % (count + 1)) / 2);
301         } else {
302             if (fill || justify) {
303                 int last = 0;
304                 if (count > 0) wraps [count - 1] = maxHeight;
305                 for (int i=0; i<count; i++) {
306                     if (wraps [i] != 0) {
307                         int wrapCount = i - last + 1;
308                         if (justify) {
309                             int wrapX = 0;
310                             for (int j=last; j<=i; j++) {
311                                 wrapX += bounds [j].width + spacing;
312                             }
313                             space = Math.max (0, (width - wrapX) / (wrapCount + 1));
314                             margin = Math.max (0, ((width - wrapX) % (wrapCount + 1)) / 2);
315                         }
316                         for (int j=last; j<=i; j++) {
317                             if (justify) bounds [j].x += (space * (j - last + 1)) + margin;
318                             if (fill) bounds [j].height = wraps [i];
319                         }
320                         last = i + 1;
321                     }
322                 }
323             }
324         }
325         for (int i=0; i<count; i++) {
326             if (!wrapped) {
327                 if (justify) bounds [i].x += (space * (i + 1)) + margin;
328                 if (fill) bounds [i].height = maxHeight;
329             }
330             children [i].setBounds (bounds [i]);
331         }
332     }
333     return new Point (maxX, y + maxHeight + marginBottom + marginHeight);
334 }
335
336 Point layoutVertical (Composite composite, boolean move, boolean wrap, int height, boolean flushCache) {
337     Control [] children = composite.getChildren ();
338     int count = 0;
339     for (int i=0; i<children.length; i++) {
340         Control control = children [i];
341         RowData data = (RowData) control.getLayoutData ();
342         if (data == null || !data.exclude) {
343             children [count++] = children [i];
344         }
345     }
346     if (count == 0) {
347         return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom);
348     }
349     int childWidth = 0, childHeight = 0, maxWidth = 0;
350     if (!pack) {
351         for (int i=0; i<count; i++) {
352             Control child = children [i];
353             Point size = computeSize (child, flushCache);
354             childWidth = Math.max (childWidth, size.x);
355             childHeight = Math.max (childHeight, size.y);
356         }
357         maxWidth = childWidth;
358     }
359     int clientX = 0, clientY = 0;
360     if (move) {
361         Rectangle rect = composite.getClientArea ();
362         clientX = rect.x;
363         clientY = rect.y;
364     }
365     int [] wraps = null;
366     boolean wrapped = false;
367     Rectangle [] bounds = null;
368     if (move && (justify || fill)) {
369         bounds = new Rectangle [count];
370         wraps = new int [count];
371     }
372     int maxY = 0, x = marginLeft + marginWidth, y = marginTop + marginHeight;
373     for (int i=0; i<count; i++) {
374         Control child = children [i];
375         if (pack) {
376             Point size = computeSize (child, flushCache);
377             childWidth = size.x;
378             childHeight = size.y;
379         }
380         if (wrap && (i != 0) && (y + childHeight > height)) {
381             wrapped = true;
382             if (move && (justify || fill)) wraps [i - 1] = maxWidth;
383             x += spacing + maxWidth;
384             y = marginTop + marginHeight;
385             if (pack) maxWidth = 0;
386         }
387         if (pack || fill) {
388             maxWidth = Math.max (maxWidth, childWidth);
389         }
390         if (move) {
391             int childX = x + clientX, childY = y + clientY;
392             if (justify || fill) {
393                 bounds [i] = new Rectangle (childX, childY, childWidth, childHeight);
394             } else {
395                 child.setBounds (childX, childY, childWidth, childHeight);
396             }
397         }
398         y += spacing + childHeight;
399         maxY = Math.max (maxY, y);
400     }
401     maxY = Math.max (clientY + marginTop + marginHeight, maxY - spacing);
402     if (!wrapped) maxY += marginBottom + marginHeight;
403     if (move && (justify || fill)) {
404         int space = 0, margin = 0;
405         if (!wrapped) {
406             space = Math.max (0, (height - maxY) / (count + 1));
407             margin = Math.max (0, ((height - maxY) % (count + 1)) / 2);
408         } else {
409             if (fill || justify) {
410                 int last = 0;
411                 if (count > 0) wraps [count - 1] = maxWidth;
412                 for (int i=0; i<count; i++) {
413                     if (wraps [i] != 0) {
414                         int wrapCount = i - last + 1;
415                         if (justify) {
416                             int wrapY = 0;
417                             for (int j=last; j<=i; j++) {
418                                 wrapY += bounds [j].height + spacing;
419                             }
420                             space = Math.max (0, (height - wrapY) / (wrapCount + 1));
421                             margin = Math.max (0, ((height - wrapY) % (wrapCount + 1)) / 2);
422                         }
423                         for (int j=last; j<=i; j++) {
424                             if (justify) bounds [j].y += (space * (j - last + 1)) + margin;
425                             if (fill) bounds [j].width = wraps [i];
426                         }
427                         last = i + 1;
428                     }
429                 }
430             }
431         }
432         for (int i=0; i<count; i++) {
433             if (!wrapped) {
434                 if (justify) bounds [i].y += (space * (i + 1)) + margin;
435                 if (fill) bounds [i].width = maxWidth;
436             }
437             children [i].setBounds (bounds [i]);
438         }
439     }
440     return new Point (x + maxWidth + marginRight + marginWidth, maxY);
441 }
442
443 /**
444  * Returns a string containing a concise, human-readable
445  * description of the receiver.
446  *
447  * @return a string representation of the layout
448  */

449 public String JavaDoc toString () {
450     String JavaDoc string = getName ()+" {";
451     string += "type="+((type != SWT.HORIZONTAL) ? "SWT.VERTICAL" : "SWT.HORIZONTAL")+" ";
452     if (marginWidth != 0) string += "marginWidth="+marginWidth+" ";
453     if (marginHeight != 0) string += "marginHeight="+marginHeight+" ";
454     if (marginLeft != 0) string += "marginLeft="+marginLeft+" ";
455     if (marginTop != 0) string += "marginTop="+marginTop+" ";
456     if (marginRight != 0) string += "marginRight="+marginRight+" ";
457     if (marginBottom != 0) string += "marginBottom="+marginBottom+" ";
458     if (spacing != 0) string += "spacing="+spacing+" ";
459     string += "wrap="+wrap+" ";
460     string += "pack="+pack+" ";
461     string += "fill="+fill+" ";
462     string += "justify="+justify+" ";
463     string = string.trim();
464     string += "}";
465     return string;
466 }
467 }
468
Popular Tags