KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > forms > widgets > ColumnLayout


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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  * dinko.ivanov@sap.com - patch #70790
11  *******************************************************************************/

12 package org.eclipse.ui.forms.widgets;
13 import org.eclipse.swt.SWT;
14 import org.eclipse.swt.graphics.Point;
15 import org.eclipse.swt.graphics.Rectangle;
16 import org.eclipse.swt.widgets.Composite;
17 import org.eclipse.swt.widgets.Control;
18 import org.eclipse.swt.widgets.Layout;
19 /**
20  * This layout manager arranges children of the composite parent in vertical
21  * columns. All the columns are identical size and children are stretched
22  * horizontally to fill the column width. The goal is to give layout some
23  * reasonable range of column numbers to allow it to handle various parent
24  * widths. That way, column number will drop to the lowest number in the range
25  * when width decreases, and grow up to the highest number in the range when
26  * allowed by the parent width.
27  * <p>
28  * In addition, the layout attempts to 'fill the space' equally i.e. to avoid
29  * large gaps at the and of the last column.
30  * <p>
31  * Child controls are layed out according to their 'natural' (preferred) size.
32  * For 'stretchy' controls that do not have natural preferred size, it is
33  * possible to set width and/or height hints using ColumnLayoutData objects.
34  *
35  * @see ColumnLayoutData
36  * @since 3.0
37  */

38 public final class ColumnLayout extends Layout implements ILayoutExtension {
39     /**
40      * Minimum number of columns (default is 1).
41      */

42     public int minNumColumns = 1;
43     /**
44      * Maximum number of columns (default is 3).
45      */

46     public int maxNumColumns = 3;
47     /**
48      * Horizontal spacing between columns (default is 5).
49      */

50     public int horizontalSpacing = 5;
51     /**
52      * Vertical spacing between controls (default is 5).
53      */

54     public int verticalSpacing = 5;
55     /**
56      * Top margin (default is 5).
57      */

58     public int topMargin = 5;
59     /**
60      * Left margin (default is 5).
61      */

62     public int leftMargin = 5;
63     /**
64      * Bottom margin (default is 5).
65      */

66     public int bottomMargin = 5;
67     /**
68      * Right margin (default is 5).
69      */

70     public int rightMargin = 5;
71
72     /**
73      * Creates a new instance of the column layout.
74      */

75     public ColumnLayout() {
76     }
77
78     protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
79         if (wHint == 0)
80             return computeSize(composite, wHint, hHint, minNumColumns);
81         else if (wHint == SWT.DEFAULT)
82             return computeSize(composite, wHint, hHint, maxNumColumns);
83         else
84             return computeSize(composite, wHint, hHint, -1);
85     }
86
87     private Point computeSize(Composite parent, int wHint, int hHint, int ncolumns) {
88         Control[] children = parent.getChildren();
89         int cwidth = 0;
90         int cheight = 0;
91         Point[] sizes = new Point[children.length];
92
93         int cwHint = SWT.DEFAULT;
94         if (ncolumns != -1) {
95             cwHint = wHint - leftMargin - rightMargin - (ncolumns - 1) * horizontalSpacing;
96             if (cwHint <= 0)
97                 cwHint = 0;
98             else
99                 cwHint /= ncolumns;
100         }
101
102         for (int i = 0; i < children.length; i++) {
103             sizes[i] = computeControlSize(children[i], cwHint);
104             cwidth = Math.max(cwidth, sizes[i].x);
105             cheight += sizes[i].y;
106         }
107         if (ncolumns == -1) {
108             // must compute
109
ncolumns = (wHint - leftMargin - rightMargin - horizontalSpacing) / (cwidth + horizontalSpacing);
110             ncolumns = Math.min(ncolumns, children.length);
111             ncolumns = Math.max(ncolumns, minNumColumns);
112             ncolumns = Math.min(ncolumns, maxNumColumns);
113         }
114         int perColHeight = cheight / ncolumns;
115         if (cheight % ncolumns != 0)
116             perColHeight++;
117         int colHeight = 0;
118         int[] heights = new int[ncolumns];
119         int ncol = 0;
120         
121         boolean fillIn = false;
122         
123         for (int i = 0; i < sizes.length; i++) {
124             int childHeight = sizes[i].y;
125             if (i>0 && colHeight + childHeight > perColHeight) {
126                 heights[ncol] = colHeight;
127                 ncol++;
128                 if (ncol == ncolumns || fillIn) {
129                     // overflow - start filling in
130
fillIn = true;
131                     ncol = findShortestColumn(heights);
132                 }
133                 colHeight = heights[ncol];
134             }
135             if (colHeight > 0)
136                 colHeight += verticalSpacing;
137             colHeight += childHeight;
138         }
139         heights[ncol] = Math.max(heights[ncol],colHeight);
140         
141         Point size = new Point(0, 0);
142         for (int i = 0; i < ncolumns; i++) {
143             size.y = Math.max(size.y, heights[i]);
144         }
145         size.x = cwidth * ncolumns + (ncolumns - 1) * horizontalSpacing;
146         size.x += leftMargin + rightMargin;
147         //System.out.println("ColumnLayout: whint="+wHint+", size.x="+size.x);
148
size.y += topMargin + bottomMargin;
149         return size;
150     }
151
152     private Point computeControlSize(Control c, int wHint) {
153         ColumnLayoutData cd = (ColumnLayoutData) c.getLayoutData();
154         int widthHint = cd != null ? cd.widthHint : wHint;
155         int heightHint = cd != null ? cd.heightHint : SWT.DEFAULT;
156         return c.computeSize(widthHint, heightHint);
157     }
158
159     private int findShortestColumn(int[] heights) {
160         int result = 0;
161         int height = Integer.MAX_VALUE;
162         for (int i = 0; i < heights.length; i++) {
163             if (height > heights[i]) {
164                 height = heights[i];
165                 result = i;
166             }
167         }
168         return result;
169     }
170
171     /*
172      * (non-Javadoc)
173      *
174      * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite,
175      * boolean)
176      */

177     protected void layout(Composite parent, boolean flushCache) {
178         Control[] children = parent.getChildren();
179         Rectangle carea = parent.getClientArea();
180         int cwidth = 0;
181         int cheight = 0;
182         Point[] sizes = new Point[children.length];
183         for (int i = 0; i < children.length; i++) {
184             sizes[i] = computeControlSize(children[i], SWT.DEFAULT);
185             cwidth = Math.max(cwidth, sizes[i].x);
186             cheight += sizes[i].y;
187         }
188         int ncolumns = (carea.width - leftMargin - rightMargin - horizontalSpacing) / (cwidth + horizontalSpacing);
189         ncolumns = Math.min(ncolumns, children.length);
190         ncolumns = Math.max(ncolumns, minNumColumns);
191         ncolumns = Math.min(ncolumns, maxNumColumns);
192         int realWidth = (carea.width - leftMargin - rightMargin + horizontalSpacing) / ncolumns - horizontalSpacing;
193 // int childrenPerColumn = children.length / ncolumns;
194
// if (children.length % ncolumns != 0)
195
// childrenPerColumn++;
196
// int colWidth = 0;
197

198         int fillWidth = Math.max(cwidth, realWidth);
199         
200         int perColHeight = cheight / ncolumns;
201         if (cheight % ncolumns != 0)
202             perColHeight++;
203         
204         int colHeight = 0;
205         int[] heights = new int[ncolumns];
206         int ncol = 0;
207         int x = leftMargin;
208         boolean fillIn = false;
209         
210         for (int i = 0; i < sizes.length; i++) {
211             Control child = children[i];
212             Point csize = sizes[i];
213             ColumnLayoutData cd = (ColumnLayoutData) child.getLayoutData();
214             int align = cd != null ? cd.horizontalAlignment : ColumnLayoutData.FILL;
215             int childWidth = align == ColumnLayoutData.FILL ? fillWidth : csize.x;
216
217             if (i>0 && colHeight + csize.y > perColHeight) {
218                 heights[ncol] = colHeight;
219                 if (fillIn || ncol == ncolumns-1) {
220                     // overflow - start filling in
221
fillIn = true;
222                     ncol = findShortestColumn(heights);
223                     
224                     x = leftMargin + ncol * (fillWidth + horizontalSpacing);
225
226                 }
227                 else {
228                     ncol++;
229                     x += fillWidth + horizontalSpacing;
230                 }
231                 colHeight = heights[ncol];
232             }
233             if (colHeight > 0)
234                 colHeight += verticalSpacing;
235             
236             
237             switch (align) {
238                 case ColumnLayoutData.LEFT :
239                 case ColumnLayoutData.FILL :
240                     child.setBounds(x, topMargin+colHeight, childWidth, csize.y);
241                     break;
242                 case ColumnLayoutData.RIGHT :
243                     child.setBounds(x + fillWidth - childWidth, topMargin+colHeight, childWidth, csize.y);
244                     break;
245                 case ColumnLayoutData.CENTER :
246                     child.setBounds(x + fillWidth / 2 - childWidth / 2, topMargin+colHeight, childWidth, csize.y);
247                     break;
248             }
249             
250             colHeight += csize.y;
251         }
252     }
253
254     /*
255      * (non-Javadoc)
256      *
257      * @see org.eclipse.ui.forms.widgets.ILayoutExtension#computeMaximumWidth(org.eclipse.swt.widgets.Composite,
258      * boolean)
259      */

260     public int computeMaximumWidth(Composite parent, boolean changed) {
261         return computeSize(parent, SWT.DEFAULT, SWT.DEFAULT, changed).x;
262     }
263
264     /*
265      * (non-Javadoc)
266      *
267      * @see org.eclipse.ui.forms.widgets.ILayoutExtension#computeMinimumWidth(org.eclipse.swt.widgets.Composite,
268      * boolean)
269      */

270     public int computeMinimumWidth(Composite parent, boolean changed) {
271         return computeSize(parent, 0, SWT.DEFAULT, changed).x;
272     }
273 }
274
Popular Tags