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.custom.ScrolledComposite; 14 15 import java.lang.all; 16 17 18 import org.eclipse.swt.SWT; 19 import org.eclipse.swt.SWTException; 20 import org.eclipse.swt.events.DisposeEvent; 21 import org.eclipse.swt.events.DisposeListener; 22 import org.eclipse.swt.graphics.Point; 23 import org.eclipse.swt.graphics.Rectangle; 24 import org.eclipse.swt.widgets.Composite; 25 import org.eclipse.swt.widgets.Control; 26 import org.eclipse.swt.widgets.Display; 27 import org.eclipse.swt.widgets.Event; 28 import org.eclipse.swt.widgets.Layout; 29 import org.eclipse.swt.widgets.Listener; 30 import org.eclipse.swt.widgets.ScrollBar; 31 import org.eclipse.swt.widgets.Shell; 32 import org.eclipse.swt.custom.ScrolledCompositeLayout; 33 34 /** 35 * A ScrolledComposite provides scrollbars and will scroll its content when the user 36 * uses the scrollbars. 37 * 38 * 39 * <p>There are two ways to use the ScrolledComposite: 40 * 41 * <p> 42 * 1) Set the size of the control that is being scrolled and the ScrolledComposite 43 * will show scrollbars when the contained control can not be fully seen. 44 * 45 * 2) The second way imitates the way a browser would work. Set the minimum size of 46 * the control and the ScrolledComposite will show scroll bars if the visible area is 47 * less than the minimum size of the control and it will expand the size of the control 48 * if the visible area is greater than the minimum size. This requires invoking 49 * both setMinWidth(), setMinHeight() and setExpandHorizontal(), setExpandVertical(). 50 * 51 * <code><pre> 52 * public static void main (String [] args) { 53 * Display display = new Display (); 54 * Color red = display.getSystemColor(SWT.COLOR_RED); 55 * Color blue = display.getSystemColor(SWT.COLOR_BLUE); 56 * Shell shell = new Shell (display); 57 * shell.setLayout(new FillLayout()); 58 * 59 * // set the size of the scrolled content - method 1 60 * final ScrolledComposite sc1 = new ScrolledComposite(shell, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); 61 * final Composite c1 = new Composite(sc1, SWT.NONE); 62 * sc1.setContent(c1); 63 * c1.setBackground(red); 64 * GridLayout layout = new GridLayout(); 65 * layout.numColumns = 4; 66 * c1.setLayout(layout); 67 * Button b1 = new Button (c1, SWT.PUSH); 68 * b1.setText("first button"); 69 * c1.setSize(c1.computeSize(SWT.DEFAULT, SWT.DEFAULT)); 70 * 71 * // set the minimum width and height of the scrolled content - method 2 72 * final ScrolledComposite sc2 = new ScrolledComposite(shell, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); 73 * sc2.setExpandHorizontal(true); 74 * sc2.setExpandVertical(true); 75 * final Composite c2 = new Composite(sc2, SWT.NONE); 76 * sc2.setContent(c2); 77 * c2.setBackground(blue); 78 * layout = new GridLayout(); 79 * layout.numColumns = 4; 80 * c2.setLayout(layout); 81 * Button b2 = new Button (c2, SWT.PUSH); 82 * b2.setText("first button"); 83 * sc2.setMinSize(c2.computeSize(SWT.DEFAULT, SWT.DEFAULT)); 84 * 85 * Button add = new Button (shell, SWT.PUSH); 86 * add.setText("add children"); 87 * final int[] index = new int[]{0}; 88 * add.addListener(SWT.Selection, new Listener() { 89 * public void handleEvent(Event e) { 90 * index[0]++; 91 * Button button = new Button(c1, SWT.PUSH); 92 * button.setText("button "+index[0]); 93 * // reset size of content so children can be seen - method 1 94 * c1.setSize(c1.computeSize(SWT.DEFAULT, SWT.DEFAULT)); 95 * c1.layout(); 96 * 97 * button = new Button(c2, SWT.PUSH); 98 * button.setText("button "+index[0]); 99 * // reset the minimum width and height so children can be seen - method 2 100 * sc2.setMinSize(c2.computeSize(SWT.DEFAULT, SWT.DEFAULT)); 101 * c2.layout(); 102 * } 103 * }); 104 * 105 * shell.open (); 106 * while (!shell.isDisposed ()) { 107 * if (!display.readAndDispatch ()) display.sleep (); 108 * } 109 * display.dispose (); 110 * } 111 * </pre></code> 112 * 113 * <dl> 114 * <dt><b>Styles:</b><dd>H_SCROLL, V_SCROLL 115 * </dl> 116 * 117 * @see <a href="http://www.eclipse.org/swt/snippets/#scrolledcomposite">ScrolledComposite snippets</a> 118 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> 119 */ 120 public class ScrolledComposite : Composite { 121 122 Control content; 123 Listener contentListener; 124 Listener filter; 125 126 int minHeight = 0; 127 int minWidth = 0; 128 bool expandHorizontal = false; 129 bool expandVertical = false; 130 bool alwaysShowScroll = false; 131 bool showFocusedControl = false; 132 133 /** 134 * Constructs a new instance of this class given its parent 135 * and a style value describing its behavior and appearance. 136 * <p> 137 * The style value is either one of the style constants defined in 138 * class <code>SWT</code> which is applicable to instances of this 139 * class, or must be built by <em>bitwise OR</em>'ing together 140 * (that is, using the <code>int</code> "|" operator) two or more 141 * of those <code>SWT</code> style constants. The class description 142 * lists the style constants that are applicable to the class. 143 * Style bits are also inherited from superclasses. 144 * </p> 145 * 146 * @param parent a widget which will be the parent of the new instance (cannot be null) 147 * @param style the style of widget to construct 148 * 149 * @exception IllegalArgumentException <ul> 150 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> 151 * </ul> 152 * @exception SWTException <ul> 153 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> 154 * </ul> 155 * 156 * @see SWT#H_SCROLL 157 * @see SWT#V_SCROLL 158 * @see #getStyle() 159 */ 160 public this(Composite parent, int style) { 161 super(parent, checkStyle(style)); 162 super.setLayout(new ScrolledCompositeLayout()); 163 ScrollBar hBar = getHorizontalBar (); 164 if (hBar !is null) { 165 hBar.setVisible(false); 166 hBar.addListener (SWT.Selection, new class() Listener { 167 public void handleEvent (Event e) { 168 hScroll(); 169 } 170 }); 171 } 172 173 ScrollBar vBar = getVerticalBar (); 174 if (vBar !is null) { 175 vBar.setVisible(false); 176 vBar.addListener (SWT.Selection, new class() Listener { 177 public void handleEvent (Event e) { 178 vScroll(); 179 } 180 }); 181 } 182 183 contentListener = new class() Listener { 184 public void handleEvent(Event e) { 185 if (e.type !is SWT.Resize) return; 186 layout(false); 187 } 188 }; 189 190 filter = new class() Listener { 191 public void handleEvent(Event event) { 192 if (auto control = cast(Control)event.widget ) { 193 if (contains(control)) showControl(control); 194 } 195 } 196 }; 197 198 addDisposeListener(new class() DisposeListener { 199 public void widgetDisposed(DisposeEvent e) { 200 getDisplay().removeFilter(SWT.FocusIn, filter); 201 } 202 }); 203 } 204 205 static int checkStyle (int style) { 206 int mask = SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT; 207 return style & mask; 208 } 209 210 bool contains(Control control) { 211 if (control is null || control.isDisposed()) return false; 212 213 Composite parent = control.getParent(); 214 while (parent !is null && !( null !is cast(Shell)parent )) { 215 if (this is parent) return true; 216 parent = parent.getParent(); 217 } 218 return false; 219 } 220 221 /** 222 * Returns the Always Show Scrollbars flag. True if the scrollbars are 223 * always shown even if they are not required. False if the scrollbars are only 224 * visible when some part of the composite needs to be scrolled to be seen. 225 * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the 226 * horizontal and vertical directions. 227 * 228 * @return the Always Show Scrollbars flag value 229 */ 230 public bool getAlwaysShowScrollBars() { 231 //checkWidget(); 232 return alwaysShowScroll; 233 } 234 235 /** 236 * Returns <code>true</code> if the content control 237 * will be expanded to fill available horizontal space. 238 * 239 * @return the receiver's horizontal expansion state 240 * 241 * @exception SWTException <ul> 242 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 243 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 244 * </ul> 245 * 246 * @since 3.2 247 */ 248 public bool getExpandHorizontal() { 249 checkWidget(); 250 return expandHorizontal; 251 } 252 253 /** 254 * Returns <code>true</code> if the content control 255 * will be expanded to fill available vertical space. 256 * 257 * @return the receiver's vertical expansion state 258 * 259 * @exception SWTException <ul> 260 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 261 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 262 * </ul> 263 * 264 * @since 3.2 265 */ 266 public bool getExpandVertical() { 267 checkWidget(); 268 return expandVertical; 269 } 270 271 /** 272 * Returns the minimum width of the content control. 273 * 274 * @return the minimum width 275 * 276 * @exception SWTException <ul> 277 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 278 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 279 * </ul> 280 * 281 * @since 3.2 282 */ 283 public int getMinWidth() { 284 checkWidget(); 285 return minWidth; 286 } 287 288 /** 289 * Returns the minimum height of the content control. 290 * 291 * @return the minimum height 292 * 293 * @exception SWTException <ul> 294 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 295 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 296 * </ul> 297 * 298 * @since 3.2 299 */ 300 public int getMinHeight() { 301 checkWidget(); 302 return minHeight; 303 } 304 305 /** 306 * Get the content that is being scrolled. 307 * 308 * @return the control displayed in the content area 309 */ 310 public Control getContent() { 311 //checkWidget(); 312 return content; 313 } 314 315 /** 316 * Returns <code>true</code> if the receiver automatically scrolls to a focused child control 317 * to make it visible. Otherwise, returns <code>false</code>. 318 * 319 * @return a bool indicating whether focused child controls are automatically scrolled into the viewport 320 * 321 * @exception SWTException <ul> 322 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 323 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 324 * </ul> 325 * 326 * @since 3.4 327 */ 328 public bool getShowFocusedControl() { 329 checkWidget(); 330 return showFocusedControl; 331 } 332 333 void hScroll() { 334 if (content is null) return; 335 Point location = content.getLocation (); 336 ScrollBar hBar = getHorizontalBar (); 337 int hSelection = hBar.getSelection (); 338 content.setLocation (-hSelection, location.y); 339 } 340 bool needHScroll(Rectangle contentRect, bool vVisible) { 341 ScrollBar hBar = getHorizontalBar(); 342 if (hBar is null) return false; 343 344 Rectangle hostRect = getBounds(); 345 int border = getBorderWidth(); 346 hostRect.width -= 2*border; 347 ScrollBar vBar = getVerticalBar(); 348 if (vVisible && vBar !is null) hostRect.width -= vBar.getSize().x; 349 350 if (!expandHorizontal && contentRect.width > hostRect.width) return true; 351 if (expandHorizontal && minWidth > hostRect.width) return true; 352 return false; 353 } 354 355 bool needVScroll(Rectangle contentRect, bool hVisible) { 356 ScrollBar vBar = getVerticalBar(); 357 if (vBar is null) return false; 358 359 Rectangle hostRect = getBounds(); 360 int border = getBorderWidth(); 361 hostRect.height -= 2*border; 362 ScrollBar hBar = getHorizontalBar(); 363 if (hVisible && hBar !is null) hostRect.height -= hBar.getSize().y; 364 365 if (!expandVertical && contentRect.height > hostRect.height) return true; 366 if (expandVertical && minHeight > hostRect.height) return true; 367 return false; 368 } 369 370 /** 371 * Return the point in the content that currently appears in the top left 372 * corner of the scrolled composite. 373 * 374 * @return the point in the content that currently appears in the top left 375 * corner of the scrolled composite. If no content has been set, this returns 376 * (0, 0). 377 * 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 * @since 2.0 384 */ 385 public Point getOrigin() { 386 checkWidget(); 387 if (content is null) return new Point(0, 0); 388 Point location = content.getLocation(); 389 return new Point(-location.x, -location.y); 390 } 391 /** 392 * Scrolls the content so that the specified point in the content is in the top 393 * left corner. If no content has been set, nothing will occur. 394 * 395 * Negative values will be ignored. Values greater than the maximum scroll 396 * distance will result in scrolling to the end of the scrollbar. 397 * 398 * @param origin the point on the content to appear in the top left corner 399 * 400 * @exception SWTException <ul> 401 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 402 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 403 * <li>ERROR_INVALID_ARGUMENT - value of origin is outside of content 404 * </ul> 405 * @since 2.0 406 */ 407 public void setOrigin(Point origin) { 408 setOrigin(origin.x, origin.y); 409 } 410 /** 411 * Scrolls the content so that the specified point in the content is in the top 412 * left corner. If no content has been set, nothing will occur. 413 * 414 * Negative values will be ignored. Values greater than the maximum scroll 415 * distance will result in scrolling to the end of the scrollbar. 416 * 417 * @param x the x coordinate of the content to appear in the top left corner 418 * 419 * @param y the y coordinate of the content to appear in the top left corner 420 * 421 * @exception SWTException <ul> 422 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 423 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 424 * </ul> 425 * 426 * @since 2.0 427 */ 428 public void setOrigin(int x, int y) { 429 checkWidget(); 430 if (content is null) return; 431 ScrollBar hBar = getHorizontalBar (); 432 if (hBar !is null) { 433 hBar.setSelection(x); 434 x = -hBar.getSelection (); 435 } else { 436 x = 0; 437 } 438 ScrollBar vBar = getVerticalBar (); 439 if (vBar !is null) { 440 vBar.setSelection(y); 441 y = -vBar.getSelection (); 442 } else { 443 y = 0; 444 } 445 content.setLocation(x, y); 446 } 447 /** 448 * Set the Always Show Scrollbars flag. True if the scrollbars are 449 * always shown even if they are not required. False if the scrollbars are only 450 * visible when some part of the composite needs to be scrolled to be seen. 451 * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the 452 * horizontal and vertical directions. 453 * 454 * @param show true to show the scrollbars even when not required, false to show scrollbars only when required 455 * 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> 459 * </ul> 460 */ 461 public void setAlwaysShowScrollBars(bool show) { 462 checkWidget(); 463 if (show is alwaysShowScroll) return; 464 alwaysShowScroll = show; 465 ScrollBar hBar = getHorizontalBar (); 466 if (hBar !is null && alwaysShowScroll) hBar.setVisible(true); 467 ScrollBar vBar = getVerticalBar (); 468 if (vBar !is null && alwaysShowScroll) vBar.setVisible(true); 469 layout(false); 470 } 471 472 /** 473 * Set the content that will be scrolled. 474 * 475 * @param content the control to be displayed in the content area 476 * 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 setContent(Control content) { 483 checkWidget(); 484 if (this.content !is null && !this.content.isDisposed()) { 485 this.content.removeListener(SWT.Resize, contentListener); 486 this.content.setBounds(new Rectangle(-200, -200, 0, 0)); 487 } 488 489 this.content = content; 490 ScrollBar vBar = getVerticalBar (); 491 ScrollBar hBar = getHorizontalBar (); 492 if (this.content !is null) { 493 if (vBar !is null) { 494 vBar.setMaximum (0); 495 vBar.setThumb (0); 496 vBar.setSelection(0); 497 } 498 if (hBar !is null) { 499 hBar.setMaximum (0); 500 hBar.setThumb (0); 501 hBar.setSelection(0); 502 } 503 content.setLocation(0, 0); 504 layout(false); 505 this.content.addListener(SWT.Resize, contentListener); 506 } else { 507 if (hBar !is null) hBar.setVisible(alwaysShowScroll); 508 if (vBar !is null) vBar.setVisible(alwaysShowScroll); 509 } 510 } 511 /** 512 * Configure the ScrolledComposite to resize the content object to be as wide as the 513 * ScrolledComposite when the width of the ScrolledComposite is greater than the 514 * minimum width specified in setMinWidth. If the ScrolledComposite is less than the 515 * minimum width, the content will not be resized and instead the horizontal scroll bar will be 516 * used to view the entire width. 517 * If expand is false, this behaviour is turned off. By default, this behaviour is turned off. 518 * 519 * @param expand true to expand the content control to fill available horizontal space 520 * 521 * @exception SWTException <ul> 522 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 523 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 524 * </ul> 525 */ 526 public void setExpandHorizontal(bool expand) { 527 checkWidget(); 528 if (expand is expandHorizontal) return; 529 expandHorizontal = expand; 530 layout(false); 531 } 532 /** 533 * Configure the ScrolledComposite to resize the content object to be as tall as the 534 * ScrolledComposite when the height of the ScrolledComposite is greater than the 535 * minimum height specified in setMinHeight. If the ScrolledComposite is less than the 536 * minimum height, the content will not be resized and instead the vertical scroll bar will be 537 * used to view the entire height. 538 * If expand is false, this behaviour is turned off. By default, this behaviour is turned off. 539 * 540 * @param expand true to expand the content control to fill available vertical space 541 * 542 * @exception SWTException <ul> 543 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 544 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 545 * </ul> 546 */ 547 public void setExpandVertical(bool expand) { 548 checkWidget(); 549 if (expand is expandVertical) return; 550 expandVertical = expand; 551 layout(false); 552 } 553 /** 554 * Sets the layout which is associated with the receiver to be 555 * the argument which may be null. 556 * <p> 557 * Note: No Layout can be set on this Control because it already 558 * manages the size and position of its children. 559 * </p> 560 * 561 * @param layout the receiver's new layout or null 562 * 563 * @exception SWTException <ul> 564 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 565 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 566 * </ul> 567 */ 568 public override void setLayout (Layout layout) { 569 checkWidget(); 570 return; 571 } 572 /** 573 * Specify the minimum height at which the ScrolledComposite will begin scrolling the 574 * content with the vertical scroll bar. This value is only relevant if 575 * setExpandVertical(true) has been set. 576 * 577 * @param height the minimum height or 0 for default height 578 * 579 * @exception SWTException <ul> 580 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 581 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 582 * </ul> 583 */ 584 public void setMinHeight(int height) { 585 setMinSize(minWidth, height); 586 } 587 /** 588 * Specify the minimum width and height at which the ScrolledComposite will begin scrolling the 589 * content with the horizontal scroll bar. This value is only relevant if 590 * setExpandHorizontal(true) and setExpandVertical(true) have been set. 591 * 592 * @param size the minimum size or null for the default size 593 * 594 * @exception SWTException <ul> 595 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 596 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 597 * </ul> 598 */ 599 public void setMinSize(Point size) { 600 if (size is null) { 601 setMinSize(0, 0); 602 } else { 603 setMinSize(size.x, size.y); 604 } 605 } 606 /** 607 * Specify the minimum width and height at which the ScrolledComposite will begin scrolling the 608 * content with the horizontal scroll bar. This value is only relevant if 609 * setExpandHorizontal(true) and setExpandVertical(true) have been set. 610 * 611 * @param width the minimum width or 0 for default width 612 * @param height the minimum height or 0 for default height 613 * 614 * @exception SWTException <ul> 615 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 616 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 617 * </ul> 618 */ 619 public void setMinSize(int width, int height) { 620 checkWidget(); 621 if (width is minWidth && height is minHeight) return; 622 minWidth = Math.max(0, width); 623 minHeight = Math.max(0, height); 624 layout(false); 625 } 626 /** 627 * Specify the minimum width at which the ScrolledComposite will begin scrolling the 628 * content with the horizontal scroll bar. This value is only relevant if 629 * setExpandHorizontal(true) has been set. 630 * 631 * @param width the minimum width or 0 for default width 632 * 633 * @exception SWTException <ul> 634 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 635 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 636 * </ul> 637 */ 638 public void setMinWidth(int width) { 639 setMinSize(width, minHeight); 640 } 641 642 /** 643 * Configure the receiver to automatically scroll to a focused child control 644 * to make it visible. 645 * 646 * If show is <code>false</code>, show a focused control is off. 647 * By default, show a focused control is off. 648 * 649 * @param show <code>true</code> to show a focused control. 650 * 651 * @exception SWTException <ul> 652 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 653 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 654 * </ul> 655 * 656 * @since 3.4 657 */ 658 public void setShowFocusedControl(bool show) { 659 checkWidget(); 660 if (showFocusedControl is show) return; 661 Display display = getDisplay(); 662 display.removeFilter(SWT.FocusIn, filter); 663 showFocusedControl = show; 664 if (!showFocusedControl) return; 665 display.addFilter(SWT.FocusIn, filter); 666 Control control = display.getFocusControl(); 667 if (contains(control)) showControl(control); 668 } 669 670 /** 671 * Scrolls the content of the receiver so that the control is visible. 672 * 673 * @param control the control to be shown 674 * 675 * @exception IllegalArgumentException <ul> 676 * <li>ERROR_NULL_ARGUMENT - if the control is null</li> 677 * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li> 678 * </ul> 679 * @exception SWTException <ul> 680 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> 681 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> 682 * </ul> 683 * 684 * @since 3.4 685 */ 686 public void showControl(Control control) { 687 checkWidget (); 688 if (control is null) SWT.error(SWT.ERROR_NULL_ARGUMENT); 689 if (control.isDisposed ()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); 690 if (!contains(control)) SWT.error(SWT.ERROR_INVALID_ARGUMENT); 691 692 Rectangle itemRect = getDisplay().map(control.getParent(), this, control.getBounds()); 693 Rectangle area = getClientArea(); 694 Point origin = getOrigin(); 695 if (itemRect.x < 0) origin.x = Math.max(0, origin.x + itemRect.x); 696 if (itemRect.y < 0) origin.y = Math.max(0, origin.y + itemRect.y); 697 if (area.width < itemRect.x + itemRect.width) origin.x = Math.max(0, origin.x + itemRect.x + itemRect.width - area.width); 698 if (area.height < itemRect.y + itemRect.height) origin.y = Math.max(0, origin.y + itemRect.y + itemRect.height - area.height); 699 setOrigin(origin); 700 } 701 702 void vScroll() { 703 if (content is null) return; 704 Point location = content.getLocation (); 705 ScrollBar vBar = getVerticalBar (); 706 int vSelection = vBar.getSelection (); 707 content.setLocation (location.x, -vSelection); 708 } 709 }