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