Mercurial > projects > dwt-win
annotate dwt/custom/CLabel.d @ 213:36f5cb12e1a2
Update to SWT 3.4M7
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 17 May 2008 17:34:28 +0200 |
parents | ab60f3309436 |
children | fd9c62a2998e |
rev | line source |
---|---|
155 | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 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 dwt.custom.CLabel; | |
14 | |
15 | |
16 import dwt.DWT; | |
17 import dwt.DWTException; | |
18 import dwt.accessibility.ACC; | |
19 import dwt.accessibility.Accessible; | |
20 import dwt.accessibility.AccessibleAdapter; | |
21 import dwt.accessibility.AccessibleControlAdapter; | |
22 import dwt.accessibility.AccessibleControlEvent; | |
23 import dwt.accessibility.AccessibleEvent; | |
24 import dwt.events.DisposeEvent; | |
25 import dwt.events.DisposeListener; | |
26 import dwt.events.PaintEvent; | |
27 import dwt.events.PaintListener; | |
28 import dwt.events.TraverseEvent; | |
29 import dwt.events.TraverseListener; | |
30 import dwt.graphics.Color; | |
31 import dwt.graphics.Font; | |
32 import dwt.graphics.GC; | |
33 import dwt.graphics.Image; | |
34 import dwt.graphics.Point; | |
35 import dwt.graphics.Rectangle; | |
213 | 36 import dwt.graphics.TextLayout; |
155 | 37 import dwt.widgets.Canvas; |
38 import dwt.widgets.Composite; | |
39 import dwt.widgets.Control; | |
40 import dwt.widgets.Display; | |
41 | |
42 static import tango.text.Unicode; | |
43 static import tango.text.convert.Utf; | |
44 import dwt.dwthelper.utils; | |
45 | |
46 /** | |
47 * A Label which supports aligned text and/or an image and different border styles. | |
48 * <p> | |
49 * If there is not enough space a CLabel uses the following strategy to fit the | |
50 * information into the available space: | |
51 * <pre> | |
52 * ignores the indent in left align mode | |
53 * ignores the image and the gap | |
54 * shortens the text by replacing the center portion of the label with an ellipsis | |
55 * shortens the text by removing the center portion of the label | |
56 * </pre> | |
57 * <p> | |
58 * <dl> | |
59 * <dt><b>Styles:</b> | |
60 * <dd>LEFT, RIGHT, CENTER, SHADOW_IN, SHADOW_OUT, SHADOW_NONE</dd> | |
61 * <dt><b>Events:</b> | |
62 * <dd></dd> | |
63 * </dl> | |
64 * | |
65 * </p><p> | |
66 * IMPORTANT: This class is <em>not</em> intended to be subclassed. | |
67 * </p> | |
68 */ | |
69 public class CLabel : Canvas { | |
70 | |
71 alias Canvas.computeSize computeSize; | |
72 | |
73 /** Gap between icon and text */ | |
74 private static const int GAP = 5; | |
75 /** Left and right margins */ | |
76 private static const int INDENT = 3; | |
77 /** a string inserted in the middle of text that has been shortened */ | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
78 private static const String ELLIPSIS = "..."; //$NON-NLS-1$ // could use the ellipsis glyph on some platforms "\u2026" |
155 | 79 /** the alignment. Either CENTER, RIGHT, LEFT. Default is LEFT*/ |
80 private int align_ = DWT.LEFT; | |
81 private int hIndent = INDENT; | |
82 private int vIndent = INDENT; | |
83 /** the current text */ | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
84 private String text; |
155 | 85 /** the current icon */ |
86 private Image image; | |
87 // The tooltip is used for two purposes - the application can set | |
88 // a tooltip or the tooltip can be used to display the full text when the | |
89 // the text has been truncated due to the label being too short. | |
90 // The appToolTip stores the tooltip set by the application. Control.tooltiptext | |
91 // contains whatever tooltip is currently being displayed. | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
92 private String appToolTipText; |
155 | 93 |
94 private Image backgroundImage; | |
95 private Color[] gradientColors; | |
96 private int[] gradientPercents; | |
97 private bool gradientVertical; | |
98 private Color background; | |
99 | |
100 private static int DRAW_FLAGS = DWT.DRAW_MNEMONIC | DWT.DRAW_TAB | DWT.DRAW_TRANSPARENT | DWT.DRAW_DELIMITER; | |
101 | |
102 /** | |
103 * Constructs a new instance of this class given its parent | |
104 * and a style value describing its behavior and appearance. | |
105 * <p> | |
106 * The style value is either one of the style constants defined in | |
107 * class <code>DWT</code> which is applicable to instances of this | |
108 * class, or must be built by <em>bitwise OR</em>'ing together | |
109 * (that is, using the <code>int</code> "|" operator) two or more | |
110 * of those <code>DWT</code> style constants. The class description | |
111 * lists the style constants that are applicable to the class. | |
112 * Style bits are also inherited from superclasses. | |
113 * </p> | |
114 * | |
115 * @param parent a widget which will be the parent of the new instance (cannot be null) | |
116 * @param style the style of widget to construct | |
117 * | |
118 * @exception IllegalArgumentException <ul> | |
119 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
120 * </ul> | |
121 * @exception DWTException <ul> | |
122 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
123 * </ul> | |
124 * | |
125 * @see DWT#LEFT | |
126 * @see DWT#RIGHT | |
127 * @see DWT#CENTER | |
128 * @see DWT#SHADOW_IN | |
129 * @see DWT#SHADOW_OUT | |
130 * @see DWT#SHADOW_NONE | |
131 * @see #getStyle() | |
132 */ | |
133 public this(Composite parent, int style) { | |
134 super(parent, checkStyle(style)); | |
135 if ((style & (DWT.CENTER | DWT.RIGHT)) is 0) style |= DWT.LEFT; | |
136 if ((style & DWT.CENTER) !is 0) align_ = DWT.CENTER; | |
137 if ((style & DWT.RIGHT) !is 0) align_ = DWT.RIGHT; | |
138 if ((style & DWT.LEFT) !is 0) align_ = DWT.LEFT; | |
139 | |
140 addPaintListener(new class() PaintListener{ | |
141 public void paintControl(PaintEvent event) { | |
142 onPaint(event); | |
143 } | |
144 }); | |
145 | |
146 addDisposeListener(new class() DisposeListener{ | |
147 public void widgetDisposed(DisposeEvent event) { | |
148 onDispose(event); | |
149 } | |
150 }); | |
151 | |
152 addTraverseListener(new class() TraverseListener { | |
153 public void keyTraversed(TraverseEvent event) { | |
154 if (event.detail is DWT.TRAVERSE_MNEMONIC) { | |
155 onMnemonic(event); | |
156 } | |
157 } | |
158 }); | |
159 | |
160 initAccessible(); | |
161 | |
162 } | |
163 /** | |
164 * Check the style bits to ensure that no invalid styles are applied. | |
165 */ | |
166 private static int checkStyle (int style) { | |
167 if ((style & DWT.BORDER) !is 0) style |= DWT.SHADOW_IN; | |
168 int mask = DWT.SHADOW_IN | DWT.SHADOW_OUT | DWT.SHADOW_NONE | DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT; | |
169 style = style & mask; | |
170 return style |= DWT.NO_FOCUS | DWT.DOUBLE_BUFFERED; | |
171 } | |
172 | |
173 //protected void checkSubclass () { | |
174 // String name = getClass().getName (); | |
175 // String validName = CLabel.class.getName(); | |
176 // if (!validName.equals(name)) { | |
177 // DWT.error (DWT.ERROR_INVALID_SUBCLASS); | |
178 // } | |
179 //} | |
180 | |
181 public override Point computeSize(int wHint, int hHint, bool changed) { | |
182 checkWidget(); | |
183 Point e = getTotalSize(image, text); | |
184 if (wHint is DWT.DEFAULT){ | |
185 e.x += 2*hIndent; | |
186 } else { | |
187 e.x = wHint; | |
188 } | |
189 if (hHint is DWT.DEFAULT) { | |
190 e.y += 2*vIndent; | |
191 } else { | |
192 e.y = hHint; | |
193 } | |
194 return e; | |
195 } | |
196 /** | |
197 * Draw a rectangle in the given colors. | |
198 */ | |
199 private void drawBevelRect(GC gc, int x, int y, int w, int h, Color topleft, Color bottomright) { | |
200 gc.setForeground(bottomright); | |
201 gc.drawLine(x+w, y, x+w, y+h); | |
202 gc.drawLine(x, y+h, x+w, y+h); | |
203 | |
204 gc.setForeground(topleft); | |
205 gc.drawLine(x, y, x+w-1, y); | |
206 gc.drawLine(x, y, x, y+h-1); | |
207 } | |
208 /* | |
209 * Return the lowercase of the first non-'&' character following | |
210 * an '&' character in the given string. If there are no '&' | |
211 * characters in the given string, return '\0'. | |
212 */ | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
213 dchar _findMnemonic (String string) { |
155 | 214 if (string is null) return '\0'; |
215 int index = 0; | |
216 int length = string.length; | |
217 do { | |
218 while (index < length && string[index] !is '&') index++; | |
219 if (++index >= length) return '\0'; | |
220 if (string[index] !is '&') { | |
221 dchar[1] tmp; uint ate; | |
222 dchar[] tmp2 = tango.text.convert.Utf.toString32( string[index .. Math.min( index + 4, string.length ) ], tmp, &ate ); | |
223 assert( tmp2.length == 1 ); | |
224 return tango.text.Unicode.toLower( tmp2 )[0]; | |
225 } | |
226 index++; | |
227 } while (index < length); | |
228 return '\0'; | |
229 } | |
230 /** | |
231 * Returns the alignment. | |
232 * The alignment style (LEFT, CENTER or RIGHT) is returned. | |
233 * | |
234 * @return DWT.LEFT, DWT.RIGHT or DWT.CENTER | |
235 */ | |
236 public int getAlignment() { | |
237 //checkWidget(); | |
238 return align_; | |
239 } | |
240 /** | |
241 * Return the CLabel's image or <code>null</code>. | |
242 * | |
243 * @return the image of the label or null | |
244 */ | |
245 public Image getImage() { | |
246 //checkWidget(); | |
247 return image; | |
248 } | |
249 /** | |
250 * Compute the minimum size. | |
251 */ | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
252 private Point getTotalSize(Image image, String text) { |
155 | 253 Point size = new Point(0, 0); |
254 | |
255 if (image !is null) { | |
256 Rectangle r = image.getBounds(); | |
257 size.x += r.width; | |
258 size.y += r.height; | |
259 } | |
260 | |
261 GC gc = new GC(this); | |
262 if (text !is null && text.length > 0) { | |
263 Point e = gc.textExtent(text, DRAW_FLAGS); | |
264 size.x += e.x; | |
265 size.y = Math.max(size.y, e.y); | |
266 if (image !is null) size.x += GAP; | |
267 } else { | |
268 size.y = Math.max(size.y, gc.getFontMetrics().getHeight()); | |
269 } | |
270 gc.dispose(); | |
271 | |
272 return size; | |
273 } | |
274 public override int getStyle () { | |
275 int style = super.getStyle(); | |
276 switch (align_) { | |
277 case DWT.RIGHT: style |= DWT.RIGHT; break; | |
278 case DWT.CENTER: style |= DWT.CENTER; break; | |
279 case DWT.LEFT: style |= DWT.LEFT; break; | |
280 default: | |
281 } | |
282 return style; | |
283 } | |
284 | |
285 /** | |
286 * Return the Label's text. | |
287 * | |
288 * @return the text of the label or null | |
289 */ | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
290 public String getText() { |
155 | 291 //checkWidget(); |
292 return text; | |
293 } | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
294 public override String getToolTipText () { |
155 | 295 checkWidget(); |
296 return appToolTipText; | |
297 } | |
298 private void initAccessible() { | |
299 Accessible accessible = getAccessible(); | |
300 accessible.addAccessibleListener(new class() AccessibleAdapter { | |
301 public void getName(AccessibleEvent e) { | |
302 e.result = getText(); | |
303 } | |
304 | |
305 public void getHelp(AccessibleEvent e) { | |
306 e.result = getToolTipText(); | |
307 } | |
308 | |
309 public void getKeyboardShortcut(AccessibleEvent e) { | |
310 dchar mnemonic = _findMnemonic(this.outer.text); | |
311 if (mnemonic !is '\0') { | |
312 dchar[1] d; | |
313 d[0] = mnemonic; | |
314 e.result = "Alt+" ~ tango.text.convert.Utf.toString(d); //$NON-NLS-1$ | |
315 } | |
316 } | |
317 }); | |
318 | |
319 accessible.addAccessibleControlListener(new class() AccessibleControlAdapter { | |
320 public void getChildAtPoint(AccessibleControlEvent e) { | |
321 e.childID = ACC.CHILDID_SELF; | |
322 } | |
323 | |
324 public void getLocation(AccessibleControlEvent e) { | |
325 Rectangle rect = getDisplay().map(getParent(), null, getBounds()); | |
326 e.x = rect.x; | |
327 e.y = rect.y; | |
328 e.width = rect.width; | |
329 e.height = rect.height; | |
330 } | |
331 | |
332 public void getChildCount(AccessibleControlEvent e) { | |
333 e.detail = 0; | |
334 } | |
335 | |
336 public void getRole(AccessibleControlEvent e) { | |
337 e.detail = ACC.ROLE_LABEL; | |
338 } | |
339 | |
340 public void getState(AccessibleControlEvent e) { | |
341 e.detail = ACC.STATE_READONLY; | |
342 } | |
343 }); | |
344 } | |
345 void onDispose(DisposeEvent event) { | |
346 gradientColors = null; | |
347 gradientPercents = null; | |
348 backgroundImage = null; | |
349 text = null; | |
350 image = null; | |
351 appToolTipText = null; | |
352 } | |
353 void onMnemonic(TraverseEvent event) { | |
354 dchar mnemonic = _findMnemonic(text); | |
355 if (mnemonic is '\0') return; | |
356 dchar[1] d; uint ate; | |
357 auto r = tango.text.convert.Utf.toString32( [event.character][], d, &ate ); | |
358 if (tango.text.Unicode.toLower(r)[0] !is mnemonic) return; | |
359 Composite control = this.getParent(); | |
360 while (control !is null) { | |
361 Control [] children = control.getChildren(); | |
362 int index = 0; | |
363 while (index < children.length) { | |
364 if (children [index] is this) break; | |
365 index++; | |
366 } | |
367 index++; | |
368 if (index < children.length) { | |
369 if (children [index].setFocus ()) { | |
370 event.doit = true; | |
371 event.detail = DWT.TRAVERSE_NONE; | |
372 } | |
373 } | |
374 control = control.getParent(); | |
375 } | |
376 } | |
377 | |
378 void onPaint(PaintEvent event) { | |
379 Rectangle rect = getClientArea(); | |
380 if (rect.width is 0 || rect.height is 0) return; | |
381 | |
382 bool shortenText_ = false; | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
383 String t = text; |
155 | 384 Image img = image; |
385 int availableWidth = Math.max(0, rect.width - 2*hIndent); | |
386 Point extent = getTotalSize(img, t); | |
387 if (extent.x > availableWidth) { | |
388 img = null; | |
389 extent = getTotalSize(img, t); | |
390 if (extent.x > availableWidth) { | |
391 shortenText_ = true; | |
392 } | |
393 } | |
394 | |
395 GC gc = event.gc; | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
396 String[] lines = text is null ? null : splitString(text); |
155 | 397 |
398 // shorten the text | |
399 if (shortenText_) { | |
400 extent.x = 0; | |
401 for(int i = 0; i < lines.length; i++) { | |
402 Point e = gc.textExtent(lines[i], DRAW_FLAGS); | |
403 if (e.x > availableWidth) { | |
404 lines[i] = shortenText(gc, lines[i], availableWidth); | |
405 extent.x = Math.max(extent.x, getTotalSize(null, lines[i]).x); | |
406 } else { | |
407 extent.x = Math.max(extent.x, e.x); | |
408 } | |
409 } | |
410 if (appToolTipText is null) { | |
411 super.setToolTipText(text); | |
412 } | |
413 } else { | |
414 super.setToolTipText(appToolTipText); | |
415 } | |
416 | |
417 // determine horizontal position | |
418 int x = rect.x + hIndent; | |
419 if (align_ is DWT.CENTER) { | |
420 x = (rect.width - extent.x)/2; | |
421 } | |
422 if (align_ is DWT.RIGHT) { | |
423 x = rect.width - hIndent - extent.x; | |
424 } | |
425 | |
426 // draw a background image behind the text | |
427 try { | |
428 if (backgroundImage !is null) { | |
429 // draw a background image behind the text | |
430 Rectangle imageRect = backgroundImage.getBounds(); | |
431 // tile image to fill space | |
432 gc.setBackground(getBackground()); | |
433 gc.fillRectangle(rect); | |
434 int xPos = 0; | |
435 while (xPos < rect.width) { | |
436 int yPos = 0; | |
437 while (yPos < rect.height) { | |
438 gc.drawImage(backgroundImage, xPos, yPos); | |
439 yPos += imageRect.height; | |
440 } | |
441 xPos += imageRect.width; | |
442 } | |
443 } else if (gradientColors !is null) { | |
444 // draw a gradient behind the text | |
445 final Color oldBackground = gc.getBackground(); | |
446 if (gradientColors.length is 1) { | |
447 if (gradientColors[0] !is null) gc.setBackground(gradientColors[0]); | |
448 gc.fillRectangle(0, 0, rect.width, rect.height); | |
449 } else { | |
450 final Color oldForeground = gc.getForeground(); | |
451 Color lastColor = gradientColors[0]; | |
452 if (lastColor is null) lastColor = oldBackground; | |
453 int pos = 0; | |
454 for (int i = 0; i < gradientPercents.length; ++i) { | |
455 gc.setForeground(lastColor); | |
456 lastColor = gradientColors[i + 1]; | |
457 if (lastColor is null) lastColor = oldBackground; | |
458 gc.setBackground(lastColor); | |
459 if (gradientVertical) { | |
460 final int gradientHeight = (gradientPercents[i] * rect.height / 100) - pos; | |
461 gc.fillGradientRectangle(0, pos, rect.width, gradientHeight, true); | |
462 pos += gradientHeight; | |
463 } else { | |
464 final int gradientWidth = (gradientPercents[i] * rect.width / 100) - pos; | |
465 gc.fillGradientRectangle(pos, 0, gradientWidth, rect.height, false); | |
466 pos += gradientWidth; | |
467 } | |
468 } | |
469 if (gradientVertical && pos < rect.height) { | |
470 gc.setBackground(getBackground()); | |
471 gc.fillRectangle(0, pos, rect.width, rect.height - pos); | |
472 } | |
473 if (!gradientVertical && pos < rect.width) { | |
474 gc.setBackground(getBackground()); | |
475 gc.fillRectangle(pos, 0, rect.width - pos, rect.height); | |
476 } | |
477 gc.setForeground(oldForeground); | |
478 } | |
479 gc.setBackground(oldBackground); | |
480 } else { | |
481 if (background !is null || (getStyle() & DWT.DOUBLE_BUFFERED) is 0) { | |
482 gc.setBackground(getBackground()); | |
483 gc.fillRectangle(rect); | |
484 } | |
485 } | |
486 } catch (DWTException e) { | |
487 if ((getStyle() & DWT.DOUBLE_BUFFERED) is 0) { | |
488 gc.setBackground(getBackground()); | |
489 gc.fillRectangle(rect); | |
490 } | |
491 } | |
492 | |
493 // draw border | |
494 int style = getStyle(); | |
495 if ((style & DWT.SHADOW_IN) !is 0 || (style & DWT.SHADOW_OUT) !is 0) { | |
496 paintBorder(gc, rect); | |
497 } | |
498 | |
499 // draw the image | |
500 if (img !is null) { | |
501 Rectangle imageRect = img.getBounds(); | |
502 gc.drawImage(img, 0, 0, imageRect.width, imageRect.height, | |
503 x, (rect.height-imageRect.height)/2, imageRect.width, imageRect.height); | |
504 x += imageRect.width + GAP; | |
505 extent.x -= imageRect.width + GAP; | |
506 } | |
507 // draw the text | |
508 if (lines !is null) { | |
509 int lineHeight = gc.getFontMetrics().getHeight(); | |
510 int textHeight = lines.length * lineHeight; | |
511 int lineY = Math.max(vIndent, rect.y + (rect.height - textHeight) / 2); | |
512 gc.setForeground(getForeground()); | |
513 for (int i = 0; i < lines.length; i++) { | |
514 int lineX = x; | |
515 if (lines.length > 1) { | |
516 if (align_ is DWT.CENTER) { | |
517 int lineWidth = gc.textExtent(lines[i], DRAW_FLAGS).x; | |
518 lineX = x + Math.max(0, (extent.x - lineWidth) / 2); | |
519 } | |
520 if (align_ is DWT.RIGHT) { | |
521 int lineWidth = gc.textExtent(lines[i], DRAW_FLAGS).x; | |
522 lineX = Math.max(x, rect.x + rect.width - hIndent - lineWidth); | |
523 } | |
524 } | |
525 gc.drawText(lines[i], lineX, lineY, DRAW_FLAGS); | |
526 lineY += lineHeight; | |
527 } | |
528 } | |
529 } | |
530 /** | |
531 * Paint the Label's border. | |
532 */ | |
533 private void paintBorder(GC gc, Rectangle r) { | |
534 Display disp= getDisplay(); | |
535 | |
536 Color c1 = null; | |
537 Color c2 = null; | |
538 | |
539 int style = getStyle(); | |
540 if ((style & DWT.SHADOW_IN) !is 0) { | |
541 c1 = disp.getSystemColor(DWT.COLOR_WIDGET_NORMAL_SHADOW); | |
542 c2 = disp.getSystemColor(DWT.COLOR_WIDGET_HIGHLIGHT_SHADOW); | |
543 } | |
544 if ((style & DWT.SHADOW_OUT) !is 0) { | |
545 c1 = disp.getSystemColor(DWT.COLOR_WIDGET_LIGHT_SHADOW); | |
546 c2 = disp.getSystemColor(DWT.COLOR_WIDGET_NORMAL_SHADOW); | |
547 } | |
548 | |
549 if (c1 !is null && c2 !is null) { | |
550 gc.setLineWidth(1); | |
551 drawBevelRect(gc, r.x, r.y, r.width-1, r.height-1, c1, c2); | |
552 } | |
553 } | |
554 /** | |
555 * Set the alignment of the CLabel. | |
556 * Use the values LEFT, CENTER and RIGHT to align image and text within the available space. | |
557 * | |
558 * @param align the alignment style of LEFT, RIGHT or CENTER | |
559 * | |
560 * @exception DWTException <ul> | |
561 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
562 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
563 * <li>ERROR_INVALID_ARGUMENT - if the value of align is not one of DWT.LEFT, DWT.RIGHT or DWT.CENTER</li> | |
564 * </ul> | |
565 */ | |
566 public void setAlignment(int align_) { | |
567 checkWidget(); | |
568 if (align_ !is DWT.LEFT && align_ !is DWT.RIGHT && align_ !is DWT.CENTER) { | |
569 DWT.error(DWT.ERROR_INVALID_ARGUMENT); | |
570 } | |
571 if (this.align_ !is align_) { | |
572 this.align_ = align_; | |
573 redraw(); | |
574 } | |
575 } | |
576 | |
577 public override void setBackground (Color color) { | |
578 super.setBackground (color); | |
579 // Are these settings the same as before? | |
580 if (backgroundImage is null && | |
581 gradientColors is null && | |
582 gradientPercents is null) { | |
583 if (color is null) { | |
584 if (background is null) return; | |
585 } else { | |
586 if (color ==/*eq*/ background) return; | |
587 } | |
588 } | |
589 background = color; | |
590 backgroundImage = null; | |
591 gradientColors = null; | |
592 gradientPercents = null; | |
593 redraw (); | |
594 } | |
595 | |
596 /** | |
597 * Specify a gradient of colours to be drawn in the background of the CLabel. | |
598 * <p>For example, to draw a gradient that varies from dark blue to blue and then to | |
599 * white and stays white for the right half of the label, use the following call | |
600 * to setBackground:</p> | |
601 * <pre> | |
602 * clabel.setBackground(new Color[]{display.getSystemColor(DWT.COLOR_DARK_BLUE), | |
603 * display.getSystemColor(DWT.COLOR_BLUE), | |
604 * display.getSystemColor(DWT.COLOR_WHITE), | |
605 * display.getSystemColor(DWT.COLOR_WHITE)}, | |
606 * new int[] {25, 50, 100}); | |
607 * </pre> | |
608 * | |
609 * @param colors an array of Color that specifies the colors to appear in the gradient | |
610 * in order of appearance from left to right; The value <code>null</code> | |
611 * clears the background gradient; the value <code>null</code> can be used | |
612 * inside the array of Color to specify the background color. | |
613 * @param percents an array of integers between 0 and 100 specifying the percent of the width | |
614 * of the widget at which the color should change; the size of the percents | |
615 * array must be one less than the size of the colors array. | |
616 * | |
617 * @exception DWTException <ul> | |
618 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
619 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
620 * <li>ERROR_INVALID_ARGUMENT - if the values of colors and percents are not consistent</li> | |
621 * </ul> | |
622 */ | |
623 public void setBackground(Color[] colors, int[] percents) { | |
624 setBackground(colors, percents, false); | |
625 } | |
626 /** | |
627 * Specify a gradient of colours to be drawn in the background of the CLabel. | |
628 * <p>For example, to draw a gradient that varies from dark blue to white in the vertical, | |
629 * direction use the following call | |
630 * to setBackground:</p> | |
631 * <pre> | |
632 * clabel.setBackground(new Color[]{display.getSystemColor(DWT.COLOR_DARK_BLUE), | |
633 * display.getSystemColor(DWT.COLOR_WHITE)}, | |
634 * new int[] {100}, true); | |
635 * </pre> | |
636 * | |
637 * @param colors an array of Color that specifies the colors to appear in the gradient | |
638 * in order of appearance from left/top to right/bottom; The value <code>null</code> | |
639 * clears the background gradient; the value <code>null</code> can be used | |
640 * inside the array of Color to specify the background color. | |
641 * @param percents an array of integers between 0 and 100 specifying the percent of the width/height | |
642 * of the widget at which the color should change; the size of the percents | |
643 * array must be one less than the size of the colors array. | |
644 * @param vertical indicate the direction of the gradient. True is vertical and false is horizontal. | |
645 * | |
646 * @exception DWTException <ul> | |
647 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
648 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
649 * <li>ERROR_INVALID_ARGUMENT - if the values of colors and percents are not consistent</li> | |
650 * </ul> | |
651 * | |
652 * @since 3.0 | |
653 */ | |
654 public void setBackground(Color[] colors, int[] percents, bool vertical) { | |
655 checkWidget(); | |
656 if (colors !is null) { | |
657 if (percents is null || percents.length !is colors.length - 1) { | |
658 DWT.error(DWT.ERROR_INVALID_ARGUMENT); | |
659 } | |
660 if (getDisplay().getDepth() < 15) { | |
661 // Don't use gradients on low color displays | |
662 colors = [colors[colors.length - 1]]; | |
663 percents = null; | |
664 } | |
665 for (int i = 0; i < percents.length; i++) { | |
666 if (percents[i] < 0 || percents[i] > 100) { | |
667 DWT.error(DWT.ERROR_INVALID_ARGUMENT); | |
668 } | |
669 if (i > 0 && percents[i] < percents[i-1]) { | |
670 DWT.error(DWT.ERROR_INVALID_ARGUMENT); | |
671 } | |
672 } | |
673 } | |
674 | |
675 // Are these settings the same as before? | |
676 final Color background = getBackground(); | |
677 if (backgroundImage is null) { | |
678 if ((gradientColors !is null) && (colors !is null) && | |
679 (gradientColors.length is colors.length)) { | |
680 bool same = false; | |
681 for (int i = 0; i < gradientColors.length; i++) { | |
682 same = (gradientColors[i] is colors[i]) || | |
683 ((gradientColors[i] is null) && (colors[i] is background)) || | |
684 ((gradientColors[i] is background) && (colors[i] is null)); | |
685 if (!same) break; | |
686 } | |
687 if (same) { | |
688 for (int i = 0; i < gradientPercents.length; i++) { | |
689 same = gradientPercents[i] is percents[i]; | |
690 if (!same) break; | |
691 } | |
692 } | |
693 if (same && this.gradientVertical is vertical) return; | |
694 } | |
695 } else { | |
696 backgroundImage = null; | |
697 } | |
698 // Store the new settings | |
699 if (colors is null) { | |
700 gradientColors = null; | |
701 gradientPercents = null; | |
702 gradientVertical = false; | |
703 } else { | |
704 gradientColors = new Color[colors.length]; | |
705 for (int i = 0; i < colors.length; ++i) | |
706 gradientColors[i] = (colors[i] !is null) ? colors[i] : background; | |
707 gradientPercents = new int[percents.length]; | |
708 for (int i = 0; i < percents.length; ++i) | |
709 gradientPercents[i] = percents[i]; | |
710 gradientVertical = vertical; | |
711 } | |
712 // Refresh with the new settings | |
713 redraw(); | |
714 } | |
715 /** | |
716 * Set the image to be drawn in the background of the label. | |
717 * | |
718 * @param image the image to be drawn in the background | |
719 * | |
720 * @exception DWTException <ul> | |
721 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
722 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
723 * </ul> | |
724 */ | |
725 public void setBackground(Image image) { | |
726 checkWidget(); | |
727 if (image is backgroundImage) return; | |
728 if (image !is null) { | |
729 gradientColors = null; | |
730 gradientPercents = null; | |
731 } | |
732 backgroundImage = image; | |
733 redraw(); | |
734 | |
735 } | |
736 public override void setFont(Font font) { | |
737 super.setFont(font); | |
738 redraw(); | |
739 } | |
740 /** | |
741 * Set the label's Image. | |
742 * The value <code>null</code> clears it. | |
743 * | |
744 * @param image the image to be displayed in the label or null | |
745 * | |
746 * @exception DWTException <ul> | |
747 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
748 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
749 * </ul> | |
750 */ | |
751 public void setImage(Image image) { | |
752 checkWidget(); | |
753 if (image !is this.image) { | |
754 this.image = image; | |
755 redraw(); | |
756 } | |
757 } | |
758 /** | |
759 * Set the label's text. | |
760 * The value <code>null</code> clears it. | |
761 * | |
762 * @param text the text to be displayed in the label or null | |
763 * | |
764 * @exception DWTException <ul> | |
765 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
766 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
767 * </ul> | |
768 */ | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
769 public void setText(String text) { |
155 | 770 checkWidget(); |
771 if (text is null) text = ""; //$NON-NLS-1$ | |
772 if ( text !=/*eq*/ this.text) { | |
773 this.text = text; | |
774 redraw(); | |
775 } | |
776 } | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
777 public override void setToolTipText (String string) { |
155 | 778 super.setToolTipText (string); |
779 appToolTipText = super.getToolTipText(); | |
780 } | |
781 /** | |
782 * Shorten the given text <code>t</code> so that its length doesn't exceed | |
783 * the given width. The default implementation replaces characters in the | |
784 * center of the original string with an ellipsis ("..."). | |
785 * Override if you need a different strategy. | |
786 * | |
787 * @param gc the gc to use for text measurement | |
788 * @param t the text to shorten | |
789 * @param width the width to shorten the text to, in pixels | |
790 * @return the shortened text | |
791 */ | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
792 protected String shortenText(GC gc, String t, int width) { |
155 | 793 if (t is null) return null; |
794 int w = gc.textExtent(ELLIPSIS, DRAW_FLAGS).x; | |
795 if (width<=w) return t; | |
796 int l = t.length; | |
797 int max = l/2; | |
798 int min = 0; | |
799 int mid = (max+min)/2 - 1; | |
800 if (mid <= 0) return t; | |
213 | 801 TextLayout layout = new TextLayout (getDisplay()); |
802 layout.setText(t); | |
803 mid = validateOffset(layout, mid); | |
155 | 804 while (min < mid && mid < max) { |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
805 String s1 = t[0 .. mid].dup; |
213 | 806 String s2 = t.substring(validateOffset(layout, l-mid), l); |
155 | 807 int l1 = gc.textExtent(s1, DRAW_FLAGS).x; |
808 int l2 = gc.textExtent(s2, DRAW_FLAGS).x; | |
809 if (l1+w+l2 > width) { | |
810 max = mid; | |
213 | 811 mid = validateOffset(layout, (max+min)/2); |
155 | 812 } else if (l1+w+l2 < width) { |
813 min = mid; | |
213 | 814 mid = validateOffset(layout, (max+min)/2); |
155 | 815 } else { |
816 min = max; | |
817 } | |
818 } | |
213 | 819 String result = mid is 0 ? t : t.substring(0, mid) ~ ELLIPSIS ~ t.substring(validateOffset(layout, l-mid), l); |
820 layout.dispose(); | |
821 return result; | |
155 | 822 } |
213 | 823 int validateOffset(TextLayout layout, int offset) { |
824 int nextOffset = layout.getNextOffset(offset, DWT.MOVEMENT_CLUSTER); | |
825 if (nextOffset !is offset) return layout.getPreviousOffset(nextOffset, DWT.MOVEMENT_CLUSTER); | |
826 return offset; | |
827 } | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
828 private String[] splitString(String text) { |
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
829 String[] lines = new String[1]; |
155 | 830 int start = 0, pos; |
831 do { | |
832 pos = tango.text.Util.locate( text, '\n', start); | |
833 if (pos is text.length ) { | |
834 lines[lines.length - 1] = text[start .. $ ]; | |
835 } else { | |
836 bool crlf = (pos > 0) && (text[ pos - 1 ] is '\r'); | |
837 lines[lines.length - 1] = text[ start .. pos - (crlf ? 1 : 0)]; | |
838 start = pos + 1; | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
155
diff
changeset
|
839 String[] newLines = new String[lines.length+1]; |
155 | 840 System.arraycopy(lines, 0, newLines, 0, lines.length); |
841 lines = newLines; | |
842 } | |
843 } while (pos !is text.length); | |
844 return lines; | |
845 } | |
846 } |