Mercurial > projects > dwt-addons
comparison dwtx/jface/wizard/WizardDialog.d @ 8:a3ff22a98bef
Dialog
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 29 Mar 2008 01:25:27 +0100 |
parents | |
children | 6c14e54dfc11 |
comparison
equal
deleted
inserted
replaced
7:8a302fdb4140 | 8:a3ff22a98bef |
---|---|
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 * Chris Gross (schtoo@schtoo.com) - patch for bug 16179 | |
11 * Port to the D programming language: | |
12 * Frank Benoit <benoit@tionex.de> | |
13 *******************************************************************************/ | |
14 module dwtx.jface.wizard.WizardDialog; | |
15 | |
16 class WizardDialog { | |
17 } | |
18 | |
19 | |
20 /++ | |
21 import java.lang.reflect.InvocationTargetException; | |
22 import java.util.ArrayList; | |
23 import java.util.HashMap; | |
24 import java.util.Map; | |
25 | |
26 import dwt.DWT; | |
27 import dwt.custom.BusyIndicator; | |
28 import dwt.events.HelpEvent; | |
29 import dwt.events.HelpListener; | |
30 import dwt.events.SelectionAdapter; | |
31 import dwt.events.SelectionEvent; | |
32 import dwt.graphics.Cursor; | |
33 import dwt.graphics.Point; | |
34 import dwt.graphics.Rectangle; | |
35 import dwt.layout.GridData; | |
36 import dwt.layout.GridLayout; | |
37 import dwt.widgets.Button; | |
38 import dwt.widgets.Composite; | |
39 import dwt.widgets.Control; | |
40 import dwt.widgets.Display; | |
41 import dwt.widgets.Label; | |
42 import dwt.widgets.Layout; | |
43 import dwt.widgets.Shell; | |
44 import dwtx.core.runtime.Assert; | |
45 import dwtx.core.runtime.IProgressMonitor; | |
46 import dwtx.core.runtime.IStatus; | |
47 import dwtx.core.runtime.ListenerList; | |
48 import dwtx.jface.dialogs.ControlEnableState; | |
49 import dwtx.jface.dialogs.IDialogConstants; | |
50 import dwtx.jface.dialogs.IMessageProvider; | |
51 import dwtx.jface.dialogs.IPageChangeProvider; | |
52 import dwtx.jface.dialogs.IPageChangedListener; | |
53 import dwtx.jface.dialogs.IPageChangingListener; | |
54 import dwtx.jface.dialogs.MessageDialog; | |
55 import dwtx.jface.dialogs.PageChangedEvent; | |
56 import dwtx.jface.dialogs.PageChangingEvent; | |
57 import dwtx.jface.dialogs.TitleAreaDialog; | |
58 import dwtx.jface.operation.IRunnableWithProgress; | |
59 import dwtx.jface.operation.ModalContext; | |
60 import dwtx.jface.resource.JFaceResources; | |
61 import dwtx.jface.util.SafeRunnable; | |
62 | |
63 /** | |
64 * A dialog to show a wizard to the end user. | |
65 * <p> | |
66 * In typical usage, the client instantiates this class with a particular | |
67 * wizard. The dialog serves as the wizard container and orchestrates the | |
68 * presentation of its pages. | |
69 * <p> | |
70 * The standard layout is roughly as follows: it has an area at the top | |
71 * containing both the wizard's title, description, and image; the actual wizard | |
72 * page appears in the middle; below that is a progress indicator (which is made | |
73 * visible if needed); and at the bottom of the page is message line and a | |
74 * button bar containing Help, Next, Back, Finish, and Cancel buttons (or some | |
75 * subset). | |
76 * </p> | |
77 * <p> | |
78 * Clients may subclass <code>WizardDialog</code>, although this is rarely | |
79 * required. | |
80 * </p> | |
81 */ | |
82 public class WizardDialog extends TitleAreaDialog implements IWizardContainer2, | |
83 IPageChangeProvider { | |
84 /** | |
85 * Image registry key for error message image (value | |
86 * <code>"dialog_title_error_image"</code>). | |
87 */ | |
88 public static final String WIZ_IMG_ERROR = "dialog_title_error_image"; //$NON-NLS-1$ | |
89 | |
90 // The wizard the dialog is currently showing. | |
91 private IWizard wizard; | |
92 | |
93 // Wizards to dispose | |
94 private ArrayList createdWizards = new ArrayList(); | |
95 | |
96 // Current nested wizards | |
97 private ArrayList nestedWizards = new ArrayList(); | |
98 | |
99 // The currently displayed page. | |
100 private IWizardPage currentPage = null; | |
101 | |
102 // The number of long running operation executed from the dialog. | |
103 private long activeRunningOperations = 0; | |
104 | |
105 // The current page message and description | |
106 private String pageMessage; | |
107 | |
108 private int pageMessageType = IMessageProvider.NONE; | |
109 | |
110 private String pageDescription; | |
111 | |
112 // The progress monitor | |
113 private ProgressMonitorPart progressMonitorPart; | |
114 | |
115 private Cursor waitCursor; | |
116 | |
117 private Cursor arrowCursor; | |
118 | |
119 private MessageDialog windowClosingDialog; | |
120 | |
121 // Navigation buttons | |
122 private Button backButton; | |
123 | |
124 private Button nextButton; | |
125 | |
126 private Button finishButton; | |
127 | |
128 private Button cancelButton; | |
129 | |
130 private Button helpButton; | |
131 | |
132 private SelectionAdapter cancelListener; | |
133 | |
134 private bool isMovingToPreviousPage = false; | |
135 | |
136 private Composite pageContainer; | |
137 | |
138 private PageContainerFillLayout pageContainerLayout = new PageContainerFillLayout( | |
139 5, 5, 300, 225); | |
140 | |
141 private int pageWidth = DWT.DEFAULT; | |
142 | |
143 private int pageHeight = DWT.DEFAULT; | |
144 | |
145 private static final String FOCUS_CONTROL = "focusControl"; //$NON-NLS-1$ | |
146 | |
147 private bool lockedUI = false; | |
148 | |
149 private ListenerList pageChangedListeners = new ListenerList(); | |
150 | |
151 private ListenerList pageChangingListeners = new ListenerList(); | |
152 | |
153 /** | |
154 * A layout for a container which includes several pages, like a notebook, | |
155 * wizard, or preference dialog. The size computed by this layout is the | |
156 * maximum width and height of all pages currently inserted into the | |
157 * container. | |
158 */ | |
159 protected class PageContainerFillLayout extends Layout { | |
160 /** | |
161 * The margin width; <code>5</code> pixels by default. | |
162 */ | |
163 public int marginWidth = 5; | |
164 | |
165 /** | |
166 * The margin height; <code>5</code> pixels by default. | |
167 */ | |
168 public int marginHeight = 5; | |
169 | |
170 /** | |
171 * The minimum width; <code>0</code> pixels by default. | |
172 */ | |
173 public int minimumWidth = 0; | |
174 | |
175 /** | |
176 * The minimum height; <code>0</code> pixels by default. | |
177 */ | |
178 public int minimumHeight = 0; | |
179 | |
180 /** | |
181 * Creates new layout object. | |
182 * | |
183 * @param mw | |
184 * the margin width | |
185 * @param mh | |
186 * the margin height | |
187 * @param minW | |
188 * the minimum width | |
189 * @param minH | |
190 * the minimum height | |
191 */ | |
192 public PageContainerFillLayout(int mw, int mh, int minW, int minH) { | |
193 marginWidth = mw; | |
194 marginHeight = mh; | |
195 minimumWidth = minW; | |
196 minimumHeight = minH; | |
197 } | |
198 | |
199 /* | |
200 * (non-Javadoc) Method declared on Layout. | |
201 */ | |
202 public Point computeSize(Composite composite, int wHint, int hHint, | |
203 bool force) { | |
204 if (wHint !is DWT.DEFAULT && hHint !is DWT.DEFAULT) { | |
205 return new Point(wHint, hHint); | |
206 } | |
207 Point result = null; | |
208 Control[] children = composite.getChildren(); | |
209 if (children.length > 0) { | |
210 result = new Point(0, 0); | |
211 for (int i = 0; i < children.length; i++) { | |
212 Point cp = children[i].computeSize(wHint, hHint, force); | |
213 result.x = Math.max(result.x, cp.x); | |
214 result.y = Math.max(result.y, cp.y); | |
215 } | |
216 result.x = result.x + 2 * marginWidth; | |
217 result.y = result.y + 2 * marginHeight; | |
218 } else { | |
219 Rectangle rect = composite.getClientArea(); | |
220 result = new Point(rect.width, rect.height); | |
221 } | |
222 result.x = Math.max(result.x, minimumWidth); | |
223 result.y = Math.max(result.y, minimumHeight); | |
224 if (wHint !is DWT.DEFAULT) { | |
225 result.x = wHint; | |
226 } | |
227 if (hHint !is DWT.DEFAULT) { | |
228 result.y = hHint; | |
229 } | |
230 return result; | |
231 } | |
232 | |
233 /** | |
234 * Returns the client area for the given composite according to this | |
235 * layout. | |
236 * | |
237 * @param c | |
238 * the composite | |
239 * @return the client area rectangle | |
240 */ | |
241 public Rectangle getClientArea(Composite c) { | |
242 Rectangle rect = c.getClientArea(); | |
243 rect.x = rect.x + marginWidth; | |
244 rect.y = rect.y + marginHeight; | |
245 rect.width = rect.width - 2 * marginWidth; | |
246 rect.height = rect.height - 2 * marginHeight; | |
247 return rect; | |
248 } | |
249 | |
250 /* | |
251 * (non-Javadoc) Method declared on Layout. | |
252 */ | |
253 public void layout(Composite composite, bool force) { | |
254 Rectangle rect = getClientArea(composite); | |
255 Control[] children = composite.getChildren(); | |
256 for (int i = 0; i < children.length; i++) { | |
257 children[i].setBounds(rect); | |
258 } | |
259 } | |
260 | |
261 /** | |
262 * Lays outs the page according to this layout. | |
263 * | |
264 * @param w | |
265 * the control | |
266 */ | |
267 public void layoutPage(Control w) { | |
268 w.setBounds(getClientArea(w.getParent())); | |
269 } | |
270 | |
271 /** | |
272 * Sets the location of the page so that its origin is in the upper left | |
273 * corner. | |
274 * | |
275 * @param w | |
276 * the control | |
277 */ | |
278 public void setPageLocation(Control w) { | |
279 w.setLocation(marginWidth, marginHeight); | |
280 } | |
281 } | |
282 | |
283 /** | |
284 * Creates a new wizard dialog for the given wizard. | |
285 * | |
286 * @param parentShell | |
287 * the parent shell | |
288 * @param newWizard | |
289 * the wizard this dialog is working on | |
290 */ | |
291 public WizardDialog(Shell parentShell, IWizard newWizard) { | |
292 super(parentShell); | |
293 setShellStyle(DWT.CLOSE | DWT.MAX | DWT.TITLE | DWT.BORDER | |
294 | DWT.APPLICATION_MODAL | DWT.RESIZE | getDefaultOrientation()); | |
295 setWizard(newWizard); | |
296 // since VAJava can't initialize an instance var with an anonymous | |
297 // class outside a constructor we do it here: | |
298 cancelListener = new SelectionAdapter() { | |
299 public void widgetSelected(SelectionEvent e) { | |
300 cancelPressed(); | |
301 } | |
302 }; | |
303 } | |
304 | |
305 /** | |
306 * About to start a long running operation triggered through the wizard. | |
307 * Shows the progress monitor and disables the wizard's buttons and | |
308 * controls. | |
309 * | |
310 * @param enableCancelButton | |
311 * <code>true</code> if the Cancel button should be enabled, | |
312 * and <code>false</code> if it should be disabled | |
313 * @return the saved UI state | |
314 */ | |
315 private Object aboutToStart(bool enableCancelButton) { | |
316 Map savedState = null; | |
317 if (getShell() !is null) { | |
318 // Save focus control | |
319 Control focusControl = getShell().getDisplay().getFocusControl(); | |
320 if (focusControl !is null && focusControl.getShell() !is getShell()) { | |
321 focusControl = null; | |
322 } | |
323 bool needsProgressMonitor = wizard.needsProgressMonitor(); | |
324 cancelButton.removeSelectionListener(cancelListener); | |
325 // Set the busy cursor to all shells. | |
326 Display d = getShell().getDisplay(); | |
327 waitCursor = new Cursor(d, DWT.CURSOR_WAIT); | |
328 setDisplayCursor(waitCursor); | |
329 // Set the arrow cursor to the cancel component. | |
330 arrowCursor = new Cursor(d, DWT.CURSOR_ARROW); | |
331 cancelButton.setCursor(arrowCursor); | |
332 // Deactivate shell | |
333 savedState = saveUIState(needsProgressMonitor && enableCancelButton); | |
334 if (focusControl !is null) { | |
335 savedState.put(FOCUS_CONTROL, focusControl); | |
336 } | |
337 // Attach the progress monitor part to the cancel button | |
338 if (needsProgressMonitor) { | |
339 progressMonitorPart.attachToCancelComponent(cancelButton); | |
340 progressMonitorPart.setVisible(true); | |
341 } | |
342 } | |
343 return savedState; | |
344 } | |
345 | |
346 /** | |
347 * The Back button has been pressed. | |
348 */ | |
349 protected void backPressed() { | |
350 IWizardPage page = currentPage.getPreviousPage(); | |
351 if (page is null) { | |
352 // should never happen since we have already visited the page | |
353 return; | |
354 } | |
355 | |
356 // set flag to indicate that we are moving back | |
357 isMovingToPreviousPage = true; | |
358 // show the page | |
359 showPage(page); | |
360 } | |
361 | |
362 /* | |
363 * (non-Javadoc) Method declared on Dialog. | |
364 */ | |
365 protected void buttonPressed(int buttonId) { | |
366 switch (buttonId) { | |
367 case IDialogConstants.HELP_ID: { | |
368 helpPressed(); | |
369 break; | |
370 } | |
371 case IDialogConstants.BACK_ID: { | |
372 backPressed(); | |
373 break; | |
374 } | |
375 case IDialogConstants.NEXT_ID: { | |
376 nextPressed(); | |
377 break; | |
378 } | |
379 case IDialogConstants.FINISH_ID: { | |
380 finishPressed(); | |
381 break; | |
382 } | |
383 // The Cancel button has a listener which calls cancelPressed | |
384 // directly | |
385 } | |
386 } | |
387 | |
388 /** | |
389 * Calculates the difference in size between the given page and the page | |
390 * container. A larger page results in a positive delta. | |
391 * | |
392 * @param page | |
393 * the page | |
394 * @return the size difference encoded as a | |
395 * <code>new Point(deltaWidth,deltaHeight)</code> | |
396 */ | |
397 private Point calculatePageSizeDelta(IWizardPage page) { | |
398 Control pageControl = page.getControl(); | |
399 if (pageControl is null) { | |
400 // control not created yet | |
401 return new Point(0, 0); | |
402 } | |
403 Point contentSize = pageControl.computeSize(DWT.DEFAULT, DWT.DEFAULT, | |
404 true); | |
405 Rectangle rect = pageContainerLayout.getClientArea(pageContainer); | |
406 Point containerSize = new Point(rect.width, rect.height); | |
407 return new Point(Math.max(0, contentSize.x - containerSize.x), Math | |
408 .max(0, contentSize.y - containerSize.y)); | |
409 } | |
410 | |
411 /* | |
412 * (non-Javadoc) Method declared on Dialog. | |
413 */ | |
414 protected void cancelPressed() { | |
415 if (activeRunningOperations <= 0) { | |
416 // Close the dialog. The check whether the dialog can be | |
417 // closed or not is done in <code>okToClose</code>. | |
418 // This ensures that the check is also evaluated when the user | |
419 // presses the window's close button. | |
420 setReturnCode(CANCEL); | |
421 close(); | |
422 } else { | |
423 cancelButton.setEnabled(false); | |
424 } | |
425 } | |
426 | |
427 /* | |
428 * (non-Javadoc) | |
429 * | |
430 * @see dwtx.jface.window.Window#close() | |
431 */ | |
432 public bool close() { | |
433 if (okToClose()) { | |
434 return hardClose(); | |
435 } | |
436 return false; | |
437 } | |
438 | |
439 /* | |
440 * (non-Javadoc) Method declared on Window. | |
441 */ | |
442 protected void configureShell(Shell newShell) { | |
443 super.configureShell(newShell); | |
444 // Register help listener on the shell | |
445 newShell.addHelpListener(new HelpListener() { | |
446 public void helpRequested(HelpEvent event) { | |
447 // call perform help on the current page | |
448 if (currentPage !is null) { | |
449 currentPage.performHelp(); | |
450 } | |
451 } | |
452 }); | |
453 } | |
454 | |
455 /** | |
456 * Creates the buttons for this dialog's button bar. | |
457 * <p> | |
458 * The <code>WizardDialog</code> implementation of this framework method | |
459 * prevents the parent composite's columns from being made equal width in | |
460 * order to remove the margin between the Back and Next buttons. | |
461 * </p> | |
462 * | |
463 * @param parent | |
464 * the parent composite to contain the buttons | |
465 */ | |
466 protected void createButtonsForButtonBar(Composite parent) { | |
467 ((GridLayout) parent.getLayout()).makeColumnsEqualWidth = false; | |
468 if (wizard.isHelpAvailable()) { | |
469 helpButton = createButton(parent, IDialogConstants.HELP_ID, | |
470 IDialogConstants.HELP_LABEL, false); | |
471 } | |
472 if (wizard.needsPreviousAndNextButtons()) { | |
473 createPreviousAndNextButtons(parent); | |
474 } | |
475 finishButton = createButton(parent, IDialogConstants.FINISH_ID, | |
476 IDialogConstants.FINISH_LABEL, true); | |
477 cancelButton = createCancelButton(parent); | |
478 } | |
479 | |
480 /* | |
481 * (non-Javadoc) | |
482 * | |
483 * @see dwtx.jface.dialogs.Dialog#setButtonLayoutData(dwt.widgets.Button) | |
484 */ | |
485 protected void setButtonLayoutData(Button button) { | |
486 GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); | |
487 int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); | |
488 | |
489 // On large fonts this can make this dialog huge | |
490 widthHint = Math.min(widthHint, | |
491 button.getDisplay().getBounds().width / 5); | |
492 Point minSize = button.computeSize(DWT.DEFAULT, DWT.DEFAULT, true); | |
493 data.widthHint = Math.max(widthHint, minSize.x); | |
494 | |
495 button.setLayoutData(data); | |
496 } | |
497 | |
498 /** | |
499 * Creates the Cancel button for this wizard dialog. Creates a standard (<code>DWT.PUSH</code>) | |
500 * button and registers for its selection events. Note that the number of | |
501 * columns in the button bar composite is incremented. The Cancel button is | |
502 * created specially to give it a removeable listener. | |
503 * | |
504 * @param parent | |
505 * the parent button bar | |
506 * @return the new Cancel button | |
507 */ | |
508 private Button createCancelButton(Composite parent) { | |
509 // increment the number of columns in the button bar | |
510 ((GridLayout) parent.getLayout()).numColumns++; | |
511 Button button = new Button(parent, DWT.PUSH); | |
512 button.setText(IDialogConstants.CANCEL_LABEL); | |
513 setButtonLayoutData(button); | |
514 button.setFont(parent.getFont()); | |
515 button.setData(new Integer(IDialogConstants.CANCEL_ID)); | |
516 button.addSelectionListener(cancelListener); | |
517 return button; | |
518 } | |
519 | |
520 /** | |
521 * Return the cancel button if the id is a the cancel id. | |
522 * | |
523 * @param id | |
524 * the button id | |
525 * @return the button corresponding to the button id | |
526 */ | |
527 protected Button getButton(int id) { | |
528 if (id is IDialogConstants.CANCEL_ID) { | |
529 return cancelButton; | |
530 } | |
531 return super.getButton(id); | |
532 } | |
533 | |
534 /** | |
535 * The <code>WizardDialog</code> implementation of this | |
536 * <code>Window</code> method calls call <code>IWizard.addPages</code> | |
537 * to allow the current wizard to add extra pages, then | |
538 * <code>super.createContents</code> to create the controls. It then calls | |
539 * <code>IWizard.createPageControls</code> to allow the wizard to | |
540 * pre-create their page controls prior to opening, so that the wizard opens | |
541 * to the correct size. And finally it shows the first page. | |
542 */ | |
543 protected Control createContents(Composite parent) { | |
544 // Allow the wizard to add pages to itself | |
545 // Need to call this now so page count is correct | |
546 // for determining if next/previous buttons are needed | |
547 wizard.addPages(); | |
548 Control contents = super.createContents(parent); | |
549 // Allow the wizard pages to precreate their page controls | |
550 createPageControls(); | |
551 // Show the first page | |
552 showStartingPage(); | |
553 return contents; | |
554 } | |
555 | |
556 /* | |
557 * (non-Javadoc) Method declared on Dialog. | |
558 */ | |
559 protected Control createDialogArea(Composite parent) { | |
560 Composite composite = (Composite) super.createDialogArea(parent); | |
561 // Build the Page container | |
562 pageContainer = createPageContainer(composite); | |
563 GridData gd = new GridData(GridData.FILL_BOTH); | |
564 gd.widthHint = pageWidth; | |
565 gd.heightHint = pageHeight; | |
566 pageContainer.setLayoutData(gd); | |
567 pageContainer.setFont(parent.getFont()); | |
568 // Insert a progress monitor | |
569 GridLayout pmlayout = new GridLayout(); | |
570 pmlayout.numColumns = 1; | |
571 progressMonitorPart = createProgressMonitorPart(composite, pmlayout); | |
572 GridData gridData = new GridData(GridData.FILL_HORIZONTAL); | |
573 progressMonitorPart.setLayoutData(gridData); | |
574 progressMonitorPart.setVisible(false); | |
575 // Build the separator line | |
576 Label separator = new Label(composite, DWT.HORIZONTAL | DWT.SEPARATOR); | |
577 separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); | |
578 | |
579 applyDialogFont(progressMonitorPart); | |
580 return composite; | |
581 } | |
582 | |
583 /** | |
584 * Create the progress monitor part in the receiver. | |
585 * | |
586 * @param composite | |
587 * @param pmlayout | |
588 * @return ProgressMonitorPart | |
589 */ | |
590 protected ProgressMonitorPart createProgressMonitorPart( | |
591 Composite composite, GridLayout pmlayout) { | |
592 return new ProgressMonitorPart(composite, pmlayout, DWT.DEFAULT) { | |
593 String currentTask = null; | |
594 | |
595 /* | |
596 * (non-Javadoc) | |
597 * | |
598 * @see dwtx.jface.wizard.ProgressMonitorPart#setBlocked(dwtx.core.runtime.IStatus) | |
599 */ | |
600 public void setBlocked(IStatus reason) { | |
601 super.setBlocked(reason); | |
602 if (!lockedUI) { | |
603 getBlockedHandler().showBlocked(getShell(), this, reason, | |
604 currentTask); | |
605 } | |
606 } | |
607 | |
608 /* | |
609 * (non-Javadoc) | |
610 * | |
611 * @see dwtx.jface.wizard.ProgressMonitorPart#clearBlocked() | |
612 */ | |
613 public void clearBlocked() { | |
614 super.clearBlocked(); | |
615 if (!lockedUI) { | |
616 getBlockedHandler().clearBlocked(); | |
617 } | |
618 } | |
619 | |
620 /* | |
621 * (non-Javadoc) | |
622 * | |
623 * @see dwtx.jface.wizard.ProgressMonitorPart#beginTask(java.lang.String, | |
624 * int) | |
625 */ | |
626 public void beginTask(String name, int totalWork) { | |
627 super.beginTask(name, totalWork); | |
628 currentTask = name; | |
629 } | |
630 | |
631 /* | |
632 * (non-Javadoc) | |
633 * | |
634 * @see dwtx.jface.wizard.ProgressMonitorPart#setTaskName(java.lang.String) | |
635 */ | |
636 public void setTaskName(String name) { | |
637 super.setTaskName(name); | |
638 currentTask = name; | |
639 } | |
640 | |
641 /* | |
642 * (non-Javadoc) | |
643 * | |
644 * @see dwtx.jface.wizard.ProgressMonitorPart#subTask(java.lang.String) | |
645 */ | |
646 public void subTask(String name) { | |
647 super.subTask(name); | |
648 // If we haven't got anything yet use this value for more | |
649 // context | |
650 if (currentTask is null) { | |
651 currentTask = name; | |
652 } | |
653 } | |
654 }; | |
655 } | |
656 | |
657 /** | |
658 * Creates the container that holds all pages. | |
659 * | |
660 * @param parent | |
661 * @return Composite | |
662 */ | |
663 private Composite createPageContainer(Composite parent) { | |
664 Composite result = new Composite(parent, DWT.NULL); | |
665 result.setLayout(pageContainerLayout); | |
666 return result; | |
667 } | |
668 | |
669 /** | |
670 * Allow the wizard's pages to pre-create their page controls. This allows | |
671 * the wizard dialog to open to the correct size. | |
672 */ | |
673 private void createPageControls() { | |
674 // Allow the wizard pages to precreate their page controls | |
675 // This allows the wizard to open to the correct size | |
676 wizard.createPageControls(pageContainer); | |
677 // Ensure that all of the created pages are initially not visible | |
678 IWizardPage[] pages = wizard.getPages(); | |
679 for (int i = 0; i < pages.length; i++) { | |
680 IWizardPage page = pages[i]; | |
681 if (page.getControl() !is null) { | |
682 page.getControl().setVisible(false); | |
683 } | |
684 } | |
685 } | |
686 | |
687 /** | |
688 * Creates the Previous and Next buttons for this wizard dialog. Creates | |
689 * standard (<code>DWT.PUSH</code>) buttons and registers for their | |
690 * selection events. Note that the number of columns in the button bar | |
691 * composite is incremented. These buttons are created specially to prevent | |
692 * any space between them. | |
693 * | |
694 * @param parent | |
695 * the parent button bar | |
696 * @return a composite containing the new buttons | |
697 */ | |
698 private Composite createPreviousAndNextButtons(Composite parent) { | |
699 // increment the number of columns in the button bar | |
700 ((GridLayout) parent.getLayout()).numColumns++; | |
701 Composite composite = new Composite(parent, DWT.NONE); | |
702 // create a layout with spacing and margins appropriate for the font | |
703 // size. | |
704 GridLayout layout = new GridLayout(); | |
705 layout.numColumns = 0; // will be incremented by createButton | |
706 layout.marginWidth = 0; | |
707 layout.marginHeight = 0; | |
708 layout.horizontalSpacing = 0; | |
709 layout.verticalSpacing = 0; | |
710 composite.setLayout(layout); | |
711 GridData data = new GridData(GridData.HORIZONTAL_ALIGN_CENTER | |
712 | GridData.VERTICAL_ALIGN_CENTER); | |
713 composite.setLayoutData(data); | |
714 composite.setFont(parent.getFont()); | |
715 backButton = createButton(composite, IDialogConstants.BACK_ID, | |
716 IDialogConstants.BACK_LABEL, false); | |
717 nextButton = createButton(composite, IDialogConstants.NEXT_ID, | |
718 IDialogConstants.NEXT_LABEL, false); | |
719 return composite; | |
720 } | |
721 | |
722 /** | |
723 * Creates and return a new wizard closing dialog without openiong it. | |
724 * | |
725 * @return MessageDalog | |
726 */ | |
727 private MessageDialog createWizardClosingDialog() { | |
728 MessageDialog result = new MessageDialog(getShell(), | |
729 JFaceResources.getString("WizardClosingDialog.title"), //$NON-NLS-1$ | |
730 null, | |
731 JFaceResources.getString("WizardClosingDialog.message"), //$NON-NLS-1$ | |
732 MessageDialog.QUESTION, | |
733 new String[] { IDialogConstants.OK_LABEL }, 0); | |
734 return result; | |
735 } | |
736 | |
737 /** | |
738 * The Finish button has been pressed. | |
739 */ | |
740 protected void finishPressed() { | |
741 // Wizards are added to the nested wizards list in setWizard. | |
742 // This means that the current wizard is always the last wizard in the | |
743 // list. | |
744 // Note that we first call the current wizard directly (to give it a | |
745 // chance to | |
746 // abort, do work, and save state) then call the remaining n-1 wizards | |
747 // in the | |
748 // list (to save state). | |
749 if (wizard.performFinish()) { | |
750 // Call perform finish on outer wizards in the nested chain | |
751 // (to allow them to save state for example) | |
752 for (int i = 0; i < nestedWizards.size() - 1; i++) { | |
753 ((IWizard) nestedWizards.get(i)).performFinish(); | |
754 } | |
755 // Hard close the dialog. | |
756 setReturnCode(OK); | |
757 hardClose(); | |
758 } | |
759 } | |
760 | |
761 /* | |
762 * (non-Javadoc) Method declared on IWizardContainer. | |
763 */ | |
764 public IWizardPage getCurrentPage() { | |
765 return currentPage; | |
766 } | |
767 | |
768 /** | |
769 * Returns the progress monitor for this wizard dialog (if it has one). | |
770 * | |
771 * @return the progress monitor, or <code>null</code> if this wizard | |
772 * dialog does not have one | |
773 */ | |
774 protected IProgressMonitor getProgressMonitor() { | |
775 return progressMonitorPart; | |
776 } | |
777 | |
778 /** | |
779 * Returns the wizard this dialog is currently displaying. | |
780 * | |
781 * @return the current wizard | |
782 */ | |
783 protected IWizard getWizard() { | |
784 return wizard; | |
785 } | |
786 | |
787 /** | |
788 * Closes this window. | |
789 * | |
790 * @return <code>true</code> if the window is (or was already) closed, and | |
791 * <code>false</code> if it is still open | |
792 */ | |
793 private bool hardClose() { | |
794 // inform wizards | |
795 for (int i = 0; i < createdWizards.size(); i++) { | |
796 IWizard createdWizard = (IWizard) createdWizards.get(i); | |
797 createdWizard.dispose(); | |
798 // Remove this dialog as a parent from the managed wizard. | |
799 // Note that we do this after calling dispose as the wizard or | |
800 // its pages may need access to the container during | |
801 // dispose code | |
802 createdWizard.setContainer(null); | |
803 } | |
804 return super.close(); | |
805 } | |
806 | |
807 /** | |
808 * The Help button has been pressed. | |
809 */ | |
810 protected void helpPressed() { | |
811 if (currentPage !is null) { | |
812 currentPage.performHelp(); | |
813 } | |
814 } | |
815 | |
816 /** | |
817 * The Next button has been pressed. | |
818 */ | |
819 protected void nextPressed() { | |
820 IWizardPage page = currentPage.getNextPage(); | |
821 if (page is null) { | |
822 // something must have happend getting the next page | |
823 return; | |
824 } | |
825 | |
826 // show the next page | |
827 showPage(page); | |
828 } | |
829 | |
830 /** | |
831 * Notifies page changing listeners and returns result of page changing | |
832 * processing to the sender. | |
833 * | |
834 * @param eventType | |
835 * @return <code>true</code> if page changing listener completes | |
836 * successfully, <code>false</code> otherwise | |
837 */ | |
838 private bool doPageChanging(IWizardPage targetPage) { | |
839 PageChangingEvent e = new PageChangingEvent(this, getCurrentPage(), | |
840 targetPage); | |
841 firePageChanging(e); | |
842 // Prevent navigation if necessary | |
843 return e.doit; | |
844 } | |
845 | |
846 /** | |
847 * Checks whether it is alright to close this wizard dialog and performed | |
848 * standard cancel processing. If there is a long running operation in | |
849 * progress, this method posts an alert message saying that the wizard | |
850 * cannot be closed. | |
851 * | |
852 * @return <code>true</code> if it is alright to close this dialog, and | |
853 * <code>false</code> if it is not | |
854 */ | |
855 private bool okToClose() { | |
856 if (activeRunningOperations > 0) { | |
857 synchronized (this) { | |
858 windowClosingDialog = createWizardClosingDialog(); | |
859 } | |
860 windowClosingDialog.open(); | |
861 synchronized (this) { | |
862 windowClosingDialog = null; | |
863 } | |
864 return false; | |
865 } | |
866 return wizard.performCancel(); | |
867 } | |
868 | |
869 /** | |
870 * Restores the enabled/disabled state of the given control. | |
871 * | |
872 * @param w | |
873 * the control | |
874 * @param h | |
875 * the map (key type: <code>String</code>, element type: | |
876 * <code>bool</code>) | |
877 * @param key | |
878 * the key | |
879 * @see #saveEnableStateAndSet | |
880 */ | |
881 private void restoreEnableState(Control w, Map h, String key) { | |
882 if (w !is null) { | |
883 bool b = (bool) h.get(key); | |
884 if (b !is null) { | |
885 w.setEnabled(b.booleanValue()); | |
886 } | |
887 } | |
888 } | |
889 | |
890 /** | |
891 * Restores the enabled/disabled state of the wizard dialog's buttons and | |
892 * the tree of controls for the currently showing page. | |
893 * | |
894 * @param state | |
895 * a map containing the saved state as returned by | |
896 * <code>saveUIState</code> | |
897 * @see #saveUIState | |
898 */ | |
899 private void restoreUIState(Map state) { | |
900 restoreEnableState(backButton, state, "back"); //$NON-NLS-1$ | |
901 restoreEnableState(nextButton, state, "next"); //$NON-NLS-1$ | |
902 restoreEnableState(finishButton, state, "finish"); //$NON-NLS-1$ | |
903 restoreEnableState(cancelButton, state, "cancel"); //$NON-NLS-1$ | |
904 restoreEnableState(helpButton, state, "help"); //$NON-NLS-1$ | |
905 Object pageValue = state.get("page"); //$NON-NLS-1$ | |
906 if (pageValue !is null) { | |
907 ((ControlEnableState) pageValue).restore(); | |
908 } | |
909 } | |
910 | |
911 /** | |
912 * This implementation of IRunnableContext#run(bool, bool, | |
913 * IRunnableWithProgress) blocks until the runnable has been run, regardless | |
914 * of the value of <code>fork</code>. It is recommended that | |
915 * <code>fork</code> is set to true in most cases. If <code>fork</code> | |
916 * is set to <code>false</code>, the runnable will run in the UI thread | |
917 * and it is the runnable's responsibility to call | |
918 * <code>Display.readAndDispatch()</code> to ensure UI responsiveness. | |
919 * | |
920 * UI state is saved prior to executing the long-running operation and is | |
921 * restored after the long-running operation completes executing. Any | |
922 * attempt to change the UI state of the wizard in the long-running | |
923 * operation will be nullified when original UI state is restored. | |
924 * | |
925 */ | |
926 public void run(bool fork, bool cancelable, | |
927 IRunnableWithProgress runnable) throws InvocationTargetException, | |
928 InterruptedException { | |
929 // The operation can only be canceled if it is executed in a separate | |
930 // thread. | |
931 // Otherwise the UI is blocked anyway. | |
932 Object state = null; | |
933 if (activeRunningOperations is 0) { | |
934 state = aboutToStart(fork && cancelable); | |
935 } | |
936 activeRunningOperations++; | |
937 try { | |
938 if (!fork) { | |
939 lockedUI = true; | |
940 } | |
941 ModalContext.run(runnable, fork, getProgressMonitor(), getShell() | |
942 .getDisplay()); | |
943 lockedUI = false; | |
944 } finally { | |
945 activeRunningOperations--; | |
946 // Stop if this is the last one | |
947 if (state !is null) { | |
948 stopped(state); | |
949 } | |
950 } | |
951 } | |
952 | |
953 /** | |
954 * Saves the enabled/disabled state of the given control in the given map, | |
955 * which must be modifiable. | |
956 * | |
957 * @param w | |
958 * the control, or <code>null</code> if none | |
959 * @param h | |
960 * the map (key type: <code>String</code>, element type: | |
961 * <code>bool</code>) | |
962 * @param key | |
963 * the key | |
964 * @param enabled | |
965 * <code>true</code> to enable the control, and | |
966 * <code>false</code> to disable it | |
967 * @see #restoreEnableState(Control, Map, String) | |
968 */ | |
969 private void saveEnableStateAndSet(Control w, Map h, String key, | |
970 bool enabled) { | |
971 if (w !is null) { | |
972 h.put(key, w.getEnabled() ? bool.TRUE : bool.FALSE); | |
973 w.setEnabled(enabled); | |
974 } | |
975 } | |
976 | |
977 /** | |
978 * Captures and returns the enabled/disabled state of the wizard dialog's | |
979 * buttons and the tree of controls for the currently showing page. All | |
980 * these controls are disabled in the process, with the possible exception | |
981 * of the Cancel button. | |
982 * | |
983 * @param keepCancelEnabled | |
984 * <code>true</code> if the Cancel button should remain | |
985 * enabled, and <code>false</code> if it should be disabled | |
986 * @return a map containing the saved state suitable for restoring later | |
987 * with <code>restoreUIState</code> | |
988 * @see #restoreUIState | |
989 */ | |
990 private Map saveUIState(bool keepCancelEnabled) { | |
991 Map savedState = new HashMap(10); | |
992 saveEnableStateAndSet(backButton, savedState, "back", false); //$NON-NLS-1$ | |
993 saveEnableStateAndSet(nextButton, savedState, "next", false); //$NON-NLS-1$ | |
994 saveEnableStateAndSet(finishButton, savedState, "finish", false); //$NON-NLS-1$ | |
995 saveEnableStateAndSet(cancelButton, savedState, | |
996 "cancel", keepCancelEnabled); //$NON-NLS-1$ | |
997 saveEnableStateAndSet(helpButton, savedState, "help", false); //$NON-NLS-1$ | |
998 if (currentPage !is null) { | |
999 savedState | |
1000 .put( | |
1001 "page", ControlEnableState.disable(currentPage.getControl())); //$NON-NLS-1$ | |
1002 } | |
1003 return savedState; | |
1004 } | |
1005 | |
1006 /** | |
1007 * Sets the given cursor for all shells currently active for this window's | |
1008 * display. | |
1009 * | |
1010 * @param c | |
1011 * the cursor | |
1012 */ | |
1013 private void setDisplayCursor(Cursor c) { | |
1014 Shell[] shells = getShell().getDisplay().getShells(); | |
1015 for (int i = 0; i < shells.length; i++) { | |
1016 shells[i].setCursor(c); | |
1017 } | |
1018 } | |
1019 | |
1020 /** | |
1021 * Sets the minimum page size used for the pages. | |
1022 * | |
1023 * @param minWidth | |
1024 * the minimum page width | |
1025 * @param minHeight | |
1026 * the minimum page height | |
1027 * @see #setMinimumPageSize(Point) | |
1028 */ | |
1029 public void setMinimumPageSize(int minWidth, int minHeight) { | |
1030 Assert.isTrue(minWidth >= 0 && minHeight >= 0); | |
1031 pageContainerLayout.minimumWidth = minWidth; | |
1032 pageContainerLayout.minimumHeight = minHeight; | |
1033 } | |
1034 | |
1035 /** | |
1036 * Sets the minimum page size used for the pages. | |
1037 * | |
1038 * @param size | |
1039 * the page size encoded as <code>new Point(width,height)</code> | |
1040 * @see #setMinimumPageSize(int,int) | |
1041 */ | |
1042 public void setMinimumPageSize(Point size) { | |
1043 setMinimumPageSize(size.x, size.y); | |
1044 } | |
1045 | |
1046 /** | |
1047 * Sets the size of all pages. The given size takes precedence over computed | |
1048 * sizes. | |
1049 * | |
1050 * @param width | |
1051 * the page width | |
1052 * @param height | |
1053 * the page height | |
1054 * @see #setPageSize(Point) | |
1055 */ | |
1056 public void setPageSize(int width, int height) { | |
1057 pageWidth = width; | |
1058 pageHeight = height; | |
1059 } | |
1060 | |
1061 /** | |
1062 * Sets the size of all pages. The given size takes precedence over computed | |
1063 * sizes. | |
1064 * | |
1065 * @param size | |
1066 * the page size encoded as <code>new Point(width,height)</code> | |
1067 * @see #setPageSize(int,int) | |
1068 */ | |
1069 public void setPageSize(Point size) { | |
1070 setPageSize(size.x, size.y); | |
1071 } | |
1072 | |
1073 /** | |
1074 * Sets the wizard this dialog is currently displaying. | |
1075 * | |
1076 * @param newWizard | |
1077 * the wizard | |
1078 */ | |
1079 protected void setWizard(IWizard newWizard) { | |
1080 wizard = newWizard; | |
1081 wizard.setContainer(this); | |
1082 if (!createdWizards.contains(wizard)) { | |
1083 createdWizards.add(wizard); | |
1084 // New wizard so just add it to the end of our nested list | |
1085 nestedWizards.add(wizard); | |
1086 if (pageContainer !is null) { | |
1087 // Dialog is already open | |
1088 // Allow the wizard pages to precreate their page controls | |
1089 // This allows the wizard to open to the correct size | |
1090 createPageControls(); | |
1091 // Ensure the dialog is large enough for the wizard | |
1092 updateSizeForWizard(wizard); | |
1093 pageContainer.layout(true); | |
1094 } | |
1095 } else { | |
1096 // We have already seen this wizard, if it is the previous wizard | |
1097 // on the nested list then we assume we have gone back and remove | |
1098 // the last wizard from the list | |
1099 int size = nestedWizards.size(); | |
1100 if (size >= 2 && nestedWizards.get(size - 2) is wizard) { | |
1101 nestedWizards.remove(size - 1); | |
1102 } else { | |
1103 // Assume we are going forward to revisit a wizard | |
1104 nestedWizards.add(wizard); | |
1105 } | |
1106 } | |
1107 } | |
1108 | |
1109 /* | |
1110 * (non-Javadoc) Method declared on IWizardContainer. | |
1111 */ | |
1112 public void showPage(IWizardPage page) { | |
1113 if (page is null || page is currentPage) { | |
1114 return; | |
1115 } | |
1116 | |
1117 if (!isMovingToPreviousPage) { | |
1118 // remember my previous page. | |
1119 page.setPreviousPage(currentPage); | |
1120 } else { | |
1121 isMovingToPreviousPage = false; | |
1122 } | |
1123 | |
1124 // If page changing evaluation unsuccessful, do not change the page | |
1125 if (!doPageChanging(page)) | |
1126 return; | |
1127 | |
1128 // Update for the new page in a busy cursor if possible | |
1129 if (getContents() is null) { | |
1130 updateForPage(page); | |
1131 } else { | |
1132 final IWizardPage finalPage = page; | |
1133 BusyIndicator.showWhile(getContents().getDisplay(), new Runnable() { | |
1134 public void run() { | |
1135 updateForPage(finalPage); | |
1136 } | |
1137 }); | |
1138 } | |
1139 } | |
1140 | |
1141 /** | |
1142 * Update the receiver for the new page. | |
1143 * | |
1144 * @param page | |
1145 */ | |
1146 private void updateForPage(IWizardPage page) { | |
1147 // ensure this page belongs to the current wizard | |
1148 if (wizard !is page.getWizard()) { | |
1149 setWizard(page.getWizard()); | |
1150 } | |
1151 // ensure that page control has been created | |
1152 // (this allows lazy page control creation) | |
1153 if (page.getControl() is null) { | |
1154 page.createControl(pageContainer); | |
1155 // the page is responsible for ensuring the created control is | |
1156 // accessable | |
1157 // via getControl. | |
1158 Assert.isNotNull(page.getControl(), JFaceResources.format( | |
1159 JFaceResources.getString("WizardDialog.missingSetControl"), //$NON-NLS-1$ | |
1160 new Object[] { page.getName() })); | |
1161 // ensure the dialog is large enough for this page | |
1162 updateSize(page); | |
1163 } | |
1164 // make the new page visible | |
1165 IWizardPage oldPage = currentPage; | |
1166 currentPage = page; | |
1167 | |
1168 currentPage.setVisible(true); | |
1169 if (oldPage !is null) { | |
1170 oldPage.setVisible(false); | |
1171 } | |
1172 // update the dialog controls | |
1173 update(); | |
1174 } | |
1175 | |
1176 /** | |
1177 * Shows the starting page of the wizard. | |
1178 */ | |
1179 private void showStartingPage() { | |
1180 currentPage = wizard.getStartingPage(); | |
1181 if (currentPage is null) { | |
1182 // something must have happend getting the page | |
1183 return; | |
1184 } | |
1185 // ensure the page control has been created | |
1186 if (currentPage.getControl() is null) { | |
1187 currentPage.createControl(pageContainer); | |
1188 // the page is responsible for ensuring the created control is | |
1189 // accessable | |
1190 // via getControl. | |
1191 Assert.isNotNull(currentPage.getControl()); | |
1192 // we do not need to update the size since the call | |
1193 // to initialize bounds has not been made yet. | |
1194 } | |
1195 // make the new page visible | |
1196 currentPage.setVisible(true); | |
1197 // update the dialog controls | |
1198 update(); | |
1199 } | |
1200 | |
1201 /** | |
1202 * A long running operation triggered through the wizard was stopped either | |
1203 * by user input or by normal end. Hides the progress monitor and restores | |
1204 * the enable state wizard's buttons and controls. | |
1205 * | |
1206 * @param savedState | |
1207 * the saved UI state as returned by <code>aboutToStart</code> | |
1208 * @see #aboutToStart | |
1209 */ | |
1210 private void stopped(Object savedState) { | |
1211 if (getShell() !is null) { | |
1212 if (wizard.needsProgressMonitor()) { | |
1213 progressMonitorPart.setVisible(false); | |
1214 progressMonitorPart.removeFromCancelComponent(cancelButton); | |
1215 } | |
1216 Map state = (Map) savedState; | |
1217 restoreUIState(state); | |
1218 cancelButton.addSelectionListener(cancelListener); | |
1219 setDisplayCursor(null); | |
1220 cancelButton.setCursor(null); | |
1221 waitCursor.dispose(); | |
1222 waitCursor = null; | |
1223 arrowCursor.dispose(); | |
1224 arrowCursor = null; | |
1225 Control focusControl = (Control) state.get(FOCUS_CONTROL); | |
1226 if (focusControl !is null) { | |
1227 focusControl.setFocus(); | |
1228 } | |
1229 } | |
1230 } | |
1231 | |
1232 /** | |
1233 * Updates this dialog's controls to reflect the current page. | |
1234 */ | |
1235 protected void update() { | |
1236 // Update the window title | |
1237 updateWindowTitle(); | |
1238 // Update the title bar | |
1239 updateTitleBar(); | |
1240 // Update the buttons | |
1241 updateButtons(); | |
1242 | |
1243 // Fires the page change event | |
1244 firePageChanged(new PageChangedEvent(this, getCurrentPage())); | |
1245 } | |
1246 | |
1247 /* | |
1248 * (non-Javadoc) Method declared on IWizardContainer. | |
1249 */ | |
1250 public void updateButtons() { | |
1251 bool canFlipToNextPage = false; | |
1252 bool canFinish = wizard.canFinish(); | |
1253 if (backButton !is null) { | |
1254 backButton.setEnabled(currentPage.getPreviousPage() !is null); | |
1255 } | |
1256 if (nextButton !is null) { | |
1257 canFlipToNextPage = currentPage.canFlipToNextPage(); | |
1258 nextButton.setEnabled(canFlipToNextPage); | |
1259 } | |
1260 finishButton.setEnabled(canFinish); | |
1261 // finish is default unless it is diabled and next is enabled | |
1262 if (canFlipToNextPage && !canFinish) { | |
1263 getShell().setDefaultButton(nextButton); | |
1264 } else { | |
1265 getShell().setDefaultButton(finishButton); | |
1266 } | |
1267 } | |
1268 | |
1269 /** | |
1270 * Update the message line with the page's description. | |
1271 * <p> | |
1272 * A discription is shown only if there is no message or error message. | |
1273 * </p> | |
1274 */ | |
1275 private void updateDescriptionMessage() { | |
1276 pageDescription = currentPage.getDescription(); | |
1277 setMessage(pageDescription); | |
1278 } | |
1279 | |
1280 /* | |
1281 * (non-Javadoc) Method declared on IWizardContainer. | |
1282 */ | |
1283 public void updateMessage() { | |
1284 | |
1285 if (currentPage is null) { | |
1286 return; | |
1287 } | |
1288 | |
1289 pageMessage = currentPage.getMessage(); | |
1290 if (pageMessage !is null && currentPage instanceof IMessageProvider) { | |
1291 pageMessageType = ((IMessageProvider) currentPage).getMessageType(); | |
1292 } else { | |
1293 pageMessageType = IMessageProvider.NONE; | |
1294 } | |
1295 if (pageMessage is null) { | |
1296 setMessage(pageDescription); | |
1297 } else { | |
1298 setMessage(pageMessage, pageMessageType); | |
1299 } | |
1300 setErrorMessage(currentPage.getErrorMessage()); | |
1301 } | |
1302 | |
1303 /** | |
1304 * Changes the shell size to the given size, ensuring that it is no larger | |
1305 * than the display bounds. | |
1306 * | |
1307 * @param width | |
1308 * the shell width | |
1309 * @param height | |
1310 * the shell height | |
1311 */ | |
1312 private void setShellSize(int width, int height) { | |
1313 Rectangle size = getShell().getBounds(); | |
1314 size.height = height; | |
1315 size.width = width; | |
1316 getShell().setBounds(getConstrainedShellBounds(size)); | |
1317 } | |
1318 | |
1319 /** | |
1320 * Computes the correct dialog size for the current page and resizes its | |
1321 * shell if nessessary. Also causes the container to refresh its layout. | |
1322 * | |
1323 * @param page | |
1324 * the wizard page to use to resize the dialog | |
1325 * @since 2.0 | |
1326 */ | |
1327 protected void updateSize(IWizardPage page) { | |
1328 if (page is null || page.getControl() is null) { | |
1329 return; | |
1330 } | |
1331 updateSizeForPage(page); | |
1332 pageContainerLayout.layoutPage(page.getControl()); | |
1333 } | |
1334 | |
1335 /* | |
1336 * (non-Javadoc) | |
1337 * | |
1338 * @see dwtx.jface.wizard.IWizardContainer2#updateSize() | |
1339 */ | |
1340 public void updateSize() { | |
1341 updateSize(currentPage); | |
1342 } | |
1343 | |
1344 /** | |
1345 * Computes the correct dialog size for the given page and resizes its shell | |
1346 * if nessessary. | |
1347 * | |
1348 * @param page | |
1349 * the wizard page | |
1350 */ | |
1351 private void updateSizeForPage(IWizardPage page) { | |
1352 // ensure the page container is large enough | |
1353 Point delta = calculatePageSizeDelta(page); | |
1354 if (delta.x > 0 || delta.y > 0) { | |
1355 // increase the size of the shell | |
1356 Shell shell = getShell(); | |
1357 Point shellSize = shell.getSize(); | |
1358 setShellSize(shellSize.x + delta.x, shellSize.y + delta.y); | |
1359 constrainShellSize(); | |
1360 } | |
1361 } | |
1362 | |
1363 /** | |
1364 * Computes the correct dialog size for the given wizard and resizes its | |
1365 * shell if nessessary. | |
1366 * | |
1367 * @param sizingWizard | |
1368 * the wizard | |
1369 */ | |
1370 private void updateSizeForWizard(IWizard sizingWizard) { | |
1371 Point delta = new Point(0, 0); | |
1372 IWizardPage[] pages = sizingWizard.getPages(); | |
1373 for (int i = 0; i < pages.length; i++) { | |
1374 // ensure the page container is large enough | |
1375 Point pageDelta = calculatePageSizeDelta(pages[i]); | |
1376 delta.x = Math.max(delta.x, pageDelta.x); | |
1377 delta.y = Math.max(delta.y, pageDelta.y); | |
1378 } | |
1379 if (delta.x > 0 || delta.y > 0) { | |
1380 // increase the size of the shell | |
1381 Shell shell = getShell(); | |
1382 Point shellSize = shell.getSize(); | |
1383 setShellSize(shellSize.x + delta.x, shellSize.y + delta.y); | |
1384 } | |
1385 } | |
1386 | |
1387 /* | |
1388 * (non-Javadoc) Method declared on IWizardContainer. | |
1389 */ | |
1390 public void updateTitleBar() { | |
1391 String s = null; | |
1392 if (currentPage !is null) { | |
1393 s = currentPage.getTitle(); | |
1394 } | |
1395 if (s is null) { | |
1396 s = ""; //$NON-NLS-1$ | |
1397 } | |
1398 setTitle(s); | |
1399 if (currentPage !is null) { | |
1400 setTitleImage(currentPage.getImage()); | |
1401 updateDescriptionMessage(); | |
1402 } | |
1403 updateMessage(); | |
1404 } | |
1405 | |
1406 /* | |
1407 * (non-Javadoc) Method declared on IWizardContainer. | |
1408 */ | |
1409 public void updateWindowTitle() { | |
1410 if (getShell() is null) { | |
1411 // Not created yet | |
1412 return; | |
1413 } | |
1414 String title = wizard.getWindowTitle(); | |
1415 if (title is null) { | |
1416 title = ""; //$NON-NLS-1$ | |
1417 } | |
1418 getShell().setText(title); | |
1419 } | |
1420 | |
1421 /* | |
1422 * (non-Javadoc) | |
1423 * | |
1424 * @see dwtx.jface.dialogs.IPageChangeProvider#getSelectedPage() | |
1425 */ | |
1426 public Object getSelectedPage() { | |
1427 return getCurrentPage(); | |
1428 } | |
1429 | |
1430 /* | |
1431 * (non-Javadoc) | |
1432 * | |
1433 * @see dwtx.jface.dialog.IPageChangeProvider#addPageChangedListener() | |
1434 */ | |
1435 public void addPageChangedListener(IPageChangedListener listener) { | |
1436 pageChangedListeners.add(listener); | |
1437 } | |
1438 | |
1439 /* | |
1440 * (non-Javadoc) | |
1441 * | |
1442 * @see dwtx.jface.dialog.IPageChangeProvider#removePageChangedListener() | |
1443 */ | |
1444 public void removePageChangedListener(IPageChangedListener listener) { | |
1445 pageChangedListeners.remove(listener); | |
1446 } | |
1447 | |
1448 /** | |
1449 * Notifies any selection changed listeners that the selected page has | |
1450 * changed. Only listeners registered at the time this method is called are | |
1451 * notified. | |
1452 * | |
1453 * @param event | |
1454 * a selection changed event | |
1455 * | |
1456 * @see IPageChangedListener#pageChanged | |
1457 * | |
1458 * @since 3.1 | |
1459 */ | |
1460 protected void firePageChanged(final PageChangedEvent event) { | |
1461 Object[] listeners = pageChangedListeners.getListeners(); | |
1462 for (int i = 0; i < listeners.length; ++i) { | |
1463 final IPageChangedListener l = (IPageChangedListener) listeners[i]; | |
1464 SafeRunnable.run(new SafeRunnable() { | |
1465 public void run() { | |
1466 l.pageChanged(event); | |
1467 } | |
1468 }); | |
1469 } | |
1470 } | |
1471 | |
1472 /** | |
1473 * Adds a listener for page changes to the list of page changing listeners | |
1474 * registered for this dialog. Has no effect if an identical listener is | |
1475 * already registered. | |
1476 * | |
1477 * @param listener | |
1478 * a page changing listener | |
1479 * @since 3.3 | |
1480 */ | |
1481 public void addPageChangingListener(IPageChangingListener listener) { | |
1482 pageChangingListeners.add(listener); | |
1483 } | |
1484 | |
1485 /** | |
1486 * Removes the provided page changing listener from the list of page | |
1487 * changing listeners registered for the dialog. | |
1488 * | |
1489 * @param listener | |
1490 * a page changing listener | |
1491 * @since 3.3 | |
1492 */ | |
1493 public void removePageChangingListener(IPageChangingListener listener) { | |
1494 pageChangingListeners.remove(listener); | |
1495 } | |
1496 | |
1497 /** | |
1498 * Notifies any page changing listeners that the currently selected dialog | |
1499 * page is changing. Only listeners registered at the time this method is | |
1500 * called are notified. | |
1501 * | |
1502 * @param event | |
1503 * a selection changing event | |
1504 * | |
1505 * @see IPageChangingListener#handlePageChanging(PageChangingEvent) | |
1506 * @since 3.3 | |
1507 */ | |
1508 protected void firePageChanging(final PageChangingEvent event) { | |
1509 Object[] listeners = pageChangingListeners.getListeners(); | |
1510 for (int i = 0; i < listeners.length; ++i) { | |
1511 final IPageChangingListener l = (IPageChangingListener) listeners[i]; | |
1512 SafeRunnable.run(new SafeRunnable() { | |
1513 public void run() { | |
1514 l.handlePageChanging(event); | |
1515 } | |
1516 }); | |
1517 } | |
1518 } | |
1519 } | |
1520 ++/ |