root/dwt/widgets/Caret.d

Revision 246:fd9c62a2998e, 18.3 kB (checked in by Frank Benoit <benoit@tionex.de>, 5 months ago)

Updater SWT 3.4M7 to 3.4

Line 
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 dwt.widgets.Caret;
14
15
16
17 import dwt.DWT;
18 import dwt.DWTException;
19 import dwt.graphics.Font;
20 import dwt.graphics.Image;
21 import dwt.graphics.Point;
22 import dwt.graphics.Rectangle;
23 import dwt.internal.win32.OS;
24
25 import dwt.widgets.Widget;
26 import dwt.widgets.Canvas;
27 import dwt.widgets.IME;
28
29 import dwt.dwthelper.utils;
30
31 /**
32  * Instances of this class provide an i-beam that is typically used
33  * as the insertion point for text.
34  * <dl>
35  * <dt><b>Styles:</b></dt>
36  * <dd>(none)</dd>
37  * <dt><b>Events:</b></dt>
38  * <dd>(none)</dd>
39  * </dl>
40  * <p>
41  * IMPORTANT: This class is intended to be subclassed <em>only</em>
42  * within the DWT implementation.
43  * </p>
44  *
45  * @see <a href="http://www.eclipse.org/swt/snippets/#caret">Caret snippets</a>
46  * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: ControlExample, Canvas tab</a>
47  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
48  */
49
50 public class Caret : Widget {
51     Canvas parent;
52     int x, y, width, height;
53     bool moved, resized;
54     bool isVisible_;
55     Image image;
56     Font font;
57     LOGFONT* oldFont;
58
59 /**
60  * Constructs a new instance of this class given its parent
61  * and a style value describing its behavior and appearance.
62  * <p>
63  * The style value is either one of the style constants defined in
64  * class <code>DWT</code> which is applicable to instances of this
65  * class, or must be built by <em>bitwise OR</em>'ing together
66  * (that is, using the <code>int</code> "|" operator) two or more
67  * of those <code>DWT</code> style constants. The class description
68  * lists the style constants that are applicable to the class.
69  * Style bits are also inherited from superclasses.
70  * </p>
71  *
72  * @param parent a composite control which will be the parent of the new instance (cannot be null)
73  * @param style the style of control to construct
74  *
75  * @exception IllegalArgumentException <ul>
76  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
77  * </ul>
78  * @exception DWTException <ul>
79  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
80  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
81  * </ul>
82  *
83  * @see DWT
84  * @see Widget#checkSubclass
85  * @see Widget#getStyle
86  */
87 public this (Canvas parent, int style) {
88     super (parent, style);
89     this.parent = parent;
90     createWidget ();
91 }
92
93 void createWidget () {
94     isVisible_ = true;
95     if (parent.getCaret () is null) {
96         parent.setCaret (this);
97     }
98 }
99
100 HFONT defaultFont () {
101     auto hwnd = parent.handle;
102     auto hwndIME = OS.ImmGetDefaultIMEWnd (hwnd);
103     HFONT hFont;
104     if (hwndIME !is null) {
105         hFont = cast(HFONT) OS.SendMessage (hwndIME, OS.WM_GETFONT, 0, 0);
106     }
107     if (hFont is null) {
108         hFont = cast(HFONT) OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
109     }
110     if (hFont is null) return parent.defaultFont ();
111     return hFont;
112 }
113
114 /**
115  * Returns a rectangle describing the receiver's size and location
116  * relative to its parent (or its display if its parent is null).
117  *
118  * @return the receiver's bounding rectangle
119  *
120  * @exception DWTException <ul>
121  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
122  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
123  * </ul>
124  */
125 public Rectangle getBounds () {
126     checkWidget();
127     if (image !is null) {
128         Rectangle rect = image.getBounds ();
129         return new Rectangle (x, y, rect.width, rect.height);
130     } else {
131         if (!OS.IsWinCE && width is 0) {
132             int buffer;
133             if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) {
134                 return new Rectangle (x, y, buffer, height);
135             }
136         }
137     }
138     return new Rectangle (x, y, width, height);
139 }
140
141 /**
142  * Returns the font that the receiver will use to paint textual information.
143  *
144  * @return the receiver's font
145  *
146  * @exception DWTException <ul>
147  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
148  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
149  * </ul>
150  */
151 public Font getFont () {
152     checkWidget();
153     if (font is null) {
154         HFONT hFont = defaultFont ();
155         return Font.win32_new (display, hFont);
156     }
157     return font;
158 }
159
160 /**
161  * Returns the image that the receiver will use to paint the caret.
162  *
163  * @return the receiver's image
164  *
165  * @exception DWTException <ul>
166  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
167  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
168  * </ul>
169  */
170 public Image getImage () {
171     checkWidget();
172     return image;
173 }
174
175 /**
176  * Returns a point describing the receiver's location relative
177  * to its parent (or its display if its parent is null).
178  *
179  * @return the receiver's location
180  *
181  * @exception DWTException <ul>
182  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
183  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
184  * </ul>
185  */
186 public Point getLocation () {
187     checkWidget();
188     return new Point (x, y);
189 }
190
191 /**
192  * Returns the receiver's parent, which must be a <code>Canvas</code>.
193  *
194  * @return the receiver's parent
195  *
196  * @exception DWTException <ul>
197  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
198  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
199  * </ul>
200  */
201 public Canvas getParent () {
202     checkWidget();
203     return parent;
204 }
205
206 /**
207  * Returns a point describing the receiver's size.
208  *
209  * @return the receiver's size
210  *
211  * @exception DWTException <ul>
212  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
213  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
214  * </ul>
215  */
216 public Point getSize () {
217     checkWidget();
218     if (image !is null) {
219         Rectangle rect = image.getBounds ();
220         return new Point (rect.width, rect.height);
221     } else {
222         if (!OS.IsWinCE && width is 0) {
223             int buffer;
224             if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) {
225                 return new Point (buffer, height);
226             }
227         }
228     }
229     return new Point (width, height);
230 }
231
232 /**
233  * Returns <code>true</code> if the receiver is visible, and
234  * <code>false</code> otherwise.
235  * <p>
236  * If one of the receiver's ancestors is not visible or some
237  * other condition makes the receiver not visible, this method
238  * may still indicate that it is considered visible even though
239  * it may not actually be showing.
240  * </p>
241  *
242  * @return the receiver's visibility state
243  *
244  * @exception DWTException <ul>
245  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
246  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
247  * </ul>
248  */
249 public bool getVisible () {
250     checkWidget();
251     return isVisible_;
252 }
253
254 bool hasFocus () {
255     return parent.handle is OS.GetFocus ();
256 }
257
258 bool isFocusCaret () {
259     return parent.caret is this && hasFocus ();
260 }
261
262 /**
263  * Returns <code>true</code> if the receiver is visible and all
264  * of the receiver's ancestors are visible and <code>false</code>
265  * otherwise.
266  *
267  * @return the receiver's visibility state
268  *
269  * @exception DWTException <ul>
270  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
271  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
272  * </ul>
273  *
274  * @see #getVisible
275  */
276 public bool isVisible () {
277     checkWidget();
278     return isVisible_ && parent.isVisible () && hasFocus ();
279 }
280
281 void killFocus () {
282     OS.DestroyCaret ();
283     restoreIMEFont ();
284 }
285
286 void move () {
287     moved = false;
288     if (!OS.SetCaretPos (x, y)) return;
289     resizeIME ();
290 }
291
292 void resizeIME () {
293     if (!OS.IsDBLocale) return;
294     POINT ptCurrentPos;
295     if (!OS.GetCaretPos (&ptCurrentPos)) return;
296     auto hwnd = parent.handle;
297     auto hIMC = OS.ImmGetContext (hwnd);
298     IME ime = parent.getIME ();
299     if (ime !is null && ime.isInlineEnabled ()) {
300         Point size = getSize ();
301         CANDIDATEFORM lpCandidate;
302         lpCandidate.dwStyle = OS.CFS_EXCLUDE;
303         lpCandidate.ptCurrentPos = ptCurrentPos;
304         //lpCandidate.rcArea = new RECT ();
305         OS.SetRect (&lpCandidate.rcArea, ptCurrentPos.x, ptCurrentPos.y, ptCurrentPos.x + size.x, ptCurrentPos.y + size.y);
306         OS.ImmSetCandidateWindow (hIMC, &lpCandidate);
307     } else {
308         RECT rect;
309         OS.GetClientRect (hwnd, &rect);
310         COMPOSITIONFORM lpCompForm;
311         lpCompForm.dwStyle = OS.CFS_RECT;
312         lpCompForm.ptCurrentPos.x = ptCurrentPos.x;
313         lpCompForm.ptCurrentPos.y = ptCurrentPos.y;
314         lpCompForm.rcArea.left = rect.left;
315         lpCompForm.rcArea.right = rect.right;
316         lpCompForm.rcArea.top = rect.top;
317         lpCompForm.rcArea.bottom = rect.bottom;
318         OS.ImmSetCompositionWindow (hIMC, &lpCompForm);
319     }
320     OS.ImmReleaseContext (hwnd, hIMC);
321 }
322
323 override void releaseParent () {
324     super.releaseParent ();
325     if (this is parent.getCaret ()) parent.setCaret (null);
326 }
327
328 override void releaseWidget () {
329     super.releaseWidget ();
330     parent = null;
331     image = null;
332     font = null;
333     oldFont = null;
334 }
335
336 void resize () {
337     resized = false;
338     auto hwnd = parent.handle;
339     OS.DestroyCaret ();
340     auto hBitmap = image !is null ? image.handle : null;
341     int width = this.width;
342     if (!OS.IsWinCE && image is null && width is 0) {
343         int buffer;
344         if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) {
345             width = buffer;
346         }
347     }
348     OS.CreateCaret (hwnd, hBitmap, width, height);
349     OS.SetCaretPos (x, y);
350     OS.ShowCaret (hwnd);
351     move ();
352 }
353
354 void restoreIMEFont () {
355     if (!OS.IsDBLocale) return;
356     if (oldFont is null) return;
357     auto hwnd = parent.handle;
358     auto hIMC = OS.ImmGetContext (hwnd);
359     OS.ImmSetCompositionFont (hIMC, oldFont);
360     OS.ImmReleaseContext (hwnd, hIMC);
361     oldFont = null;
362 }
363
364 /**
365  * Sets the receiver's size and location to the rectangular
366  * area specified by the arguments. The <code>x</code> and
367  * <code>y</code> arguments are relative to the receiver's
368  * parent (or its display if its parent is null).
369  *
370  * @param x the new x coordinate for the receiver
371  * @param y the new y coordinate for the receiver
372  * @param width the new width for the receiver
373  * @param height the new height for the receiver
374  *
375  * @exception DWTException <ul>
376  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
377  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
378  * </ul>
379  */
380 public void setBounds (int x, int y, int width, int height) {
381     checkWidget();
382     bool samePosition = this.x is x && this.y is y;
383     bool sameExtent = this.width is width && this.height is height;
384     if (samePosition && sameExtent) return;
385     this.x = x;
386     this.y = y;
387     this.width = width;
388     this.height = height;
389     if (sameExtent) {
390         moved = true;
391         if (isVisible_ && hasFocus ()) move ();
392     } else {
393         resized = true;
394         if (isVisible_ && hasFocus ()) resize ();
395     }
396 }
397
398 /**
399  * Sets the receiver's size and location to the rectangular
400  * area specified by the argument. The <code>x</code> and
401  * <code>y</code> fields of the rectangle are relative to
402  * the receiver's parent (or its display if its parent is null).
403  *
404  * @param rect the new bounds for the receiver
405  *
406  * @exception DWTException <ul>
407  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
408  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
409  * </ul>
410  */
411 public void setBounds (Rectangle rect) {
412     if (rect is null) error (DWT.ERROR_NULL_ARGUMENT);
413     setBounds (rect.x, rect.y, rect.width, rect.height);
414 }
415
416 void setFocus () {
417     auto hwnd = parent.handle;
418     HBITMAP hBitmap;
419     if (image !is null) hBitmap = image.handle;
420     int width = this.width;
421     if (!OS.IsWinCE && image is null && width is 0) {
422         int buffer;
423         if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) {
424             width = buffer;
425         }
426     }
427     OS.CreateCaret (hwnd, hBitmap, width, height);
428     move ();
429     setIMEFont ();
430     if (isVisible_) OS.ShowCaret (hwnd);
431 }
432
433 /**
434  * Sets the font that the receiver will use to paint textual information
435  * to the font specified by the argument, or to the default font for that
436  * kind of control if the argument is null.
437  *
438  * @param font the new font (or null)
439  *
440  * @exception IllegalArgumentException <ul>
441  *    <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</li>
442  * </ul>
443  * @exception DWTException <ul>
444  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
445  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
446  * </ul>
447  */
448 public void setFont (Font font) {
449     checkWidget();
450     if (font !is null && font.isDisposed ()) {
451         error (DWT.ERROR_INVALID_ARGUMENT);
452     }
453     this.font = font;
454     if (hasFocus ()) setIMEFont ();
455 }
456
457 /**
458  * Sets the image that the receiver will use to paint the caret
459  * to the image specified by the argument, or to the default
460  * which is a filled rectangle if the argument is null
461  *
462  * @param image the new image (or null)
463  *
464  * @exception IllegalArgumentException <ul>
465  *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
466  * </ul>
467  * @exception DWTException <ul>
468  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
469  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
470  * </ul>
471  */
472 public void setImage (Image image) {
473     checkWidget();
474     if (image !is null && image.isDisposed ()) {
475         error (DWT.ERROR_INVALID_ARGUMENT);
476     }
477     this.image = image;
478     if (isVisible_ && hasFocus ()) resize ();
479 }
480
481 void setIMEFont () {
482     if (!OS.IsDBLocale) return;
483     HFONT hFont;
484     if (font !is null) hFont = font.handle;
485     if (hFont is null) hFont = defaultFont ();
486     auto hwnd = parent.handle;
487     auto hIMC = OS.ImmGetContext (hwnd);
488     /* Save the current IME font */
489     if (oldFont is null) {
490         oldFont = new LOGFONT;
491         if (!OS.ImmGetCompositionFont (hIMC, oldFont)) oldFont = null;
492     }
493     /* Set new IME font */
494     LOGFONT logFont;
495     if (OS.GetObject (hFont, LOGFONT.sizeof, &logFont) !is 0) {
496         OS.ImmSetCompositionFont (hIMC, &logFont);
497     }
498     OS.ImmReleaseContext (hwnd, hIMC);
499 }
500
501 /**
502  * Sets the receiver's location to the point specified by
503  * the arguments which are relative to the receiver's
504  * parent (or its display if its parent is null).
505  *
506  * @param x the new x coordinate for the receiver
507  * @param y the new y coordinate for the receiver
508  *
509  * @exception DWTException <ul>
510  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
511  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
512  * </ul>
513  */
514 public void setLocation (int x, int y) {
515     checkWidget();
516     if (this.x is x && this.y is y) return;
517     this.x = x;  this.y = y;
518     moved = true;
519     if (isVisible_ && hasFocus ()) move ();
520 }
521
522 /**
523  * Sets the receiver's location to the point specified by
524  * the argument which is relative to the receiver's
525  * parent (or its display if its parent is null).
526  *
527  * @param location the new location for the receiver
528  *
529  * @exception DWTException <ul>
530  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
531  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
532  * </ul>
533  */
534 public void setLocation (Point location) {
535     checkWidget();
536     if (location is null) error (DWT.ERROR_NULL_ARGUMENT);
537     setLocation (location.x, location.y);
538 }
539
540 /**
541  * Sets the receiver's size to the point specified by the arguments.
542  *
543  * @param width the new width for the receiver
544  * @param height the new height for the receiver
545  *
546  * @exception DWTException <ul>
547  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
548  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
549  * </ul>
550  */
551 public void setSize (int width, int height) {
552     checkWidget();
553     if (this.width is width && this.height is height) return;
554     this.width = width;  this.height = height;
555     resized = true;
556     if (isVisible_ && hasFocus ()) resize ();
557 }
558
559 /**
560  * Sets the receiver's size to the point specified by the argument.
561  *
562  * @param size the new extent for the receiver
563  *
564  * @exception IllegalArgumentException <ul>
565  *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
566  * </ul>
567  * @exception DWTException <ul>
568  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
569  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
570  * </ul>
571  */
572 public void setSize (Point size) {
573     checkWidget();
574     if (size is null) error (DWT.ERROR_NULL_ARGUMENT);
575     setSize (size.x, size.y);
576 }
577
578 /**
579  * Marks the receiver as visible if the argument is <code>true</code>,
580  * and marks it invisible otherwise.
581  * <p>
582  * If one of the receiver's ancestors is not visible or some
583  * other condition makes the receiver not visible, marking
584  * it visible may not actually cause it to be displayed.
585  * </p>
586  *
587  * @param visible the new visibility state
588  *
589  * @exception DWTException <ul>
590  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
591  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
592  * </ul>
593  */
594 public void setVisible (bool visible) {
595     checkWidget();
596     if (visible is isVisible_) return;
597     isVisible_ = visible;
598     auto hwnd = parent.handle;
599     if (OS.GetFocus () !is hwnd) return;
600     if (!isVisible_) {
601         OS.HideCaret (hwnd);
602     } else {
603         if (resized) {
604             resize ();
605         } else {
606             if (moved) move ();
607         }
608         OS.ShowCaret (hwnd);
609     }
610 }
611
612 }
Note: See TracBrowser for help on using the browser.