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