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