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