]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Label.java
e15b7da731e36e1a283dfe92373f71a14311ebe9
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / widgets / Label.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2019 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *     Paul Pazderski - Bug 205199: setImage(null) on Label overrides text
14  *******************************************************************************/
15 package org.eclipse.swt.widgets;
16
17
18 import org.eclipse.swt.*;
19 import org.eclipse.swt.graphics.*;
20 import org.eclipse.swt.internal.*;
21 import org.eclipse.swt.internal.win32.*;
22
23 /**
24  * Instances of this class represent a non-selectable
25  * user interface object that displays a string or image.
26  * When SEPARATOR is specified, displays a single
27  * vertical or horizontal line.
28  * <p>
29  * Shadow styles are hints and may not be honored
30  * by the platform.  To create a separator label
31  * with the default shadow style for the platform,
32  * do not specify a shadow style.
33  * </p>
34  * <dl>
35  * <dt><b>Styles:</b></dt>
36  * <dd>SEPARATOR, HORIZONTAL, VERTICAL</dd>
37  * <dd>SHADOW_IN, SHADOW_OUT, SHADOW_NONE</dd>
38  * <dd>CENTER, LEFT, RIGHT, WRAP</dd>
39  * <dt><b>Events:</b></dt>
40  * <dd>(none)</dd>
41  * </dl>
42  * <p>
43  * Note: Only one of SHADOW_IN, SHADOW_OUT and SHADOW_NONE may be specified.
44  * SHADOW_NONE is a HINT. Only one of HORIZONTAL and VERTICAL may be specified.
45  * Only one of CENTER, LEFT and RIGHT may be specified.
46  * </p><p>
47  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
48  * </p>
49  *
50  * @see <a href="http://www.eclipse.org/swt/snippets/#label">Label snippets</a>
51  * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
52  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
53  * @noextend This class is not intended to be subclassed by clients.
54  */
55 public class Label extends Control {
56         String text = "";
57         Image image;
58         static final int MARGIN = 4;
59         static /*final*/ boolean IMAGE_AND_TEXT = false;
60         static final long LabelProc;
61         static final TCHAR LabelClass = new TCHAR (0, "STATIC", true);
62         static {
63                 WNDCLASS lpWndClass = new WNDCLASS ();
64                 OS.GetClassInfo (0, LabelClass, lpWndClass);
65                 LabelProc = lpWndClass.lpfnWndProc;
66         }
67
68 /**
69  * Constructs a new instance of this class given its parent
70  * and a style value describing its behavior and appearance.
71  * <p>
72  * The style value is either one of the style constants defined in
73  * class <code>SWT</code> which is applicable to instances of this
74  * class, or must be built by <em>bitwise OR</em>'ing together
75  * (that is, using the <code>int</code> "|" operator) two or more
76  * of those <code>SWT</code> style constants. The class description
77  * lists the style constants that are applicable to the class.
78  * Style bits are also inherited from superclasses.
79  * </p>
80  *
81  * @param parent a composite control which will be the parent of the new instance (cannot be null)
82  * @param style the style of control to construct
83  *
84  * @exception IllegalArgumentException <ul>
85  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
86  * </ul>
87  * @exception SWTException <ul>
88  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
89  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
90  * </ul>
91  *
92  * @see SWT#SEPARATOR
93  * @see SWT#HORIZONTAL
94  * @see SWT#VERTICAL
95  * @see SWT#SHADOW_IN
96  * @see SWT#SHADOW_OUT
97  * @see SWT#SHADOW_NONE
98  * @see SWT#CENTER
99  * @see SWT#LEFT
100  * @see SWT#RIGHT
101  * @see SWT#WRAP
102  * @see Widget#checkSubclass
103  * @see Widget#getStyle
104  */
105 public Label (Composite parent, int style) {
106         super (parent, checkStyle (style));
107 }
108
109 @Override
110 long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
111         if (handle == 0) return 0;
112         /*
113         * Feature in Windows 7.  When the user double clicks
114         * on the label, the text of the label is copied to the
115         * clipboard.  This is unwanted. The fix is to avoid
116         * calling the label window proc.
117         */
118         if (OS.WIN32_VERSION >= OS.VERSION(6, 1)) {
119                 switch (msg) {
120                         case OS.WM_LBUTTONDBLCLK: return OS.DefWindowProc (hwnd, msg, wParam, lParam);
121                 }
122         }
123         return OS.CallWindowProc (LabelProc, hwnd, msg, wParam, lParam);
124 }
125
126 static int checkStyle (int style) {
127         style |= SWT.NO_FOCUS;
128         if ((style & SWT.SEPARATOR) != 0) {
129                 style = checkBits (style, SWT.VERTICAL, SWT.HORIZONTAL, 0, 0, 0, 0);
130                 return checkBits (style, SWT.SHADOW_OUT, SWT.SHADOW_IN, SWT.SHADOW_NONE, 0, 0, 0);
131         }
132         return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
133 }
134
135 @Override Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
136         checkWidget ();
137         int width = 0, height = 0, border = getBorderWidthInPixels ();
138         if ((style & SWT.SEPARATOR) != 0) {
139                 int lineWidth = OS.GetSystemMetrics (OS.SM_CXBORDER);
140                 if ((style & SWT.HORIZONTAL) != 0) {
141                         width = DEFAULT_WIDTH;  height = lineWidth * 2;
142                 } else {
143                         width = lineWidth * 2; height = DEFAULT_HEIGHT;
144                 }
145                 if (wHint != SWT.DEFAULT) width = wHint;
146                 if (hHint != SWT.DEFAULT) height = hHint;
147                 width += border * 2; height += border * 2;
148                 return new Point (width, height);
149         }
150         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
151         boolean drawText = true;
152         boolean drawImage = (bits & OS.SS_OWNERDRAW) == OS.SS_OWNERDRAW;
153         if (drawImage) {
154                 if (image != null) {
155                         Rectangle rect = image.getBoundsInPixels();
156                         width += rect.width;
157                         height += rect.height;
158                         if (IMAGE_AND_TEXT) {
159                                 if (text.length () != 0) width += MARGIN;
160                         } else {
161                                 drawText = false;
162                         }
163                 }
164         }
165         if (drawText) {
166                 long hDC = OS.GetDC (handle);
167                 long newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
168                 long oldFont = OS.SelectObject (hDC, newFont);
169                 int length = OS.GetWindowTextLength (handle);
170                 if (length == 0) {
171                         TEXTMETRIC tm = new TEXTMETRIC ();
172                         OS.GetTextMetrics (hDC, tm);
173                         height = Math.max (height, tm.tmHeight);
174                 } else {
175                         RECT rect = new RECT ();
176                         int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_EXPANDTABS;
177                         if ((style & SWT.WRAP) != 0 && wHint != SWT.DEFAULT) {
178                                 flags |= OS.DT_WORDBREAK;
179                                 rect.right = Math.max (0, wHint - width);
180                         }
181                         char [] buffer = new char [length + 1];
182                         OS.GetWindowText (handle, buffer, length + 1);
183                         OS.DrawText (hDC, buffer, length, rect, flags);
184                         width += rect.right - rect.left;
185                         height = Math.max (height, rect.bottom - rect.top);
186                 }
187                 if (newFont != 0) OS.SelectObject (hDC, oldFont);
188                 OS.ReleaseDC (handle, hDC);
189         }
190         if (wHint != SWT.DEFAULT) width = wHint;
191         if (hHint != SWT.DEFAULT) height = hHint;
192         width += border * 2;
193         height += border * 2;
194         return new Point (width, height);
195 }
196
197 @Override
198 void createHandle () {
199         super.createHandle ();
200         state |= THEME_BACKGROUND;
201 }
202
203 /**
204  * Returns a value which describes the position of the
205  * text or image in the receiver. The value will be one of
206  * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>
207  * unless the receiver is a <code>SEPARATOR</code> label, in
208  * which case, <code>NONE</code> is returned.
209  *
210  * @return the alignment
211  *
212  * @exception SWTException <ul>
213  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
214  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
215  * </ul>
216  */
217 public int getAlignment () {
218         checkWidget ();
219         if ((style & SWT.SEPARATOR) != 0) return 0;
220         if ((style & SWT.LEFT) != 0) return SWT.LEFT;
221         if ((style & SWT.CENTER) != 0) return SWT.CENTER;
222         if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
223         return SWT.LEFT;
224 }
225
226 /**
227  * Returns the receiver's image if it has one, or null
228  * if it does not.
229  *
230  * @return the receiver's image
231  *
232  * @exception SWTException <ul>
233  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
234  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
235  * </ul>
236  */
237 public Image getImage () {
238         checkWidget ();
239         return image;
240 }
241
242 @Override
243 String getNameText () {
244         return getText ();
245 }
246
247 /**
248  * Returns the receiver's text, which will be an empty
249  * string if it has never been set or if the receiver is
250  * a <code>SEPARATOR</code> label.
251  *
252  * @return the receiver's text
253  *
254  * @exception SWTException <ul>
255  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
256  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
257  * </ul>
258  */
259 public String getText () {
260         checkWidget ();
261         if ((style & SWT.SEPARATOR) != 0) return "";
262         return text;
263 }
264
265 @Override
266 boolean mnemonicHit (char key) {
267         Control control = this;
268         while (control.parent != null) {
269                 Control [] children = control.parent._getChildren ();
270                 int index = 0;
271                 while (index < children.length) {
272                         if (children [index] == control) break;
273                         index++;
274                 }
275                 index++;
276                 if (index < children.length) {
277                         if (children [index].setFocus ()) return true;
278                 }
279                 control = control.parent;
280         }
281         return false;
282 }
283
284 @Override
285 boolean mnemonicMatch (char key) {
286         char mnemonic = findMnemonic (getText ());
287         if (mnemonic == '\0') return false;
288         return Character.toUpperCase (key) == Character.toUpperCase (mnemonic);
289 }
290
291 @Override
292 void releaseWidget () {
293         super.releaseWidget ();
294         text = null;
295         image = null;
296 }
297
298 @Override
299 int resolveTextDirection() {
300         return (style & SWT.SEPARATOR) != 0 ? SWT.NONE : BidiUtil.resolveTextDirection (text);
301 }
302
303 /**
304  * Controls how text and images will be displayed in the receiver.
305  * The argument should be one of <code>LEFT</code>, <code>RIGHT</code>
306  * or <code>CENTER</code>.  If the receiver is a <code>SEPARATOR</code>
307  * label, the argument is ignored and the alignment is not changed.
308  *
309  * @param alignment the new alignment
310  *
311  * @exception SWTException <ul>
312  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
313  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
314  * </ul>
315  */
316 public void setAlignment (int alignment) {
317         checkWidget ();
318         if ((style & SWT.SEPARATOR) != 0) return;
319         if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return;
320         style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
321         style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
322         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
323         if ((bits & OS.SS_OWNERDRAW) != OS.SS_OWNERDRAW) {
324                 bits &= ~(OS.SS_LEFTNOWORDWRAP | OS.SS_CENTER | OS.SS_RIGHT);
325                 if ((style & SWT.LEFT) != 0) {
326                         if ((style & SWT.WRAP) != 0) {
327                                 bits |= OS.SS_LEFT;
328                         } else {
329                                 bits |= OS.SS_LEFTNOWORDWRAP;
330                         }
331                 }
332                 if ((style & SWT.CENTER) != 0) bits |= OS.SS_CENTER;
333                 if ((style & SWT.RIGHT) != 0) bits |= OS.SS_RIGHT;
334                 OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
335         }
336         OS.InvalidateRect (handle, null, true);
337 }
338
339 /**
340  * Sets the receiver's image to the argument, which may be
341  * null indicating that no image should be displayed.
342  *
343  * @param image the image to display on the receiver (may be null)
344  *
345  * @exception IllegalArgumentException <ul>
346  *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
347  * </ul>
348  * @exception SWTException <ul>
349  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
350  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
351  * </ul>
352  */
353 public void setImage (Image image) {
354         checkWidget ();
355         if ((style & SWT.SEPARATOR) != 0) return;
356         if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
357         this.image = image;
358         updateStyleBits(image == null);
359         OS.InvalidateRect (handle, null, true);
360 }
361
362 /**
363  * Sets the receiver's text.
364  * <p>
365  * This method sets the widget label.  The label may include
366  * the mnemonic character and line delimiters.
367  * </p>
368  * <p>
369  * Mnemonics are indicated by an '&amp;' that causes the next
370  * character to be the mnemonic.  When the user presses a
371  * key sequence that matches the mnemonic, focus is assigned
372  * to the control that follows the label. On most platforms,
373  * the mnemonic appears underlined but may be emphasised in a
374  * platform specific manner.  The mnemonic indicator character
375  * '&amp;' can be escaped by doubling it in the string, causing
376  * a single '&amp;' to be displayed.
377  * </p>
378  * <p>
379  * Note: If control characters like '\n', '\t' etc. are used
380  * in the string, then the behavior is platform dependent.
381  * </p>
382  *
383  * @param string the new text
384  *
385  * @exception IllegalArgumentException <ul>
386  *    <li>ERROR_NULL_ARGUMENT - if the text is null</li>
387  * </ul>
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  * </ul>
392  */
393 public void setText (String string) {
394         checkWidget ();
395         if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
396         if ((style & SWT.SEPARATOR) != 0) return;
397         updateStyleBits(true);
398         /*
399         * Feature in Windows.  For some reason, SetWindowText() for
400         * static controls redraws the control, even when the text has
401         * has not changed.  The fix is to check for this case and do
402         * nothing.
403         */
404         if (string.equals (text)) return;
405         text = string;
406         string = Display.withCrLf (string);
407         TCHAR buffer = new TCHAR (getCodePage (), string, true);
408         OS.SetWindowText (handle, buffer);
409         if ((state & HAS_AUTO_DIRECTION) != 0) {
410                 updateTextDirection (AUTO_TEXT_DIRECTION);
411         }
412 }
413
414 /**
415  * Update the control's static style bits to reflect the changed image vs. text
416  * situation.
417  *
418  * @param showText if <code>true</code> set required style bits to render text
419  *                 otherwise to render the image
420  */
421 void updateStyleBits(boolean showText) {
422         if (showText) {
423                 int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE), newBits = oldBits;
424                 newBits &= ~OS.SS_OWNERDRAW;
425                 if ((style & SWT.LEFT) != 0) {
426                         if ((style & SWT.WRAP) != 0) {
427                                 newBits |= OS.SS_LEFT;
428                         } else {
429                                 newBits |= OS.SS_LEFTNOWORDWRAP;
430                         }
431                 }
432                 if ((style & SWT.CENTER) != 0) newBits |= OS.SS_CENTER;
433                 if ((style & SWT.RIGHT) != 0) newBits |= OS.SS_RIGHT;
434                 if (oldBits != newBits) OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
435         } else {
436                 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
437                 if ((bits & OS.SS_OWNERDRAW) != OS.SS_OWNERDRAW) {
438                         bits &= ~(OS.SS_LEFTNOWORDWRAP | OS.SS_CENTER | OS.SS_RIGHT);
439                         bits |= OS.SS_OWNERDRAW;
440                         OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
441                 }
442         }
443 }
444
445 @Override
446 int widgetExtStyle () {
447         int bits = super.widgetExtStyle () & ~OS.WS_EX_CLIENTEDGE;
448         if ((style & SWT.BORDER) != 0) return bits | OS.WS_EX_STATICEDGE;
449         return bits;
450 }
451
452 @Override
453 int widgetStyle () {
454         int bits = super.widgetStyle () | OS.SS_NOTIFY;
455         if ((style & SWT.SEPARATOR) != 0) return bits | OS.SS_OWNERDRAW;
456         if ((style & SWT.WRAP) != 0) bits |= OS.SS_EDITCONTROL;
457         if ((style & SWT.CENTER) != 0) return bits | OS.SS_CENTER;
458         if ((style & SWT.RIGHT) != 0) return bits | OS.SS_RIGHT;
459         if ((style & SWT.WRAP) != 0) return bits | OS.SS_LEFT;
460         return bits | OS.SS_LEFTNOWORDWRAP;
461 }
462
463 @Override
464 TCHAR windowClass () {
465         return LabelClass;
466 }
467
468 @Override
469 long windowProc () {
470         return LabelProc;
471 }
472
473 @Override
474 LRESULT WM_ERASEBKGND (long wParam, long lParam) {
475         LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
476         if (result != null) return result;
477         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
478         if ((bits & OS.SS_OWNERDRAW) == OS.SS_OWNERDRAW) {
479                 return LRESULT.ONE;
480         }
481         return result;
482 }
483
484 @Override
485 LRESULT WM_SIZE (long wParam, long lParam) {
486         LRESULT result = super.WM_SIZE (wParam, lParam);
487         if (isDisposed ()) return result;
488         if ((style & SWT.SEPARATOR) != 0) {
489                 OS.InvalidateRect (handle, null, true);
490                 return result;
491         }
492         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
493         if ((bits & OS.SS_OWNERDRAW) == OS.SS_OWNERDRAW) {
494                 OS.InvalidateRect (handle, null, true);
495                 return result;
496         }
497         /*
498         * Bug in Windows.  For some reason, a label with
499         * style SS_LEFT, SS_CENTER or SS_RIGHT does not
500         * redraw the text in the new position when resized.
501         * Note that SS_LEFTNOWORDWRAP does not have the
502         * problem.  The fix is to force the redraw.
503         */
504         if ((bits & OS.SS_LEFTNOWORDWRAP) != OS.SS_LEFTNOWORDWRAP) {
505                 OS.InvalidateRect (handle, null, true);
506                 return result;
507         }
508         return result;
509 }
510
511 @Override
512 LRESULT WM_UPDATEUISTATE (long wParam, long lParam) {
513         LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam);
514         if (result != null) return result;
515         /*
516         * Feature in Windows.  When WM_UPDATEUISTATE is sent to
517         * a static control, it sends WM_CTLCOLORSTATIC to get the
518         * foreground and background.  If any drawing happens in
519         * WM_CTLCOLORSTATIC, it overwrites the contents of the control.
520         * The fix is draw the static without drawing the background
521         * and avoid the static window proc.
522         */
523         boolean redraw = findImageControl () != null;
524         if (!redraw) {
525                 if ((state & THEME_BACKGROUND) != 0) {
526                         if (OS.IsAppThemed ()) {
527                                 redraw = findThemeControl () != null;
528                         }
529                 }
530         }
531         if (redraw) {
532                 OS.InvalidateRect (handle, null, false);
533                 long code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
534                 return new LRESULT (code);
535         }
536         return result;
537 }
538
539 @Override
540 LRESULT wmDrawChild (long wParam, long lParam) {
541         DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
542         OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof);
543         drawBackground (struct.hDC);
544         if ((style & SWT.SEPARATOR) != 0) {
545                 if ((style & SWT.SHADOW_NONE) != 0) return null;
546                 RECT rect = new RECT ();
547                 int lineWidth = OS.GetSystemMetrics (OS.SM_CXBORDER);
548                 int flags = (style & SWT.SHADOW_IN) != 0 ? OS.EDGE_SUNKEN : OS.EDGE_ETCHED;
549                 if ((style & SWT.HORIZONTAL) != 0) {
550                         int bottom = struct.top + Math.max (lineWidth * 2, (struct.bottom - struct.top) / 2);
551                         OS.SetRect (rect, struct.left, struct.top, struct.right, bottom);
552                         OS.DrawEdge (struct.hDC, rect, flags, OS.BF_BOTTOM);
553                 } else {
554                         int right = struct.left + Math.max (lineWidth * 2, (struct.right - struct.left) / 2);
555                         OS.SetRect (rect, struct.left, struct.top, right, struct.bottom);
556                         OS.DrawEdge (struct.hDC, rect, flags, OS.BF_RIGHT);
557                 }
558         } else {
559                 int width = struct.right - struct.left;
560                 int height = struct.bottom - struct.top;
561                 if (width != 0 && height != 0) {
562                         boolean drawImage = image != null;
563                         boolean drawText = IMAGE_AND_TEXT && text.length () != 0;
564                         int margin = drawText && drawImage ? MARGIN : 0;
565                         int imageWidth = 0, imageHeight = 0;
566                         if (drawImage) {
567                                 Rectangle rect = image.getBoundsInPixels ();
568                                 imageWidth = rect.width;
569                                 imageHeight = rect.height;
570                         }
571                         RECT rect = null;
572                         char [] buffer = null;
573                         int textWidth = 0, textHeight = 0, flags = 0;
574                         if (drawText) {
575                                 rect = new RECT ();
576                                 flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_EXPANDTABS;
577                                 if ((style & SWT.LEFT) != 0) flags |= OS.DT_LEFT;
578                                 if ((style & SWT.CENTER) != 0) flags |= OS.DT_CENTER;
579                                 if ((style & SWT.RIGHT) != 0) flags |= OS.DT_RIGHT;
580                                 if ((style & SWT.WRAP) != 0) {
581                                         flags |= OS.DT_WORDBREAK;
582                                         rect.right = Math.max (0, width - imageWidth - margin);
583                                 }
584                                 buffer = text.toCharArray ();
585                                 OS.DrawText (struct.hDC, buffer, buffer.length, rect, flags);
586                                 textWidth = rect.right - rect.left;
587                                 textHeight = rect.bottom - rect.top;
588                         }
589                         int x = 0;
590                         if ((style & SWT.CENTER) != 0) {
591                                 x = Math.max (0, (width - imageWidth - textWidth - margin) / 2);
592                         } else {
593                                 if ((style & SWT.RIGHT) != 0) {
594                                         x = width - imageWidth - textWidth - margin;
595                                 }
596                         }
597                         if (drawImage) {
598                                 GCData data = new GCData();
599                                 data.device = display;
600                                 GC gc = GC.win32_new (struct.hDC, data);
601                                 Image image = getEnabled () ? this.image : new Image (display, this.image, SWT.IMAGE_DISABLE);
602                                 gc.drawImage (image, DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(Math.max (0, (height - imageHeight) / 2)));
603                                 if (image != this.image) image.dispose ();
604                                 gc.dispose ();
605                                 x += imageWidth + margin;
606                         }
607                         if (drawText) {
608                                 flags &= ~OS.DT_CALCRECT;
609                                 rect.left = x;
610                                 rect.right += rect.left;
611                                 rect.top = Math.max (0, (height - textHeight) / 2);
612                                 rect.bottom += rect.top;
613                                 OS.DrawText (struct.hDC, buffer, buffer.length, rect, flags);
614                         }
615                 }
616         }
617         return null;
618 }
619
620 }