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.CoolItem; 14 15 import java.lang.all; 16 import org.eclipse.swt.SWT; 17 import org.eclipse.swt.SWTException; 18 import org.eclipse.swt.events.SelectionEvent; 19 import org.eclipse.swt.events.SelectionListener; 20 import org.eclipse.swt.graphics.Color; 21 import org.eclipse.swt.graphics.GC; 22 import org.eclipse.swt.graphics.Image; 23 import org.eclipse.swt.graphics.ImageData; 24 import org.eclipse.swt.graphics.PaletteData; 25 import org.eclipse.swt.graphics.Point; 26 import org.eclipse.swt.graphics.RGB; 27 import org.eclipse.swt.graphics.Rectangle; 28 import org.eclipse.swt.widgets.Item; 29 import org.eclipse.swt.widgets.Control; 30 import org.eclipse.swt.widgets.CoolBar; 31 import org.eclipse.swt.widgets.ToolBar; 32 import org.eclipse.swt.widgets.Event; 33 import org.eclipse.swt.widgets.TypedListener; 34 import org.eclipse.swt.widgets.ToolBar; 35 import org.eclipse.swt.widgets.ToolItem; 36 import org.eclipse.swt.widgets.Listener; 37 38 /** 39 * Instances of this class are selectable user interface 40 * objects that represent the dynamically positionable 41 * areas of a <code>CoolBar</code>. 42 * <dl> 43 * <dt><b>Styles:</b></dt> 44 * <dd>DROP_DOWN</dd> 45 * <dt><b>Events:</b></dt> 46 * <dd>Selection</dd> 47 * </dl> 48 * <p> 49 * IMPORTANT: This class is <em>not</em> intended to be subclassed. 50 * </p> 51 * 52 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> 53 */ 54 public class CoolItem : Item { 55 Control control; 56 CoolBar parent; 57 bool ideal; 58 int preferredWidth, preferredHeight, minimumWidth, minimumHeight, requestedWidth; 59 Rectangle itemBounds; 60 61 static const int MARGIN_WIDTH = 4; 62 static const int GRABBER_WIDTH = 2; 63 static const int MINIMUM_WIDTH = (2 * MARGIN_WIDTH) + GRABBER_WIDTH; 64 65 private int CHEVRON_HORIZONTAL_TRIM = -1; //platform dependent values 66 private int CHEVRON_VERTICAL_TRIM = -1; 67 private static const int CHEVRON_LEFT_MARGIN = 2; 68 private static const int CHEVRON_IMAGE_WIDTH = 8; //Width to draw the double arrow 69 70 ToolBar chevron; 71 bool wrap; 72 Image arrowImage = null; 73 74 /** 75 * Constructs a new instance of this class given its parent 76 * (which must be a <code>CoolBar</code>) and a style value 77 * describing its behavior and appearance. The item is added 78 * to the end of the items maintained by its parent. 79 * <p> 80 * The style value is either one of the style constants defined in 81 * class <code>SWT</code> which is applicable to instances of this 82 * class, or must be built by <em>bitwise OR</em>'ing together 83 * (that is, using the <code>int</code> "|" operator) two or more 84 * of those <code>SWT</code> style constants. The class description 85 * lists the style constants that are applicable to the class. 86 * Style bits are also inherited from superclasses. 87 * </p> 88 * 89 * @param parent a composite control which will be the parent of the new instance (cannot be null) 90 * @param style the style of control to construct 91 * 92 * @exception IllegalArgumentException <ul> 93 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> 94 * </ul> 95 * @exception SWTException <ul> 96 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> 97 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> 98 * </ul> 99 * 100 * @see SWT#DROP_DOWN 101 * @see Widget#checkSubclass 102 * @see Widget#getStyle 103 */ 104 public this (CoolBar parent, int style) { 105 super(parent, style); 106 itemBounds = new Rectangle(0, 0, 0, 0); 107 this.parent = parent; 108 parent.createItem (this, parent.getItemCount()); 109 calculateChevronTrim (); 110 } 111 /** 112 * Constructs a new instance of this class given its parent 113 * (which must be a <code>CoolBar</code>), a style value 114 * describing its behavior and appearance, and the index 115 * at which to place it in the items maintained by its parent. 116 * <p> 117 * The style value is either one of the style constants defined in 118 * class <code>SWT</code> which is applicable to instances of this 119 * class, or must be built by <em>bitwise OR</em>'ing together 120 * (that is, using the <code>int</code> "|" operator) two or more 121 * of those <code>SWT</code> style constants. The class description 122 * lists the style constants that are applicable to the class. 123 * Style bits are also inherited from superclasses. 124 * </p> 125 * 126 * @param parent a composite control which will be the parent of the new instance (cannot be null) 127 * @param style the style of control to construct 128 * @param index the zero-relative index at which to store the receiver in its parent 129 * 130 * @exception IllegalArgumentException <ul> 131 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> 132 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li> 133 * </ul> 134 * @exception SWTException <ul> 135 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> 136 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> 137 * </ul> 138 * 139 * @see SWT#DROP_DOWN 140 * @see Widget#checkSubclass 141 * @see Widget#getStyle 142 */ 143 public this (CoolBar parent, int style, int index) { 144 super(parent, style); 145 itemBounds = new Rectangle(0, 0, 0, 0); 146 this.parent = parent; 147 parent.createItem (this, index); 148 calculateChevronTrim (); 149 } 150 /** 151 * Adds the listener to the collection of listeners that will 152 * be notified when the control is selected by the user, by sending it one 153 * of the messages defined in the <code>SelectionListener</code> 154 * interface. 155 * <p> 156 * If <code>widgetSelected</code> is called when the mouse is over 157 * the drop-down arrow (or 'chevron') portion of the cool item, 158 * the event object detail field contains the value <code>SWT.ARROW</code>, 159 * and the x and y fields in the event object represent the point at 160 * the bottom left of the chevron, where the menu should be popped up. 161 * <code>widgetDefaultSelected</code> is not called. 162 * </p> 163 * 164 * @param listener the listener which should be notified when the control is selected by the user 165 * 166 * @exception IllegalArgumentException <ul> 167 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 168 * </ul> 169 * @exception SWTException <ul> 170 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 171 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 172 * </ul> 173 * 174 * @see SelectionListener 175 * @see #removeSelectionListener 176 * @see SelectionEvent 177 * 178 * @since 2.0 179 */ 180 public void addSelectionListener(SelectionListener listener) { 181 checkWidget(); 182 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 183 TypedListener typedListener = new TypedListener (listener); 184 addListener (SWT.Selection,typedListener); 185 addListener (SWT.DefaultSelection,typedListener); 186 } 187 protected override void checkSubclass () { 188 if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); 189 } 190 /* 191 * Find the trim size of the Toolbar widget in the current platform. 192 */ 193 void calculateChevronTrim () { 194 ToolBar tb = new ToolBar (parent, SWT.FLAT); 195 ToolItem ti = new ToolItem (tb, SWT.PUSH); 196 Image image = new Image (display, 1, 1); 197 ti.setImage (image); 198 Point size = tb.computeSize (SWT.DEFAULT, SWT.DEFAULT); 199 size = parent.fixPoint(size.x, size.y); 200 CHEVRON_HORIZONTAL_TRIM = size.x - 1; 201 CHEVRON_VERTICAL_TRIM = size.y - 1; 202 tb.dispose (); 203 ti.dispose (); 204 image.dispose (); 205 } 206 /** 207 * Returns the preferred size of the receiver. 208 * <p> 209 * The <em>preferred size</em> of a <code>CoolItem</code> is the size that 210 * it would best be displayed at. The width hint and height hint arguments 211 * allow the caller to ask the instance questions such as "Given a particular 212 * width, how high does it need to be to show all of the contents?" 213 * To indicate that the caller does not wish to constrain a particular 214 * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint. 215 * </p> 216 * 217 * @param wHint the width hint (can be <code>SWT.DEFAULT</code>) 218 * @param hHint the height hint (can be <code>SWT.DEFAULT</code>) 219 * @return the preferred size 220 * 221 * @exception SWTException <ul> 222 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 223 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 224 * </ul> 225 * 226 * @see Layout 227 * @see #getBounds 228 * @see #getSize 229 * @see Control#getBorderWidth 230 * @see Scrollable#computeTrim 231 * @see Scrollable#getClientArea 232 */ 233 public Point computeSize (int wHint, int hHint) { 234 checkWidget(); 235 int width = wHint, height = hHint; 236 if (wHint is SWT.DEFAULT) width = 32; 237 if (hHint is SWT.DEFAULT) height = 32; 238 if ((parent.style & SWT.VERTICAL) !is 0) { 239 height += MINIMUM_WIDTH; 240 } else { 241 width += MINIMUM_WIDTH; 242 } 243 return new Point (width, height); 244 } 245 public override void dispose () { 246 if (isDisposed()) return; 247 248 /* 249 * Must call parent.destroyItem() before super.dispose(), since it needs to 250 * query the bounds to properly remove the item. 251 */ 252 parent.destroyItem(this); 253 super.dispose (); 254 parent = null; 255 control = null; 256 257 /* 258 * Although the parent for the chevron is the CoolBar (CoolItem can not be the parent) 259 * it has to be disposed with the item 260 */ 261 if (chevron !is null && !chevron.isDisposed()) chevron.dispose(); 262 chevron = null; 263 if (arrowImage !is null && !arrowImage.isDisposed()) arrowImage.dispose(); 264 arrowImage = null; 265 } 266 267 Image createArrowImage (int width, int height) { 268 Point point = parent.fixPoint(width, height); 269 width = point.x; 270 height = point.y; 271 Color foreground = parent.getForeground (); 272 Color black = display.getSystemColor (SWT.COLOR_BLACK); 273 Color background = parent.getBackground (); 274 275 PaletteData palette = new PaletteData ( [foreground.getRGB(), background.getRGB(), black.getRGB() ] ); 276 ImageData imageData = new ImageData (width, height, 4, palette); 277 imageData.transparentPixel = 1; 278 Image image = new Image (display, imageData); 279 280 GC gc = new GC (image, parent.getStyle() & SWT.RIGHT_TO_LEFT); 281 gc.setBackground (background); 282 gc.fillRectangle (0, 0, width, height); 283 gc.setForeground (black); 284 285 int startX = 0 ; 286 if ((parent.style & SWT.VERTICAL) !is 0) { 287 startX = width - CHEVRON_IMAGE_WIDTH; 288 } 289 int startY = height / 6; 290 int step = 2; 291 gc.drawLine (startX, startY, startX + step, startY + step); 292 gc.drawLine (startX, startY + (2 * step), startX + step, startY + step); 293 startX++; 294 gc.drawLine (startX, startY, startX + step, startY + step); 295 gc.drawLine (startX, startY + (2 * step), startX + step, startY + step); 296 startX += 3; 297 gc.drawLine (startX, startY, startX + step, startY + step); 298 gc.drawLine (startX, startY + (2 * step), startX + step, startY + step); 299 startX++; 300 gc.drawLine (startX, startY, startX + step, startY + step); 301 gc.drawLine (startX, startY + (2 * step), startX + step, startY + step); 302 gc.dispose (); 303 return image; 304 } 305 /** 306 * Returns a rectangle describing the receiver's size and location 307 * relative to its parent. 308 * 309 * @return the receiver's bounding rectangle 310 * 311 * @exception SWTException <ul> 312 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 313 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 314 * </ul> 315 */ 316 public Rectangle getBounds () { 317 checkWidget(); 318 return parent.fixRectangle(itemBounds.x, itemBounds.y, itemBounds.width, itemBounds.height); 319 } 320 Rectangle internalGetBounds () { 321 return new Rectangle(itemBounds.x, itemBounds.y, itemBounds.width, itemBounds.height); 322 } 323 /** 324 * Returns the control that is associated with the receiver. 325 * 326 * @return the control that is contained by the receiver 327 * 328 * @exception SWTException <ul> 329 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 330 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 331 * </ul> 332 */ 333 public Control getControl () { 334 checkWidget(); 335 return control; 336 } 337 /** 338 * Returns the minimum size that the cool item can 339 * be resized to using the cool item's gripper. 340 * 341 * @return a point containing the minimum width and height of the cool item, in pixels 342 * 343 * @exception SWTException <ul> 344 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 345 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 346 * </ul> 347 * 348 * @since 2.0 349 */ 350 public Point getMinimumSize () { 351 checkWidget(); 352 return parent.fixPoint(minimumWidth, minimumHeight); 353 } 354 /** 355 * Returns the receiver's parent, which must be a <code>CoolBar</code>. 356 * 357 * @return the receiver's parent 358 * 359 * @exception SWTException <ul> 360 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 361 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 362 * </ul> 363 */ 364 public CoolBar getParent () { 365 checkWidget(); 366 return parent; 367 } 368 /** 369 * Returns a point describing the receiver's ideal size. 370 * The x coordinate of the result is the ideal width of the receiver. 371 * The y coordinate of the result is the ideal height of the receiver. 372 * 373 * @return the receiver's ideal size 374 * 375 * @exception SWTException <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 Point getPreferredSize () { 381 checkWidget(); 382 return parent.fixPoint(preferredWidth, preferredHeight); 383 } 384 /** 385 * Returns a point describing the receiver's size. The 386 * x coordinate of the result is the width of the receiver. 387 * The y coordinate of the result is the height of the 388 * receiver. 389 * 390 * @return the receiver's size 391 * 392 * @exception SWTException <ul> 393 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 394 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 395 * </ul> 396 */ 397 public Point getSize () { 398 checkWidget(); 399 return parent.fixPoint(itemBounds.width, itemBounds.height); 400 } 401 int internalGetMinimumWidth () { 402 int width = minimumWidth + MINIMUM_WIDTH; 403 if ((style & SWT.DROP_DOWN) !is 0 && width < preferredWidth) { 404 width += CHEVRON_IMAGE_WIDTH + CHEVRON_HORIZONTAL_TRIM + CHEVRON_LEFT_MARGIN; 405 } 406 return width; 407 } 408 /* 409 * Called when the chevron is selected. 410 */ 411 void onSelection (Event ev) { 412 Rectangle bounds = chevron.getBounds(); 413 Event event = new Event(); 414 event.detail = SWT.ARROW; 415 if ((parent.style & SWT.VERTICAL) !is 0) { 416 event.x = bounds.x + bounds.width; 417 event.y = bounds.y; 418 } else { 419 event.x = bounds.x; 420 event.y = bounds.y + bounds.height; 421 } 422 postEvent (SWT.Selection, event); 423 } 424 /** 425 * Removes the listener from the collection of listeners that 426 * will be notified when the control is selected by the user. 427 * 428 * @param listener the listener which should no longer be notified 429 * 430 * @exception IllegalArgumentException <ul> 431 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> 432 * </ul> 433 * @exception SWTException <ul> 434 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 435 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 436 * </ul> 437 * 438 * @see SelectionListener 439 * @see #addSelectionListener 440 * 441 * @since 2.0 442 */ 443 public void removeSelectionListener(SelectionListener listener) { 444 checkWidget(); 445 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); 446 if (eventTable is null) return; 447 eventTable.unhook (SWT.Selection, listener); 448 eventTable.unhook (SWT.DefaultSelection,listener); 449 } 450 void setBounds (int x, int y, int width, int height) { 451 itemBounds.x = x; 452 itemBounds.y = y; 453 itemBounds.width = width; 454 itemBounds.height = height; 455 if (control !is null) { 456 int controlWidth = width - MINIMUM_WIDTH; 457 if ((style & SWT.DROP_DOWN) !is 0 && width < preferredWidth) { 458 controlWidth -= CHEVRON_IMAGE_WIDTH + CHEVRON_HORIZONTAL_TRIM + CHEVRON_LEFT_MARGIN; 459 } 460 control.setBounds (parent.fixRectangle(x + MINIMUM_WIDTH, y, controlWidth, height)); 461 } 462 updateChevron(); 463 } 464 /** 465 * Sets the control that is associated with the receiver 466 * to the argument. 467 * 468 * @param control the new control that will be contained by the receiver 469 * 470 * @exception IllegalArgumentException <ul> 471 * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li> 472 * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li> 473 * </ul> 474 * @exception SWTException <ul> 475 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 476 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 477 * </ul> 478 */ 479 public void setControl (Control control) { 480 checkWidget(); 481 if (control !is null) { 482 if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT); 483 if (control.parent !is parent) error (SWT.ERROR_INVALID_PARENT); 484 } 485 this.control = control; 486 if (control !is null) { 487 int controlWidth = itemBounds.width - MINIMUM_WIDTH; 488 if ((style & SWT.DROP_DOWN) !is 0 && itemBounds.width < preferredWidth) { 489 controlWidth -= CHEVRON_IMAGE_WIDTH + CHEVRON_HORIZONTAL_TRIM + CHEVRON_LEFT_MARGIN; 490 } 491 control.setBounds (parent.fixRectangle(itemBounds.x + MINIMUM_WIDTH, itemBounds.y, controlWidth, itemBounds.height)); 492 } 493 } 494 /** 495 * Sets the minimum size that the cool item can be resized to 496 * using the cool item's gripper, to the point specified by the arguments. 497 * 498 * @param width the minimum width of the cool item, in pixels 499 * @param height the minimum height of the cool item, in pixels 500 * 501 * @exception SWTException <ul> 502 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 503 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 504 * </ul> 505 * 506 * @since 2.0 507 */ 508 public void setMinimumSize (int width, int height) { 509 checkWidget (); 510 Point point = parent.fixPoint(width, height); 511 minimumWidth = point.x; 512 minimumHeight = point.y; 513 } 514 /** 515 * Sets the minimum size that the cool item can be resized to 516 * using the cool item's gripper, to the point specified by the argument. 517 * 518 * @param size a point representing the minimum width and height of the cool item, in pixels 519 * 520 * @exception IllegalArgumentException <ul> 521 * <li>ERROR_NULL_ARGUMENT - if the point is null</li> 522 * </ul> 523 * @exception SWTException <ul> 524 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 525 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 526 * </ul> 527 * 528 * @since 2.0 529 */ 530 public void setMinimumSize (Point size) { 531 checkWidget (); 532 if (size is null) error(SWT.ERROR_NULL_ARGUMENT); 533 setMinimumSize(size.x, size.y); 534 } 535 /** 536 * Sets the receiver's ideal size to the point specified by the arguments. 537 * 538 * @param width the new ideal width for the receiver 539 * @param height the new ideal height for the receiver 540 * 541 * @exception SWTException <ul> 542 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 543 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 544 * </ul> 545 */ 546 public void setPreferredSize (int width, int height) { 547 checkWidget(); 548 ideal = true; 549 Point point = parent.fixPoint(width, height); 550 preferredWidth = Math.max (point.x, MINIMUM_WIDTH); 551 preferredHeight = point.y; 552 } 553 /** 554 * Sets the receiver's ideal size to the point specified by the argument. 555 * 556 * @param size the new ideal size for the receiver 557 * 558 * @exception IllegalArgumentException <ul> 559 * <li>ERROR_NULL_ARGUMENT - if the point is null</li> 560 * </ul> 561 * @exception SWTException <ul> 562 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 563 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 564 * </ul> 565 */ 566 public void setPreferredSize (Point size) { 567 checkWidget(); 568 if (size is null) error(SWT.ERROR_NULL_ARGUMENT); 569 setPreferredSize(size.x, size.y); 570 } 571 /** 572 * Sets the receiver's size to the point specified by the arguments. 573 * <p> 574 * Note: Attempting to set the width or height of the 575 * receiver to a negative number will cause that 576 * value to be set to zero instead. 577 * </p> 578 * 579 * @param width the new width for the receiver 580 * @param height the new height for the receiver 581 * 582 * @exception SWTException <ul> 583 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 584 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 585 * </ul> 586 */ 587 public void setSize (int width, int height) { 588 checkWidget(); 589 Point point = parent.fixPoint(width, height); 590 width = Math.max(point.x, minimumWidth + MINIMUM_WIDTH); 591 height = point.y; 592 if (!ideal) { 593 preferredWidth = width; 594 preferredHeight = height; 595 } 596 itemBounds.width = requestedWidth = width; 597 itemBounds.height = height; 598 if (control !is null) { 599 int controlWidth = width - MINIMUM_WIDTH; 600 if ((style & SWT.DROP_DOWN) !is 0 && width < preferredWidth) { 601 controlWidth -= CHEVRON_IMAGE_WIDTH + CHEVRON_HORIZONTAL_TRIM + CHEVRON_LEFT_MARGIN; 602 } 603 control.setSize(parent.fixPoint(controlWidth, height)); 604 } 605 parent.relayout(); 606 updateChevron(); 607 } 608 /** 609 * Sets the receiver's size to the point specified by the argument. 610 * <p> 611 * Note: Attempting to set the width or height of the 612 * receiver to a negative number will cause them to be 613 * set to zero instead. 614 * </p> 615 * 616 * @param size the new size for the receiver 617 * 618 * @exception IllegalArgumentException <ul> 619 * <li>ERROR_NULL_ARGUMENT - if the point is null</li> 620 * </ul> 621 * @exception SWTException <ul> 622 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 623 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 624 * </ul> 625 */ 626 public void setSize (Point size) { 627 checkWidget(); 628 if (size is null) error (SWT.ERROR_NULL_ARGUMENT); 629 setSize (size.x, size.y); 630 } 631 void updateChevron() { 632 if (control !is null) { 633 int width = itemBounds.width; 634 if ((style & SWT.DROP_DOWN) !is 0 && width < preferredWidth) { 635 if (chevron is null) { 636 chevron = new ToolBar (parent, SWT.FLAT | SWT.NO_FOCUS); 637 ToolItem toolItem = new ToolItem (chevron, SWT.PUSH); 638 toolItem.addListener (SWT.Selection, new class () Listener { 639 public void handleEvent (Event event) { 640 this.outer.onSelection (event); 641 } 642 }); 643 } 644 int controlHeight, currentImageHeight = 0; 645 if ((parent.style & SWT.VERTICAL) !is 0) { 646 controlHeight = control.getSize ().x; 647 if (arrowImage !is null) currentImageHeight = arrowImage.getBounds().width; 648 } else { 649 controlHeight = control.getSize ().y; 650 if (arrowImage !is null) currentImageHeight = arrowImage.getBounds().height; 651 } 652 int height = Math.min (controlHeight, itemBounds.height); 653 int imageHeight = Math.max(1, height - CHEVRON_VERTICAL_TRIM); 654 if (currentImageHeight !is imageHeight) { 655 Image image = createArrowImage (CHEVRON_IMAGE_WIDTH, imageHeight); 656 chevron.getItem (0).setImage (image); 657 if (arrowImage !is null) arrowImage.dispose (); 658 arrowImage = image; 659 } 660 chevron.setBackground (parent.getBackground()); 661 chevron.setBounds (parent.fixRectangle ( 662 itemBounds.x + width - CHEVRON_LEFT_MARGIN - CHEVRON_IMAGE_WIDTH - CHEVRON_HORIZONTAL_TRIM, 663 itemBounds.y, 664 CHEVRON_IMAGE_WIDTH + CHEVRON_HORIZONTAL_TRIM, 665 height)); 666 chevron.setVisible(true); 667 } else { 668 if (chevron !is null) { 669 chevron.setVisible(false); 670 } 671 } 672 } 673 } 674 }