Mercurial > projects > dwt2
comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CBanner.d @ 0:6dd524f61e62
add dwt win and basic java stuff
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Mon, 02 Mar 2009 14:44:16 +0100 |
parents | |
children | 6bf2837c50fe |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:6dd524f61e62 |
---|---|
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.custom.CBanner; | |
14 | |
15 | |
16 | |
17 import org.eclipse.swt.SWT; | |
18 import org.eclipse.swt.SWTException; | |
19 import org.eclipse.swt.graphics.Color; | |
20 import org.eclipse.swt.graphics.Cursor; | |
21 import org.eclipse.swt.graphics.GC; | |
22 import org.eclipse.swt.graphics.Point; | |
23 import org.eclipse.swt.graphics.RGB; | |
24 import org.eclipse.swt.graphics.Rectangle; | |
25 import org.eclipse.swt.widgets.Composite; | |
26 import org.eclipse.swt.widgets.Control; | |
27 import org.eclipse.swt.widgets.Event; | |
28 import org.eclipse.swt.widgets.Layout; | |
29 import org.eclipse.swt.widgets.Listener; | |
30 import org.eclipse.swt.custom.CBannerLayout; | |
31 | |
32 import Math = tango.math.Math; | |
33 | |
34 | |
35 /** | |
36 * Instances of this class implement a Composite that lays out its | |
37 * children and allows programmatic control of the layout. It draws | |
38 * a separator between the left and right children which can be dragged | |
39 * to resize the right control. | |
40 * CBanner is used in the workbench to layout the toolbar area and | |
41 * perspective switching toolbar. | |
42 * <p> | |
43 * Note that although this class is a subclass of <code>Composite</code>, | |
44 * it does not make sense to set a layout on it. | |
45 * </p><p> | |
46 * <dl> | |
47 * <dt><b>Styles:</b></dt> | |
48 * <dd>NONE</dd> | |
49 * <dt><b>Events:</b></dt> | |
50 * <dd>(None)</dd> | |
51 * </dl> | |
52 * <p> | |
53 * IMPORTANT: This class is <em>not</em> intended to be subclassed. | |
54 * </p> | |
55 * | |
56 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
57 * | |
58 * @since 3.0 | |
59 */ | |
60 | |
61 public class CBanner : Composite { | |
62 | |
63 Control left; | |
64 Control right; | |
65 Control bottom; | |
66 | |
67 bool simple = true; | |
68 | |
69 int[] curve; | |
70 int curveStart = 0; | |
71 Rectangle curveRect; | |
72 int curve_width = 5; | |
73 int curve_indent = -2; | |
74 | |
75 int rightWidth = SWT.DEFAULT; | |
76 int rightMinWidth = 0; | |
77 int rightMinHeight = 0; | |
78 Cursor resizeCursor; | |
79 bool dragging = false; | |
80 int rightDragDisplacement = 0; | |
81 | |
82 static const int OFFSCREEN = -200; | |
83 static const int BORDER_BOTTOM = 2; | |
84 static const int BORDER_TOP = 3; | |
85 static const int BORDER_STRIPE = 1; | |
86 static const int CURVE_TAIL = 200; | |
87 static const int BEZIER_RIGHT = 30; | |
88 static const int BEZIER_LEFT = 30; | |
89 static const int MIN_LEFT = 10; | |
90 static int BORDER1 = SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW; | |
91 | |
92 | |
93 /** | |
94 * Constructs a new instance of this class given its parent | |
95 * and a style value describing its behavior and appearance. | |
96 * <p> | |
97 * The style value is either one of the style constants defined in | |
98 * class <code>SWT</code> which is applicable to instances of this | |
99 * class, or must be built by <em>bitwise OR</em>'ing together | |
100 * (that is, using the <code>int</code> "|" operator) two or more | |
101 * of those <code>SWT</code> style constants. The class description | |
102 * lists the style constants that are applicable to the class. | |
103 * Style bits are also inherited from superclasses. | |
104 * </p> | |
105 * | |
106 * @param parent a widget which will be the parent of the new instance (cannot be null) | |
107 * @param style the style of widget to construct | |
108 * | |
109 * @exception IllegalArgumentException <ul> | |
110 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
111 * </ul> | |
112 * @exception SWTException <ul> | |
113 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
114 * </ul> | |
115 * | |
116 */ | |
117 public this(Composite parent, int style) { | |
118 curveRect = new Rectangle(0, 0, 0, 0); | |
119 super(parent, checkStyle(style)); | |
120 super.setLayout(new CBannerLayout()); | |
121 resizeCursor = new Cursor(getDisplay(), SWT.CURSOR_SIZEWE); | |
122 | |
123 Listener listener = new class() Listener { | |
124 public void handleEvent(Event e) { | |
125 switch (e.type) { | |
126 case SWT.Dispose: | |
127 onDispose(); break; | |
128 case SWT.MouseDown: | |
129 onMouseDown (e.x, e.y); break; | |
130 case SWT.MouseExit: | |
131 onMouseExit(); break; | |
132 case SWT.MouseMove: | |
133 onMouseMove(e.x, e.y); break; | |
134 case SWT.MouseUp: | |
135 onMouseUp(); break; | |
136 case SWT.Paint: | |
137 onPaint(e.gc); break; | |
138 case SWT.Resize: | |
139 onResize(); break; | |
140 default: | |
141 } | |
142 } | |
143 }; | |
144 int[] events = [SWT.Dispose, SWT.MouseDown, SWT.MouseExit, SWT.MouseMove, SWT.MouseUp, SWT.Paint, SWT.Resize]; | |
145 for (int i = 0; i < events.length; i++) { | |
146 addListener(events[i], listener); | |
147 } | |
148 } | |
149 static int[] bezier(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, int count) { | |
150 // The parametric equations for a Bezier curve for x[t] and y[t] where 0 <= t <=1 are: | |
151 // x[t] = x0+3(x1-x0)t+3(x0+x2-2x1)t^2+(x3-x0+3x1-3x2)t^3 | |
152 // y[t] = y0+3(y1-y0)t+3(y0+y2-2y1)t^2+(y3-y0+3y1-3y2)t^3 | |
153 double a0 = x0; | |
154 double a1 = 3*(x1 - x0); | |
155 double a2 = 3*(x0 + x2 - 2*x1); | |
156 double a3 = x3 - x0 + 3*x1 - 3*x2; | |
157 double b0 = y0; | |
158 double b1 = 3*(y1 - y0); | |
159 double b2 = 3*(y0 + y2 - 2*y1); | |
160 double b3 = y3 - y0 + 3*y1 - 3*y2; | |
161 | |
162 int[] polygon = new int[2*count + 2]; | |
163 for (int i = 0; i <= count; i++) { | |
164 double t = cast(double)i / cast(double)count; | |
165 polygon[2*i] = cast(int)(a0 + a1*t + a2*t*t + a3*t*t*t); | |
166 polygon[2*i + 1] = cast(int)(b0 + b1*t + b2*t*t + b3*t*t*t); | |
167 } | |
168 return polygon; | |
169 } | |
170 static int checkStyle (int style) { | |
171 return SWT.NONE; | |
172 } | |
173 /** | |
174 * Returns the Control that appears on the bottom side of the banner. | |
175 * | |
176 * @return the control that appears on the bottom side of the banner or null | |
177 * | |
178 * @exception SWTException <ul> | |
179 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
180 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
181 * </ul> | |
182 * | |
183 * @since 3.0 | |
184 */ | |
185 public Control getBottom() { | |
186 checkWidget(); | |
187 return bottom; | |
188 } | |
189 public override Rectangle getClientArea() { | |
190 return new Rectangle(0, 0, 0, 0); | |
191 } | |
192 | |
193 /** | |
194 * Returns the Control that appears on the left side of the banner. | |
195 * | |
196 * @return the control that appears on the left side of the banner or null | |
197 * | |
198 * @exception SWTException <ul> | |
199 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
200 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
201 * </ul> | |
202 * | |
203 * @since 3.0 | |
204 */ | |
205 public Control getLeft() { | |
206 checkWidget(); | |
207 return left; | |
208 } | |
209 | |
210 /** | |
211 * Returns the Control that appears on the right side of the banner. | |
212 * | |
213 * @return the control that appears on the right side of the banner or null | |
214 * | |
215 * @exception SWTException <ul> | |
216 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
217 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
218 * </ul> | |
219 * | |
220 * @since 3.0 | |
221 */ | |
222 public Control getRight() { | |
223 checkWidget(); | |
224 return right; | |
225 } | |
226 /** | |
227 * Returns the minimum size of the control that appears on the right of the banner. | |
228 * | |
229 * @return the minimum size of the control that appears on the right of the banner | |
230 * | |
231 * @since 3.1 | |
232 */ | |
233 public Point getRightMinimumSize() { | |
234 checkWidget(); | |
235 return new Point(rightMinWidth, rightMinHeight); | |
236 } | |
237 /** | |
238 * Returns the width of the control that appears on the right of the banner. | |
239 * | |
240 * @return the width of the control that appears on the right of the banner | |
241 * | |
242 * @since 3.0 | |
243 */ | |
244 public int getRightWidth() { | |
245 checkWidget(); | |
246 if (right is null) return 0; | |
247 if (rightWidth is SWT.DEFAULT) { | |
248 Point size = right.computeSize(SWT.DEFAULT, SWT.DEFAULT, false); | |
249 return size.x; | |
250 } | |
251 return rightWidth; | |
252 } | |
253 /** | |
254 * Returns <code>true</code> if the CBanner is rendered | |
255 * with a simple, traditional shape. | |
256 * | |
257 * @return <code>true</code> if the CBanner is rendered with a simple shape | |
258 * | |
259 * @since 3.0 | |
260 */ | |
261 public bool getSimple() { | |
262 checkWidget(); | |
263 return simple; | |
264 } | |
265 void onDispose() { | |
266 if (resizeCursor !is null) resizeCursor.dispose(); | |
267 resizeCursor = null; | |
268 left = null; | |
269 right = null; | |
270 bottom = null; | |
271 } | |
272 void onMouseDown (int x, int y) { | |
273 if (curveRect.contains(x, y)) { | |
274 dragging = true; | |
275 rightDragDisplacement = curveStart - x + curve_width - curve_indent; | |
276 } | |
277 } | |
278 void onMouseExit() { | |
279 if (!dragging) setCursor(null); | |
280 } | |
281 void onMouseMove(int x, int y) { | |
282 if (dragging) { | |
283 Point size = getSize(); | |
284 if (!(0 < x && x < size.x)) return; | |
285 rightWidth = Math.max(0, size.x - x - rightDragDisplacement); | |
286 if (rightMinWidth is SWT.DEFAULT) { | |
287 Point minSize = right.computeSize(rightMinWidth, rightMinHeight); | |
288 rightWidth = Math.max(minSize.x, rightWidth); | |
289 } else { | |
290 rightWidth = Math.max(rightMinWidth, rightWidth); | |
291 } | |
292 layout(false); | |
293 return; | |
294 } | |
295 if (curveRect.contains(x, y)) { | |
296 setCursor(resizeCursor); | |
297 } else { | |
298 setCursor(null); | |
299 } | |
300 } | |
301 void onMouseUp () { | |
302 dragging = false; | |
303 } | |
304 void onPaint(GC gc) { | |
305 // Useful for debugging paint problems | |
306 // { | |
307 // Point size = getSize(); | |
308 // gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GREEN)); | |
309 // gc.fillRectangle(-10, -10, size.x+20, size.y+20); | |
310 // } | |
311 if (left is null && right is null) return; | |
312 Point size = getSize(); | |
313 Color border1 = getDisplay().getSystemColor(BORDER1); | |
314 if (bottom !is null) { | |
315 int y = bottom.getBounds().y - BORDER_STRIPE - 1; | |
316 gc.setForeground(border1); | |
317 gc.drawLine(0, y, size.x, y); | |
318 } | |
319 if (left is null || right is null) return; | |
320 int[] line1 = new int[curve.length+6]; | |
321 int index = 0; | |
322 int x = curveStart; | |
323 line1[index++] = x + 1; | |
324 line1[index++] = size.y - BORDER_STRIPE; | |
325 for (int i = 0; i < curve.length/2; i++) { | |
326 line1[index++]=x+curve[2*i]; | |
327 line1[index++]=curve[2*i+1]; | |
328 } | |
329 line1[index++] = x + curve_width; | |
330 line1[index++] = 0; | |
331 line1[index++] = size.x; | |
332 line1[index++] = 0; | |
333 | |
334 Color background = getBackground(); | |
335 | |
336 if (getDisplay().getDepth() >= 15) { | |
337 // Anti- aliasing | |
338 int[] line2 = new int[line1.length]; | |
339 index = 0; | |
340 for (int i = 0; i < line1.length/2; i++) { | |
341 line2[index] = line1[index++] - 1; | |
342 line2[index] = line1[index++]; | |
343 } | |
344 int[] line3 = new int[line1.length]; | |
345 index = 0; | |
346 for (int i = 0; i < line1.length/2; i++) { | |
347 line3[index] = line1[index++] + 1; | |
348 line3[index] = line1[index++]; | |
349 } | |
350 RGB from = border1.getRGB(); | |
351 RGB to = background.getRGB(); | |
352 int red = from.red + 3*(to.red - from.red)/4; | |
353 int green = from.green + 3*(to.green - from.green)/4; | |
354 int blue = from.blue + 3*(to.blue - from.blue)/4; | |
355 Color color = new Color(getDisplay(), red, green, blue); | |
356 gc.setForeground(color); | |
357 gc.drawPolyline(line2); | |
358 gc.drawPolyline(line3); | |
359 color.dispose(); | |
360 | |
361 // draw tail fading to background | |
362 int x1 = Math.max(0, curveStart - CURVE_TAIL); | |
363 gc.setForeground(background); | |
364 gc.setBackground(border1); | |
365 gc.fillGradientRectangle(x1, size.y - BORDER_STRIPE, curveStart-x1+1, 1, false); | |
366 } else { | |
367 // draw solid tail | |
368 int x1 = Math.max(0, curveStart - CURVE_TAIL); | |
369 gc.setForeground(border1); | |
370 gc.drawLine(x1, size.y - BORDER_STRIPE, curveStart+1, size.y - BORDER_STRIPE); | |
371 } | |
372 | |
373 // draw border | |
374 gc.setForeground(border1); | |
375 gc.drawPolyline(line1); | |
376 } | |
377 | |
378 void onResize() { | |
379 updateCurve(getSize().y); | |
380 } | |
381 /** | |
382 * Set the control that appears on the bottom side of the banner. | |
383 * The bottom control is optional. Setting the bottom control to null will remove it from | |
384 * the banner - however, the creator of the control must dispose of the control. | |
385 * | |
386 * @param control the control to be displayed on the bottom or null | |
387 * | |
388 * @exception SWTException <ul> | |
389 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
390 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
391 * <li>ERROR_INVALID_ARGUMENT - if the bottom control was not created as a child of the receiver</li> | |
392 * </ul> | |
393 * | |
394 * @since 3.0 | |
395 */ | |
396 public void setBottom(Control control) { | |
397 checkWidget(); | |
398 if (control !is null && control.getParent() !is this) { | |
399 SWT.error(SWT.ERROR_INVALID_ARGUMENT); | |
400 } | |
401 if (bottom !is null && !bottom.isDisposed()) { | |
402 Point size = bottom.getSize(); | |
403 bottom.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y); | |
404 } | |
405 bottom = control; | |
406 layout(false); | |
407 } | |
408 /** | |
409 * Sets the layout which is associated with the receiver to be | |
410 * the argument which may be null. | |
411 * <p> | |
412 * Note: No Layout can be set on this Control because it already | |
413 * manages the size and position of its children. | |
414 * </p> | |
415 * | |
416 * @param layout the receiver's new layout or null | |
417 * | |
418 * @exception SWTException <ul> | |
419 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
420 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
421 * </ul> | |
422 */ | |
423 public override void setLayout (Layout layout) { | |
424 checkWidget(); | |
425 return; | |
426 } | |
427 | |
428 /** | |
429 * Set the control that appears on the left side of the banner. | |
430 * The left control is optional. Setting the left control to null will remove it from | |
431 * the banner - however, the creator of the control must dispose of the control. | |
432 * | |
433 * @param control the control to be displayed on the left or null | |
434 * | |
435 * @exception SWTException <ul> | |
436 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
437 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
438 * <li>ERROR_INVALID_ARGUMENT - if the left control was not created as a child of the receiver</li> | |
439 * </ul> | |
440 * | |
441 * @since 3.0 | |
442 */ | |
443 public void setLeft(Control control) { | |
444 checkWidget(); | |
445 if (control !is null && control.getParent() !is this) { | |
446 SWT.error(SWT.ERROR_INVALID_ARGUMENT); | |
447 } | |
448 if (left !is null && !left.isDisposed()) { | |
449 Point size = left.getSize(); | |
450 left.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y); | |
451 } | |
452 left = control; | |
453 layout(false); | |
454 } | |
455 /** | |
456 * Set the control that appears on the right side of the banner. | |
457 * The right control is optional. Setting the right control to null will remove it from | |
458 * the banner - however, the creator of the control must dispose of the control. | |
459 * | |
460 * @param control the control to be displayed on the right or null | |
461 * | |
462 * @exception SWTException <ul> | |
463 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
464 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
465 * <li>ERROR_INVALID_ARGUMENT - if the right control was not created as a child of the receiver</li> | |
466 * </ul> | |
467 * | |
468 * @since 3.0 | |
469 */ | |
470 public void setRight(Control control) { | |
471 checkWidget(); | |
472 if (control !is null && control.getParent() !is this) { | |
473 SWT.error(SWT.ERROR_INVALID_ARGUMENT); | |
474 } | |
475 if (right !is null && !right.isDisposed()) { | |
476 Point size = right.getSize(); | |
477 right.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y); | |
478 } | |
479 right = control; | |
480 layout(false); | |
481 } | |
482 /** | |
483 * Set the minimum height of the control that appears on the right side of the banner. | |
484 * | |
485 * @param size the minimum size of the control on the right | |
486 * | |
487 * @exception SWTException <ul> | |
488 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
489 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
490 * <li>ERROR_INVALID_ARGUMENT - if the size is null or the values of size are less than SWT.DEFAULT</li> | |
491 * </ul> | |
492 * | |
493 * @since 3.1 | |
494 */ | |
495 public void setRightMinimumSize(Point size) { | |
496 checkWidget(); | |
497 if (size is null || size.x < SWT.DEFAULT || size.y < SWT.DEFAULT) SWT.error(SWT.ERROR_INVALID_ARGUMENT); | |
498 rightMinWidth = size.x; | |
499 rightMinHeight = size.y; | |
500 layout(false); | |
501 } | |
502 /** | |
503 * Set the width of the control that appears on the right side of the banner. | |
504 * | |
505 * @param width the width of the control on the right | |
506 * | |
507 * @exception SWTException <ul> | |
508 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
509 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
510 * <li>ERROR_INVALID_ARGUMENT - if width is less than SWT.DEFAULT</li> | |
511 * </ul> | |
512 * | |
513 * @since 3.0 | |
514 */ | |
515 public void setRightWidth(int width) { | |
516 checkWidget(); | |
517 if (width < SWT.DEFAULT) SWT.error(SWT.ERROR_INVALID_ARGUMENT); | |
518 rightWidth = width; | |
519 layout(false); | |
520 } | |
521 /** | |
522 * Sets the shape that the CBanner will use to render itself. | |
523 * | |
524 * @param simple <code>true</code> if the CBanner should render itself in a simple, traditional style | |
525 * | |
526 * @exception SWTException <ul> | |
527 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
528 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
529 * </ul> | |
530 * | |
531 * @since 3.0 | |
532 */ | |
533 public void setSimple(bool simple) { | |
534 checkWidget(); | |
535 if (this.simple !is simple) { | |
536 this.simple = simple; | |
537 if (simple) { | |
538 curve_width = 5; | |
539 curve_indent = -2; | |
540 } else { | |
541 curve_width = 50; | |
542 curve_indent = 5; | |
543 } | |
544 updateCurve(getSize().y); | |
545 layout(false); | |
546 redraw(); | |
547 } | |
548 } | |
549 void updateCurve(int height) { | |
550 int h = height - BORDER_STRIPE; | |
551 if (simple) { | |
552 curve = [0,h, 1,h, 2,h-1, 3,h-2, | |
553 3,2, 4,1, 5,0]; | |
554 } else { | |
555 curve = bezier(0, h+1, BEZIER_LEFT, h+1, | |
556 curve_width-BEZIER_RIGHT, 0, curve_width, 0, | |
557 curve_width); | |
558 } | |
559 } | |
560 } |