1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 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 org.eclipse.swt.layout.GridData;
14 
15 import org.eclipse.swt.SWT;
16 import org.eclipse.swt.graphics.Point;
17 import org.eclipse.swt.widgets.Control;
18 
19 import java.lang.all;
20 
21 /**
22  * <code>GridData</code> is the layout data object associated with
23  * <code>GridLayout</code>. To set a <code>GridData</code> object into a
24  * control, you use the <code>Control.setLayoutData(Object)</code> method.
25  * <p>
26  * There are two ways to create a <code>GridData</code> object with certain
27  * fields set. The first is to set the fields directly, like this:
28  * <pre>
29  *      GridData gridData = new GridData();
30  *      gridData.horizontalAlignment = GridData.FILL;
31  *      gridData.grabExcessHorizontalSpace = true;
32  *      button1.setLayoutData(gridData);
33  * </pre>
34  * The second is to take advantage of convenience style bits defined
35  * by <code>GridData</code>:
36  * <pre>
37  *      button1.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
38  * </pre>
39  * </p>
40  * <p>
41  * NOTE: Do not reuse <code>GridData</code> objects. Every control in a
42  * <code>Composite</code> that is managed by a <code>GridLayout</code>
43  * must have a unique <code>GridData</code> object. If the layout data
44  * for a control in a <code>GridLayout</code> is null at layout time,
45  * a unique <code>GridData</code> object is created for it.
46  * </p>
47  *
48  * @see GridLayout
49  * @see Control#setLayoutData
50  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
51  */
52 public final class GridData {
53     /**
54      * verticalAlignment specifies how controls will be positioned
55      * vertically within a cell.
56      *
57      * The default value is CENTER.
58      *
59      * Possible values are: <ul>
60      *    <li>SWT.BEGINNING (or SWT.TOP): Position the control at the top of the cell</li>
61      *    <li>SWT.CENTER: Position the control in the vertical center of the cell</li>
62      *    <li>SWT.END (or SWT.BOTTOM): Position the control at the bottom of the cell</li>
63      *    <li>SWT.FILL: Resize the control to fill the cell vertically</li>
64      * </ul>
65      */
66     public int verticalAlignment = CENTER;
67 
68     /**
69      * horizontalAlignment specifies how controls will be positioned
70      * horizontally within a cell.
71      *
72      * The default value is BEGINNING.
73      *
74      * Possible values are: <ul>
75      *    <li>SWT.BEGINNING (or SWT.LEFT): Position the control at the left of the cell</li>
76      *    <li>SWT.CENTER: Position the control in the horizontal center of the cell</li>
77      *    <li>SWT.END (or SWT.RIGHT): Position the control at the right of the cell</li>
78      *    <li>SWT.FILL: Resize the control to fill the cell horizontally</li>
79      * </ul>
80      */
81     public int horizontalAlignment = BEGINNING;
82 
83     /**
84      * widthHint specifies the preferred width in pixels. This value
85      * is the wHint passed into Control.computeSize(int, int, bool)
86      * to determine the preferred size of the control.
87      *
88      * The default value is SWT.DEFAULT.
89      *
90      * @see Control#computeSize(int, int, bool)
91      */
92     public int widthHint = SWT.DEFAULT;
93 
94     /**
95      * heightHint specifies the preferred height in pixels. This value
96      * is the hHint passed into Control.computeSize(int, int, bool)
97      * to determine the preferred size of the control.
98      *
99      * The default value is SWT.DEFAULT.
100      *
101      * @see Control#computeSize(int, int, bool)
102      */
103     public int heightHint = SWT.DEFAULT;
104 
105     /**
106      * horizontalIndent specifies the number of pixels of indentation
107      * that will be placed along the left side of the cell.
108      *
109      * The default value is 0.
110      */
111     public int horizontalIndent = 0;
112 
113     /**
114      * verticalIndent specifies the number of pixels of indentation
115      * that will be placed along the top side of the cell.
116      *
117      * The default value is 0.
118      *
119      * @since 3.1
120      */
121     public int verticalIndent = 0;
122 
123     /**
124      * horizontalSpan specifies the number of column cells that the control
125      * will take up.
126      *
127      * The default value is 1.
128      */
129     public int horizontalSpan = 1;
130 
131     /**
132      * verticalSpan specifies the number of row cells that the control
133      * will take up.
134      *
135      * The default value is 1.
136      */
137     public int verticalSpan = 1;
138 
139     /**
140      * <p>grabExcessHorizontalSpace specifies whether the width of the cell
141      * changes depending on the size of the parent Composite.  If
142      * grabExcessHorizontalSpace is <code>true</code>, the following rules
143      * apply to the width of the cell:</p>
144      * <ul>
145      * <li>If extra horizontal space is available in the parent, the cell will
146      * grow to be wider than its preferred width.  The new width
147      * will be "preferred width + delta" where delta is the extra
148      * horizontal space divided by the number of grabbing columns.</li>
149      * <li>If there is not enough horizontal space available in the parent, the
150      * cell will shrink until it reaches its minimum width as specified by
151      * GridData.minimumWidth. The new width will be the maximum of
152      * "minimumWidth" and "preferred width - delta", where delta is
153      * the amount of space missing divided by the number of grabbing columns.</li>
154      * <li>If the parent is packed, the cell will be its preferred width
155      * as specified by GridData.widthHint.</li>
156      * <li>If the control spans multiple columns and there are no other grabbing
157      * controls in any of the spanned columns, the last column in the span will
158      * grab the extra space.  If there is at least one other grabbing control
159      * in the span, the grabbing will be spread over the columns already
160      * marked as grabExcessHorizontalSpace.</li>
161      * </ul>
162      *
163      * <p>The default value is false.</p>
164      *
165      * @see GridData#minimumWidth
166      * @see GridData#widthHint
167      */
168     public bool grabExcessHorizontalSpace = false;
169 
170     /**
171      * <p>grabExcessVerticalSpace specifies whether the height of the cell
172      * changes depending on the size of the parent Composite.  If
173      * grabExcessVerticalSpace is <code>true</code>, the following rules
174      * apply to the height of the cell:</p>
175      * <ul>
176      * <li>If extra vertical space is available in the parent, the cell will
177      * grow to be taller than its preferred height.  The new height
178      * will be "preferred height + delta" where delta is the extra
179      * vertical space divided by the number of grabbing rows.</li>
180      * <li>If there is not enough vertical space available in the parent, the
181      * cell will shrink until it reaches its minimum height as specified by
182      * GridData.minimumHeight. The new height will be the maximum of
183      * "minimumHeight" and "preferred height - delta", where delta is
184      * the amount of space missing divided by the number of grabbing rows.</li>
185      * <li>If the parent is packed, the cell will be its preferred height
186      * as specified by GridData.heightHint.</li>
187      * <li>If the control spans multiple rows and there are no other grabbing
188      * controls in any of the spanned rows, the last row in the span will
189      * grab the extra space.  If there is at least one other grabbing control
190      * in the span, the grabbing will be spread over the rows already
191      * marked as grabExcessVerticalSpace.</li>
192      * </ul>
193      *
194      * <p>The default value is false.</p>
195      *
196      * @see GridData#minimumHeight
197      * @see GridData#heightHint
198      */
199     public bool grabExcessVerticalSpace = false;
200 
201     /**
202      * minimumWidth specifies the minimum width in pixels.  This value
203      * applies only if grabExcessHorizontalSpace is true. A value of
204      * SWT.DEFAULT means that the minimum width will be the result
205      * of Control.computeSize(int, int, bool) where wHint is
206      * determined by GridData.widthHint.
207      *
208      * The default value is 0.
209      *
210      * @since 3.1
211      * @see Control#computeSize(int, int, bool)
212      * @see GridData#widthHint
213      */
214     public int minimumWidth = 0;
215 
216     /**
217      * minimumHeight specifies the minimum height in pixels.  This value
218      * applies only if grabExcessVerticalSpace is true.  A value of
219      * SWT.DEFAULT means that the minimum height will be the result
220      * of Control.computeSize(int, int, bool) where hHint is
221      * determined by GridData.heightHint.
222      *
223      * The default value is 0.
224      *
225      * @since 3.1
226      * @see Control#computeSize(int, int, bool)
227      * @see GridData#heightHint
228      */
229     public int minimumHeight = 0;
230 
231     /**
232      * exclude informs the layout to ignore this control when sizing
233      * and positioning controls.  If this value is <code>true</code>,
234      * the size and position of the control will not be managed by the
235      * layout.  If this value is <code>false</code>, the size and
236      * position of the control will be computed and assigned.
237      *
238      * The default value is <code>false</code>.
239      *
240      * @since 3.1
241      */
242     public bool exclude = false;
243 
244     /**
245      * Value for horizontalAlignment or verticalAlignment.
246      * Position the control at the top or left of the cell.
247      * Not recommended. Use SWT.BEGINNING, SWT.TOP or SWT.LEFT instead.
248      */
249     public static const int BEGINNING = SWT.BEGINNING;
250 
251     /**
252      * Value for horizontalAlignment or verticalAlignment.
253      * Position the control in the vertical or horizontal center of the cell
254      * Not recommended. Use SWT.CENTER instead.
255      */
256     public static const int CENTER = 2;
257 
258     /**
259      * Value for horizontalAlignment or verticalAlignment.
260      * Position the control at the bottom or right of the cell
261      * Not recommended. Use SWT.END, SWT.BOTTOM or SWT.RIGHT instead.
262      */
263     public static const int END = 3;
264 
265     /**
266      * Value for horizontalAlignment or verticalAlignment.
267      * Resize the control to fill the cell horizontally or vertically.
268      * Not recommended. Use SWT.FILL instead.
269      */
270     public static const int FILL = SWT.FILL;
271 
272     /**
273      * Style bit for <code>new GridData(int)</code>.
274      * Position the control at the top of the cell.
275      * Not recommended. Use
276      * <code>new GridData(int, SWT.BEGINNING, bool, bool)</code>
277      * instead.
278      */
279     public static const int VERTICAL_ALIGN_BEGINNING =  1 << 1;
280 
281     /**
282      * Style bit for <code>new GridData(int)</code> to position the
283      * control in the vertical center of the cell.
284      * Not recommended. Use
285      * <code>new GridData(int, SWT.CENTER, bool, bool)</code>
286      * instead.
287      */
288     public static const int VERTICAL_ALIGN_CENTER = 1 << 2;
289 
290     /**
291      * Style bit for <code>new GridData(int)</code> to position the
292      * control at the bottom of the cell.
293      * Not recommended. Use
294      * <code>new GridData(int, SWT.END, bool, bool)</code>
295      * instead.
296      */
297     public static const int VERTICAL_ALIGN_END = 1 << 3;
298 
299     /**
300      * Style bit for <code>new GridData(int)</code> to resize the
301      * control to fill the cell vertically.
302      * Not recommended. Use
303      * <code>new GridData(int, SWT.FILL, bool, bool)</code>
304      * instead
305      */
306     public static const int VERTICAL_ALIGN_FILL = 1 << 4;
307 
308     /**
309      * Style bit for <code>new GridData(int)</code> to position the
310      * control at the left of the cell.
311      * Not recommended. Use
312      * <code>new GridData(SWT.BEGINNING, int, bool, bool)</code>
313      * instead.
314      */
315     public static const int HORIZONTAL_ALIGN_BEGINNING =  1 << 5;
316 
317     /**
318      * Style bit for <code>new GridData(int)</code> to position the
319      * control in the horizontal center of the cell.
320      * Not recommended. Use
321      * <code>new GridData(SWT.CENTER, int, bool, bool)</code>
322      * instead.
323      */
324     public static const int HORIZONTAL_ALIGN_CENTER = 1 << 6;
325 
326     /**
327      * Style bit for <code>new GridData(int)</code> to position the
328      * control at the right of the cell.
329      * Not recommended. Use
330      * <code>new GridData(SWT.END, int, bool, bool)</code>
331      * instead.
332      */
333     public static const int HORIZONTAL_ALIGN_END = 1 << 7;
334 
335     /**
336      * Style bit for <code>new GridData(int)</code> to resize the
337      * control to fill the cell horizontally.
338      * Not recommended. Use
339      * <code>new GridData(SWT.FILL, int, bool, bool)</code>
340      * instead.
341      */
342     public static const int HORIZONTAL_ALIGN_FILL = 1 << 8;
343 
344     /**
345      * Style bit for <code>new GridData(int)</code> to resize the
346      * control to fit the remaining horizontal space.
347      * Not recommended. Use
348      * <code>new GridData(int, int, true, bool)</code>
349      * instead.
350      */
351     public static const int GRAB_HORIZONTAL = 1 << 9;
352 
353     /**
354      * Style bit for <code>new GridData(int)</code> to resize the
355      * control to fit the remaining vertical space.
356      * Not recommended. Use
357      * <code>new GridData(int, int, bool, true)</code>
358      * instead.
359      */
360     public static const int GRAB_VERTICAL = 1 << 10;
361 
362     /**
363      * Style bit for <code>new GridData(int)</code> to resize the
364      * control to fill the cell vertically and to fit the remaining
365      * vertical space.
366      * FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL
367      * Not recommended. Use
368      * <code>new GridData(int, SWT.FILL, bool, true)</code>
369      * instead.
370      */
371     public static const int FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL;
372 
373     /**
374      * Style bit for <code>new GridData(int)</code> to resize the
375      * control to fill the cell horizontally and to fit the remaining
376      * horizontal space.
377      * FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL
378      * Not recommended. Use
379      * <code>new GridData(SWT.FILL, int, true, bool)</code>
380      * instead.
381      */
382     public static const int FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL;
383 
384     /**
385      * Style bit for <code>new GridData(int)</code> to resize the
386      * control to fill the cell horizontally and vertically and
387      * to fit the remaining horizontal and vertical space.
388      * FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL
389      * Not recommended. Use
390      * <code>new GridData(SWT.FILL, SWT.FILL, true, true)</code>
391      * instead.
392      */
393     public static const int FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL;
394 
395     int cacheWidth = -1, cacheHeight = -1;
396     int defaultWhint, defaultHhint, defaultWidth = -1, defaultHeight = -1;
397     int currentWhint, currentHhint, currentWidth = -1, currentHeight = -1;
398 
399 /**
400  * Constructs a new instance of GridData using
401  * default values.
402  */
403 public this () {
404 }
405 
406 /**
407  * Constructs a new instance based on the GridData style.
408  * This constructor is not recommended.
409  *
410  * @param style the GridData style
411  */
412 public this (int style) {
413     if ((style & VERTICAL_ALIGN_BEGINNING) !is 0) verticalAlignment = BEGINNING;
414     if ((style & VERTICAL_ALIGN_CENTER) !is 0) verticalAlignment = CENTER;
415     if ((style & VERTICAL_ALIGN_FILL) !is 0) verticalAlignment = FILL;
416     if ((style & VERTICAL_ALIGN_END) !is 0) verticalAlignment = END;
417     if ((style & HORIZONTAL_ALIGN_BEGINNING) !is 0) horizontalAlignment = BEGINNING;
418     if ((style & HORIZONTAL_ALIGN_CENTER) !is 0) horizontalAlignment = CENTER;
419     if ((style & HORIZONTAL_ALIGN_FILL) !is 0) horizontalAlignment = FILL;
420     if ((style & HORIZONTAL_ALIGN_END) !is 0) horizontalAlignment = END;
421     grabExcessHorizontalSpace = (style & GRAB_HORIZONTAL) !is 0;
422     grabExcessVerticalSpace = (style & GRAB_VERTICAL) !is 0;
423 }
424 
425 /**
426  * Constructs a new instance of GridData according to the parameters.
427  *
428  * @param horizontalAlignment how control will be positioned horizontally within a cell,
429  *      one of: SWT.BEGINNING (or SWT.LEFT), SWT.CENTER, SWT.END (or SWT.RIGHT), or SWT.FILL
430  * @param verticalAlignment how control will be positioned vertically within a cell,
431  *      one of: SWT.BEGINNING (or SWT.TOP), SWT.CENTER, SWT.END (or SWT.BOTTOM), or SWT.FILL
432  * @param grabExcessHorizontalSpace whether cell will be made wide enough to fit the remaining horizontal space
433  * @param grabExcessVerticalSpace whether cell will be made high enough to fit the remaining vertical space
434  *
435  * @since 3.0
436  */
437 public this (int horizontalAlignment, int verticalAlignment, bool grabExcessHorizontalSpace, bool grabExcessVerticalSpace) {
438     this (horizontalAlignment, verticalAlignment, grabExcessHorizontalSpace, grabExcessVerticalSpace, 1, 1);
439 }
440 
441 /**
442  * Constructs a new instance of GridData according to the parameters.
443  *
444  * @param horizontalAlignment how control will be positioned horizontally within a cell,
445  *      one of: SWT.BEGINNING (or SWT.LEFT), SWT.CENTER, SWT.END (or SWT.RIGHT), or SWT.FILL
446  * @param verticalAlignment how control will be positioned vertically within a cell,
447  *      one of: SWT.BEGINNING (or SWT.TOP), SWT.CENTER, SWT.END (or SWT.BOTTOM), or SWT.FILL
448  * @param grabExcessHorizontalSpace whether cell will be made wide enough to fit the remaining horizontal space
449  * @param grabExcessVerticalSpace whether cell will be made high enough to fit the remaining vertical space
450  * @param horizontalSpan the number of column cells that the control will take up
451  * @param verticalSpan the number of row cells that the control will take up
452  *
453  * @since 3.0
454  */
455 public this (int horizontalAlignment, int verticalAlignment, bool grabExcessHorizontalSpace, bool grabExcessVerticalSpace, int horizontalSpan, int verticalSpan) {
456     this.horizontalAlignment = horizontalAlignment;
457     this.verticalAlignment = verticalAlignment;
458     this.grabExcessHorizontalSpace = grabExcessHorizontalSpace;
459     this.grabExcessVerticalSpace = grabExcessVerticalSpace;
460     this.horizontalSpan = horizontalSpan;
461     this.verticalSpan = verticalSpan;
462 }
463 
464 /**
465  * Constructs a new instance of GridData according to the parameters.
466  * A value of SWT.DEFAULT indicates that no minimum width or
467  * no minimum height is specified.
468  *
469  * @param width a minimum width for the column
470  * @param height a minimum height for the row
471  *
472  * @since 3.0
473  */
474 public this (int width, int height) {
475     this.widthHint = width;
476     this.heightHint = height;
477 }
478 
479 void computeSize (Control control, int wHint, int hHint, bool flushCache) {
480     if (cacheWidth !is -1 && cacheHeight !is -1) return;
481     if (wHint is this.widthHint && hHint is this.heightHint) {
482         if (defaultWidth is -1 || defaultHeight is -1 || wHint !is defaultWhint || hHint !is defaultHhint) {
483             Point size = control.computeSize (wHint, hHint, flushCache);
484             defaultWhint = wHint;
485             defaultHhint = hHint;
486             defaultWidth = size.x;
487             defaultHeight = size.y;
488         }
489         cacheWidth = defaultWidth;
490         cacheHeight = defaultHeight;
491         return;
492     }
493     if (currentWidth is -1 || currentHeight is -1 || wHint !is currentWhint || hHint !is currentHhint) {
494         Point size = control.computeSize (wHint, hHint, flushCache);
495         currentWhint = wHint;
496         currentHhint = hHint;
497         currentWidth = size.x;
498         currentHeight = size.y;
499     }
500     cacheWidth = currentWidth;
501     cacheHeight = currentHeight;
502 }
503 
504 void flushCache () {
505     cacheWidth = cacheHeight = -1;
506     defaultWidth = defaultHeight = -1;
507     currentWidth = currentHeight = -1;
508 }
509 
510 String getName () {
511     String string = this.classinfo.name;
512     int index = string.lastIndexOf('.');
513     if (index is -1 ) return string;
514     return string[ index + 1 .. string.length ];
515 }
516 
517 /**
518  * Returns a string containing a concise, human-readable
519  * description of the receiver.
520  *
521  * @return a string representation of the GridData object
522  */
523 override public String toString () {
524     String hAlign = "";
525     switch (horizontalAlignment) {
526         case SWT.FILL: hAlign = "SWT.FILL"; break;
527         case SWT.BEGINNING: hAlign = "SWT.BEGINNING"; break;
528         case SWT.LEFT: hAlign = "SWT.LEFT"; break;
529         case SWT.END: hAlign = "SWT.END"; break;
530         case END: hAlign = "GridData.END"; break;
531         case SWT.RIGHT: hAlign = "SWT.RIGHT"; break;
532         case SWT.CENTER: hAlign = "SWT.CENTER"; break;
533         case CENTER: hAlign = "GridData.CENTER"; break;
534         default: hAlign = "Undefined "~String_valueOf(horizontalAlignment); break;
535     }
536     String vAlign = "";
537     switch (verticalAlignment) {
538         case SWT.FILL: vAlign = "SWT.FILL"; break;
539         case SWT.BEGINNING: vAlign = "SWT.BEGINNING"; break;
540         case SWT.TOP: vAlign = "SWT.TOP"; break;
541         case SWT.END: vAlign = "SWT.END"; break;
542         case END: vAlign = "GridData.END"; break;
543         case SWT.BOTTOM: vAlign = "SWT.BOTTOM"; break;
544         case SWT.CENTER: vAlign = "SWT.CENTER"; break;
545         case CENTER: vAlign = "GridData.CENTER"; break;
546         default: vAlign = "Undefined "~String_valueOf(verticalAlignment); break;
547     }
548     String string = getName()~" {";
549     string ~= "horizontalAlignment="~hAlign~" ";
550     if (horizontalIndent !is 0) string ~= "horizontalIndent="~String_valueOf(horizontalIndent)~" ";
551     if (horizontalSpan !is 1) string ~= "horizontalSpan="~String_valueOf(horizontalSpan)~" ";
552     if (grabExcessHorizontalSpace) string ~= "grabExcessHorizontalSpace="~String_valueOf(grabExcessHorizontalSpace)~" ";
553     if (widthHint !is SWT.DEFAULT) string ~= "widthHint="~String_valueOf(widthHint)~" ";
554     if (minimumWidth !is 0) string ~= "minimumWidth="~String_valueOf(minimumWidth)~" ";
555     string ~= "verticalAlignment="~vAlign~" ";
556     if (verticalIndent !is 0) string ~= "verticalIndent="~String_valueOf(verticalIndent)~" ";
557     if (verticalSpan !is 1) string ~= "verticalSpan="~String_valueOf(verticalSpan)~" ";
558     if (grabExcessVerticalSpace) string ~= "grabExcessVerticalSpace="~String_valueOf(grabExcessVerticalSpace)~" ";
559     if (heightHint !is SWT.DEFAULT) string ~= "heightHint="~String_valueOf(heightHint)~" ";
560     if (minimumHeight !is 0) string ~= "minimumHeight="~String_valueOf(minimumHeight)~" ";
561     if (exclude) string ~= "exclude="~String_valueOf(exclude)~" ";
562     string = string.trim();
563     string ~= "}";
564     return string;
565 }
566 }