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.Decorations; 14 15 import org.eclipse.swt.widgets.Control; 16 import org.eclipse.swt.widgets.Menu; 17 import org.eclipse.swt.widgets.Composite; 18 19 import org.eclipse.swt.SWT; 20 import org.eclipse.swt.internal.gtk.OS; 21 //import org.eclipse.swt.graphics.; 22 import org.eclipse.swt.widgets.Canvas; 23 import org.eclipse.swt.graphics.Image; 24 import org.eclipse.swt.graphics.ImageData; 25 import org.eclipse.swt.widgets.Control; 26 import org.eclipse.swt.widgets.Display; 27 import org.eclipse.swt.widgets.Widget; 28 import org.eclipse.swt.widgets.Button; 29 import java.lang.all; 30 31 /** 32 * Instances of this class provide the appearance and 33 * behavior of <code>Shells</code>, but are not top 34 * level shells or dialogs. Class <code>Shell</code> 35 * shares a significant amount of code with this class, 36 * and is a subclass. 37 * <p> 38 * IMPORTANT: This class was intended to be abstract and 39 * should <em>never</em> be referenced or instantiated. 40 * Instead, the class <code>Shell</code> should be used. 41 * </p> 42 * <p> 43 * Instances are always displayed in one of the maximized, 44 * minimized or normal states: 45 * <ul> 46 * <li> 47 * When an instance is marked as <em>maximized</em>, the 48 * window manager will typically resize it to fill the 49 * entire visible area of the display, and the instance 50 * is usually put in a state where it can not be resized 51 * (even if it has style <code>RESIZE</code>) until it is 52 * no longer maximized. 53 * </li><li> 54 * When an instance is in the <em>normal</em> state (neither 55 * maximized or minimized), its appearance is controlled by 56 * the style constants which were specified when it was created 57 * and the restrictions of the window manager (see below). 58 * </li><li> 59 * When an instance has been marked as <em>minimized</em>, 60 * its contents (client area) will usually not be visible, 61 * and depending on the window manager, it may be 62 * "iconified" (that is, replaced on the desktop by a small 63 * simplified representation of itself), relocated to a 64 * distinguished area of the screen, or hidden. Combinations 65 * of these changes are also possible. 66 * </li> 67 * </ul> 68 * </p> 69 * Note: The styles supported by this class must be treated 70 * as <em>HINT</em>s, since the window manager for the 71 * desktop on which the instance is visible has ultimate 72 * control over the appearance and behavior of decorations. 73 * For example, some window managers only support resizable 74 * windows and will always assume the RESIZE style, even if 75 * it is not set. 76 * <dl> 77 * <dt><b>Styles:</b></dt> 78 * <dd>BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL</dd> 79 * <dt><b>Events:</b></dt> 80 * <dd>(none)</dd> 81 * </dl> 82 * Class <code>SWT</code> provides two "convenience constants" 83 * for the most commonly required style combinations: 84 * <dl> 85 * <dt><code>SHELL_TRIM</code></dt> 86 * <dd> 87 * the result of combining the constants which are required 88 * to produce a typical application top level shell: (that 89 * is, <code>CLOSE | TITLE | MIN | MAX | RESIZE</code>) 90 * </dd> 91 * <dt><code>DIALOG_TRIM</code></dt> 92 * <dd> 93 * the result of combining the constants which are required 94 * to produce a typical application dialog shell: (that 95 * is, <code>TITLE | CLOSE | BORDER</code>) 96 * </dd> 97 * </dl> 98 * <p> 99 * IMPORTANT: This class is intended to be subclassed <em>only</em> 100 * within the SWT implementation. 101 * </p> 102 * 103 * @see #getMinimized 104 * @see #getMaximized 105 * @see Shell 106 * @see SWT 107 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> 108 */ 109 public class Decorations : Canvas { 110 111 alias Canvas.sort sort; 112 113 String text; 114 Image image; 115 Image [] images; 116 bool minimized, maximized; 117 Menu menuBar; 118 Menu [] menus; 119 Control savedFocus; 120 Button defaultButton, saveDefault; 121 GtkAccelGroup* accelGroup; 122 GtkWidget* vboxHandle; 123 124 this () { 125 /* Do nothing */ 126 } 127 128 /** 129 * Constructs a new instance of this class given its parent 130 * and a style value describing its behavior and appearance. 131 * <p> 132 * The style value is either one of the style constants defined in 133 * class <code>SWT</code> which is applicable to instances of this 134 * class, or must be built by <em>bitwise OR</em>'ing together 135 * (that is, using the <code>int</code> "|" operator) two or more 136 * of those <code>SWT</code> style constants. The class description 137 * lists the style constants that are applicable to the class. 138 * Style bits are also inherited from superclasses. 139 * </p> 140 * 141 * @param parent a composite control which will be the parent of the new instance (cannot be null) 142 * @param style the style of control to construct 143 * 144 * @exception IllegalArgumentException <ul> 145 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> 146 * </ul> 147 * @exception SWTException <ul> 148 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> 149 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> 150 * </ul> 151 * 152 * @see SWT#BORDER 153 * @see SWT#CLOSE 154 * @see SWT#MIN 155 * @see SWT#MAX 156 * @see SWT#RESIZE 157 * @see SWT#TITLE 158 * @see SWT#NO_TRIM 159 * @see SWT#SHELL_TRIM 160 * @see SWT#DIALOG_TRIM 161 * @see SWT#ON_TOP 162 * @see SWT#TOOL 163 * @see Widget#checkSubclass 164 * @see Widget#getStyle 165 */ 166 public this (Composite parent, int style) { 167 super (parent, checkStyle (style)); 168 } 169 170 static int checkStyle (int style) { 171 if ((style & SWT.NO_TRIM) !is 0) { 172 style &= ~(SWT.CLOSE | SWT.TITLE | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.BORDER); 173 } 174 if ((style & (SWT.MENU | SWT.MIN | SWT.MAX | SWT.CLOSE)) !is 0) { 175 style |= SWT.TITLE; 176 } 177 return style; 178 } 179 180 override protected void checkSubclass () { 181 if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); 182 } 183 184 void _setImages (Image [] images) { 185 if (images !is null && images.length > 1) { 186 Image [] bestImages = new Image [images.length]; 187 System.arraycopy (images, 0, bestImages, 0, images.length); 188 sort (bestImages); 189 images = bestImages; 190 } 191 GList* pixbufs; 192 if (images !is null) { 193 for (int i = 0; i < images.length; i++) { 194 Image image = images [i]; 195 auto pixbuf = Display.createPixbuf (image); 196 pixbufs = OS.g_list_append (pixbufs, pixbuf); 197 } 198 } 199 OS.gtk_window_set_icon_list (cast(GtkWindow*)topHandle (), pixbufs); 200 GList* data; 201 auto temp = pixbufs; 202 while (temp !is null) { 203 data = *cast(GList**)temp; 204 OS.g_object_unref (data); 205 temp = cast(GList*)OS.g_list_next (temp); 206 } 207 if (pixbufs !is null) OS.g_list_free (pixbufs); 208 } 209 210 void addMenu (Menu menu) { 211 if (menus is null) menus = new Menu [4]; 212 for (int i=0; i<menus.length; i++) { 213 if (menus [i] is null) { 214 menus [i] = menu; 215 return; 216 } 217 } 218 Menu [] newMenus = new Menu [menus.length + 4]; 219 newMenus [menus.length] = menu; 220 System.arraycopy (menus, 0, newMenus, 0, menus.length); 221 menus = newMenus; 222 } 223 224 int compare (ImageData data1, ImageData data2) { 225 if (data1.width is data2.width && data1.height is data2.height) { 226 int transparent1 = data1.getTransparencyType (); 227 int transparent2 = data2.getTransparencyType (); 228 if (transparent1 is SWT.TRANSPARENCY_ALPHA) return -1; 229 if (transparent2 is SWT.TRANSPARENCY_ALPHA) return 1; 230 if (transparent1 is SWT.TRANSPARENCY_MASK) return -1; 231 if (transparent2 is SWT.TRANSPARENCY_MASK) return 1; 232 if (transparent1 is SWT.TRANSPARENCY_PIXEL) return -1; 233 if (transparent2 is SWT.TRANSPARENCY_PIXEL) return 1; 234 return 0; 235 } 236 return data1.width > data2.width || data1.height > data2.height ? -1 : 1; 237 } 238 239 override Control computeTabGroup () { 240 return this; 241 } 242 243 override Control computeTabRoot () { 244 return this; 245 } 246 247 void createAccelGroup () { 248 if (accelGroup !is null) return; 249 accelGroup = OS.gtk_accel_group_new (); 250 if (accelGroup is null) SWT.error (SWT.ERROR_NO_HANDLES); 251 //FIXME - what should we do for Decorations 252 auto shellHandle = topHandle (); 253 OS.gtk_window_add_accel_group (cast(GtkWindow*)shellHandle, accelGroup); 254 } 255 256 override void createWidget (int index) { 257 super.createWidget (index); 258 text = ""; 259 } 260 261 void destroyAccelGroup () { 262 if (accelGroup is null) return; 263 auto shellHandle = topHandle (); 264 OS.gtk_window_remove_accel_group (cast(GtkWindow*)shellHandle, accelGroup); 265 //TEMPORARY CODE 266 // OS.g_object_unref (accelGroup); 267 accelGroup = null; 268 } 269 270 void fixAccelGroup () { 271 if (menuBar is null) return; 272 destroyAccelGroup (); 273 createAccelGroup (); 274 menuBar.addAccelerators (accelGroup); 275 } 276 277 void fixDecorations (Decorations newDecorations, Control control, Menu [] menus) { 278 if (this is newDecorations) return; 279 if (control is savedFocus) savedFocus = null; 280 if (control is defaultButton) defaultButton = null; 281 if (control is saveDefault) saveDefault = null; 282 if (menus is null) return; 283 Menu menu = control.menu; 284 if (menu !is null) { 285 int index = 0; 286 while (index <menus.length) { 287 if (menus [index] is menu) { 288 control.setMenu (null); 289 return; 290 } 291 index++; 292 } 293 menu.fixMenus (newDecorations); 294 } 295 } 296 297 /** 298 * Returns the receiver's default button if one had 299 * previously been set, otherwise returns null. 300 * 301 * @return the default button or null 302 * 303 * @exception SWTException <ul> 304 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 305 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 306 * </ul> 307 * 308 * @see #setDefaultButton(Button) 309 */ 310 public Button getDefaultButton () { 311 checkWidget(); 312 return defaultButton !is null ? defaultButton : saveDefault; 313 } 314 315 /** 316 * Returns the receiver's image if it had previously been 317 * set using <code>setImage()</code>. The image is typically 318 * displayed by the window manager when the instance is 319 * marked as iconified, and may also be displayed somewhere 320 * in the trim when the instance is in normal or maximized 321 * states. 322 * <p> 323 * Note: This method will return null if called before 324 * <code>setImage()</code> is called. It does not provide 325 * access to a window manager provided, "default" image 326 * even if one exists. 327 * </p> 328 * 329 * @return the image 330 * 331 * @exception SWTException <ul> 332 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 333 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 334 * </ul> 335 */ 336 public Image getImage () { 337 checkWidget (); 338 return image; 339 } 340 341 /** 342 * Returns the receiver's images if they had previously been 343 * set using <code>setImages()</code>. Images are typically 344 * displayed by the window manager when the instance is 345 * marked as iconified, and may also be displayed somewhere 346 * in the trim when the instance is in normal or maximized 347 * states. Depending where the icon is displayed, the platform 348 * chooses the icon with the "best" attributes. It is expected 349 * that the array will contain the same icon rendered at different 350 * sizes, with different depth and transparency attributes. 351 * 352 * <p> 353 * Note: This method will return an empty array if called before 354 * <code>setImages()</code> is called. It does not provide 355 * access to a window manager provided, "default" image 356 * even if one exists. 357 * </p> 358 * 359 * @return the images 360 * 361 * @exception SWTException <ul> 362 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 363 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 364 * </ul> 365 * 366 * @since 3.0 367 */ 368 public Image [] getImages () { 369 checkWidget (); 370 if (images is null) return new Image [0]; 371 Image [] result = new Image [images.length]; 372 System.arraycopy (images, 0, result, 0, images.length); 373 return result; 374 } 375 376 /** 377 * Returns <code>true</code> if the receiver is currently 378 * maximized, and false otherwise. 379 * <p> 380 * 381 * @return the maximized state 382 * 383 * @exception SWTException <ul> 384 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 385 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 386 * </ul> 387 * 388 * @see #setMaximized 389 */ 390 public bool getMaximized () { 391 checkWidget(); 392 return maximized; 393 } 394 395 /** 396 * Returns the receiver's menu bar if one had previously 397 * been set, otherwise returns null. 398 * 399 * @return the menu bar or null 400 * 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 Menu getMenuBar () { 407 checkWidget(); 408 return menuBar; 409 } 410 411 /** 412 * Returns <code>true</code> if the receiver is currently 413 * minimized, and false otherwise. 414 * <p> 415 * 416 * @return the minimized state 417 * 418 * @exception SWTException <ul> 419 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 420 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 421 * </ul> 422 * 423 * @see #setMinimized 424 */ 425 public bool getMinimized () { 426 checkWidget(); 427 return minimized; 428 } 429 430 override String getNameText () { 431 return getText (); 432 } 433 434 /** 435 * Returns the receiver's text, which is the string that the 436 * window manager will typically display as the receiver's 437 * <em>title</em>. If the text has not previously been set, 438 * returns an empty string. 439 * 440 * @return the text 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 String getText () { 448 checkWidget(); 449 return text; 450 } 451 452 override public bool isReparentable () { 453 checkWidget (); 454 return false; 455 } 456 457 override bool isTabGroup () { 458 return true; 459 } 460 461 override bool isTabItem () { 462 return false; 463 } 464 465 override Decorations menuShell () { 466 return this; 467 } 468 469 void removeMenu (Menu menu) { 470 if (menus is null) return; 471 for (int i=0; i<menus.length; i++) { 472 if (menus [i] is menu) { 473 menus [i] = null; 474 return; 475 } 476 } 477 } 478 479 override void releaseChildren (bool destroy) { 480 if (menuBar !is null) { 481 menuBar.release (false); 482 menuBar = null; 483 } 484 super.releaseChildren (destroy); 485 if (menus !is null) { 486 for (int i=0; i<menus.length; i++) { 487 Menu menu = menus [i]; 488 if (menu !is null && !menu.isDisposed ()) { 489 menu.dispose (); 490 } 491 } 492 menus = null; 493 } 494 } 495 496 override void releaseHandle () { 497 super.releaseHandle (); 498 vboxHandle = null; 499 } 500 501 override void releaseWidget () { 502 super.releaseWidget (); 503 image = null; 504 images = null; 505 savedFocus = null; 506 defaultButton = saveDefault = null; 507 } 508 509 bool restoreFocus () { 510 if (savedFocus !is null && savedFocus.isDisposed ()) savedFocus = null; 511 bool restored = savedFocus !is null && savedFocus.setFocus (); 512 savedFocus = null; 513 /* 514 * This code is intentionally commented. When no widget 515 * has been given focus, some platforms give focus to the 516 * default button. Motif doesn't do this. 517 */ 518 // if (restored) return true; 519 // if (defaultButton !is null && !defaultButton.isDisposed ()) { 520 // if (defaultButton.setFocus ()) return true; 521 // } 522 // return false; 523 return restored; 524 } 525 526 /** 527 * If the argument is not null, sets the receiver's default 528 * button to the argument, and if the argument is null, sets 529 * the receiver's default button to the first button which 530 * was set as the receiver's default button (called the 531 * <em>saved default button</em>). If no default button had 532 * previously been set, or the saved default button was 533 * disposed, the receiver's default button will be set to 534 * null. 535 * <p> 536 * The default button is the button that is selected when 537 * the receiver is active and the user presses ENTER. 538 * </p> 539 * 540 * @param button the new default button 541 * 542 * @exception IllegalArgumentException <ul> 543 * <li>ERROR_INVALID_ARGUMENT - if the button has been disposed</li> 544 * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li> 545 * </ul> 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> 549 * </ul> 550 */ 551 public void setDefaultButton (Button button) { 552 checkWidget(); 553 GtkWidget* buttonHandle; 554 if (button !is null) { 555 if (button.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); 556 if (button.menuShell () !is this) error (SWT.ERROR_INVALID_PARENT); 557 buttonHandle = button.handle; 558 } 559 saveDefault = defaultButton = button; 560 OS.gtk_window_set_default (cast(GtkWindow*)topHandle (), buttonHandle); 561 } 562 563 /** 564 * Sets the receiver's image to the argument, which may 565 * be null. The image is typically displayed by the window 566 * manager when the instance is marked as iconified, and 567 * may also be displayed somewhere in the trim when the 568 * instance is in normal or maximized states. 569 * 570 * @param image the new image (or null) 571 * 572 * @exception IllegalArgumentException <ul> 573 * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li> 574 * </ul> 575 * @exception SWTException <ul> 576 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 577 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 578 * </ul> 579 */ 580 public void setImage (Image image) { 581 checkWidget (); 582 this.image = image; 583 _setImages (image !is null ? [image] : null); 584 } 585 586 /** 587 * Sets the receiver's images to the argument, which may 588 * be an empty array. Images are typically displayed by the 589 * window manager when the instance is marked as iconified, 590 * and may also be displayed somewhere in the trim when the 591 * instance is in normal or maximized states. Depending where 592 * the icon is displayed, the platform chooses the icon with 593 * the "best" attributes. It is expected that the array will 594 * contain the same icon rendered at different sizes, with 595 * different depth and transparency attributes. 596 * 597 * @param images the new image array 598 * 599 * @exception IllegalArgumentException <ul> 600 * <li>ERROR_INVALID_ARGUMENT - if one of the images is null or has been disposed</li> 601 * </ul> 602 * @exception SWTException <ul> 603 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 604 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 605 * </ul> 606 * 607 * @since 3.0 608 */ 609 public void setImages (Image [] images) { 610 checkWidget (); 611 // SWT extension: allow null for zero length string 612 //if (images is null) error (SWT.ERROR_INVALID_ARGUMENT); 613 for (int i = 0; i < images.length; i++) { 614 if (images [i] is null || images [i].isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); 615 } 616 this.images = images; 617 _setImages (images); 618 } 619 620 /** 621 * Sets the maximized state of the receiver. 622 * If the argument is <code>true</code> causes the receiver 623 * to switch to the maximized state, and if the argument is 624 * <code>false</code> and the receiver was previously maximized, 625 * causes the receiver to switch back to either the minimized 626 * or normal states. 627 * <p> 628 * Note: The result of intermixing calls to <code>setMaximized(true)</code> 629 * and <code>setMinimized(true)</code> will vary by platform. Typically, 630 * the behavior will match the platform user's expectations, but not 631 * always. This should be avoided if possible. 632 * </p> 633 * 634 * @param maximized the new maximized state 635 * 636 * @exception SWTException <ul> 637 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 638 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 639 * </ul> 640 * 641 * @see #setMinimized 642 */ 643 public void setMaximized (bool maximized) { 644 checkWidget(); 645 this.maximized = maximized; 646 } 647 648 /** 649 * Sets the receiver's menu bar to the argument, which 650 * may be null. 651 * 652 * @param menu the new menu bar 653 * 654 * @exception IllegalArgumentException <ul> 655 * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li> 656 * <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li> 657 * </ul> 658 * @exception SWTException <ul> 659 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 660 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 661 * </ul> 662 */ 663 public void setMenuBar (Menu menu) { 664 checkWidget(); 665 if (menuBar is menu) return; 666 if (menu !is null) { 667 if ((menu.style & SWT.BAR) is 0) error (SWT.ERROR_MENU_NOT_BAR); 668 if (menu.parent !is this) error (SWT.ERROR_INVALID_PARENT); 669 } 670 menuBar = menu; 671 } 672 673 /** 674 * Sets the minimized stated of the receiver. 675 * If the argument is <code>true</code> causes the receiver 676 * to switch to the minimized state, and if the argument is 677 * <code>false</code> and the receiver was previously minimized, 678 * causes the receiver to switch back to either the maximized 679 * or normal states. 680 * <p> 681 * Note: The result of intermixing calls to <code>setMaximized(true)</code> 682 * and <code>setMinimized(true)</code> will vary by platform. Typically, 683 * the behavior will match the platform user's expectations, but not 684 * always. This should be avoided if possible. 685 * </p> 686 * 687 * @param minimized the new maximized state 688 * 689 * @exception SWTException <ul> 690 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 691 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 692 * </ul> 693 * 694 * @see #setMaximized 695 */ 696 public void setMinimized (bool minimized) { 697 checkWidget(); 698 this.minimized = minimized; 699 } 700 701 void setSavedFocus (Control control) { 702 if (this is control) return; 703 savedFocus = control; 704 } 705 706 /** 707 * Sets the receiver's text, which is the string that the 708 * window manager will typically display as the receiver's 709 * <em>title</em>, to the argument, which must not be null. 710 * 711 * @param string the new text 712 * 713 * @exception SWTException <ul> 714 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 715 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 716 * </ul> 717 */ 718 public void setText (String string) { 719 checkWidget(); 720 // SWT extension: allow null for zero length string 721 //if (string is null) error (SWT.ERROR_NULL_ARGUMENT); 722 text = string; 723 } 724 725 void sort (Image [] images) { 726 /* Shell Sort from K&R, pg 108 */ 727 ptrdiff_t length = images.length; 728 if (length <= 1) return; 729 ImageData [] datas = new ImageData [length]; 730 for (int i = 0; i < length; i++) { 731 datas [i] = images [i].getImageData (); 732 } 733 for (ptrdiff_t gap=length/2; gap>0; gap/=2) { 734 for (ptrdiff_t i=gap; i<length; i++) { 735 for (ptrdiff_t j=i-gap; j>=0; j-=gap) { 736 if (compare (datas [j], datas [j + gap]) >= 0) { 737 Image swap = images [j]; 738 images [j] = images [j + gap]; 739 images [j + gap] = swap; 740 ImageData swapData = datas [j]; 741 datas [j] = datas [j + gap]; 742 datas [j + gap] = swapData; 743 } 744 } 745 } 746 } 747 } 748 749 override bool traverseItem (bool next) { 750 return false; 751 } 752 753 override bool traverseReturn () { 754 Button button = defaultButton !is null ? defaultButton: saveDefault; 755 if (button is null || button.isDisposed ()) return false; 756 /* 757 * Bug in GTK. When a default button that is disabled is 758 * activated using the Enter key, GTK GP's. The fix is to 759 * detect this case and stop GTK from processing the Enter 760 * key. 761 */ 762 if (!button.isVisible () || !button.isEnabled ()) return true; 763 auto shellHandle = _getShell ().topHandle (); 764 return cast(bool)OS.gtk_window_activate_default (cast(GtkWindow*)shellHandle); 765 } 766 767 }