Mercurial > projects > dwt-mac
comparison dwt/layout/FormLayout.d @ 40:fbe68c33eeee
Sync layout with dwt-linux
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 07 Oct 2008 14:41:31 +0200 |
parents | a9ab4c738ed8 |
children | d8635bb48c7c |
comparison
equal
deleted
inserted
replaced
39:43be986a1372 | 40:fbe68c33eeee |
---|---|
1 /******************************************************************************* | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2007 IBM Corporation and others. | 2 * Copyright (c) 2000, 2008 IBM Corporation and others. |
3 * All rights reserved. This program and the accompanying materials | 3 * All rights reserved. This program and the accompanying materials |
4 * are made available under the terms of the Eclipse Public License v1.0 | 4 * are made available under the terms of the Eclipse Public License v1.0 |
5 * which accompanies this distribution, and is available at | 5 * which accompanies this distribution, and is available at |
6 * http://www.eclipse.org/legal/epl-v10.html | 6 * http://www.eclipse.org/legal/epl-v10.html |
7 * | 7 * |
8 * Contributors: | 8 * Contributors: |
9 * IBM Corporation - initial API and implementation | 9 * IBM Corporation - initial API and implementation |
10 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
10 *******************************************************************************/ | 12 *******************************************************************************/ |
11 module dwt.layout.FormLayout; | 13 module dwt.layout.FormLayout; |
12 | 14 |
13 import dwt.dwthelper.utils; | 15 import dwt.layout.FormAttachment; |
14 | 16 import dwt.layout.FormData; |
15 import dwt.DWT; | 17 import dwt.DWT; |
16 import dwt.graphics.Point; | 18 import dwt.graphics.Point; |
17 import dwt.graphics.Rectangle; | 19 import dwt.graphics.Rectangle; |
18 import dwt.widgets.Composite; | |
19 import dwt.widgets.Control; | 20 import dwt.widgets.Control; |
20 import dwt.widgets.Layout; | 21 import dwt.widgets.Layout; |
22 import dwt.widgets.Composite; | |
21 import dwt.widgets.Scrollable; | 23 import dwt.widgets.Scrollable; |
22 | 24 |
25 import tango.util.Convert; | |
26 import Math = tango.math.Math; | |
27 import dwt.dwthelper.utils; | |
28 | |
23 /** | 29 /** |
24 * Instances of this class control the position and size of the | 30 * Instances of this class control the position and size of the |
25 * children of a composite control by using <code>FormAttachments</code> | 31 * children of a composite control by using <code>FormAttachments</code> |
26 * to optionally configure the left, top, right and bottom edges of | 32 * to optionally configure the left, top, right and bottom edges of |
27 * each child. | 33 * each child. |
28 * <p> | 34 * <p> |
29 * The following example code creates a <code>FormLayout</code> and then sets | 35 * The following example code creates a <code>FormLayout</code> and then sets |
55 * data2.right = new FormAttachment(100, 0); | 61 * data2.right = new FormAttachment(100, 0); |
56 * button2.setLayoutData(data2); | 62 * button2.setLayoutData(data2); |
57 * </pre> | 63 * </pre> |
58 * </p> | 64 * </p> |
59 * <p> | 65 * <p> |
60 * Each side of a child control can be attached to a position in the parent | 66 * Each side of a child control can be attached to a position in the parent |
61 * composite, or to other controls within the <code>Composite</code> by | 67 * composite, or to other controls within the <code>Composite</code> by |
62 * creating instances of <code>FormAttachment</code> and setting them into | 68 * creating instances of <code>FormAttachment</code> and setting them into |
63 * the top, bottom, left, and right fields of the child's <code>FormData</code>. | 69 * the top, bottom, left, and right fields of the child's <code>FormData</code>. |
64 * </p> | 70 * </p> |
65 * <p> | 71 * <p> |
81 * the right edge of <code>button1</code> to the left edge of <code>button2</code> | 87 * the right edge of <code>button1</code> to the left edge of <code>button2</code> |
82 * and then attach the left edge of <code>button2</code> to the right edge of | 88 * and then attach the left edge of <code>button2</code> to the right edge of |
83 * <code>button1</code>. This will over constrain the layout, causing undefined | 89 * <code>button1</code>. This will over constrain the layout, causing undefined |
84 * behavior. The algorithm will terminate, but the results are undefined. | 90 * behavior. The algorithm will terminate, but the results are undefined. |
85 * </p> | 91 * </p> |
86 * | 92 * |
87 * @see FormData | 93 * @see FormData |
88 * @see FormAttachment | 94 * @see FormAttachment |
89 * | 95 * @see <a href="http://www.eclipse.org/swt/snippets/#formlayout">FormLayout snippets</a> |
96 * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: LayoutExample</a> | |
97 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
98 * | |
90 * @since 2.0 | 99 * @since 2.0 |
91 * | |
92 */ | 100 */ |
93 public final class FormLayout : Layout { | 101 public final class FormLayout : Layout { |
94 | 102 |
95 /** | 103 /** |
96 * marginWidth specifies the number of pixels of horizontal margin | 104 * marginWidth specifies the number of pixels of horizontal margin |
97 * that will be placed along the left and right edges of the layout. | 105 * that will be placed along the left and right edges of the layout. |
98 * | 106 * |
99 * The default value is 0. | 107 * The default value is 0. |
100 */ | 108 */ |
101 public int marginWidth = 0; | 109 public int marginWidth = 0; |
102 | 110 |
103 /** | 111 /** |
104 * marginHeight specifies the number of pixels of vertical margin | 112 * marginHeight specifies the number of pixels of vertical margin |
105 * that will be placed along the top and bottom edges of the layout. | 113 * that will be placed along the top and bottom edges of the layout. |
106 * | 114 * |
107 * The default value is 0. | 115 * The default value is 0. |
108 */ | 116 */ |
109 public int marginHeight = 0; | 117 public int marginHeight = 0; |
110 | 118 |
111 | 119 |
112 /** | 120 /** |
113 * marginLeft specifies the number of pixels of horizontal margin | 121 * marginLeft specifies the number of pixels of horizontal margin |
114 * that will be placed along the left edge of the layout. | 122 * that will be placed along the left edge of the layout. |
115 * | 123 * |
116 * The default value is 0. | 124 * The default value is 0. |
117 * | 125 * |
118 * @since 3.1 | 126 * @since 3.1 |
119 */ | 127 */ |
120 public int marginLeft = 0; | 128 public int marginLeft = 0; |
121 | 129 |
122 /** | 130 /** |
123 * marginTop specifies the number of pixels of vertical margin | 131 * marginTop specifies the number of pixels of vertical margin |
124 * that will be placed along the top edge of the layout. | 132 * that will be placed along the top edge of the layout. |
125 * | 133 * |
126 * The default value is 0. | 134 * The default value is 0. |
127 * | 135 * |
128 * @since 3.1 | 136 * @since 3.1 |
129 */ | 137 */ |
130 public int marginTop = 0; | 138 public int marginTop = 0; |
131 | 139 |
132 /** | 140 /** |
133 * marginRight specifies the number of pixels of horizontal margin | 141 * marginRight specifies the number of pixels of horizontal margin |
134 * that will be placed along the right edge of the layout. | 142 * that will be placed along the right edge of the layout. |
135 * | 143 * |
136 * The default value is 0. | 144 * The default value is 0. |
137 * | 145 * |
138 * @since 3.1 | 146 * @since 3.1 |
139 */ | 147 */ |
140 public int marginRight = 0; | 148 public int marginRight = 0; |
141 | 149 |
142 /** | 150 /** |
143 * marginBottom specifies the number of pixels of vertical margin | 151 * marginBottom specifies the number of pixels of vertical margin |
144 * that will be placed along the bottom edge of the layout. | 152 * that will be placed along the bottom edge of the layout. |
145 * | 153 * |
146 * The default value is 0. | 154 * The default value is 0. |
147 * | 155 * |
148 * @since 3.1 | 156 * @since 3.1 |
149 */ | 157 */ |
150 public int marginBottom = 0; | 158 public int marginBottom = 0; |
151 | 159 |
152 /** | 160 /** |
153 * spacing specifies the number of pixels between the edge of one control | 161 * spacing specifies the number of pixels between the edge of one control |
154 * and the edge of its neighbouring control. | 162 * and the edge of its neighbouring control. |
155 * | 163 * |
156 * The default value is 0. | 164 * The default value is 0. |
157 * | 165 * |
158 * @since 3.0 | 166 * @since 3.0 |
159 */ | 167 */ |
160 public int spacing = 0; | 168 public int spacing = 0; |
161 | 169 |
162 /** | 170 /** |
163 * Constructs a new instance of this class. | 171 * Constructs a new instance of this class. |
164 */ | 172 */ |
165 public this () { | 173 public this () { |
166 } | 174 } |
167 | 175 |
168 /* | 176 /* |
169 * Computes the preferred height of the form with | 177 * Computes the preferred height of the form with |
170 * respect to the preferred height of the control. | 178 * respect to the preferred height of the control. |
171 * | 179 * |
172 * Given that the equations for top cast(T) and bottom cast(B) | 180 * Given that the equations for top (T) and bottom (B) |
173 * of the control in terms of the height of the form cast(X) | 181 * of the control in terms of the height of the form (X) |
174 * are: | 182 * are: |
175 * T = AX + B | 183 * T = AX + B |
176 * B = CX + D | 184 * B = CX + D |
177 * | 185 * |
178 * The equation for the height of the control cast(H) | 186 * The equation for the height of the control (H) |
179 * is bottom cast(B) minus top cast(T) or (H = B - T) or: | 187 * is bottom (B) minus top (T) or (H = B - T) or: |
180 * | 188 * |
181 * H = (CX + D) - (AX + B) | 189 * H = (CX + D) - (AX + B) |
182 * | 190 * |
183 * Solving for cast(X), the height of the form, we get: | 191 * Solving for (X), the height of the form, we get: |
184 * | 192 * |
185 * X = (H + B - D) / (C - A) | 193 * X = (H + B - D) / (C - A) |
186 * | 194 * |
187 * When (A = C), (C - A = 0) and the equation has no | 195 * When (A = C), (C - A = 0) and the equation has no |
188 * solution for X. This is a special case meaning that | 196 * solution for X. This is a special case meaning that |
189 * the control does not constrain the height of the | 197 * the control does not constrain the height of the |
190 * form. In this case, we need to arbitrarily define | 198 * form. In this case, we need to arbitrarily define |
191 * the height of the form cast(X): | 199 * the height of the form (X): |
192 * | 200 * |
193 * Case 1: A = C, A = 0, C = 0 | 201 * Case 1: A = C, A = 0, C = 0 |
194 * | 202 * |
195 * Let X = D, the distance from the top of the form | 203 * Let X = D, the distance from the top of the form |
196 * to the bottom edge of the control. In this case, | 204 * to the bottom edge of the control. In this case, |
197 * the control was attached to the top of the form | 205 * the control was attached to the top of the form |
198 * and the form needs to be large enough to show the | 206 * and the form needs to be large enough to show the |
199 * bottom edge of the control. | 207 * bottom edge of the control. |
200 * | 208 * |
201 * Case 2: A = C, A = 1, C = 1 | 209 * Case 2: A = C, A = 1, C = 1 |
202 * | 210 * |
203 * Let X = -B, the distance from the bottom of the | 211 * Let X = -B, the distance from the bottom of the |
204 * form to the top edge of the control. In this case, | 212 * form to the top edge of the control. In this case, |
205 * the control was attached to the bottom of the form | 213 * the control was attached to the bottom of the form |
206 * and the only way that the control would be visible | 214 * and the only way that the control would be visible |
207 * is if the offset is negative. If the offset is | 215 * is if the offset is negative. If the offset is |
208 * positive, there is no possible height for the form | 216 * positive, there is no possible height for the form |
209 * that will show the control as it will always be | 217 * that will show the control as it will always be |
210 * below the bottom edge of the form. | 218 * below the bottom edge of the form. |
211 * | 219 * |
212 * Case 3: A = C, A !is 0, C !is 0 and A !is 1, C !is 0 | 220 * Case 3: A = C, A !is 0, C !is 0 and A !is 1, C !is 0 |
213 * | 221 * |
214 * Let X = D / (1 - C), the distance from the top of the | 222 * Let X = D / (1 - C), the distance from the top of the |
215 * form to the bottom edge of the control. In this case, | 223 * form to the bottom edge of the control. In this case, |
216 * since C is not 0 or 1, it must be a fraction, U / V. | 224 * since C is not 0 or 1, it must be a fraction, U / V. |
217 * The offset D is the distance from CX to the bottom edge | 225 * The offset D is the distance from CX to the bottom edge |
218 * of the control. This represents a fraction of the form | 226 * of the control. This represents a fraction of the form |
219 * (1 - C)X. Since the height of a fraction of the form is | 227 * (1 - C)X. Since the height of a fraction of the form is |
220 * known, the height of the entire form can be found by setting | 228 * known, the height of the entire form can be found by setting |
221 * (1 - C)X = D. We solve this equation for X in terms of U | 229 * (1 - C)X = D. We solve this equation for X in terms of U |
222 * and V, giving us X = (U * D) / (U - V). Similarly, if the | 230 * and V, giving us X = (U * D) / (U - V). Similarly, if the |
223 * offset D is negative, the control is positioned above CX. | 231 * offset D is negative, the control is positioned above CX. |
224 * The offset -B is the distance from the top edge of the control | 232 * The offset -B is the distance from the top edge of the control |
225 * to CX. We can find the height of the entire form by setting | 233 * to CX. We can find the height of the entire form by setting |
226 * CX = -B. Solving in terms of U and V gives us X = (-B * V) / U. | 234 * CX = -B. Solving in terms of U and V gives us X = (-B * V) / U. |
227 */ | 235 */ |
228 int computeHeight (Control control, FormData data, bool flushCache) { | 236 int computeHeight (Control control, FormData data, bool flushCache) { |
229 FormAttachment top = data.getTopAttachment (control, spacing, flushCache); | 237 FormAttachment top = data.getTopAttachment (control, spacing, flushCache); |
230 FormAttachment bottom = data.getBottomAttachment (control, spacing, flushCache); | 238 FormAttachment bottom = data.getBottomAttachment (control, spacing, flushCache); |
233 if (bottom.numerator is 0) return bottom.offset; | 241 if (bottom.numerator is 0) return bottom.offset; |
234 if (bottom.numerator is bottom.denominator) return -top.offset; | 242 if (bottom.numerator is bottom.denominator) return -top.offset; |
235 if (bottom.offset <= 0) { | 243 if (bottom.offset <= 0) { |
236 return -top.offset * top.denominator / bottom.numerator; | 244 return -top.offset * top.denominator / bottom.numerator; |
237 } | 245 } |
238 int divider = bottom.denominator - bottom.numerator; | 246 int divider = bottom.denominator - bottom.numerator; |
239 return bottom.denominator * bottom.offset / divider; | 247 return bottom.denominator * bottom.offset / divider; |
240 } | 248 } |
241 return height.solveY (data.getHeight (control, flushCache)); | 249 return height.solveY (data.getHeight (control, flushCache)); |
242 } | 250 } |
243 | 251 |
244 protected Point computeSize (Composite composite, int wHint, int hHint, bool flushCache) { | 252 override protected Point computeSize (Composite composite, int wHint, int hHint, bool flushCache) { |
245 Point size = layout (composite, false, 0, 0, wHint, hHint, flushCache); | 253 Point size = layout (composite, false, 0, 0, wHint, hHint, flushCache); |
246 if (wHint !is DWT.DEFAULT) size.x = wHint; | 254 if (wHint !is DWT.DEFAULT) size.x = wHint; |
247 if (hHint !is DWT.DEFAULT) size.y = hHint; | 255 if (hHint !is DWT.DEFAULT) size.y = hHint; |
248 return size; | 256 return size; |
249 } | 257 } |
250 | 258 |
251 protected bool flushCache (Control control) { | 259 override protected bool flushCache (Control control) { |
252 Object data = control.getLayoutData (); | 260 Object data = control.getLayoutData (); |
253 if (data !is null) (cast(FormData) data).flushCache (); | 261 if (data !is null) (cast(FormData) data).flushCache (); |
254 return true; | 262 return true; |
255 } | 263 } |
256 | 264 |
257 String getName () { | 265 String getName () { |
258 String string = getClass ().getName (); | 266 String string = this.classinfo.name; |
259 int index = string.lastIndexOf ('.'); | 267 int index = string.lastIndexOf('.'); |
260 if (index is -1) return string; | 268 if (index is -1 ) return string; |
261 return string.substring (index + 1, string.length ()); | 269 return string[ index + 1 .. string.length ]; |
262 } | 270 } |
263 | 271 |
264 /* | 272 /* |
265 * Computes the preferred height of the form with | 273 * Computes the preferred height of the form with |
266 * respect to the preferred height of the control. | 274 * respect to the preferred height of the control. |
273 if (right.numerator is 0) return right.offset; | 281 if (right.numerator is 0) return right.offset; |
274 if (right.numerator is right.denominator) return -left.offset; | 282 if (right.numerator is right.denominator) return -left.offset; |
275 if (right.offset <= 0) { | 283 if (right.offset <= 0) { |
276 return -left.offset * left.denominator / left.numerator; | 284 return -left.offset * left.denominator / left.numerator; |
277 } | 285 } |
278 int divider = right.denominator - right.numerator; | 286 int divider = right.denominator - right.numerator; |
279 return right.denominator * right.offset / divider; | 287 return right.denominator * right.offset / divider; |
280 } | 288 } |
281 return width.solveY (data.getWidth (control, flushCache)); | 289 return width.solveY (data.getWidth (control, flushCache)); |
282 } | 290 } |
283 | 291 |
284 protected void layout (Composite composite, bool flushCache) { | 292 override protected void layout (Composite composite, bool flushCache) { |
285 Rectangle rect = composite.getClientArea (); | 293 Rectangle rect = composite.getClientArea (); |
286 int x = rect.x + marginLeft + marginWidth; | 294 int x = rect.x + marginLeft + marginWidth; |
287 int y = rect.y + marginTop + marginHeight; | 295 int y = rect.y + marginTop + marginHeight; |
288 int width = Math.max (0, rect.width - marginLeft - 2 * marginWidth - marginRight); | 296 int width = Math.max (0, rect.width - marginLeft - 2 * marginWidth - marginRight); |
289 int height = Math.max (0, rect.height - marginTop - 2 * marginHeight - marginBottom); | 297 int height = Math.max (0, rect.height - marginTop - 2 * marginHeight - marginBottom); |
311 FormAttachment right = data.getRightAttachment (child, spacing, flushCache); | 319 FormAttachment right = data.getRightAttachment (child, spacing, flushCache); |
312 int x1 = left.solveX (width), x2 = right.solveX (width); | 320 int x1 = left.solveX (width), x2 = right.solveX (width); |
313 if (data.height is DWT.DEFAULT && !data.needed) { | 321 if (data.height is DWT.DEFAULT && !data.needed) { |
314 int trim = 0; | 322 int trim = 0; |
315 //TEMPORARY CODE | 323 //TEMPORARY CODE |
316 if ( null !is cast(Scrollable)child ) { | 324 if ( auto sa = cast(Scrollable)child) { |
317 Rectangle rect = (cast(Scrollable) child).computeTrim (0, 0, 0, 0); | 325 Rectangle rect = sa.computeTrim (0, 0, 0, 0); |
318 trim = rect.width; | 326 trim = rect.width; |
319 } else { | 327 } else { |
320 trim = child.getBorderWidth () * 2; | 328 trim = child.getBorderWidth () * 2; |
321 } | 329 } |
322 data.cacheWidth = data.cacheHeight = -1; | 330 data.cacheWidth = data.cacheHeight = -1; |
371 * Returns a string containing a concise, human-readable | 379 * Returns a string containing a concise, human-readable |
372 * description of the receiver. | 380 * description of the receiver. |
373 * | 381 * |
374 * @return a string representation of the layout | 382 * @return a string representation of the layout |
375 */ | 383 */ |
376 public String toString () { | 384 override public String toString () { |
377 String string = getName ()+" {"; | 385 String string = getName ()~" {"; |
378 if (marginWidth !is 0) string += "marginWidth="+marginWidth+" "; | 386 if (marginWidth !is 0) string ~= "marginWidth="~to!(String)(marginWidth)~" "; |
379 if (marginHeight !is 0) string += "marginHeight="+marginHeight+" "; | 387 if (marginHeight !is 0) string ~= "marginHeight="~to!(String)(marginHeight)~" "; |
380 if (marginLeft !is 0) string += "marginLeft="+marginLeft+" "; | 388 if (marginLeft !is 0) string ~= "marginLeft="~to!(String)(marginLeft)~" "; |
381 if (marginRight !is 0) string += "marginRight="+marginRight+" "; | 389 if (marginRight !is 0) string ~= "marginRight="~to!(String)(marginRight)~" "; |
382 if (marginTop !is 0) string += "marginTop="+marginTop+" "; | 390 if (marginTop !is 0) string ~= "marginTop="~to!(String)(marginTop)~" "; |
383 if (marginBottom !is 0) string += "marginBottom="+marginBottom+" "; | 391 if (marginBottom !is 0) string ~= "marginBottom="~to!(String)(marginBottom)~" "; |
384 if (spacing !is 0) string += "spacing="+spacing+" "; | 392 if (spacing !is 0) string ~= "spacing="~to!(String)(spacing)~" "; |
385 string = string.trim(); | 393 string = string.trim(); |
386 string += "}"; | 394 string ~= "}"; |
387 return string; | 395 return string; |
388 } | 396 } |
389 } | 397 } |