]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/layout/RowLayout.java
cb21fcd139a0f11963ec181d9b27ee9008e091a8
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / layout / RowLayout.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2018 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.swt.layout;
15
16 import org.eclipse.swt.*;
17 import org.eclipse.swt.graphics.*;
18 import org.eclipse.swt.widgets.*;
19
20 /**
21  * Instances of this class determine the size and position of the
22  * children of a <code>Composite</code> by placing them either in
23  * horizontal rows or vertical columns within the parent <code>Composite</code>.
24  * <p>
25  * <code>RowLayout</code> aligns all controls in one row if the
26  * <code>type</code> is set to horizontal, and one column if it is
27  * set to vertical. It has the ability to wrap, and provides configurable
28  * margins and spacing. <code>RowLayout</code> has a number of configuration
29  * fields. In addition, the height and width of each control in a
30  * <code>RowLayout</code> can be specified by setting a <code>RowData</code>
31  * object into the control using <code>setLayoutData ()</code>.
32  * </p>
33  * <p>
34  * The following example code creates a <code>RowLayout</code>, sets all
35  * of its fields to non-default values, and then sets it into a
36  * <code>Shell</code>.</p>
37  * <pre>
38  *              RowLayout rowLayout = new RowLayout();
39  *              rowLayout.wrap = false;
40  *              rowLayout.pack = false;
41  *              rowLayout.justify = true;
42  *              rowLayout.type = SWT.VERTICAL;
43  *              rowLayout.marginLeft = 5;
44  *              rowLayout.marginTop = 5;
45  *              rowLayout.marginRight = 5;
46  *              rowLayout.marginBottom = 5;
47  *              rowLayout.spacing = 0;
48  *              shell.setLayout(rowLayout);
49  * </pre>
50  * If you are using the default field values, you only need one line of code:
51  * <pre>
52  *              shell.setLayout(new RowLayout());
53  * </pre>
54  *
55  * @see RowData
56  * @see <a href="http://www.eclipse.org/swt/snippets/#rowlayout">RowLayout snippets</a>
57  * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: LayoutExample</a>
58  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
59  */
60 public final class RowLayout extends Layout {
61
62         /**
63          * type specifies whether the layout places controls in rows or
64          * columns.
65          *
66          * The default value is HORIZONTAL.
67          *
68          * Possible values are: <ul>
69          *    <li>HORIZONTAL: Position the controls horizontally from left to right</li>
70          *    <li>VERTICAL: Position the controls vertically from top to bottom</li>
71          * </ul>
72          *
73          * @since 2.0
74          */
75         public int type = SWT.HORIZONTAL;
76
77         /**
78          * marginWidth specifies the number of points of horizontal margin
79          * that will be placed along the left and right edges of the layout.
80          *
81          * The default value is 0.
82          *
83          * @since 3.0
84          */
85         public int marginWidth = 0;
86
87         /**
88          * marginHeight specifies the number of points of vertical margin
89          * that will be placed along the top and bottom edges of the layout.
90          *
91          * The default value is 0.
92          *
93          * @since 3.0
94          */
95         public int marginHeight = 0;
96
97         /**
98          * spacing specifies the number of points between the edge of one cell
99          * and the edge of its neighbouring cell.
100          *
101          * The default value is 3.
102          */
103         public int spacing = 3;
104
105         /**
106          * wrap specifies whether a control will be wrapped to the next
107          * row if there is insufficient space on the current row.
108          *
109          * The default value is true.
110          */
111         public boolean wrap = true;
112
113         /**
114          * pack specifies whether all controls in the layout take
115          * their preferred size.  If pack is false, all controls will
116          * have the same size which is the size required to accommodate the
117          * largest preferred height and the largest preferred width of all
118          * the controls in the layout.
119          *
120          * The default value is true.
121          */
122         public boolean pack = true;
123
124         /**
125          * fill specifies whether the controls in a row should be
126          * all the same height for horizontal layouts, or the same
127          * width for vertical layouts.
128          *
129          * The default value is false.
130          *
131          * @since 3.0
132          */
133         public boolean fill = false;
134
135         /**
136          * center specifies whether the controls in a row should be
137          * centered vertically in each cell for horizontal layouts,
138          * or centered horizontally in each cell for vertical layouts.
139          *
140          * The default value is false.
141          *
142          * @since 3.4
143          */
144         public boolean center = false;
145
146         /**
147          * justify specifies whether the controls in a row should be
148          * fully justified, with any extra space placed between the controls.
149          *
150          * The default value is false.
151          */
152         public boolean justify = false;
153
154         /**
155          * marginLeft specifies the number of points of horizontal margin
156          * that will be placed along the left edge of the layout.
157          *
158          * The default value is 3.
159          */
160         public int marginLeft = 3;
161
162         /**
163          * marginTop specifies the number of points of vertical margin
164          * that will be placed along the top edge of the layout.
165          *
166          * The default value is 3.
167          */
168         public int marginTop = 3;
169
170         /**
171          * marginRight specifies the number of points of horizontal margin
172          * that will be placed along the right edge of the layout.
173          *
174          * The default value is 3.
175          */
176         public int marginRight = 3;
177
178         /**
179          * marginBottom specifies the number of points of vertical margin
180          * that will be placed along the bottom edge of the layout.
181          *
182          * The default value is 3.
183          */
184         public int marginBottom = 3;
185
186 /**
187  * Constructs a new instance of this class with type HORIZONTAL.
188  */
189 public RowLayout () {
190 }
191
192 /**
193  * Constructs a new instance of this class given the type.
194  *
195  * @param type the type of row layout
196  *
197  * @since 2.0
198  */
199 public RowLayout (int type) {
200         this.type = type;
201 }
202
203 @Override
204 protected Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache) {
205         Point extent;
206         if (type == SWT.HORIZONTAL) {
207                 extent = layoutHorizontal (composite, false, (wHint != SWT.DEFAULT) && wrap, wHint, flushCache);
208         } else {
209                 extent = layoutVertical (composite, false, (hHint != SWT.DEFAULT) && wrap, hHint, flushCache);
210         }
211         if (wHint != SWT.DEFAULT) extent.x = wHint;
212         if (hHint != SWT.DEFAULT) extent.y = hHint;
213         return extent;
214 }
215
216 Point computeSize (Control control, boolean flushCache) {
217         int wHint = SWT.DEFAULT, hHint = SWT.DEFAULT;
218         RowData data = (RowData) control.getLayoutData ();
219         if (data != null) {
220                 wHint = data.width;
221                 hHint = data.height;
222         }
223         return control.computeSize (wHint, hHint, flushCache);
224 }
225
226 @Override
227 protected boolean flushCache (Control control) {
228         return true;
229 }
230
231 String getName () {
232         String string = getClass ().getName ();
233         int index = string.lastIndexOf ('.');
234         if (index == -1) return string;
235         return string.substring (index + 1, string.length ());
236 }
237
238 @Override
239 protected void layout (Composite composite, boolean flushCache) {
240         Rectangle clientArea = composite.getClientArea ();
241         if (type == SWT.HORIZONTAL) {
242                 layoutHorizontal (composite, true, wrap, clientArea.width, flushCache);
243         } else {
244                 layoutVertical (composite, true, wrap, clientArea.height, flushCache);
245         }
246 }
247
248 Point layoutHorizontal (Composite composite, boolean move, boolean wrap, int width, boolean flushCache) {
249         Control [] children = composite.getChildren ();
250         int count = 0;
251         for (int i=0; i<children.length; i++) {
252                 Control control = children [i];
253                 RowData data = (RowData) control.getLayoutData ();
254                 if (data == null || !data.exclude) {
255                         children [count++] = children [i];
256                 }
257         }
258         if (count == 0) {
259                 return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom);
260         }
261         int childWidth = 0, childHeight = 0, maxHeight = 0;
262         if (!pack) {
263                 for (int i=0; i<count; i++) {
264                         Control child = children [i];
265                         Point size = computeSize (child, flushCache);
266                         if (width > SWT.DEFAULT && width < size.x && wrap) {
267                                 size = child.computeSize (width, child.getLayoutData() == null ? SWT.DEFAULT : ((RowData) child.getLayoutData()).height, flushCache);
268                         }
269                         childWidth = Math.max (childWidth, size.x);
270                         childHeight = Math.max (childHeight, size.y);
271                 }
272                 maxHeight = childHeight;
273         }
274         int clientX = 0, clientY = 0;
275         if (move) {
276                 Rectangle rect = composite.getClientArea ();
277                 clientX = rect.x;
278                 clientY = rect.y;
279         }
280         int [] wraps = null;
281         boolean wrapped = false;
282         Rectangle [] bounds = null;
283         if (move && (justify || fill || center)) {
284                 bounds = new Rectangle [count];
285                 wraps = new int [count];
286         }
287         int maxX = 0, x = marginLeft + marginWidth, y = marginTop + marginHeight;
288         for (int i=0; i<count; i++) {
289                 Control child = children [i];
290                 if (pack) {
291                         Point size = computeSize (child, flushCache);
292                         if (width > SWT.DEFAULT && width < size.x && wrap) {
293                                 size = child.computeSize (width, child.getLayoutData() == null ? SWT.DEFAULT : ((RowData) child.getLayoutData()).height, flushCache);
294                         }
295                         childWidth = size.x;
296                         childHeight = size.y;
297                 }
298                 if (wrap && (i != 0) && (x + childWidth > width)) {
299                         wrapped = true;
300                         if (move && (justify || fill || center)) wraps [i - 1] = maxHeight;
301                         x = marginLeft + marginWidth;
302                         y += spacing + maxHeight;
303                         if (pack) maxHeight = 0;
304                 }
305                 if (pack || fill || center) {
306                         maxHeight = Math.max (maxHeight, childHeight);
307                 }
308                 if (move) {
309                         int childX = x + clientX, childY = y + clientY;
310                         if (justify || fill || center) {
311                                 bounds [i] = new Rectangle (childX, childY, childWidth, childHeight);
312                         } else {
313                                 child.setBounds (childX, childY, childWidth, childHeight);
314                         }
315                 }
316                 x += spacing + childWidth;
317                 maxX = Math.max (maxX, x);
318         }
319         maxX = Math.max (clientX + marginLeft + marginWidth, maxX - spacing);
320         if (!wrapped) maxX += marginRight + marginWidth;
321         if (move && (justify || fill || center)) {
322                 int space = 0, margin = 0;
323                 if (!wrapped) {
324                         space = Math.max (0, (width - maxX) / (count + 1));
325                         margin = Math.max (0, ((width - maxX) % (count + 1)) / 2);
326                 } else {
327                         if (fill || justify || center) {
328                                 int last = 0;
329                                 if (count > 0) wraps [count - 1] = maxHeight;
330                                 for (int i=0; i<count; i++) {
331                                         if (wraps [i] != 0) {
332                                                 int wrapCount = i - last + 1;
333                                                 if (justify) {
334                                                         int wrapX = 0;
335                                                         for (int j=last; j<=i; j++) {
336                                                                 wrapX += bounds [j].width + spacing;
337                                                         }
338                                                         space = Math.max (0, (width - wrapX) / (wrapCount + 1));
339                                                         margin = Math.max (0, ((width - wrapX) % (wrapCount + 1)) / 2);
340                                                 }
341                                                 for (int j=last; j<=i; j++) {
342                                                         if (justify) bounds [j].x += (space * (j - last + 1)) + margin;
343                                                         if (fill) {
344                                                                 bounds [j].height = wraps [i];
345                                                         } else {
346                                                                 if (center) {
347                                                                         bounds [j].y += Math.max (0, (wraps [i] - bounds [j].height) / 2);
348                                                                 }
349                                                         }
350                                                 }
351                                                 last = i + 1;
352                                         }
353                                 }
354                         }
355                 }
356                 for (int i=0; i<count; i++) {
357                         if (!wrapped) {
358                                 if (justify) bounds [i].x += (space * (i + 1)) + margin;
359                                 if (fill) {
360                                         bounds [i].height = maxHeight;
361                                 } else {
362                                         if (center) {
363                                                 bounds [i].y += Math.max (0, (maxHeight - bounds [i].height) / 2);
364                                         }
365                                 }
366                         }
367                         children [i].setBounds (bounds [i]);
368                 }
369         }
370         return new Point (maxX, y + maxHeight + marginBottom + marginHeight);
371 }
372
373 Point layoutVertical (Composite composite, boolean move, boolean wrap, int height, boolean flushCache) {
374         Control [] children = composite.getChildren ();
375         int count = 0;
376         for (int i=0; i<children.length; i++) {
377                 Control control = children [i];
378                 RowData data = (RowData) control.getLayoutData ();
379                 if (data == null || !data.exclude) {
380                         children [count++] = children [i];
381                 }
382         }
383         if (count == 0) {
384                 return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom);
385         }
386         int childWidth = 0, childHeight = 0, maxWidth = 0;
387         if (!pack) {
388                 for (int i=0; i<count; i++) {
389                         Control child = children [i];
390                         Point size = computeSize (child, flushCache);
391                         if(height>SWT.DEFAULT && height<size.y && wrap)
392                                 size=child.computeSize(child.getLayoutData()==null?SWT.DEFAULT:((RowData)child.getLayoutData()).width,height,flushCache);
393                         childWidth = Math.max (childWidth, size.x);
394                         childHeight = Math.max (childHeight, size.y);
395                 }
396                 maxWidth = childWidth;
397         }
398         int clientX = 0, clientY = 0;
399         if (move) {
400                 Rectangle rect = composite.getClientArea ();
401                 clientX = rect.x;
402                 clientY = rect.y;
403         }
404         int [] wraps = null;
405         boolean wrapped = false;
406         Rectangle [] bounds = null;
407         if (move && (justify || fill || center)) {
408                 bounds = new Rectangle [count];
409                 wraps = new int [count];
410         }
411         int maxY = 0, x = marginLeft + marginWidth, y = marginTop + marginHeight;
412         for (int i=0; i<count; i++) {
413                 Control child = children [i];
414                 if (pack) {
415                         Point size = computeSize (child, flushCache);
416                         if(height>SWT.DEFAULT && height<size.y && wrap)
417                                 size=child.computeSize(child.getLayoutData()==null?SWT.DEFAULT:((RowData)child.getLayoutData()).width,height,flushCache);
418                         childWidth = size.x;
419                         childHeight = size.y;
420                 }
421                 if (wrap && (i != 0) && (y + childHeight > height)) {
422                         wrapped = true;
423                         if (move && (justify || fill || center)) wraps [i - 1] = maxWidth;
424                         x += spacing + maxWidth;
425                         y = marginTop + marginHeight;
426                         if (pack) maxWidth = 0;
427                 }
428                 if (pack || fill || center) {
429                         maxWidth = Math.max (maxWidth, childWidth);
430                 }
431                 if (move) {
432                         int childX = x + clientX, childY = y + clientY;
433                         if (justify || fill || center) {
434                                 bounds [i] = new Rectangle (childX, childY, childWidth, childHeight);
435                         } else {
436                                 child.setBounds (childX, childY, childWidth, childHeight);
437                         }
438                 }
439                 y += spacing + childHeight;
440                 maxY = Math.max (maxY, y);
441         }
442         maxY = Math.max (clientY + marginTop + marginHeight, maxY - spacing);
443         if (!wrapped) maxY += marginBottom + marginHeight;
444         if (move && (justify || fill || center)) {
445                 int space = 0, margin = 0;
446                 if (!wrapped) {
447                         space = Math.max (0, (height - maxY) / (count + 1));
448                         margin = Math.max (0, ((height - maxY) % (count + 1)) / 2);
449                 } else {
450                         if (fill || justify || center) {
451                                 int last = 0;
452                                 if (count > 0) wraps [count - 1] = maxWidth;
453                                 for (int i=0; i<count; i++) {
454                                         if (wraps [i] != 0) {
455                                                 int wrapCount = i - last + 1;
456                                                 if (justify) {
457                                                         int wrapY = 0;
458                                                         for (int j=last; j<=i; j++) {
459                                                                 wrapY += bounds [j].height + spacing;
460                                                         }
461                                                         space = Math.max (0, (height - wrapY) / (wrapCount + 1));
462                                                         margin = Math.max (0, ((height - wrapY) % (wrapCount + 1)) / 2);
463                                                 }
464                                                 for (int j=last; j<=i; j++) {
465                                                         if (justify) bounds [j].y += (space * (j - last + 1)) + margin;
466                                                         if (fill) {
467                                                                 bounds [j].width = wraps [i];
468                                                         } else {
469                                                                 if (center) {
470                                                                         bounds [j].x += Math.max (0, (wraps [i] - bounds [j].width) / 2);
471                                                                 }
472                                                         }
473                                                 }
474                                                 last = i + 1;
475                                         }
476                                 }
477                         }
478                 }
479                 for (int i=0; i<count; i++) {
480                         if (!wrapped) {
481                                 if (justify) bounds [i].y += (space * (i + 1)) + margin;
482                                 if (fill) {
483                                         bounds [i].width = maxWidth;
484                                 } else {
485                                         if (center) {
486                                                 bounds [i].x += Math.max (0, (maxWidth - bounds [i].width) / 2);
487                                         }
488                                 }
489
490                         }
491                         children [i].setBounds (bounds [i]);
492                 }
493         }
494         return new Point (x + maxWidth + marginRight + marginWidth, maxY);
495 }
496
497 /**
498  * Returns a string containing a concise, human-readable
499  * description of the receiver.
500  *
501  * @return a string representation of the layout
502  */
503 @Override
504 public String toString () {
505         String string = getName ()+" {";
506         string += "type="+((type != SWT.HORIZONTAL) ? "SWT.VERTICAL" : "SWT.HORIZONTAL")+" ";
507         if (marginWidth != 0) string += "marginWidth="+marginWidth+" ";
508         if (marginHeight != 0) string += "marginHeight="+marginHeight+" ";
509         if (marginLeft != 0) string += "marginLeft="+marginLeft+" ";
510         if (marginTop != 0) string += "marginTop="+marginTop+" ";
511         if (marginRight != 0) string += "marginRight="+marginRight+" ";
512         if (marginBottom != 0) string += "marginBottom="+marginBottom+" ";
513         if (spacing != 0) string += "spacing="+spacing+" ";
514         string += "wrap="+wrap+" ";
515         string += "pack="+pack+" ";
516         string += "fill="+fill+" ";
517         string += "justify="+justify+" ";
518         string = string.trim();
519         string += "}";
520         return string;
521 }
522 }