1 11 package org.eclipse.jface.window; 12 13 import java.util.ArrayList ; 14 15 import org.eclipse.jface.resource.JFaceResources; 16 import org.eclipse.core.runtime.Assert; 17 import org.eclipse.jface.util.Geometry; 18 import org.eclipse.jface.util.IPropertyChangeListener; 19 import org.eclipse.jface.util.PropertyChangeEvent; 20 import org.eclipse.swt.SWT; 21 import org.eclipse.swt.events.ShellAdapter; 22 import org.eclipse.swt.events.ShellEvent; 23 import org.eclipse.swt.events.ShellListener; 24 import org.eclipse.swt.graphics.Image; 25 import org.eclipse.swt.graphics.Point; 26 import org.eclipse.swt.graphics.Rectangle; 27 import org.eclipse.swt.layout.GridLayout; 28 import org.eclipse.swt.widgets.Composite; 29 import org.eclipse.swt.widgets.Control; 30 import org.eclipse.swt.widgets.Display; 31 import org.eclipse.swt.widgets.Event; 32 import org.eclipse.swt.widgets.Layout; 33 import org.eclipse.swt.widgets.Listener; 34 import org.eclipse.swt.widgets.Monitor; 35 import org.eclipse.swt.widgets.Shell; 36 37 84 public abstract class Window implements IShellProvider { 85 86 92 public static final int OK = 0; 93 94 100 public static final int CANCEL = 1; 101 102 106 private static Image[] defaultImages; 107 108 112 public static interface IExceptionHandler { 113 119 public void handleException(Throwable t); 120 } 121 122 125 private static class DefaultExceptionHandler implements IExceptionHandler { 126 131 public void handleException(Throwable t) { 132 if (t instanceof ThreadDeath ) { 133 throw (ThreadDeath ) t; 136 } 137 t.printStackTrace(); 139 } 140 } 141 142 145 private static IExceptionHandler exceptionHandler = new DefaultExceptionHandler(); 146 147 152 private static int orientation = SWT.NONE; 153 154 157 private static IShellProvider defaultModalParent = new IShellProvider() { 158 public Shell getShell() { 159 Display d = Display.getCurrent(); 160 161 if (d == null) { 162 return null; 163 } 164 165 Shell parent = d.getActiveShell(); 166 167 if (parent == null) { 169 parent = getModalChild(Display.getCurrent().getShells()); 171 } else { 172 Shell modalChild = getModalChild(parent.getShells()); 174 if (modalChild != null) { 175 parent = modalChild; 176 } 177 } 178 179 return parent; 180 } 181 }; 182 183 186 private IShellProvider parentShell; 187 188 193 private int shellStyle = SWT.SHELL_TRIM; 194 195 200 private WindowManager windowManager; 201 202 205 private Shell shell; 206 207 210 private Control contents; 211 212 217 private int returnCode = OK; 218 219 227 private boolean block = false; 228 229 232 private class FontChangeListener implements IPropertyChangeListener { 233 public void propertyChange(PropertyChangeEvent event) { 234 handleFontChange(event); 235 } 236 } 237 238 241 private FontChangeListener fontChangeListener; 242 243 246 private boolean resizeHasOccurred = false; 247 248 private Listener resizeListener; 249 250 262 protected Window(Shell parentShell) { 263 this(new SameShellProvider(parentShell)); 264 265 if(parentShell == null) { 266 setShellStyle(getShellStyle() | getDefaultOrientation()); 267 } 268 } 269 270 278 protected Window(IShellProvider shellProvider) { 279 Assert.isNotNull(shellProvider); 280 this.parentShell = shellProvider; 281 } 282 283 294 protected boolean canHandleShellCloseEvent() { 295 return true; 296 } 297 298 309 public boolean close() { 310 311 if (fontChangeListener != null) { 313 JFaceResources.getFontRegistry().removeListener(fontChangeListener); 314 fontChangeListener = null; 315 } 316 317 if (windowManager != null) { 319 windowManager.remove(this); 320 windowManager = null; 321 } 322 323 if (shell == null || shell.isDisposed()) { 324 return true; 325 } 326 327 shell.dispose(); 331 shell = null; 332 contents = null; 333 334 return true; 335 } 336 337 347 protected void configureShell(Shell newShell) { 348 349 if (defaultImages != null && defaultImages.length > 0) { 356 ArrayList nonDisposedImages = new ArrayList (defaultImages.length); 357 for (int i = 0; i < defaultImages.length; ++i) { 358 if (defaultImages[i] != null && !defaultImages[i].isDisposed()) { 359 nonDisposedImages.add(defaultImages[i]); 360 } 361 } 362 363 if (nonDisposedImages.size() <= 0) { 364 System.err.println("Window.configureShell: images disposed"); } else { 366 Image[] array = new Image[nonDisposedImages.size()]; 367 nonDisposedImages.toArray(array); 368 newShell.setImages(array); 369 } 370 } 371 372 Layout layout = getLayout(); 373 if (layout != null) { 374 newShell.setLayout(layout); 375 } 376 } 377 378 394 protected Layout getLayout() { 395 GridLayout layout = new GridLayout(); 396 layout.marginHeight = 0; 397 layout.marginWidth = 0; 398 return layout; 399 } 400 401 406 protected void constrainShellSize() { 407 Rectangle bounds = shell.getBounds(); 409 Rectangle constrained = getConstrainedShellBounds(bounds); 410 if (!bounds.equals(constrained)) { 411 shell.setBounds(constrained); 412 } 413 } 414 415 424 public void create() { 425 shell = createShell(); 426 contents = createContents(shell); 427 428 initializeBounds(); 431 } 432 433 457 protected Control createContents(Composite parent) { 458 return new Composite(parent, SWT.NONE); 460 } 461 462 473 protected final Shell createShell() { 474 475 Shell newParent = getParentShell(); 476 if(newParent != null && newParent.isDisposed()){ 477 parentShell = new SameShellProvider(null); 478 newParent = getParentShell(); } 480 481 Shell newShell = new Shell(newParent, getShellStyle()); 483 484 resizeListener = new Listener() { 485 public void handleEvent(Event e) { 486 resizeHasOccurred = true; 487 } 488 }; 489 490 newShell.addListener(SWT.Resize, resizeListener); 491 newShell.setData(this); 492 493 newShell.addShellListener(getShellListener()); 495 496 configureShell(newShell); 498 499 if (fontChangeListener == null) { 501 fontChangeListener = new FontChangeListener(); 502 } 503 JFaceResources.getFontRegistry().addListener(fontChangeListener); 504 505 return newShell; 506 } 507 508 515 protected Control getContents() { 516 return contents; 517 } 518 519 527 public static Image getDefaultImage() { 528 return (defaultImages == null || defaultImages.length < 1) ? null 529 : defaultImages[0]; 530 } 531 532 543 public static Image[] getDefaultImages() { 544 return (defaultImages == null ? new Image[0] : defaultImages); 545 } 546 547 559 protected Point getInitialLocation(Point initialSize) { 560 Composite parent = shell.getParent(); 561 562 Monitor monitor = shell.getDisplay().getPrimaryMonitor(); 563 if (parent != null) { 564 monitor = parent.getMonitor(); 565 } 566 567 Rectangle monitorBounds = monitor.getClientArea(); 568 Point centerPoint; 569 if (parent != null) { 570 centerPoint = Geometry.centerPoint(parent.getBounds()); 571 } else { 572 centerPoint = Geometry.centerPoint(monitorBounds); 573 } 574 575 return new Point(centerPoint.x - (initialSize.x / 2), Math.max( 576 monitorBounds.y, Math.min(centerPoint.y 577 - (initialSize.y * 2 / 3), monitorBounds.y 578 + monitorBounds.height - initialSize.y))); 579 } 580 581 588 protected Point getInitialSize() { 589 return shell.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); 590 } 591 592 600 private static Shell getModalChild(Shell[] toSearch) { 601 int modal = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL | SWT.PRIMARY_MODAL; 602 603 for (int i = toSearch.length - 1; i >= 0; i--) { 604 Shell shell = toSearch[i]; 605 606 Shell[] children = shell.getShells(); 608 Shell modalChild = getModalChild(children); 609 if (modalChild != null) { 610 return modalChild; 611 } 612 613 if (shell.isVisible() && (shell.getStyle() & modal) != 0) { 615 return shell; 616 } 617 } 618 619 return null; 620 } 621 622 628 protected Shell getParentShell() { 629 Shell parent = parentShell.getShell(); 630 631 int modal = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL | SWT.PRIMARY_MODAL; 632 633 if ((getShellStyle() & modal) != 0) { 634 if (parent == null) { 636 parent = defaultModalParent.getShell(); 637 } 638 } 639 640 return parent; 641 } 642 643 650 public int getReturnCode() { 651 return returnCode; 652 } 653 654 660 public Shell getShell() { 661 return shell; 662 } 663 664 677 protected ShellListener getShellListener() { 678 return new ShellAdapter() { 679 public void shellClosed(ShellEvent event) { 680 event.doit = false; if (canHandleShellCloseEvent()) { 682 handleShellCloseEvent(); 683 } 684 } 685 }; 686 } 687 688 698 protected int getShellStyle() { 699 return shellStyle; 700 } 701 702 707 public WindowManager getWindowManager() { 708 return windowManager; 709 } 710 711 721 protected void handleFontChange(PropertyChangeEvent event) { 722 } 724 725 734 protected void handleShellCloseEvent() { 735 setReturnCode(CANCEL); 736 close(); 737 } 738 739 751 protected void initializeBounds() { 752 if (resizeListener != null) { 753 shell.removeListener(SWT.Resize, resizeListener); 754 } 755 if (resizeHasOccurred) { return; 757 } 758 759 Point size = getInitialSize(); 760 Point location = getInitialLocation(size); 761 shell.setBounds(getConstrainedShellBounds(new Rectangle(location.x, 762 location.y, size.x, size.y))); 763 } 764 765 780 public int open() { 781 782 if (shell == null || shell.isDisposed()) { 783 shell = null; 784 create(); 786 } 787 788 constrainShellSize(); 790 791 shell.open(); 793 794 if (block) { 796 runEventLoop(shell); 797 } 798 799 return returnCode; 800 } 801 802 808 private void runEventLoop(Shell loopShell) { 809 810 Display display; 812 if (shell == null) { 813 display = Display.getCurrent(); 814 } else { 815 display = loopShell.getDisplay(); 816 } 817 818 while (loopShell != null && !loopShell.isDisposed()) { 819 try { 820 if (!display.readAndDispatch()) { 821 display.sleep(); 822 } 823 } catch (Throwable e) { 824 exceptionHandler.handleException(e); 825 } 826 } 827 display.update(); 828 } 829 830 839 public void setBlockOnOpen(boolean shouldBlock) { 840 block = shouldBlock; 841 } 842 843 851 public static void setDefaultImage(Image image) { 852 defaultImages = image == null ? null : new Image[] { image }; 853 } 854 855 866 public static void setDefaultImages(Image[] images) { 867 Image[] newArray = new Image[images.length]; 868 System.arraycopy(images, 0, newArray, 0, newArray.length); 869 defaultImages = newArray; 870 } 871 872 882 protected void setParentShell(final Shell newParentShell) { 883 Assert.isTrue((shell == null), "There must not be an existing shell."); parentShell = new SameShellProvider(newParentShell); 885 } 886 887 896 protected void setReturnCode(int code) { 897 returnCode = code; 898 } 899 900 912 private static Monitor getClosestMonitor(Display toSearch, Point toFind) { 913 int closest = Integer.MAX_VALUE; 914 915 Monitor[] monitors = toSearch.getMonitors(); 916 Monitor result = monitors[0]; 917 918 for (int idx = 0; idx < monitors.length; idx++) { 919 Monitor current = monitors[idx]; 920 921 Rectangle clientArea = current.getClientArea(); 922 923 if (clientArea.contains(toFind)) { 924 return current; 925 } 926 927 int distance = Geometry.distanceSquared(Geometry 928 .centerPoint(clientArea), toFind); 929 if (distance < closest) { 930 closest = distance; 931 result = current; 932 } 933 } 934 935 return result; 936 } 937 938 952 protected Rectangle getConstrainedShellBounds(Rectangle preferredSize) { 953 Rectangle result = new Rectangle(preferredSize.x, preferredSize.y, 954 preferredSize.width, preferredSize.height); 955 956 Monitor mon = getClosestMonitor(getShell().getDisplay(), Geometry 957 .centerPoint(result)); 958 959 Rectangle bounds = mon.getClientArea(); 960 961 if (result.height > bounds.height) { 962 result.height = bounds.height; 963 } 964 965 if (result.width > bounds.width) { 966 result.width = bounds.width; 967 } 968 969 result.x = Math.max(bounds.x, Math.min(result.x, bounds.x 970 + bounds.width - result.width)); 971 result.y = Math.max(bounds.y, Math.min(result.y, bounds.y 972 + bounds.height - result.height)); 973 974 return result; 975 } 976 977 988 protected void setShellStyle(int newShellStyle) { 989 shellStyle = newShellStyle; 990 } 991 992 1002 public void setWindowManager(WindowManager manager) { 1003 windowManager = manager; 1004 1005 1007 if (manager != null) { 1008 Window[] windows = manager.getWindows(); 1009 for (int i = 0; i < windows.length; i++) { 1010 if (windows[i] == this) { 1011 return; 1012 } 1013 } 1014 manager.add(this); 1015 } 1016 } 1017 1018 1028 public static void setExceptionHandler(IExceptionHandler handler) { 1029 if (exceptionHandler instanceof DefaultExceptionHandler) { 1030 exceptionHandler = handler; 1031 } 1032 } 1033 1034 1042 public static void setDefaultModalParent(IShellProvider provider) { 1043 defaultModalParent = provider; 1044 } 1045 1046 1057 public static int getDefaultOrientation() { 1058 return orientation; 1059 1060 } 1061 1062 1071 public static void setDefaultOrientation(int defaultOrientation) { 1072 orientation = defaultOrientation; 1073 1074 } 1075 1076} 1077 | Popular Tags |