Mercurial > projects > dwt2
comparison org.eclipse.jface/src/org/eclipse/jface/window/Window.d @ 12:bc29606a740c
Added dwt-addons in original directory structure of eclipse.org
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 14 Mar 2009 18:23:29 +0100 |
parents | |
children | 735224fcc45f |
comparison
equal
deleted
inserted
replaced
11:43904fec5dca | 12:bc29606a740c |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2000, 2007 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.jface.window.Window; | |
14 | |
15 import org.eclipse.jface.window.IShellProvider; | |
16 import org.eclipse.jface.window.WindowManager; | |
17 import org.eclipse.jface.window.SameShellProvider; | |
18 | |
19 | |
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 import org.eclipse.core.runtime.Assert; | |
37 import org.eclipse.jface.resource.JFaceResources; | |
38 import org.eclipse.jface.util.Geometry; | |
39 import org.eclipse.jface.util.IPropertyChangeListener; | |
40 import org.eclipse.jface.util.PropertyChangeEvent; | |
41 | |
42 import java.lang.all; | |
43 import java.util.ArrayList; | |
44 import java.util.Set; | |
45 import tango.io.Stdout; | |
46 | |
47 /** | |
48 * A JFace window is an object that has no visual representation (no widgets) | |
49 * until it is told to open. | |
50 * <p> | |
51 * Creating a window involves the following steps: | |
52 * <ul> | |
53 * <li>creating an instance of a concrete subclass of <code>Window</code> | |
54 * </li> | |
55 * <li>creating the window's shell and widget tree by calling | |
56 * <code>create</code> (optional)</li> | |
57 * <li>assigning the window to a window manager using | |
58 * <code>WindowManager.add</code> (optional)</li> | |
59 * <li>opening the window by calling <code>open</code></li> | |
60 * </ul> | |
61 * Opening the window will create its shell and widget tree if they have not | |
62 * already been created. When the window is closed, the shell and widget tree | |
63 * are disposed of and are no longer referenced, and the window is automatically | |
64 * removed from its window manager. A window may be reopened. | |
65 * </p> | |
66 * <p> | |
67 * The JFace window framework (this package) consists of this class, | |
68 * <code>Window</code>, the abstract base of all windows, and one concrete | |
69 * window classes (<code>ApplicationWindow</code>) which may also be | |
70 * subclassed. Clients may define additional window subclasses as required. | |
71 * </p> | |
72 * <p> | |
73 * The <code>Window</code> class provides methods that subclasses may | |
74 * override to configure the window, including: | |
75 * <ul> | |
76 * <li><code>close</code>- extend to free other SWT resources</li> | |
77 * <li><code>configureShell</code>- extend or reimplement to set shell | |
78 * properties before window opens</li> | |
79 * <li><code>createContents</code>- extend or reimplement to create controls | |
80 * before window opens</li> | |
81 * <li><code>getInitialSize</code>- reimplement to give the initial size for | |
82 * the shell</li> | |
83 * <li><code>getInitialLocation</code>- reimplement to give the initial | |
84 * location for the shell</li> | |
85 * <li><code>getShellListener</code>- extend or reimplement to receive shell | |
86 * events</li> | |
87 * <li><code>handleFontChange</code>- reimplement to respond to font changes | |
88 * </li> | |
89 * <li><code>handleShellCloseEvent</code>- extend or reimplement to handle | |
90 * shell closings</li> | |
91 * </ul> | |
92 * </p> | |
93 */ | |
94 public abstract class Window : IShellProvider { | |
95 | |
96 /** | |
97 * Standard return code constant (value 0) indicating that the window was | |
98 * opened. | |
99 * | |
100 * @see #open | |
101 */ | |
102 public static const int OK = 0; | |
103 | |
104 /** | |
105 * Standard return code constant (value 1) indicating that the window was | |
106 * canceled. | |
107 * | |
108 * @see #open | |
109 */ | |
110 public static const int CANCEL = 1; | |
111 | |
112 /** | |
113 * An array of images to be used for the window. It is expected that the | |
114 * array will contain the same icon rendered at different resolutions. | |
115 */ | |
116 private static Image[] defaultImages; | |
117 | |
118 /** | |
119 * This interface defines a Exception Handler which can be set as a global | |
120 * handler and will be called if an exception happens in the event loop. | |
121 */ | |
122 public interface IExceptionHandler { | |
123 /** | |
124 * Handle the exception. | |
125 * | |
126 * @param t | |
127 * The exception that occured. | |
128 */ | |
129 public void handleException(Exception t); | |
130 } | |
131 | |
132 /** | |
133 * Defines a default exception handler. | |
134 */ | |
135 private static class DefaultExceptionHandler : IExceptionHandler { | |
136 /* | |
137 * (non-Javadoc) | |
138 * | |
139 * @see org.eclipse.jface.window.Window.IExceptionHandler#handleException(java.lang.Throwable) | |
140 */ | |
141 public void handleException(Exception t) { | |
142 /+ | |
143 if (t instanceof ThreadDeath) { | |
144 // Don't catch ThreadDeath as this is a normal occurrence when | |
145 // the thread dies | |
146 throw (ThreadDeath) t; | |
147 } | |
148 +/ | |
149 // Try to keep running. | |
150 ExceptionPrintStackTrace(t); | |
151 } | |
152 } | |
153 | |
154 /** | |
155 * The exception handler for this application. | |
156 */ | |
157 private static IExceptionHandler exceptionHandler_; | |
158 private static IExceptionHandler exceptionHandler(){ | |
159 if( exceptionHandler_ is null ){ | |
160 synchronized if( exceptionHandler_ is null ){ | |
161 exceptionHandler_ = new DefaultExceptionHandler(); | |
162 } | |
163 } | |
164 return exceptionHandler_; | |
165 } | |
166 /** | |
167 * The default orientation of the window. By default | |
168 * it is SWT#NONE but it can also be SWT#LEFT_TO_RIGHT | |
169 * or SWT#RIGHT_TO_LEFT | |
170 */ | |
171 private static int orientation = SWT.NONE; | |
172 | |
173 /** | |
174 * Object used to locate the default parent for modal shells | |
175 */ | |
176 private static IShellProvider defaultModalParent_; | |
177 private static IShellProvider defaultModalParent(){ | |
178 if( defaultModalParent_ is null ){ | |
179 synchronized if( defaultModalParent_ is null ){ | |
180 defaultModalParent_ = new class IShellProvider { | |
181 public Shell getShell() { | |
182 Display d = Display.getCurrent(); | |
183 | |
184 if (d is null) { | |
185 return null; | |
186 } | |
187 | |
188 Shell parent = d.getActiveShell(); | |
189 | |
190 // Make sure we don't pick a parent that has a modal child (this can lock the app) | |
191 if (parent is null) { | |
192 // If this is a top-level window, then there must not be any open modal windows. | |
193 parent = getModalChild(Display.getCurrent().getShells()); | |
194 } else { | |
195 // If we picked a parent with a modal child, use the modal child instead | |
196 Shell modalChild = getModalChild(parent.getShells()); | |
197 if (modalChild !is null) { | |
198 parent = modalChild; | |
199 } | |
200 } | |
201 | |
202 return parent; | |
203 } | |
204 }; | |
205 } | |
206 } | |
207 return defaultModalParent_; | |
208 } | |
209 | |
210 /** | |
211 * Object that returns the parent shell. | |
212 */ | |
213 private IShellProvider parentShell; | |
214 | |
215 /** | |
216 * Shell style bits. | |
217 * | |
218 * @see #setShellStyle | |
219 */ | |
220 private int shellStyle = SWT.SHELL_TRIM; | |
221 | |
222 /** | |
223 * Window manager, or <code>null</code> if none. | |
224 * | |
225 * @see #setWindowManager | |
226 */ | |
227 private WindowManager windowManager; | |
228 | |
229 /** | |
230 * Window shell, or <code>null</code> if none. | |
231 */ | |
232 private Shell shell; | |
233 | |
234 /** | |
235 * Top level SWT control, or <code>null</code> if none | |
236 */ | |
237 private Control contents; | |
238 | |
239 /** | |
240 * Window return code; initially <code>OK</code>. | |
241 * | |
242 * @see #setReturnCode | |
243 */ | |
244 private int returnCode = OK; | |
245 | |
246 /** | |
247 * <code>true</code> if the <code>open</code> method should not return | |
248 * until the window closes, and <code>false</code> if the | |
249 * <code>open</code> method should return immediately; initially | |
250 * <code>false</code> (non-blocking). | |
251 * | |
252 * @see #setBlockOnOpen | |
253 */ | |
254 private bool block = false; | |
255 | |
256 /** | |
257 * Internal class for informing this window when fonts change. | |
258 */ | |
259 private class FontChangeListener : IPropertyChangeListener { | |
260 public void propertyChange(PropertyChangeEvent event) { | |
261 handleFontChange(event); | |
262 } | |
263 } | |
264 | |
265 /** | |
266 * Internal font change listener. | |
267 */ | |
268 private FontChangeListener fontChangeListener; | |
269 | |
270 /** | |
271 * Internal fields to detect if shell size has been set | |
272 */ | |
273 private bool resizeHasOccurred = false; | |
274 | |
275 private Listener resizeListener; | |
276 | |
277 /** | |
278 * Creates a window instance, whose shell will be created under the given | |
279 * parent shell. Note that the window will have no visual representation | |
280 * until it is told to open. By default, <code>open</code> does not block. | |
281 * | |
282 * @param parentShell | |
283 * the parent shell, or <code>null</code> to create a top-level | |
284 * shell. Try passing "(Shell)null" to this method instead of "null" | |
285 * if your compiler complains about an ambiguity error. | |
286 * @see #setBlockOnOpen | |
287 * @see #getDefaultOrientation() | |
288 */ | |
289 protected this(Shell parentShell) { | |
290 this(new SameShellProvider(parentShell)); | |
291 | |
292 if(parentShell is null) { | |
293 setShellStyle(getShellStyle() | getDefaultOrientation()); | |
294 } | |
295 } | |
296 | |
297 /** | |
298 * Creates a new window which will create its shell as a child of whatever | |
299 * the given shellProvider returns. | |
300 * | |
301 * @param shellProvider object that will return the current parent shell. Not null. | |
302 * | |
303 * @since 3.1 | |
304 */ | |
305 protected this(IShellProvider shellProvider) { | |
306 Assert.isNotNull(cast(Object)shellProvider); | |
307 this.parentShell = shellProvider; | |
308 } | |
309 | |
310 /** | |
311 * Determines if the window should handle the close event or do nothing. | |
312 * <p> | |
313 * The default implementation of this framework method returns | |
314 * <code>true</code>, which will allow the | |
315 * <code>handleShellCloseEvent</code> method to be called. Subclasses may | |
316 * extend or reimplement. | |
317 * </p> | |
318 * | |
319 * @return whether the window should handle the close event. | |
320 */ | |
321 protected bool canHandleShellCloseEvent() { | |
322 return true; | |
323 } | |
324 | |
325 /** | |
326 * Closes this window, disposes its shell, and removes this window from its | |
327 * window manager (if it has one). | |
328 * <p> | |
329 * This framework method may be extended (<code>super.close</code> must | |
330 * be called). | |
331 * </p> | |
332 * <p> | |
333 * Note that in order to prevent recursive calls to this method | |
334 * it does not call <code>Shell#close()</code>. As a result <code>ShellListener</code>s | |
335 * will not receive a <code>shellClosed</code> event. | |
336 * </p> | |
337 * | |
338 * @return <code>true</code> if the window is (or was already) closed, and | |
339 * <code>false</code> if it is still open | |
340 */ | |
341 public bool close() { | |
342 | |
343 // stop listening for font changes | |
344 if (fontChangeListener !is null) { | |
345 JFaceResources.getFontRegistry().removeListener(fontChangeListener); | |
346 fontChangeListener = null; | |
347 } | |
348 | |
349 // remove this window from a window manager if it has one | |
350 if (windowManager !is null) { | |
351 windowManager.remove(this); | |
352 windowManager = null; | |
353 } | |
354 | |
355 if (shell is null || shell.isDisposed()) { | |
356 return true; | |
357 } | |
358 | |
359 // If we "close" the shell recursion will occur. | |
360 // Instead, we need to "dispose" the shell to remove it from the | |
361 // display. | |
362 shell.dispose(); | |
363 shell = null; | |
364 contents = null; | |
365 | |
366 return true; | |
367 } | |
368 | |
369 /** | |
370 * Configures the given shell in preparation for opening this window in it. | |
371 * <p> | |
372 * The default implementation of this framework method sets the shell's | |
373 * image and gives it a grid layout. Subclasses may extend or reimplement. | |
374 * </p> | |
375 * | |
376 * @param newShell | |
377 * the shell | |
378 */ | |
379 protected void configureShell(Shell newShell) { | |
380 | |
381 // The single image version of this code had a comment related to bug | |
382 // 46624, | |
383 // and some code that did nothing if the stored image was already | |
384 // disposed. | |
385 // The equivalent in the multi-image version seems to be to remove the | |
386 // disposed images from the array passed to the shell. | |
387 if (defaultImages !is null && defaultImages.length > 0) { | |
388 ArrayList nonDisposedImages = new ArrayList(defaultImages.length); | |
389 for (int i = 0; i < defaultImages.length; ++i) { | |
390 if (defaultImages[i] !is null && !defaultImages[i].isDisposed()) { | |
391 nonDisposedImages.add(defaultImages[i]); | |
392 } | |
393 } | |
394 | |
395 if (nonDisposedImages.size() <= 0) { | |
396 Stderr.formatln("Window.configureShell: images disposed"); //$NON-NLS-1$ | |
397 } else { | |
398 newShell.setImages(arraycast!(Image)(nonDisposedImages.toArray())); | |
399 } | |
400 } | |
401 | |
402 Layout layout = getLayout(); | |
403 if (layout !is null) { | |
404 newShell.setLayout(layout); | |
405 } | |
406 } | |
407 | |
408 /** | |
409 * Creates the layout for the shell. The layout created here will be | |
410 * attached to the composite passed into createContents. The default | |
411 * implementation returns a GridLayout with no margins. Subclasses that | |
412 * change the layout type by overriding this method should also override | |
413 * createContents. | |
414 * | |
415 * <p> | |
416 * A return value of null indicates that no layout should be attached to the | |
417 * composite. In this case, the layout may be attached within | |
418 * createContents. | |
419 * </p> | |
420 * | |
421 * @return a newly created Layout or null if no layout should be attached. | |
422 * @since 3.0 | |
423 */ | |
424 protected Layout getLayout() { | |
425 GridLayout layout = new GridLayout(); | |
426 layout.marginHeight = 0; | |
427 layout.marginWidth = 0; | |
428 return layout; | |
429 } | |
430 | |
431 /** | |
432 * Constrain the shell size to be no larger than the display bounds. | |
433 * | |
434 * @since 2.0 | |
435 */ | |
436 protected void constrainShellSize() { | |
437 // limit the shell size to the display size | |
438 Rectangle bounds = shell.getBounds(); | |
439 Rectangle constrained = getConstrainedShellBounds(bounds); | |
440 if (!bounds.opEquals(constrained)) { | |
441 shell.setBounds(constrained); | |
442 } | |
443 } | |
444 | |
445 /** | |
446 * Creates this window's widgetry in a new top-level shell. | |
447 * <p> | |
448 * The default implementation of this framework method creates this window's | |
449 * shell (by calling <code>createShell</code>), and its controls (by | |
450 * calling <code>createContents</code>), then initializes this window's | |
451 * shell bounds (by calling <code>initializeBounds</code>). | |
452 * </p> | |
453 */ | |
454 public void create() { | |
455 shell = createShell(); | |
456 contents = createContents(shell); | |
457 | |
458 //initialize the bounds of the shell to that appropriate for the | |
459 // contents | |
460 initializeBounds(); | |
461 } | |
462 | |
463 /** | |
464 * Creates and returns this window's contents. Subclasses may attach any | |
465 * number of children to the parent. As a convenience, the return value of | |
466 * this method will be remembered and returned by subsequent calls to | |
467 * getContents(). Subclasses may modify the parent's layout if they overload | |
468 * getLayout() to return null. | |
469 * | |
470 * <p> | |
471 * It is common practise to create and return a single composite that | |
472 * contains the entire window contents. | |
473 * </p> | |
474 * | |
475 * <p> | |
476 * The default implementation of this framework method creates an instance | |
477 * of <code>Composite</code>. Subclasses may override. | |
478 * </p> | |
479 * | |
480 * @param parent | |
481 * the parent composite for the controls in this window. The type | |
482 * of layout used is determined by getLayout() | |
483 * | |
484 * @return the control that will be returned by subsequent calls to | |
485 * getContents() | |
486 */ | |
487 protected Control createContents(Composite parent) { | |
488 // by default, just create a composite | |
489 return new Composite(parent, SWT.NONE); | |
490 } | |
491 | |
492 /** | |
493 * Creates and returns this window's shell. | |
494 * <p> | |
495 * The default implementation of this framework method creates a new shell | |
496 * and configures it using <code/>configureShell</code>. Rather than | |
497 * override this method, subclasses should instead override | |
498 * <code/>configureShell</code>. | |
499 * </p> | |
500 * | |
501 * @return the shell | |
502 */ | |
503 protected final Shell createShell() { | |
504 | |
505 Shell newParent = getParentShell(); | |
506 if(newParent !is null && newParent.isDisposed()){ | |
507 parentShell = new SameShellProvider(null); | |
508 newParent = getParentShell();//Find a better parent | |
509 } | |
510 | |
511 //Create the shell | |
512 Shell newShell = new Shell(newParent, getShellStyle()); | |
513 | |
514 resizeListener = new class Listener { | |
515 public void handleEvent(Event e) { | |
516 resizeHasOccurred = true; | |
517 } | |
518 }; | |
519 | |
520 newShell.addListener(SWT.Resize, resizeListener); | |
521 newShell.setData(this); | |
522 | |
523 //Add a listener | |
524 newShell.addShellListener(getShellListener()); | |
525 | |
526 //Set the layout | |
527 configureShell(newShell); | |
528 | |
529 //Register for font changes | |
530 if (fontChangeListener is null) { | |
531 fontChangeListener = new FontChangeListener(); | |
532 } | |
533 JFaceResources.getFontRegistry().addListener(fontChangeListener); | |
534 | |
535 return newShell; | |
536 } | |
537 | |
538 /** | |
539 * Returns the top level control for this window. The parent of this control | |
540 * is the shell. | |
541 * | |
542 * @return the top level control, or <code>null</code> if this window's | |
543 * control has not been created yet | |
544 */ | |
545 protected Control getContents() { | |
546 return contents; | |
547 } | |
548 | |
549 /** | |
550 * Returns the default image. This is the image that will be used for | |
551 * windows that have no shell image at the time they are opened. There is no | |
552 * default image unless one is installed via <code>setDefaultImage</code>. | |
553 * | |
554 * @return the default image, or <code>null</code> if none | |
555 * @see #setDefaultImage | |
556 */ | |
557 public static Image getDefaultImage() { | |
558 return (defaultImages is null || defaultImages.length < 1) ? null | |
559 : defaultImages[0]; | |
560 } | |
561 | |
562 /** | |
563 * Returns the array of default images to use for newly opened windows. It | |
564 * is expected that the array will contain the same icon rendered at | |
565 * different resolutions. | |
566 * | |
567 * @see org.eclipse.swt.widgets.Decorations#setImages(org.eclipse.swt.graphics.Image[]) | |
568 * | |
569 * @return the array of images to be used when a new window is opened | |
570 * @see #setDefaultImages | |
571 * @since 3.0 | |
572 */ | |
573 public static Image[] getDefaultImages() { | |
574 return (defaultImages is null ? new Image[0] : defaultImages); | |
575 } | |
576 | |
577 /** | |
578 * Returns the initial location to use for the shell. The default | |
579 * implementation centers the shell horizontally (1/2 of the difference to | |
580 * the left and 1/2 to the right) and vertically (1/3 above and 2/3 below) | |
581 * relative to the parent shell, or display bounds if there is no parent | |
582 * shell. | |
583 * | |
584 * @param initialSize | |
585 * the initial size of the shell, as returned by | |
586 * <code>getInitialSize</code>. | |
587 * @return the initial location of the shell | |
588 */ | |
589 protected Point getInitialLocation(Point initialSize) { | |
590 Composite parent = shell.getParent(); | |
591 | |
592 org.eclipse.swt.widgets.Monitor.Monitor monitor = shell.getDisplay().getPrimaryMonitor(); | |
593 if (parent !is null) { | |
594 monitor = parent.getMonitor(); | |
595 } | |
596 | |
597 Rectangle monitorBounds = monitor.getClientArea(); | |
598 Point centerPoint; | |
599 if (parent !is null) { | |
600 centerPoint = Geometry.centerPoint(parent.getBounds()); | |
601 } else { | |
602 centerPoint = Geometry.centerPoint(monitorBounds); | |
603 } | |
604 | |
605 return new Point(centerPoint.x - (initialSize.x / 2), Math.max( | |
606 monitorBounds.y, Math.min(centerPoint.y | |
607 - (initialSize.y * 2 / 3), monitorBounds.y | |
608 + monitorBounds.height - initialSize.y))); | |
609 } | |
610 | |
611 /** | |
612 * Returns the initial size to use for the shell. The default implementation | |
613 * returns the preferred size of the shell, using | |
614 * <code>Shell.computeSize(SWT.DEFAULT, SWT.DEFAULT, true)</code>. | |
615 * | |
616 * @return the initial size of the shell | |
617 */ | |
618 protected Point getInitialSize() { | |
619 return shell.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); | |
620 } | |
621 | |
622 /** | |
623 * Returns the most specific modal child from the given list of Shells. | |
624 * | |
625 * @param toSearch shells to search for modal children | |
626 * @return the most specific modal child, or null if none | |
627 * | |
628 * @since 3.1 | |
629 */ | |
630 private static Shell getModalChild(Shell[] toSearch) { | |
631 int modal = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL | SWT.PRIMARY_MODAL; | |
632 | |
633 for (int i = toSearch.length - 1; i >= 0; i--) { | |
634 Shell shell = toSearch[i]; | |
635 | |
636 // Check if this shell has a modal child | |
637 Shell[] children = shell.getShells(); | |
638 Shell modalChild = getModalChild(children); | |
639 if (modalChild !is null) { | |
640 return modalChild; | |
641 } | |
642 | |
643 // If not, check if this shell is modal itself | |
644 if (shell.isVisible() && (shell.getStyle() & modal) !is 0) { | |
645 return shell; | |
646 } | |
647 } | |
648 | |
649 return null; | |
650 } | |
651 | |
652 /** | |
653 * Returns parent shell, under which this window's shell is created. | |
654 * | |
655 * @return the parent shell, or <code>null</code> if there is no parent | |
656 * shell | |
657 */ | |
658 protected Shell getParentShell() { | |
659 Shell parent = parentShell.getShell(); | |
660 | |
661 int modal = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL | SWT.PRIMARY_MODAL; | |
662 | |
663 if ((getShellStyle() & modal) !is 0) { | |
664 // If this is a modal shell with no parent, pick a shell using defaultModalParent. | |
665 if (parent is null) { | |
666 parent = defaultModalParent.getShell(); | |
667 } | |
668 } | |
669 | |
670 return parent; | |
671 } | |
672 | |
673 /** | |
674 * Returns this window's return code. A window's return codes are | |
675 * window-specific, although two standard return codes are predefined: | |
676 * <code>OK</code> and <code>CANCEL</code>. | |
677 * | |
678 * @return the return code | |
679 */ | |
680 public int getReturnCode() { | |
681 return returnCode; | |
682 } | |
683 | |
684 /** | |
685 * Returns this window's shell. | |
686 * | |
687 * @return this window's shell, or <code>null</code> if this window's | |
688 * shell has not been created yet | |
689 */ | |
690 public Shell getShell() { | |
691 return shell; | |
692 } | |
693 | |
694 /** | |
695 * Returns a shell listener. This shell listener gets registered with this | |
696 * window's shell. | |
697 * <p> | |
698 * The default implementation of this framework method returns a new | |
699 * listener that makes this window the active window for its window manager | |
700 * (if it has one) when the shell is activated, and calls the framework | |
701 * method <code>handleShellCloseEvent</code> when the shell is closed. | |
702 * Subclasses may extend or reimplement. | |
703 * </p> | |
704 * | |
705 * @return a shell listener | |
706 */ | |
707 protected ShellListener getShellListener() { | |
708 return new class ShellAdapter { | |
709 public void shellClosed(ShellEvent event) { | |
710 event.doit = false; // don't close now | |
711 if (canHandleShellCloseEvent()) { | |
712 handleShellCloseEvent(); | |
713 } | |
714 } | |
715 }; | |
716 } | |
717 | |
718 /** | |
719 * Returns the shell style bits. | |
720 * <p> | |
721 * The default value is <code>SWT.CLOSE|SWT.MIN|SWT.MAX|SWT.RESIZE</code>. | |
722 * Subclassers should call <code>setShellStyle</code> to change this | |
723 * value, rather than overriding this method. | |
724 * </p> | |
725 * | |
726 * @return the shell style bits | |
727 */ | |
728 protected int getShellStyle() { | |
729 return shellStyle; | |
730 } | |
731 | |
732 /** | |
733 * Returns the window manager of this window. | |
734 * | |
735 * @return the WindowManager, or <code>null</code> if none | |
736 */ | |
737 public WindowManager getWindowManager() { | |
738 return windowManager; | |
739 } | |
740 | |
741 /** | |
742 * Notifies of a font property change. | |
743 * <p> | |
744 * The default implementation of this framework method does nothing. | |
745 * Subclasses may reimplement. | |
746 * </p> | |
747 * | |
748 * @param event | |
749 * the property change event detailing what changed | |
750 */ | |
751 protected void handleFontChange(PropertyChangeEvent event) { | |
752 // do nothing | |
753 } | |
754 | |
755 /** | |
756 * Notifies that the window's close button was pressed, the close menu was | |
757 * selected, or the ESCAPE key pressed. | |
758 * <p> | |
759 * The default implementation of this framework method sets the window's | |
760 * return code to <code>CANCEL</code> and closes the window using | |
761 * <code>close</code>. Subclasses may extend or reimplement. | |
762 * </p> | |
763 */ | |
764 protected void handleShellCloseEvent() { | |
765 setReturnCode(CANCEL); | |
766 close(); | |
767 } | |
768 | |
769 /** | |
770 * Initializes the location and size of this window's SWT shell after it has | |
771 * been created. | |
772 * <p> | |
773 * This framework method is called by the <code>create</code> framework | |
774 * method. The default implementation calls <code>getInitialSize</code> | |
775 * and <code>getInitialLocation</code> and passes the results to | |
776 * <code>Shell.setBounds</code>. This is only done if the bounds of the | |
777 * shell have not already been modified. Subclasses may extend or | |
778 * reimplement. | |
779 * </p> | |
780 */ | |
781 protected void initializeBounds() { | |
782 if (resizeListener !is null) { | |
783 shell.removeListener(SWT.Resize, resizeListener); | |
784 } | |
785 if (resizeHasOccurred) { // Check if shell size has been set already. | |
786 return; | |
787 } | |
788 | |
789 Point size = getInitialSize(); | |
790 Point location = getInitialLocation(size); | |
791 shell.setBounds(getConstrainedShellBounds(new Rectangle(location.x, | |
792 location.y, size.x, size.y))); | |
793 } | |
794 | |
795 /** | |
796 * Opens this window, creating it first if it has not yet been created. | |
797 * <p> | |
798 * If this window has been configured to block on open ( | |
799 * <code>setBlockOnOpen</code>), this method waits until the window is | |
800 * closed by the end user, and then it returns the window's return code; | |
801 * otherwise, this method returns immediately. A window's return codes are | |
802 * window-specific, although two standard return codes are predefined: | |
803 * <code>OK</code> and <code>CANCEL</code>. | |
804 * </p> | |
805 * | |
806 * @return the return code | |
807 * | |
808 * @see #create() | |
809 */ | |
810 public int open() { | |
811 | |
812 if (shell is null || shell.isDisposed()) { | |
813 shell = null; | |
814 // create the window | |
815 create(); | |
816 } | |
817 | |
818 // limit the shell size to the display size | |
819 constrainShellSize(); | |
820 | |
821 // open the window | |
822 shell.open(); | |
823 | |
824 // run the event loop if specified | |
825 if (block) { | |
826 runEventLoop(shell); | |
827 } | |
828 | |
829 return returnCode; | |
830 } | |
831 | |
832 /** | |
833 * Runs the event loop for the given shell. | |
834 * | |
835 * @param loopShell | |
836 * the shell | |
837 */ | |
838 private void runEventLoop(Shell loopShell) { | |
839 | |
840 //Use the display provided by the shell if possible | |
841 Display display; | |
842 if (shell is null) { | |
843 display = Display.getCurrent(); | |
844 } else { | |
845 display = loopShell.getDisplay(); | |
846 } | |
847 | |
848 while (loopShell !is null && !loopShell.isDisposed()) { | |
849 try { | |
850 if (!display.readAndDispatch()) { | |
851 display.sleep(); | |
852 } | |
853 } catch (Exception e) { | |
854 exceptionHandler.handleException(e); | |
855 } | |
856 } | |
857 display.update(); | |
858 } | |
859 | |
860 /** | |
861 * Sets whether the <code>open</code> method should block until the window | |
862 * closes. | |
863 * | |
864 * @param shouldBlock | |
865 * <code>true</code> if the <code>open</code> method should | |
866 * not return until the window closes, and <code>false</code> | |
867 * if the <code>open</code> method should return immediately | |
868 */ | |
869 public void setBlockOnOpen(bool shouldBlock) { | |
870 block = shouldBlock; | |
871 } | |
872 | |
873 /** | |
874 * Sets the default image. This is the image that will be used for windows | |
875 * that have no shell image at the time they are opened. There is no default | |
876 * image unless one is installed via this method. | |
877 * | |
878 * @param image | |
879 * the default image, or <code>null</code> if none | |
880 */ | |
881 public static void setDefaultImage(Image image) { | |
882 defaultImages = image is null ? null : [ image ]; | |
883 } | |
884 | |
885 /** | |
886 * Sets the array of default images to use for newly opened windows. It is | |
887 * expected that the array will contain the same icon rendered at different | |
888 * resolutions. | |
889 * | |
890 * @see org.eclipse.swt.widgets.Decorations#setImages(org.eclipse.swt.graphics.Image[]) | |
891 * | |
892 * @param images | |
893 * the array of images to be used when this window is opened | |
894 * @since 3.0 | |
895 */ | |
896 public static void setDefaultImages(Image[] images) { | |
897 Image[] newArray = new Image[images.length]; | |
898 System.arraycopy(images, 0, newArray, 0, newArray.length); | |
899 defaultImages = newArray; | |
900 } | |
901 | |
902 /** | |
903 * Changes the parent shell. This is only safe to use when the shell is not | |
904 * yet realized (i.e., created). Once the shell is created, it must be | |
905 * disposed (i.e., closed) before this method can be called. | |
906 * | |
907 * @param newParentShell | |
908 * The new parent shell; this value may be <code>null</code> if | |
909 * there is to be no parent. | |
910 * @since 3.1 | |
911 */ | |
912 protected void setParentShell(Shell newParentShell) { | |
913 Assert.isTrue((shell is null), "There must not be an existing shell."); //$NON-NLS-1$ | |
914 parentShell = new SameShellProvider(newParentShell); | |
915 } | |
916 | |
917 /** | |
918 * Sets this window's return code. The return code is automatically returned | |
919 * by <code>open</code> if block on open is enabled. For non-blocking | |
920 * opens, the return code needs to be retrieved manually using | |
921 * <code>getReturnCode</code>. | |
922 * | |
923 * @param code | |
924 * the return code | |
925 */ | |
926 protected void setReturnCode(int code) { | |
927 returnCode = code; | |
928 } | |
929 | |
930 /** | |
931 * Returns the monitor whose client area contains the given point. If no | |
932 * monitor contains the point, returns the monitor that is closest to the | |
933 * point. If this is ever made public, it should be moved into a separate | |
934 * utility class. | |
935 * | |
936 * @param toSearch | |
937 * point to find (display coordinates) | |
938 * @param toFind | |
939 * point to find (display coordinates) | |
940 * @return the montor closest to the given point | |
941 */ | |
942 private static org.eclipse.swt.widgets.Monitor.Monitor getClosestMonitor(Display toSearch, Point toFind) { | |
943 int closest = Integer.MAX_VALUE; | |
944 | |
945 org.eclipse.swt.widgets.Monitor.Monitor[] monitors = toSearch.getMonitors(); | |
946 org.eclipse.swt.widgets.Monitor.Monitor result = monitors[0]; | |
947 | |
948 for (int idx = 0; idx < monitors.length; idx++) { | |
949 org.eclipse.swt.widgets.Monitor.Monitor current = monitors[idx]; | |
950 | |
951 Rectangle clientArea = current.getClientArea(); | |
952 | |
953 if (clientArea.contains(toFind)) { | |
954 return current; | |
955 } | |
956 | |
957 int distance = Geometry.distanceSquared(Geometry | |
958 .centerPoint(clientArea), toFind); | |
959 if (distance < closest) { | |
960 closest = distance; | |
961 result = current; | |
962 } | |
963 } | |
964 | |
965 return result; | |
966 } | |
967 | |
968 /** | |
969 * Given the desired position of the window, this method returns an adjusted | |
970 * position such that the window is no larger than its monitor, and does not | |
971 * extend beyond the edge of the monitor. This is used for computing the | |
972 * initial window position, and subclasses can use this as a utility method | |
973 * if they want to limit the region in which the window may be moved. | |
974 * | |
975 * @param preferredSize | |
976 * the preferred position of the window | |
977 * @return a rectangle as close as possible to preferredSize that does not | |
978 * extend outside the monitor | |
979 * | |
980 * @since 3.0 | |
981 */ | |
982 protected Rectangle getConstrainedShellBounds(Rectangle preferredSize) { | |
983 Rectangle result = new Rectangle(preferredSize.x, preferredSize.y, | |
984 preferredSize.width, preferredSize.height); | |
985 | |
986 org.eclipse.swt.widgets.Monitor.Monitor mon = getClosestMonitor(getShell().getDisplay(), Geometry | |
987 .centerPoint(result)); | |
988 | |
989 Rectangle bounds = mon.getClientArea(); | |
990 | |
991 if (result.height > bounds.height) { | |
992 result.height = bounds.height; | |
993 } | |
994 | |
995 if (result.width > bounds.width) { | |
996 result.width = bounds.width; | |
997 } | |
998 | |
999 result.x = Math.max(bounds.x, Math.min(result.x, bounds.x | |
1000 + bounds.width - result.width)); | |
1001 result.y = Math.max(bounds.y, Math.min(result.y, bounds.y | |
1002 + bounds.height - result.height)); | |
1003 | |
1004 return result; | |
1005 } | |
1006 | |
1007 /** | |
1008 * Sets the shell style bits. This method has no effect after the shell is | |
1009 * created. | |
1010 * <p> | |
1011 * The shell style bits are used by the framework method | |
1012 * <code>createShell</code> when creating this window's shell. | |
1013 * </p> | |
1014 * | |
1015 * @param newShellStyle | |
1016 * the new shell style bits | |
1017 */ | |
1018 protected void setShellStyle(int newShellStyle) { | |
1019 shellStyle = newShellStyle; | |
1020 } | |
1021 | |
1022 /** | |
1023 * Sets the window manager of this window. | |
1024 * <p> | |
1025 * Note that this method is used by <code>WindowManager</code> to maintain | |
1026 * a backpointer. Clients must not call the method directly. | |
1027 * </p> | |
1028 * | |
1029 * @param manager | |
1030 * the window manager, or <code>null</code> if none | |
1031 */ | |
1032 public void setWindowManager(WindowManager manager) { | |
1033 windowManager = manager; | |
1034 | |
1035 // Code to detect invalid usage | |
1036 | |
1037 if (manager !is null) { | |
1038 Window[] windows = manager.getWindows(); | |
1039 for (int i = 0; i < windows.length; i++) { | |
1040 if (windows[i] is this) { | |
1041 return; | |
1042 } | |
1043 } | |
1044 manager.add(this); | |
1045 } | |
1046 } | |
1047 | |
1048 /** | |
1049 * Sets the exception handler for this application. | |
1050 * <p> | |
1051 * Note that the handler may only be set once. Subsequent calls to this method will be | |
1052 * ignored. | |
1053 * <p> | |
1054 * | |
1055 * @param handler | |
1056 * the exception handler for the application. | |
1057 */ | |
1058 public static void setExceptionHandler(IExceptionHandler handler) { | |
1059 if ( cast(DefaultExceptionHandler)exceptionHandler ) { | |
1060 exceptionHandler_ = handler; | |
1061 } | |
1062 } | |
1063 | |
1064 /** | |
1065 * Sets the default parent for modal Windows. This will be used to locate | |
1066 * the parent for any modal Window constructed with a null parent. | |
1067 * | |
1068 * @param provider shell provider that will be used to locate the parent shell | |
1069 * whenever a Window is created with a null parent | |
1070 * @since 3.1 | |
1071 */ | |
1072 public static void setDefaultModalParent(IShellProvider provider) { | |
1073 defaultModalParent_ = provider; | |
1074 } | |
1075 | |
1076 /** | |
1077 * Gets the default orientation for windows. If it is not | |
1078 * set the default value will be unspecified (SWT#NONE). | |
1079 * | |
1080 * | |
1081 * @return SWT#NONE, SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT | |
1082 * @see SWT#RIGHT_TO_LEFT | |
1083 * @see SWT#LEFT_TO_RIGHT | |
1084 * @see SWT#NONE | |
1085 * @since 3.1 | |
1086 */ | |
1087 public static int getDefaultOrientation() { | |
1088 return orientation; | |
1089 | |
1090 } | |
1091 | |
1092 /** | |
1093 * Sets the default orientation of windows. | |
1094 * @param defaultOrientation one of | |
1095 * SWT#RIGHT_TO_LEFT, SWT#LEFT_TO_RIGHT ,SWT#NONE | |
1096 * @see SWT#RIGHT_TO_LEFT | |
1097 * @see SWT#LEFT_TO_RIGHT | |
1098 * @see SWT#NONE | |
1099 * @since 3.1 | |
1100 */ | |
1101 public static void setDefaultOrientation(int defaultOrientation) { | |
1102 orientation = defaultOrientation; | |
1103 | |
1104 } | |
1105 | |
1106 } |