Source code: org/eclipse/swt/widgets/Caret.java
1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.swt.widgets;
12
13
14 import org.eclipse.swt.*;
15 import org.eclipse.swt.internal.gtk.*;
16 import org.eclipse.swt.graphics.*;
17
18 /**
19 * Instances of this class provide an i-beam that is typically used
20 * as the insertion point for text.
21 * <dl>
22 * <dt><b>Styles:</b></dt>
23 * <dd>(none)</dd>
24 * <dt><b>Events:</b></dt>
25 * <dd>(none)</dd>
26 * </dl>
27 * <p>
28 * IMPORTANT: This class is intended to be subclassed <em>only</em>
29 * within the SWT implementation.
30 * </p>
31 */
32 public class Caret extends Widget {
33 Canvas parent;
34 int x, y, width, height;
35 boolean isVisible, isShowing;
36 int blinkRate = 500;
37 Image image;
38 Font font;
39
40 /**
41 * Constructs a new instance of this class given its parent
42 * and a style value describing its behavior and appearance.
43 * <p>
44 * The style value is either one of the style constants defined in
45 * class <code>SWT</code> which is applicable to instances of this
46 * class, or must be built by <em>bitwise OR</em>'ing together
47 * (that is, using the <code>int</code> "|" operator) two or more
48 * of those <code>SWT</code> style constants. The class description
49 * lists the style constants that are applicable to the class.
50 * Style bits are also inherited from superclasses.
51 * </p>
52 *
53 * @param parent a composite control which will be the parent of the new instance (cannot be null)
54 * @param style the style of control to construct
55 *
56 * @exception IllegalArgumentException <ul>
57 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
58 * </ul>
59 * @exception SWTException <ul>
60 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
61 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
62 * </ul>
63 *
64 * @see SWT
65 * @see Widget#checkSubclass
66 * @see Widget#getStyle
67 */
68 public Caret (Canvas parent, int style) {
69 super (parent, style);
70 this.parent = parent;
71 createWidget (0);
72 }
73
74 boolean blinkCaret () {
75 if (!isVisible) return true;
76 if (!isShowing) return showCaret ();
77 if (blinkRate == 0) return true;
78 return hideCaret ();
79 }
80
81 void createWidget (int index) {
82 super.createWidget (index);
83 isVisible = true;
84 if (parent.getCaret () == null) {
85 parent.setCaret (this);
86 }
87 }
88
89 boolean drawCaret () {
90 if (parent == null) return false;
91 if (parent.isDisposed ()) return false;
92 long /*int*/ window = parent.paintWindow ();
93 long /*int*/ gc = OS.gdk_gc_new (window);
94 GdkColor color = new GdkColor ();
95 color.red = (short) 0xffff;
96 color.green = (short) 0xffff;
97 color.blue = (short) 0xffff;
98 long /*int*/ colormap = OS.gdk_colormap_get_system ();
99 OS.gdk_colormap_alloc_color (colormap, color, true, true);
100 OS.gdk_gc_set_foreground (gc, color);
101 OS.gdk_gc_set_function (gc, OS.GDK_XOR);
102 if (image != null && !image.isDisposed() && image.mask == 0) {
103 int[] width = new int[1]; int[] height = new int[1];
104 OS.gdk_drawable_get_size(image.pixmap, width, height);
105 OS.gdk_draw_drawable(window, gc, image.pixmap, 0, 0, x, y, width[0], height[0]);
106 } else {
107 int nWidth = width, nHeight = height;
108 if (nWidth <= 0) nWidth = 1;
109 OS.gdk_draw_rectangle (window, gc, 1, x, y, nWidth, nHeight);
110 }
111 OS.g_object_unref (gc);
112 OS.gdk_colormap_free_colors (colormap, color, 1);
113 return true;
114 }
115
116 /**
117 * Returns a rectangle describing the receiver's size and location
118 * relative to its parent (or its display if its parent is null).
119 *
120 * @return the receiver's bounding rectangle
121 *
122 * @exception SWTException <ul>
123 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
124 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
125 * </ul>
126 */
127 public Rectangle getBounds () {
128 checkWidget();
129 if (image != null) {
130 Rectangle rect = image.getBounds ();
131 return new Rectangle (x, y, rect.width, rect.height);
132 }
133 return new Rectangle (x, y, width, height);
134 }
135
136 /**
137 * Returns the font that the receiver will use to paint textual information.
138 *
139 * @return the receiver's font
140 *
141 * @exception SWTException <ul>
142 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
143 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
144 * </ul>
145 */
146 public Font getFont () {
147 checkWidget();
148 if (font != null) return font;
149 return parent.getFont ();
150 }
151
152 /**
153 * Returns the image that the receiver will use to paint the caret.
154 *
155 * @return the receiver's image
156 *
157 * @exception SWTException <ul>
158 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
159 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
160 * </ul>
161 */
162 public Image getImage () {
163 checkWidget();
164 return image;
165 }
166
167 /**
168 * Returns a point describing the receiver's location relative
169 * to its parent (or its display if its parent is null).
170 *
171 * @return the receiver's location
172 *
173 * @exception SWTException <ul>
174 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
175 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
176 * </ul>
177 */
178 public Point getLocation () {
179 checkWidget();
180 return new Point (x, y);
181 }
182
183 /**
184 * Returns the receiver's parent, which must be a <code>Canvas</code>.
185 *
186 * @return the receiver's parent
187 *
188 * @exception SWTException <ul>
189 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
190 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
191 * </ul>
192 */
193 public Canvas getParent () {
194 checkWidget();
195 return parent;
196 }
197
198 /**
199 * Returns a point describing the receiver's size.
200 *
201 * @return the receiver's size
202 *
203 * @exception SWTException <ul>
204 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
205 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
206 * </ul>
207 */
208 public Point getSize () {
209 checkWidget();
210 if (image != null) {
211 Rectangle rect = image.getBounds ();
212 return new Point (rect.width, rect.height);
213 }
214 return new Point (width, height);
215 }
216
217 /**
218 * Returns <code>true</code> if the receiver is visible, and
219 * <code>false</code> otherwise.
220 * <p>
221 * If one of the receiver's ancestors is not visible or some
222 * other condition makes the receiver not visible, this method
223 * may still indicate that it is considered visible even though
224 * it may not actually be showing.
225 * </p>
226 *
227 * @return the receiver's visibility state
228 *
229 * @exception SWTException <ul>
230 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
231 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
232 * </ul>
233 */
234 public boolean getVisible () {
235 checkWidget();
236 return isVisible;
237 }
238
239 boolean hideCaret () {
240 if (!isShowing) return true;
241 isShowing = false;
242 return drawCaret ();
243 }
244
245 /**
246 * Returns <code>true</code> if the receiver is visible and all
247 * of the receiver's ancestors are visible and <code>false</code>
248 * otherwise.
249 *
250 * @return the receiver's visibility state
251 *
252 * @exception SWTException <ul>
253 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
254 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
255 * </ul>
256 *
257 * @see #getVisible
258 */
259 public boolean isVisible () {
260 checkWidget();
261 return isVisible && parent.isVisible () && parent.hasFocus ();
262 }
263
264 boolean isFocusCaret () {
265 return this == display.currentCaret;
266 }
267
268 void killFocus () {
269 if (display.currentCaret != this) return;
270 display.setCurrentCaret (null);
271 if (isVisible) hideCaret ();
272 }
273
274 void releaseChild () {
275 super.releaseChild ();
276 if (this == parent.getCaret ()) parent.setCaret (null);
277 }
278
279 void releaseWidget () {
280 super.releaseWidget ();
281 if (display.currentCaret == this) {
282 hideCaret ();
283 display.setCurrentCaret (null);
284 }
285 parent = null;
286 image = null;
287 }
288
289 /**
290 * Sets the receiver's size and location to the rectangular
291 * area specified by the arguments. The <code>x</code> and
292 * <code>y</code> arguments are relative to the receiver's
293 * parent (or its display if its parent is null).
294 *
295 * @param x the new x coordinate for the receiver
296 * @param y the new y coordinate for the receiver
297 * @param width the new width for the receiver
298 * @param height the new height for the receiver
299 *
300 * @exception SWTException <ul>
301 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
302 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
303 * </ul>
304 */
305 public void setBounds (int x, int y, int width, int height) {
306 checkWidget();
307 if (this.x == x && this.y == y && this.width == width && this.height == height) return;
308 boolean isFocus = isFocusCaret ();
309 if (isFocus) hideCaret ();
310 this.x = x; this.y = y;
311 this.width = width; this.height = height;
312 parent.updateCaret ();
313 if (isFocus) showCaret ();
314 }
315
316 /**
317 * Sets the receiver's size and location to the rectangular
318 * area specified by the argument. The <code>x</code> and
319 * <code>y</code> fields of the rectangle are relative to
320 * the receiver's parent (or its display if its parent is null).
321 *
322 * @param rect the new bounds for the receiver
323 *
324 * @exception SWTException <ul>
325 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
326 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
327 * </ul>
328 */
329 public void setBounds (Rectangle rect) {
330 checkWidget();
331 if (rect == null) error (SWT.ERROR_NULL_ARGUMENT);
332 setBounds (rect.x, rect.y, rect.width, rect.height);
333 }
334
335 void setFocus () {
336 if (display.currentCaret == this) return;
337 display.setCurrentCaret (this);
338 if (isVisible) showCaret ();
339 }
340
341 /**
342 * Sets the font that the receiver will use to paint textual information
343 * to the font specified by the argument, or to the default font for that
344 * kind of control if the argument is null.
345 *
346 * @param font the new font (or null)
347 *
348 * @exception IllegalArgumentException <ul>
349 * <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</li>
350 * </ul>
351 * @exception SWTException <ul>
352 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
353 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
354 * </ul>
355 */
356 public void setFont (Font font) {
357 checkWidget();
358 if (font != null && font.isDisposed ()) {
359 error (SWT.ERROR_INVALID_ARGUMENT);
360 }
361 this.font = font;
362 }
363
364 /**
365 * Sets the image that the receiver will use to paint the caret
366 * to the image specified by the argument, or to the default
367 * which is a filled rectangle if the argument is null
368 *
369 * @param image the new image (or null)
370 *
371 * @exception IllegalArgumentException <ul>
372 * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
373 * </ul>
374 * @exception SWTException <ul>
375 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
376 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
377 * </ul>
378 */
379 public void setImage (Image image) {
380 checkWidget();
381 if (image != null && image.isDisposed ()) {
382 error (SWT.ERROR_INVALID_ARGUMENT);
383 }
384 boolean isFocus = isFocusCaret ();
385 if (isFocus) hideCaret ();
386 this.image = image;
387 if (isFocus) showCaret ();
388 }
389
390 /**
391 * Sets the receiver's location to the point specified by
392 * the arguments which are relative to the receiver's
393 * parent (or its display if its parent is null).
394 *
395 * @param x the new x coordinate for the receiver
396 * @param y the new y coordinate for the receiver
397 *
398 * @exception SWTException <ul>
399 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
400 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
401 * </ul>
402 */
403 public void setLocation (int x, int y) {
404 checkWidget();
405 setBounds (x, y, width, height);
406 }
407
408 /**
409 * Sets the receiver's location to the point specified by
410 * the argument which is relative to the receiver's
411 * parent (or its display if its parent is null).
412 *
413 * @param location the new location for the receiver
414 *
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>
418 * </ul>
419 */
420 public void setLocation (Point location) {
421 checkWidget();
422 if (location == null) error (SWT.ERROR_NULL_ARGUMENT);
423 setLocation (location.x, location.y);
424 }
425
426 /**
427 * Sets the receiver's size to the point specified by the arguments.
428 *
429 * @param width the new width for the receiver
430 * @param height the new height for the receiver
431 *
432 * @exception SWTException <ul>
433 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
434 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
435 * </ul>
436 */
437 public void setSize (int width, int height) {
438 checkWidget();
439 setBounds (x, y, width, height);
440 }
441
442 /**
443 * Sets the receiver's size to the point specified by the argument.
444 *
445 * @param size the new extent for the receiver
446 *
447 * @exception IllegalArgumentException <ul>
448 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
449 * </ul>
450 * @exception SWTException <ul>
451 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
452 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
453 * </ul>
454 */
455 public void setSize (Point size) {
456 checkWidget();
457 if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
458 setSize (size.x, size.y);
459 }
460
461 /**
462 * Marks the receiver as visible if the argument is <code>true</code>,
463 * and marks it invisible otherwise.
464 * <p>
465 * If one of the receiver's ancestors is not visible or some
466 * other condition makes the receiver not visible, marking
467 * it visible may not actually cause it to be displayed.
468 * </p>
469 *
470 * @param visible the new visibility state
471 *
472 * @exception SWTException <ul>
473 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
474 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
475 * </ul>
476 */
477 public void setVisible (boolean visible) {
478 checkWidget();
479 if (visible == isVisible) return;
480 isVisible = visible;
481 if (!isFocusCaret ()) return;
482 if (isVisible) {
483 showCaret ();
484 } else {
485 hideCaret ();
486 }
487 }
488
489 boolean showCaret () {
490 if (isShowing) return true;
491 isShowing = true;
492 return drawCaret ();
493 }
494
495 }