1/*******************************************************************************
2 * Copyright (c) 2005, 2011 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 *******************************************************************************/
11package org.eclipse.wb.internal.core.utils.ui;
12
13import org.eclipse.swt.graphics.Point;
14import org.eclipse.swt.layout.GridData;
15import org.eclipse.swt.widgets.Control;
16
17/**
18 * This class provides a convienient shorthand for creating and initializing GridData. This offers
19 * several benefits over creating GridData normal way:
20 *
21 * <ul>
22 * <li>The same factory can be used many times to create several GridData instances</li>
23 * <li>The setters on GridDataFactory all return "this", allowing them to be chained</li>
24 * <li>GridDataFactory uses vector setters (it accepts Points), making it easy to set X and Y values
25 * together</li>
26 * </ul>
27 *
28 * <p>
29 * GridDataFactory instances are created using one of the static methods on this class.
30 * </p>
31 *
32 * <p>
33 * Example usage:
34 * </p>
35 * <code>
36 *
37 * ////////////////////////////////////////////////////////////
38 * // Example 1: Typical grid data for a non-wrapping label
39 *
40 *     // GridDataFactory version
41 *     GridDataFactory.fillDefaults().applyTo(myLabel);
42 *
43 *     // Equivalent SWT version
44 *     GridData labelData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
45 *     myLabel.setLayoutData(labelData);
46 *
47 * ///////////////////////////////////////////////////////////
48 * // Example 2: Typical grid data for a wrapping label
49 *
50 *     // GridDataFactory version
51 *     GridDataFactory.fillDefaults()
52 *          .align(SWT.FILL, SWT.CENTER)
53 *    	    .hint(150, SWT.DEFAULT)
54 *    	    .grab(true, false)
55 *          .applyTo(wrappingLabel);
56 *
57 *     // Equivalent SWT version
58 *     GridData wrappingLabelData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER);
59 *     wrappingLabelData.minimumWidth = 1;
60 *     wrappingLabelData.widthHint = 150;
61 *     wrappingLabel.setLayoutData(wrappingLabelData);
62 *
63 * //////////////////////////////////////////////////////////////
64 * // Example 3: Typical grid data for a scrollable control (a list box, tree, table, etc.)
65 *
66 *     // GridDataFactory version
67 *     GridDataFactory.fillDefaults().grab(true, true).hint(150, 150).applyTo(listBox);
68 *
69 *     // Equivalent SWT version
70 *     GridData listBoxData = new GridData(GridData.FILL_BOTH);
71 *     listBoxData.widthHint = 150;
72 *     listBoxData.heightHint = 150;
73 *     listBoxData.minimumWidth = 1;
74 *     listBoxData.minimumHeight = 1;
75 *     listBox.setLayoutData(listBoxData);
76 *
77 * /////////////////////////////////////////////////////////////
78 * // Example 4: Typical grid data for a button
79 *
80 *     // GridDataFactory version
81 *     Point preferredSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, false);
82 *     Point hint = Geometry.max(LayoutConstants.getMinButtonSize(), preferredSize);
83 *     GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).hint(hint).applyTo(button);
84 *
85 *     // Equivalent SWT version
86 *     Point preferredSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, false);
87 *     Point hint = Geometry.max(LayoutConstants.getMinButtonSize(), preferredSize);
88 *     GridData buttonData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER);
89 *     buttonData.widthHint = hint.x;
90 *     buttonData.heightHint = hint.y;
91 *     button.setLayoutData(buttonData);
92 * </code>
93 *
94 * <p>
95 * IMPORTANT: WHEN ASSIGNING LAYOUT DATA TO A CONTROL, BE SURE TO USE
96 * gridDataFactory.applyTo(control) AND NEVER control.setLayoutData(gridDataFactory).
97 * </p>
98 *
99 * @since 3.2
100 */
101public final class GridDataFactory {
102  private final Control m_control;
103  private final PixelConverter m_pixelConverter;
104  private final GridData m_data;
105
106  ////////////////////////////////////////////////////////////////////////////
107  //
108  // Constructor
109  //
110  ////////////////////////////////////////////////////////////////////////////
111  private GridDataFactory(Control control, GridData gridData) {
112    m_control = control;
113    m_pixelConverter = new PixelConverter(m_control);
114    //
115    m_data = gridData;
116    if (m_control.getLayoutData() != m_data) {
117      m_control.setLayoutData(m_data);
118    }
119  }
120
121  /**
122   * Creates new {@link GridDataFactory} with new {@link GridData}.
123   */
124  public static GridDataFactory create(Control control) {
125    return new GridDataFactory(control, new GridData());
126  }
127
128  /**
129   * Creates new {@link GridDataFactory} for modifying {@link GridData} already installed in
130   * control.
131   */
132  public static GridDataFactory modify(Control control) {
133    GridData gridData;
134    {
135      Object existingLayoutData = control.getLayoutData();
136      if (existingLayoutData instanceof GridData) {
137        gridData = (GridData) existingLayoutData;
138      } else {
139        gridData = new GridData();
140      }
141    }
142    return new GridDataFactory(control, gridData);
143  }
144
145  ////////////////////////////////////////////////////////////////////////////
146  //
147  // Span
148  //
149  ////////////////////////////////////////////////////////////////////////////
150  /**
151   * Sets the GridData span. The span controls how many cells are filled by the control.
152   *
153   * @param hSpan
154   *          number of columns spanned by the control
155   * @param vSpan
156   *          number of rows spanned by the control
157   * @return this
158   */
159  public GridDataFactory span(int hSpan, int vSpan) {
160    m_data.horizontalSpan = hSpan;
161    m_data.verticalSpan = vSpan;
162    return this;
163  }
164
165  /**
166   * Sets the GridData span. The span controls how many cells are filled by the control.
167   *
168   * @param hSpan
169   *          number of columns spanned by the control
170   * @return this
171   */
172  public GridDataFactory spanH(int hSpan) {
173    m_data.horizontalSpan = hSpan;
174    return this;
175  }
176
177  /**
178   * Sets the GridData span. The span controls how many cells are filled by the control.
179   *
180   * @param vSpan
181   *          number of rows spanned by the control
182   * @return this
183   */
184  public GridDataFactory spanV(int vSpan) {
185    m_data.verticalSpan = vSpan;
186    return this;
187  }
188
189  ////////////////////////////////////////////////////////////////////////////
190  //
191  // Hint
192  //
193  ////////////////////////////////////////////////////////////////////////////
194  /**
195   * Sets the width and height hints. The width and height hints override the control's preferred
196   * size. If either hint is set to SWT.DEFAULT, the control's preferred size is used.
197   *
198   * @param xHint
199   *          horizontal hint (pixels), or SWT.DEFAULT to use the control's preferred size
200   * @param yHint
201   *          vertical hint (pixels), or SWT.DEFAULT to use the control's preferred size
202   * @return this
203   */
204  public GridDataFactory hint(int xHint, int yHint) {
205    m_data.widthHint = xHint;
206    m_data.heightHint = yHint;
207    return this;
208  }
209
210  /**
211   * Sets hint in chars.
212   */
213  public GridDataFactory hintC(int xHintInChars, int yHintInChars) {
214    hintHC(xHintInChars);
215    hintVC(yHintInChars);
216    return this;
217  }
218
219  /**
220   * Sets the width hint.
221   *
222   * @return this
223   */
224  public GridDataFactory hintH(int xHint) {
225    m_data.widthHint = xHint;
226    return this;
227  }
228
229  /**
230   * Sets the width hint to the minimum of current hint and given <code>otherHint</code>.
231   *
232   * @return this
233   */
234  public GridDataFactory hintHMin(int otherHint) {
235    m_data.widthHint = Math.min(m_data.widthHint, otherHint);
236    return this;
237  }
238
239  /**
240   * Sets the width hint in chars.
241   *
242   * @return this
243   */
244  public GridDataFactory hintHC(int hintInChars) {
245    return hintH(m_pixelConverter.convertWidthInCharsToPixels(hintInChars));
246  }
247
248  /**
249   * Sets the width hint.
250   *
251   * @return this
252   */
253  public GridDataFactory hintHU(int hintInDLU) {
254    return hintH(m_pixelConverter.convertHorizontalDLUsToPixels(hintInDLU));
255  }
256
257  /**
258   * Sets the height hint.
259   *
260   * @return this
261   */
262  public GridDataFactory hintV(int yHint) {
263    m_data.heightHint = yHint;
264    return this;
265  }
266
267  /**
268   * Sets the height hint in chars.
269   *
270   * @return this
271   */
272  public GridDataFactory hintVC(int hintInChars) {
273    return hintV(m_pixelConverter.convertHeightInCharsToPixels(hintInChars));
274  }
275
276  /**
277   * Increments horizontal hint on given value.
278   *
279   * @return this
280   */
281  public GridDataFactory hintHAdd(int increment) {
282    return hintV(m_data.widthHint + increment);
283  }
284
285  /**
286   * Increments vertical hint on given value.
287   *
288   * @return this
289   */
290  public GridDataFactory hintVAdd(int increment) {
291    return hintV(m_data.heightHint + increment);
292  }
293
294  /**
295   * Sets the width and height hints. The width and height hints override the control's preferred
296   * size. If either hint is set to SWT.DEFAULT, the control's preferred size is used.
297   *
298   * @param hint
299   *          size (pixels) to be used instead of the control's preferred size. If the x or y values
300   *          are set to SWT.DEFAULT, the control's computeSize() method will be used to obtain that
301   *          dimension of the preferred size.
302   * @return this
303   */
304  public GridDataFactory hint(Point hint) {
305    m_data.widthHint = hint.x;
306    m_data.heightHint = hint.y;
307    return this;
308  }
309
310  ////////////////////////////////////////////////////////////////////////////
311  //
312  // Minimum size
313  //
314  ////////////////////////////////////////////////////////////////////////////
315  public GridDataFactory minH(int minimumWidth) {
316    m_data.minimumWidth = minimumWidth;
317    return this;
318  }
319
320  public GridDataFactory minHC(int widthInChars) {
321    return minH(m_pixelConverter.convertWidthInCharsToPixels(widthInChars));
322  }
323
324  public GridDataFactory minV(int minimumHeight) {
325    m_data.minimumHeight = minimumHeight;
326    return this;
327  }
328
329  public GridDataFactory minVC(int heightInChars) {
330    return minV(m_pixelConverter.convertHeightInCharsToPixels(heightInChars));
331  }
332
333  ////////////////////////////////////////////////////////////////////////////
334  //
335  // Alignment
336  //
337  ////////////////////////////////////////////////////////////////////////////
338  /**
339   * Sets the alignment of the control within its cell.
340   *
341   * @param hAlign
342   *          horizontal alignment. One of SWT.BEGINNING, SWT.CENTER, SWT.END, or SWT.FILL.
343   * @param vAlign
344   *          vertical alignment. One of SWT.BEGINNING, SWT.CENTER, SWT.END, or SWT.FILL.
345   * @return this
346   */
347  public GridDataFactory align(int hAlign, int vAlign) {
348    m_data.horizontalAlignment = hAlign;
349    m_data.verticalAlignment = vAlign;
350    return this;
351  }
352
353  /**
354   * Sets the horizontal and vertical alignment to GridData.FILL.
355   */
356  public GridDataFactory fill() {
357    return align(GridData.FILL, GridData.FILL);
358  }
359
360  /**
361   * Sets the horizontal alignment of the control within its cell.
362   *
363   * @param hAlign
364   *          horizontal alignment. One of SWT.BEGINNING, SWT.CENTER, SWT.END, or SWT.FILL.
365   * @return this
366   */
367  public GridDataFactory alignH(int hAlign) {
368    m_data.horizontalAlignment = hAlign;
369    return this;
370  }
371
372  /**
373   * Sets the horizontal alignment of the control to GridData.BEGINNING
374   *
375   * @return this
376   */
377  public GridDataFactory alignHL() {
378    return alignH(GridData.BEGINNING);
379  }
380
381  /**
382   * Sets the horizontal alignment of the control to GridData.CENTER
383   *
384   * @return this
385   */
386  public GridDataFactory alignHC() {
387    return alignH(GridData.CENTER);
388  }
389
390  /**
391   * Sets the horizontal alignment of the control to GridData.FILL
392   *
393   * @return this
394   */
395  public GridDataFactory alignHF() {
396    return alignH(GridData.FILL);
397  }
398
399  /**
400   * Sets the horizontal alignment of the control to GridData.FILL
401   *
402   * @return this
403   */
404  public GridDataFactory fillH() {
405    return alignHF();
406  }
407
408  /**
409   * Sets the horizontal alignment of the control to GridData.END
410   *
411   * @return this
412   */
413  public GridDataFactory alignHR() {
414    return alignH(GridData.END);
415  }
416
417  /**
418   * Sets the vertical alignment of the control within its cell.
419   *
420   * @param vAlign
421   *          vertical alignment. One of SWT.BEGINNING, SWT.CENTER, SWT.END, or SWT.FILL.
422   * @return this
423   */
424  public GridDataFactory alignV(int vAlign) {
425    m_data.verticalAlignment = vAlign;
426    return this;
427  }
428
429  /**
430   * Sets the vertical alignment of the control to GridData.BEGINNING
431   *
432   * @return this
433   */
434  public GridDataFactory alignVT() {
435    return alignV(GridData.BEGINNING);
436  }
437
438  /**
439   * Sets the vertical alignment of the control to GridData.CENTER
440   *
441   * @return this
442   */
443  public GridDataFactory alignVM() {
444    return alignV(GridData.CENTER);
445  }
446
447  /**
448   * Sets the vertical alignment of the control to GridData.FILL
449   *
450   * @return this
451   */
452  public GridDataFactory alignVF() {
453    return alignV(GridData.FILL);
454  }
455
456  /**
457   * Sets the vertical alignment of the control to GridData.FILL
458   *
459   * @return this
460   */
461  public GridDataFactory fillV() {
462    return alignVF();
463  }
464
465  /**
466   * Sets the vertical alignment of the control to GridData.END
467   *
468   * @return this
469   */
470  public GridDataFactory alignVB() {
471    return alignV(GridData.END);
472  }
473
474  ////////////////////////////////////////////////////////////////////////////
475  //
476  // Indent
477  //
478  ////////////////////////////////////////////////////////////////////////////
479  /**
480   * Sets the indent of the control within the cell in pixels.
481   */
482  public GridDataFactory indentH(int hIndent) {
483    m_data.horizontalIndent = hIndent;
484    return this;
485  }
486
487  /**
488   * Sets the indent of the control within the cell in characters.
489   */
490  public GridDataFactory indentHC(int hIndent) {
491    m_data.horizontalIndent = m_pixelConverter.convertWidthInCharsToPixels(hIndent);
492    return this;
493  }
494
495  ////////////////////////////////////////////////////////////////////////////
496  //
497  // Grab
498  //
499  ////////////////////////////////////////////////////////////////////////////
500  /**
501   * Determines whether extra horizontal or vertical space should be allocated to this control's
502   * column when the layout resizes. If any control in the column is set to grab horizontal then the
503   * whole column will grab horizontal space. If any control in the row is set to grab vertical then
504   * the whole row will grab vertical space.
505   *
506   * @param horizontal
507   *          true if the control's column should grow horizontally
508   * @param vertical
509   *          true if the control's row should grow vertically
510   * @return this
511   */
512  public GridDataFactory grab(boolean horizontal, boolean vertical) {
513    m_data.grabExcessHorizontalSpace = horizontal;
514    m_data.grabExcessVerticalSpace = vertical;
515    return this;
516  }
517
518  public GridDataFactory grabH() {
519    m_data.grabExcessHorizontalSpace = true;
520    return this;
521  }
522
523  public GridDataFactory grabV() {
524    m_data.grabExcessVerticalSpace = true;
525    return this;
526  }
527
528  public GridDataFactory grab() {
529    return grab(true, true);
530  }
531
532  ////////////////////////////////////////////////////////////////////////////
533  //
534  // Exclude
535  //
536  ////////////////////////////////////////////////////////////////////////////
537  public GridDataFactory exclude(boolean value) {
538    m_data.exclude = value;
539    return this;
540  }
541}
542