13
|
1 /*******************************************************************************
|
|
2 * Copyright (c) 2005, 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 dwtx.jface.layout.LayoutGenerator;
|
|
14
|
|
15 import dwtx.jface.layout.GridDataFactory;
|
|
16 import dwtx.jface.layout.LayoutConstants;
|
|
17
|
|
18 import dwt.DWT;
|
|
19 import dwt.events.ModifyListener;
|
|
20 import dwt.graphics.Point;
|
|
21 import dwt.layout.GridData;
|
|
22 import dwt.layout.GridLayout;
|
|
23 import dwt.widgets.Button;
|
|
24 import dwt.widgets.Composite;
|
|
25 import dwt.widgets.Control;
|
|
26 import dwt.widgets.Layout;
|
|
27 import dwt.widgets.Scrollable;
|
|
28 import dwtx.jface.util.Geometry;
|
|
29
|
|
30 import dwt.dwthelper.utils;
|
|
31
|
|
32 /* package */class LayoutGenerator {
|
|
33
|
|
34 /**
|
|
35 * Default size for controls with varying contents
|
|
36 */
|
|
37 private static const Point defaultSize;
|
|
38
|
|
39 /**
|
|
40 * Default wrapping size for wrapped labels
|
|
41 */
|
|
42 private static const int wrapSize = 350;
|
|
43
|
|
44 private static const GridDataFactory nonWrappingLabelData;
|
|
45
|
|
46 static this(){
|
|
47 defaultSize = new Point(150, 150);
|
|
48 nonWrappingLabelData = GridDataFactory.fillDefaults().align_(DWT.BEGINNING, DWT.CENTER).grab(false, false);
|
|
49 }
|
|
50
|
|
51 private static bool hasStyle(Control c, int style) {
|
|
52 return (c.getStyle() & style) !is 0;
|
|
53 }
|
|
54
|
|
55 /**
|
|
56 * Generates a GridLayout for the given composite by examining its child
|
|
57 * controls and attaching layout data to any immediate children that do not
|
|
58 * already have layout data.
|
|
59 *
|
|
60 * @param toGenerate
|
|
61 * composite to generate a layout for
|
|
62 */
|
|
63 public static void generateLayout(Composite toGenerate) {
|
|
64 Control[] children = toGenerate.getChildren();
|
|
65
|
|
66 for (int i = 0; i < children.length; i++) {
|
|
67 Control control = children[i];
|
|
68
|
|
69 // Skip any children that already have layout data
|
|
70 if (control.getLayoutData() !is null) {
|
|
71 continue;
|
|
72 }
|
|
73
|
|
74 applyLayoutDataTo(control);
|
|
75 }
|
|
76 }
|
|
77
|
|
78 private static void applyLayoutDataTo(Control control) {
|
|
79 defaultsFor(control).applyTo(control);
|
|
80 }
|
|
81
|
|
82 /**
|
|
83 * Creates default factory for this control types:
|
|
84 * <ul>
|
|
85 * <li>{@link Button} with {@link DWT#CHECK}</li>
|
|
86 * <li>{@link Button}</li>
|
|
87 * <li>{@link Composite}</li>
|
|
88 * </ul>
|
|
89 * @param control the control the factory is search for
|
|
90 * @return a default factory for the control
|
|
91 */
|
|
92 public static GridDataFactory defaultsFor(Control control) {
|
|
93 if ( auto button = cast(Button) control ) {
|
|
94
|
|
95 if (hasStyle(button, DWT.CHECK)) {
|
|
96 return nonWrappingLabelData.copy();
|
|
97 } else {
|
|
98 return GridDataFactory.fillDefaults().align_(DWT.FILL, DWT.CENTER).hint(Geometry.max(button.computeSize(DWT.DEFAULT, DWT.DEFAULT, true), LayoutConstants.getMinButtonSize()));
|
|
99 }
|
|
100 }
|
|
101
|
|
102 if (auto scrollable = cast(Scrollable) control ) {
|
|
103
|
|
104 if ( auto composite = cast(Composite) scrollable ) {
|
|
105
|
|
106 Layout theLayout = composite.getLayout();
|
|
107 if ( cast(GridLayout) theLayout ) {
|
|
108 bool growsHorizontally = false;
|
|
109 bool growsVertically = false;
|
|
110
|
|
111 Control[] children = composite.getChildren();
|
|
112 for (int i = 0; i < children.length; i++) {
|
|
113 Control child = children[i];
|
|
114
|
|
115 GridData data = cast(GridData) child.getLayoutData();
|
|
116
|
|
117 if (data !is null) {
|
|
118 if (data.grabExcessHorizontalSpace) {
|
|
119 growsHorizontally = true;
|
|
120 }
|
|
121 if (data.grabExcessVerticalSpace) {
|
|
122 growsVertically = true;
|
|
123 }
|
|
124 }
|
|
125 }
|
|
126
|
|
127 return GridDataFactory.fillDefaults().grab(growsHorizontally, growsVertically);
|
|
128 }
|
|
129 }
|
|
130 }
|
|
131
|
|
132 bool wrapping = hasStyle(control, DWT.WRAP);
|
|
133
|
|
134 // Assume any control with the H_SCROLL or V_SCROLL flags are
|
|
135 // horizontally or vertically
|
|
136 // scrollable, respectively.
|
|
137 bool hScroll = hasStyle(control, DWT.H_SCROLL);
|
|
138 bool vScroll = hasStyle(control, DWT.V_SCROLL);
|
|
139
|
|
140 bool containsText = hasMethod(control, "setText", [ ArrayWrapperString.classinfo ] ); //$NON-NLS-1$
|
|
141
|
|
142 // If the control has a setText method, an addModifyListener method, and
|
|
143 // does not have
|
|
144 // the DWT.READ_ONLY flag, assume it contains user-editable text.
|
|
145 bool userEditable = !hasStyle(control, DWT.READ_ONLY) && containsText && hasMethod(control, "addModifyListener", [ ModifyListener.classinfo ]); //$NON-NLS-1$
|
|
146
|
|
147 // For controls containing user-editable text...
|
|
148 if (userEditable) {
|
|
149 if (hasStyle(control, DWT.MULTI)) {
|
|
150 vScroll = true;
|
|
151 }
|
|
152
|
|
153 if (!wrapping) {
|
|
154 hScroll = true;
|
|
155 }
|
|
156 }
|
|
157
|
|
158 // Compute the horizontal hint
|
|
159 int hHint = DWT.DEFAULT;
|
|
160 bool grabHorizontal = hScroll;
|
|
161
|
|
162 // For horizontally-scrollable controls, override their horizontal
|
|
163 // preferred size
|
|
164 // with a constant
|
|
165 if (hScroll) {
|
|
166 hHint = defaultSize.x;
|
|
167 } else {
|
|
168 // For wrapping controls, there are two cases.
|
|
169 // 1. For controls that contain text (like wrapping labels,
|
|
170 // read-only text boxes,
|
|
171 // etc.) override their preferred size with the preferred wrapping
|
|
172 // point and
|
|
173 // make them grab horizontal space.
|
|
174 // 2. For non-text controls (like wrapping toolbars), assume that
|
|
175 // their non-wrapped
|
|
176 // size is best.
|
|
177
|
|
178 if (wrapping) {
|
|
179 if (containsText) {
|
|
180 hHint = wrapSize;
|
|
181 grabHorizontal = true;
|
|
182 }
|
|
183 }
|
|
184 }
|
|
185
|
|
186 int vAlign = DWT.FILL;
|
|
187
|
|
188 // Heuristic for labels: Controls that contain non-wrapping read-only
|
|
189 // text should be
|
|
190 // center-aligned rather than fill-aligned
|
|
191 if (!vScroll && !wrapping && !userEditable && containsText) {
|
|
192 vAlign = DWT.CENTER;
|
|
193 }
|
|
194
|
|
195 return GridDataFactory.fillDefaults().grab(grabHorizontal, vScroll).align_(DWT.FILL, vAlign).hint(hHint, vScroll ? defaultSize.y : DWT.DEFAULT);
|
|
196 }
|
|
197
|
|
198 private static bool hasMethod(Control control, String name, ClassInfo[] parameterTypes) {
|
|
199 ClassInfo c = control.classinfo;
|
|
200 implMissing(__FILE__,__LINE__);
|
|
201 pragma(msg, "FIXME dwtx.jface.layout.LayoutGenerator hasMethod reflection" );
|
|
202 return true;
|
|
203 /+ try {
|
|
204 return c.getMethod(name, parameterTypes) !is null;
|
|
205 } catch (SecurityException e) {
|
|
206 return false;
|
|
207 } catch (NoSuchMethodException e) {
|
|
208 return false;
|
|
209 }+/
|
|
210 }
|
|
211 }
|