Mercurial > projects > dwt-addons
annotate dwtx/ui/forms/widgets/Section.d @ 104:04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
These new wrappers now use the tango.util.containers instead of the tango.util.collections.
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Thu, 07 Aug 2008 15:01:33 +0200 |
parents | 0953c252a764 |
children |
rev | line source |
---|---|
75 | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2007 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 * Michael Williamson (eclipse-bugs@magnaworks.com) - patch (see Bugzilla #92545) | |
11 * | |
12 * Port to the D programming language: | |
13 * Frank Benoit <benoit@tionex.de> | |
14 *******************************************************************************/ | |
15 module dwtx.ui.forms.widgets.Section; | |
16 | |
17 import dwtx.ui.forms.widgets.ExpandableComposite; | |
18 import dwtx.ui.forms.widgets.SharedScrolledComposite; | |
19 | |
20 import dwt.DWT; | |
21 import dwt.events.PaintEvent; | |
22 import dwt.graphics.Color; | |
23 import dwt.graphics.GC; | |
24 import dwt.graphics.Image; | |
25 import dwt.graphics.Point; | |
26 import dwt.graphics.Rectangle; | |
27 import dwt.widgets.Composite; | |
28 import dwt.widgets.Control; | |
29 import dwt.widgets.Event; | |
30 import dwt.widgets.Listener; | |
31 import dwt.widgets.Text; | |
32 import dwtx.core.runtime.Assert; | |
33 import dwtx.ui.internal.forms.widgets.FormImages; | |
34 import dwtx.ui.internal.forms.widgets.FormUtil; | |
35 | |
36 import dwt.dwthelper.utils; | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
79
diff
changeset
|
37 import dwtx.dwtxhelper.Collection; |
75 | 38 |
39 /** | |
40 * A variation of the expandable composite that adds optional description below | |
41 * the title. Section is often used as a basic building block in forms because | |
42 * it provides for logical grouping of information. | |
43 * <p> | |
44 * In case of the TITLE_BAR style, Section renders the title bar in a way | |
45 * compatible with the rest of the workbench. Since it is a widget, all the | |
46 * colors must be supplied directly. When created by the form toolkit, these | |
47 * colors are supplied by the toolkit. The toolkit initializes these colors | |
48 * based on the system colors. For this reason, it is recommended to create the | |
49 * section by the toolkit instead of through its own constructor. | |
50 * <p> | |
51 * Since 3.1, it is possible to set a control to be used for section | |
52 * description. If used, <code>DESCRIPTION</code> style should not be set. A | |
53 * typical way to take advantage of the new method is to set an instance of | |
54 * <code>FormText</code> to provide for hyperlinks and images in the | |
55 * description area. | |
56 * | |
57 * @since 3.0 | |
58 */ | |
59 public class Section : ExpandableComposite { | |
60 /** | |
61 * Description style. If used, description will be rendered below the title. | |
62 */ | |
63 public static const int DESCRIPTION = 1 << 7; | |
64 | |
65 private Control descriptionControl; | |
66 | |
67 private Control separator; | |
68 | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
79
diff
changeset
|
69 private Hashtable titleColors; |
75 | 70 |
71 private static const String COLOR_BG = "bg"; //$NON-NLS-1$ | |
72 | |
73 private static const String COLOR_GBG = "gbg"; //$NON-NLS-1$ | |
74 | |
75 private static const String COLOR_BORDER = "border"; //$NON-NLS-1$ | |
76 | |
77 /** | |
78 * Creates a new section instance in the provided parent. | |
79 * | |
80 * @param parent | |
81 * the parent composite | |
82 * @param style | |
83 * the style to use | |
84 */ | |
85 public this(Composite parent, int style) { | |
86 this(parent, DWT.NULL, style); | |
87 } | |
88 | |
89 this(Composite parent, int cstyle, int style) { | |
90 super(parent, cstyle | getBackgroundStyle(style), style); | |
91 int rtl = cstyle & DWT.RIGHT_TO_LEFT; | |
92 if ((style & DESCRIPTION) !is 0) { | |
93 descriptionControl = new Text(this, DWT.READ_ONLY | DWT.WRAP | rtl); | |
94 } | |
95 if ((style & TITLE_BAR) !is 0) { | |
96 Listener listener = new class Listener{ | |
97 public void handleEvent(Event e) { | |
98 Image image = this.outer.callSuperGetBackgroundImage(); | |
99 if (image !is null) { | |
100 FormImages.getInstance().markFinished(image); | |
101 } | |
102 this.outer.callSuperSetBackgroundImage(null); | |
103 } | |
104 }; | |
105 addListener(DWT.Dispose, listener); | |
106 addListener(DWT.Resize, listener); | |
107 } | |
108 } | |
109 | |
110 private static int getBackgroundStyle(int estyle) { | |
111 return ((estyle & TITLE_BAR) !is 0) ? DWT.NO_BACKGROUND : DWT.NULL; | |
112 } | |
113 | |
114 private Image callSuperGetBackgroundImage(){ | |
115 return super.getBackgroundImage(); | |
116 } | |
117 private void callSuperSetBackgroundImage(Image image){ | |
118 return super.setBackgroundImage(image); | |
119 } | |
120 protected void internalSetExpanded(bool expanded) { | |
121 super.internalSetExpanded(expanded); | |
122 if ((getExpansionStyle() & TITLE_BAR) !is 0) { | |
123 if (!expanded) | |
79 | 124 super.setBackgroundImage(cast(Image)null); |
75 | 125 } |
126 reflow(); | |
127 } | |
128 | |
129 /** | |
130 * Reflows this section and all the parents up the hierarchy until a | |
131 * SharedScrolledComposite is reached. | |
132 */ | |
133 protected void reflow() { | |
134 Composite c = this; | |
135 while (c !is null) { | |
136 c.setRedraw(false); | |
137 c = c.getParent(); | |
138 if (null !is cast(SharedScrolledComposite)c ) { | |
139 break; | |
140 } | |
141 } | |
142 c = this; | |
143 while (c !is null) { | |
144 c.layout(true); | |
145 c = c.getParent(); | |
146 if (null !is cast(SharedScrolledComposite)c ) { | |
147 (cast(SharedScrolledComposite) c).reflow(true); | |
148 break; | |
149 } | |
150 } | |
151 c = this; | |
152 while (c !is null) { | |
153 c.setRedraw(true); | |
154 c = c.getParent(); | |
155 if (null !is cast(SharedScrolledComposite)c ) { | |
156 break; | |
157 } | |
158 } | |
159 } | |
160 | |
161 /** | |
162 * Sets the description text. Has no effect if DESCRIPTION style was not | |
163 * used to create the control. | |
164 * | |
165 * @param description | |
166 */ | |
167 public void setDescription(String description) { | |
168 if (null !is cast(Text)descriptionControl ) | |
169 (cast(Text) descriptionControl).setText(description); | |
170 } | |
171 | |
172 /** | |
173 * Returns the current description text. | |
174 * | |
175 * @return description text or <code>null</code> if DESCRIPTION style was | |
176 * not used to create the control. | |
177 */ | |
178 public String getDescription() { | |
179 if (null !is cast(Text)descriptionControl ) | |
180 return (cast(Text) descriptionControl).getText(); | |
181 return null; | |
182 } | |
183 | |
184 /** | |
185 * Sets the separator control of this section. The separator must not be | |
186 * <samp>null </samp> and must be a direct child of this container. If | |
187 * defined, separator will be placed below the title text and will remain | |
188 * visible regardless of the expansion state. | |
189 * | |
190 * @param separator | |
191 * the separator that will be placed below the title text. | |
192 */ | |
193 public void setSeparatorControl(Control separator) { | |
194 Assert.isTrue(separator !is null && separator.getParent().opEquals(this)); | |
195 this.separator = separator; | |
196 } | |
197 | |
198 /** | |
199 * Returns the control that is used as a separator betweeen the title and | |
200 * the client, or <samp>null </samp> if not set. | |
201 * | |
202 * @return separator control or <samp>null </samp> if not set. | |
203 */ | |
204 public Control getSeparatorControl() { | |
205 return separator; | |
206 } | |
207 | |
208 /** | |
209 * Sets the background of the section. | |
210 * | |
211 * @param bg | |
212 * the new background | |
213 */ | |
214 public void setBackground(Color bg) { | |
215 super.setBackground(bg); | |
216 if (descriptionControl !is null | |
217 && (getExpansionStyle() & DESCRIPTION) !is 0) | |
218 descriptionControl.setBackground(bg); | |
219 } | |
220 | |
221 /** | |
222 * Sets the foreground of the section. | |
223 * | |
224 * @param fg | |
225 * the new foreground. | |
226 */ | |
227 public void setForeground(Color fg) { | |
228 super.setForeground(fg); | |
229 if (descriptionControl !is null | |
230 && (getExpansionStyle() & DESCRIPTION) !is 0) | |
231 descriptionControl.setForeground(fg); | |
232 } | |
233 | |
234 /** | |
235 * Returns the control used to render the description. In 3.1, this method | |
236 * was promoted to public. | |
237 * | |
238 * @return description control or <code>null</code> if DESCRIPTION style | |
239 * was not used to create the control and description control was | |
240 * not set by the client. | |
241 * @see #setDescriptionControl(dwt.widgets.Control) | |
242 */ | |
243 public Control getDescriptionControl() { | |
244 return descriptionControl; | |
245 } | |
246 | |
247 /** | |
248 * Sets the description control of this section. The control must not be | |
249 * <samp>null</samp> and must be a direct child of this container. If | |
250 * defined, contol will be placed below the title text and the separator and | |
251 * will be hidden int he collapsed state. | |
252 * <p> | |
253 * This method and <code>DESCRIPTION</code> style are mutually exclusive. | |
254 * Use the method only if you want to create the description control | |
255 * yourself. | |
256 * | |
257 * @since 3.1 | |
258 * @param descriptionControl | |
259 * the control that will be placed below the title text. | |
260 */ | |
261 public void setDescriptionControl(Control descriptionControl) { | |
262 Assert.isTrue((getExpansionStyle() & DESCRIPTION) is 0); | |
263 Assert.isTrue(descriptionControl !is null | |
264 && descriptionControl.getParent().opEquals(this)); | |
265 this.descriptionControl = descriptionControl; | |
266 } | |
267 | |
268 /** | |
269 * Sets the color of the title bar border when TITLE_BAR style is used. | |
270 * | |
271 * @param color | |
272 * the title bar border color | |
273 */ | |
274 public void setTitleBarBorderColor(Color color) { | |
275 putTitleBarColor(COLOR_BORDER, color); | |
276 } | |
277 | |
278 /** | |
279 * Sets the color of the title bar background when TITLE_BAR style is used. | |
280 * This color is used as a starting color for the vertical gradient. | |
281 * | |
282 * @param color | |
283 * the title bar border background | |
284 */ | |
285 public void setTitleBarBackground(Color color) { | |
286 putTitleBarColor(COLOR_BG, color); | |
287 } | |
288 | |
289 /** | |
290 * Sets the color of the title bar gradient background when TITLE_BAR style | |
291 * is used. This color is used at the height where title controls end | |
292 * (toggle, tool bar). | |
293 * | |
294 * @param color | |
295 * the title bar gradient background | |
296 */ | |
297 public void setTitleBarGradientBackground(Color color) { | |
298 putTitleBarColor(COLOR_GBG, color); | |
299 } | |
300 | |
301 /** | |
302 * Returns the title bar border color when TITLE_BAR style is used. | |
303 * | |
304 * @return the title bar border color | |
305 */ | |
306 public Color getTitleBarBorderColor() { | |
307 if (titleColors is null) | |
308 return null; | |
309 return cast(Color) titleColors.get(COLOR_BORDER); | |
310 } | |
311 | |
312 /** | |
313 * Returns the title bar gradient background color when TITLE_BAR style is | |
314 * used. | |
315 * | |
316 * @return the title bar gradient background | |
317 */ | |
318 public Color getTitleBarGradientBackground() { | |
319 if (titleColors is null) | |
320 return null; | |
321 if ((getExpansionStyle() & SHORT_TITLE_BAR) !is 0) | |
322 return getBackground(); | |
323 return cast(Color) titleColors.get(COLOR_GBG); | |
324 } | |
325 | |
326 /** | |
327 * Returns the title bar background when TITLE_BAR style is used. | |
328 * | |
329 * @return the title bar background | |
330 */ | |
331 public Color getTitleBarBackground() { | |
332 if (titleColors is null) | |
333 return null; | |
334 return cast(Color) titleColors.get(COLOR_BG); | |
335 } | |
336 | |
337 private void putTitleBarColor(String key, Color color) { | |
338 if (color is null) | |
339 return; | |
340 if (titleColors is null) | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
79
diff
changeset
|
341 titleColors = new Hashtable(); |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
79
diff
changeset
|
342 titleColors.put(key, color); |
75 | 343 } |
344 | |
345 protected void onPaint(PaintEvent e) { | |
346 Color bg = null; | |
347 Color fg = null; | |
348 Color border = null; | |
349 | |
350 GC gc = e.gc; | |
351 Image buffer = null; | |
352 Rectangle bounds = getClientArea(); | |
353 | |
354 if ((getExpansionStyle() & TITLE_BAR) !is 0) { | |
355 buffer = new Image(getDisplay(), bounds.width, bounds.height); | |
356 buffer.setBackground(getBackground()); | |
357 gc = new GC(buffer); | |
358 } | |
359 if (titleColors !is null) { | |
360 bg = cast(Color) titleColors.get(COLOR_BG); | |
361 fg = getTitleBarForeground(); | |
362 border = cast(Color) titleColors.get(COLOR_BORDER); | |
363 } | |
364 if (bg is null) | |
365 bg = getBackground(); | |
366 if (fg is null) | |
367 fg = getForeground(); | |
368 if (border is null) | |
369 border = fg; | |
370 int theight = 0; | |
371 int gradientheight = 0; | |
372 int tvmargin = IGAP; | |
373 if ((getExpansionStyle() & TITLE_BAR) !is 0) { | |
374 Point tsize = null; | |
375 Point tcsize = null; | |
376 if (toggle !is null) | |
377 tsize = toggle.getSize(); | |
378 int twidth = bounds.width - marginWidth - marginWidth; | |
379 if (tsize !is null) | |
380 twidth -= tsize.x + IGAP; | |
381 if (getTextClient() !is null) | |
382 tcsize = getTextClient().getSize(); | |
383 if (tcsize !is null) | |
384 twidth -= tcsize.x + IGAP; | |
385 Point size = textLabel.getSize(); | |
386 if (tsize !is null) | |
387 theight += Math.max(theight, tsize.y); | |
388 gradientheight = theight; | |
389 if (tcsize !is null) { | |
390 theight = Math.max(theight, tcsize.y); | |
391 } | |
392 theight = Math.max(theight, size.y); | |
393 gradientheight = Math.max(gradientheight, size.y); | |
394 theight += tvmargin + tvmargin; | |
395 gradientheight += tvmargin + tvmargin; | |
396 } else { | |
397 theight = 5; | |
398 } | |
399 if ((getExpansionStyle() & TITLE_BAR) !is 0) { | |
400 if (getBackgroundImage() is null) | |
401 updateHeaderImage(bg, bounds, gradientheight, theight); | |
402 gc.setBackground(getBackground()); | |
403 gc.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height); | |
404 drawBackground(gc, bounds.x, bounds.y, bounds.width, theight); | |
405 if (marginWidth > 0) { | |
406 // fix up margins | |
407 gc.setBackground(getBackground()); | |
408 gc.fillRectangle(0, 0, marginWidth, theight); | |
409 gc.fillRectangle(bounds.x + bounds.width - marginWidth, 0, | |
410 marginWidth, theight); | |
411 } | |
412 } else if (isExpanded()) { | |
413 gc.setForeground(bg); | |
414 gc.setBackground(getBackground()); | |
415 gc.fillGradientRectangle(marginWidth, marginHeight, bounds.width | |
416 - marginWidth - marginWidth, theight, true); | |
417 } | |
418 gc.setBackground(getBackground()); | |
419 FormUtil.setAntialias(gc, DWT.ON); | |
420 // repair the upper left corner | |
421 gc.fillPolygon([ marginWidth, marginHeight, marginWidth, | |
422 marginHeight + 2, marginWidth + 2, marginHeight ]); | |
423 // repair the upper right corner | |
424 gc.fillPolygon([ bounds.width - marginWidth - 3, | |
425 marginHeight, bounds.width - marginWidth, marginHeight, | |
426 bounds.width - marginWidth, marginHeight + 3 ]); | |
427 gc.setForeground(border); | |
428 if (isExpanded() || (getExpansionStyle() & TITLE_BAR) !is 0) { | |
429 // top left curve | |
430 gc.drawLine(marginWidth, marginHeight + 2, marginWidth + 2, | |
431 marginHeight); | |
432 // top edge | |
433 gc.drawLine(marginWidth + 2, marginHeight, bounds.width | |
434 - marginWidth - 3, marginHeight); | |
435 // top right curve | |
436 gc.drawLine(bounds.width - marginWidth - 3, marginHeight, | |
437 bounds.width - marginWidth - 1, marginHeight + 2); | |
438 } else { | |
439 // collapsed short title bar | |
440 // top edge | |
441 gc.drawLine(marginWidth, marginHeight, bounds.width - 1, | |
442 marginHeight); | |
443 } | |
444 if ((getExpansionStyle() & TITLE_BAR) !is 0 || isExpanded()) { | |
445 // left vertical edge gradient | |
446 gc.fillGradientRectangle(marginWidth, marginHeight + 2, 1, | |
447 gradientheight - 2, true); | |
448 // right vertical edge gradient | |
449 gc.fillGradientRectangle(bounds.width - marginWidth - 1, | |
450 marginHeight + 2, 1, gradientheight - 2, true); | |
451 } | |
452 if ((getExpansionStyle() & TITLE_BAR) !is 0) { | |
453 // New in 3.3 - edge treatmant | |
454 gc.setForeground(getDisplay().getSystemColor(DWT.COLOR_WHITE)); | |
455 gc.drawPolyline([ marginWidth + 1, | |
456 marginHeight + gradientheight - 1, marginWidth + 1, | |
457 marginHeight + 2, marginWidth + 2, marginHeight + 2, | |
458 marginWidth + 2, marginHeight + 1, | |
459 bounds.width - marginWidth - 3, marginHeight + 1, | |
460 bounds.width - marginWidth - 3, marginHeight + 2, | |
461 bounds.width - marginWidth - 2, marginHeight + 2, | |
462 bounds.width - marginWidth - 2, | |
463 marginHeight + gradientheight - 1 ]); | |
464 } | |
465 if (buffer !is null) { | |
466 gc.dispose(); | |
467 e.gc.drawImage(buffer, 0, 0); | |
468 buffer.dispose(); | |
469 } | |
470 } | |
471 | |
472 private void updateHeaderImage(Color bg, Rectangle bounds, int theight, | |
473 int realtheight) { | |
474 Image image = FormImages.getInstance().getGradient(getDisplay(), getBackground(), bg, realtheight, theight, marginHeight); | |
475 super.setBackgroundImage(image); | |
476 } | |
477 | |
478 /** | |
479 * Background image is used for the title gradient - does nothing. | |
480 */ | |
481 public final void setBackgroundImage(Image image) { | |
482 } | |
483 } |