1 /*******************************************************************************
2 * Copyright (c) 2000, 2019 IBM Corporation and others.
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/
9 * SPDX-License-Identifier: EPL-2.0
12 * IBM Corporation - initial API and implementation
13 *******************************************************************************/
14 package org.eclipse.swt.widgets;
17 import org.eclipse.swt.*;
18 import org.eclipse.swt.graphics.*;
19 import org.eclipse.swt.internal.*;
20 import org.eclipse.swt.internal.win32.*;
23 * Instances of this class provide an i-beam that is typically used
24 * as the insertion point for text.
26 * <dt><b>Styles:</b></dt>
28 * <dt><b>Events:</b></dt>
32 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
35 * @see <a href="http://www.eclipse.org/swt/snippets/#caret">Caret snippets</a>
36 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Canvas tab</a>
37 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
38 * @noextend This class is not intended to be subclassed by clients.
40 public class Caret extends Widget {
42 int x, y, width, height;
43 boolean moved, resized;
50 * Constructs a new instance of this class given its parent
51 * and a style value describing its behavior and appearance.
53 * The style value is either one of the style constants defined in
54 * class <code>SWT</code> which is applicable to instances of this
55 * class, or must be built by <em>bitwise OR</em>'ing together
56 * (that is, using the <code>int</code> "|" operator) two or more
57 * of those <code>SWT</code> style constants. The class description
58 * lists the style constants that are applicable to the class.
59 * Style bits are also inherited from superclasses.
62 * @param parent a composite control which will be the parent of the new instance (cannot be null)
63 * @param style the style of control to construct
65 * @exception IllegalArgumentException <ul>
66 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
68 * @exception SWTException <ul>
69 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
70 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
74 * @see Widget#checkSubclass
75 * @see Widget#getStyle
77 public Caret (Canvas parent, int style) {
78 super (parent, style);
83 void createWidget () {
85 if (parent.getCaret () == null) {
86 parent.setCaret (this);
91 long hwnd = parent.handle;
92 long hwndIME = OS.ImmGetDefaultIMEWnd (hwnd);
95 hFont = OS.SendMessage (hwndIME, OS.WM_GETFONT, 0, 0);
98 hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
100 if (hFont == 0) return parent.defaultFont ();
105 * Returns a rectangle describing the receiver's size and location
106 * relative to its parent (or its display if its parent is null).
108 * @return the receiver's bounding rectangle
110 * @exception SWTException <ul>
111 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
112 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
115 public Rectangle getBounds () {
117 return DPIUtil.autoScaleDown(getBoundsInPixels());
120 Rectangle getBoundsInPixels () {
122 Rectangle rect = image.getBoundsInPixels ();
123 return new Rectangle (x, y, rect.width, rect.height);
126 int [] buffer = new int [1];
127 if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, buffer, 0)) {
128 return new Rectangle (x, y, buffer [0], height);
131 return new Rectangle (x, y, width, height);
135 * Returns the font that the receiver will use to paint textual information.
137 * @return the receiver's font
139 * @exception SWTException <ul>
140 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
141 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
144 public Font getFont () {
147 long hFont = defaultFont ();
148 return Font.win32_new (display, hFont);
154 * Returns the image that the receiver will use to paint the caret.
156 * @return the receiver's image
158 * @exception SWTException <ul>
159 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
160 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
163 public Image getImage () {
169 * Returns a point describing the receiver's location relative
170 * to its parent (or its display if its parent is null).
172 * @return the receiver's location
174 * @exception SWTException <ul>
175 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
176 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
179 public Point getLocation () {
181 return DPIUtil.autoScaleDown(getLocationInPixels());
184 Point getLocationInPixels () {
185 return new Point (x, y);
189 * Returns the receiver's parent, which must be a <code>Canvas</code>.
191 * @return the receiver's parent
193 * @exception SWTException <ul>
194 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
195 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
198 public Canvas getParent () {
204 * Returns a point describing the receiver's size.
206 * @return the receiver's size
208 * @exception SWTException <ul>
209 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
210 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
213 public Point getSize () {
215 return DPIUtil.autoScaleDown(getSizeInPixels());
218 Point getSizeInPixels () {
220 Rectangle rect = image.getBoundsInPixels ();
221 return new Point (rect.width, rect.height);
224 int [] buffer = new int [1];
225 if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, buffer, 0)) {
226 return new Point (buffer [0], height);
229 return new Point (width, height);
233 * Returns <code>true</code> if the receiver is visible, and
234 * <code>false</code> otherwise.
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.
242 * @return the receiver's visibility state
244 * @exception SWTException <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>
249 public boolean getVisible () {
254 boolean hasFocus () {
255 return parent.handle == OS.GetFocus ();
258 boolean isFocusCaret () {
259 return parent.caret == this && hasFocus ();
263 * Returns <code>true</code> if the receiver is visible and all
264 * of the receiver's ancestors are visible and <code>false</code>
267 * @return the receiver's visibility state
269 * @exception SWTException <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>
276 public boolean isVisible () {
278 return isVisible && parent.isVisible () && hasFocus ();
288 if (!OS.SetCaretPos (x, y)) return;
293 if (!OS.IsDBLocale) return;
294 POINT ptCurrentPos = new POINT ();
295 if (!OS.GetCaretPos (ptCurrentPos)) return;
296 long hwnd = parent.handle;
297 long hIMC = OS.ImmGetContext (hwnd);
298 IME ime = parent.getIME ();
299 if (ime != null && ime.isInlineEnabled ()) {
300 Point size = getSizeInPixels ();
301 CANDIDATEFORM lpCandidate = new CANDIDATEFORM ();
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);
308 RECT rect = new RECT ();
309 OS.GetClientRect (hwnd, rect);
310 COMPOSITIONFORM lpCompForm = new COMPOSITIONFORM ();
311 lpCompForm.dwStyle = OS.CFS_RECT;
312 lpCompForm.x = ptCurrentPos.x;
313 lpCompForm.y = ptCurrentPos.y;
314 lpCompForm.left = rect.left;
315 lpCompForm.right = rect.right;
316 lpCompForm.top = rect.top;
317 lpCompForm.bottom = rect.bottom;
318 OS.ImmSetCompositionWindow (hIMC, lpCompForm);
320 OS.ImmReleaseContext (hwnd, hIMC);
324 void releaseParent () {
325 super.releaseParent ();
326 if (parent != null && this == parent.caret) {
327 if (!parent.isDisposed()) parent.setCaret (null);
328 else parent.caret = null;
333 void releaseWidget () {
334 super.releaseWidget ();
343 long hwnd = parent.handle;
345 long hBitmap = image != null ? image.handle : 0;
346 int width = this.width;
347 if (image == null && width == 0) {
348 int [] buffer = new int [1];
349 if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, buffer, 0)) {
353 OS.CreateCaret (hwnd, hBitmap, width, height);
354 OS.SetCaretPos (x, y);
359 void restoreIMEFont () {
360 if (!OS.IsDBLocale) return;
361 if (oldFont == null) return;
362 long hwnd = parent.handle;
363 long hIMC = OS.ImmGetContext (hwnd);
364 OS.ImmSetCompositionFont (hIMC, oldFont);
365 OS.ImmReleaseContext (hwnd, hIMC);
370 * Sets the receiver's size and location to the rectangular
371 * area specified by the arguments. The <code>x</code> and
372 * <code>y</code> arguments are relative to the receiver's
373 * parent (or its display if its parent is null).
375 * @param x the new x coordinate for the receiver
376 * @param y the new y coordinate for the receiver
377 * @param width the new width for the receiver
378 * @param height the new height for the receiver
380 * @exception SWTException <ul>
381 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
382 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
385 public void setBounds (int x, int y, int width, int height) {
387 setBoundsInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y), DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
390 void setBoundsInPixels (int x, int y, int width, int height) {
391 boolean samePosition = this.x == x && this.y == y;
392 boolean sameExtent = this.width == width && this.height == height;
393 if (samePosition && sameExtent) return;
397 this.height = height;
400 if (isVisible && hasFocus ()) move ();
403 if (isVisible && hasFocus ()) resize ();
408 * Sets the receiver's size and location to the rectangular
409 * area specified by the argument. The <code>x</code> and
410 * <code>y</code> fields of the rectangle are relative to
411 * the receiver's parent (or its display if its parent is null).
413 * @param rect the new bounds for the receiver
415 * @exception SWTException <ul>
416 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
417 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
420 public void setBounds (Rectangle rect) {
421 if (rect == null) error (SWT.ERROR_NULL_ARGUMENT);
422 setBoundsInPixels(DPIUtil.autoScaleUp(rect));
425 void setBoundsInPixels (Rectangle rect) {
426 setBoundsInPixels (rect.x, rect.y, rect.width, rect.height);
430 long hwnd = parent.handle;
432 if (image != null) hBitmap = image.handle;
433 int width = this.width;
434 if (image == null && width == 0) {
435 int [] buffer = new int [1];
436 if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, buffer, 0)) {
440 OS.CreateCaret (hwnd, hBitmap, width, height);
443 if (isVisible) OS.ShowCaret (hwnd);
447 * Sets the font that the receiver will use to paint textual information
448 * to the font specified by the argument, or to the default font for that
449 * kind of control if the argument is null.
451 * @param font the new font (or null)
453 * @exception IllegalArgumentException <ul>
454 * <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</li>
456 * @exception SWTException <ul>
457 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
458 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
461 public void setFont (Font font) {
463 if (font != null && font.isDisposed ()) {
464 error (SWT.ERROR_INVALID_ARGUMENT);
467 if (hasFocus ()) setIMEFont ();
471 * Sets the image that the receiver will use to paint the caret
472 * to the image specified by the argument, or to the default
473 * which is a filled rectangle if the argument is null
475 * @param image the new image (or null)
477 * @exception IllegalArgumentException <ul>
478 * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
480 * @exception SWTException <ul>
481 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
482 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
485 public void setImage (Image image) {
487 if (image != null && image.isDisposed ()) {
488 error (SWT.ERROR_INVALID_ARGUMENT);
491 if (isVisible && hasFocus ()) resize ();
495 if (!OS.IsDBLocale) return;
497 if (font != null) hFont = font.handle;
498 if (hFont == 0) hFont = defaultFont ();
499 long hwnd = parent.handle;
500 long hIMC = OS.ImmGetContext (hwnd);
501 /* Save the current IME font */
502 if (oldFont == null) {
503 oldFont = new LOGFONT ();
504 if (!OS.ImmGetCompositionFont (hIMC, oldFont)) oldFont = null;
506 /* Set new IME font */
507 LOGFONT logFont = new LOGFONT ();
508 if (OS.GetObject (hFont, LOGFONT.sizeof, logFont) != 0) {
509 OS.ImmSetCompositionFont (hIMC, logFont);
511 OS.ImmReleaseContext (hwnd, hIMC);
515 * Sets the receiver's location to the point specified by
516 * the arguments which are relative to the receiver's
517 * parent (or its display if its parent is null).
519 * @param x the new x coordinate for the receiver
520 * @param y the new y coordinate for the receiver
522 * @exception SWTException <ul>
523 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
524 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
527 public void setLocation (int x, int y) {
529 setLocationInPixels(DPIUtil.autoScaleUp(x), DPIUtil.autoScaleUp(y));
532 void setLocationInPixels (int x, int y) {
533 if (this.x == x && this.y == y) return;
534 this.x = x; this.y = y;
536 if (isVisible && hasFocus ()) move ();
540 * Sets the receiver's location to the point specified by
541 * the argument which is relative to the receiver's
542 * parent (or its display if its parent is null).
544 * @param location the new location for the receiver
546 * @exception SWTException <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>
551 public void setLocation (Point location) {
553 if (location == null) error (SWT.ERROR_NULL_ARGUMENT);
554 location = DPIUtil.autoScaleUp(location);
555 setLocationInPixels(location.x, location.y);
559 * Sets the receiver's size to the point specified by the arguments.
561 * @param width the new width for the receiver
562 * @param height the new height for the receiver
564 * @exception SWTException <ul>
565 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
566 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
569 public void setSize (int width, int height) {
571 setSizeInPixels(DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
574 void setSizeInPixels (int width, int height) {
575 if (this.width == width && this.height == height) return;
576 this.width = width; this.height = height;
578 if (isVisible && hasFocus ()) resize ();
582 * Sets the receiver's size to the point specified by the argument.
584 * @param size the new extent for the receiver
586 * @exception IllegalArgumentException <ul>
587 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
589 * @exception SWTException <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>
594 public void setSize (Point size) {
596 if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
597 size = DPIUtil.autoScaleUp(size);
598 setSizeInPixels(size.x, size.y);
602 * Marks the receiver as visible if the argument is <code>true</code>,
603 * and marks it invisible otherwise.
605 * If one of the receiver's ancestors is not visible or some
606 * other condition makes the receiver not visible, marking
607 * it visible may not actually cause it to be displayed.
610 * @param visible the new visibility state
612 * @exception SWTException <ul>
613 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
614 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
617 public void setVisible (boolean visible) {
619 if (visible == isVisible) return;
621 long hwnd = parent.handle;
622 if (OS.GetFocus () != hwnd) return;