Guidelines
1) Extend Wizard
2) Create the pages extending WizardPage.
3) Add pages to the wizard in constructor.
4) In the page constructor identify each with an ID — see WizardPage.
5) Launch the Wizard through a WizardDialog
Notes
1) Don’t use WizardPage canFlipToNext()…Use setPageComplete() instead.
Adding Pages to a Wizard
Add pages in the Wizard constructor:
public NewRateWizard() {
super();
this.addPage(new RateTypePage());
this.addPage(new FlatRatePage());
this.addPage(new WeightBreakRatePage());
this.addPage(new WeightBreakLineSetPage());
}
Page Navigation
Page navigation is managed at the page level through the page identifier that is set in the WizardPage constructor with a call to super(“myPageId”) and by overriding the nextPage method of WizardPage.
To control access to following pages use calls to setPageComplete(boolean).
Here’s the constructor example:
public RateTypePage() {
super("rateType");
setTitle("Rate Type");
setDescription("Select the rate type...");
this.setPageComplete(false);
}
Here’s the override of getNextPage(). If there is no next page, return null.
@Override
public IWizardPage getNextPage() {
if (this.flatRateButton.getSelection()) {
return this.getWizard().getPage("flatRate");
}
if (this.weightBreakButton.getSelection()) {
return this.getWizard().getPage("weightBreak1");
}
}
Enable Finish Button
The default implementation of the canFinish() method in the Wizard class will return true only if all the wizard pages are complete:
public boolean canFinish() { // Default implementation is to check if all pages are complete. for (int i = 0; i < pages.size(); i++) { if (!((IWizardPage) pages.get(i)).isPageComplete()) { return false; } } return true; }
So in order to make sure Wizard.canFinish() will return true, you need to call setPageComplete(true) on all Wizard pages. The logical thing to do would be to use a for-each loop as shown in the following enableFinish method... but you will be disappointed.
private void enableFinish(){ IWizard w = this.getWizard(); IWizardPage [] pages = w.getPages(); WizardPage p; for(IWizardPage wp : pages){ p = (WizardPage) wp; p.setPageComplete(true); } }
The for-each loop will sometimes fail to iterate through all the pages in the Wizard and debugging this will be painful to the point that it may even inspire you to drop everything that you know about java and switch to .Net. So, promise yourself not to use the for-each loop on any array returned by any eclipse class. The safe way to enable finish would be something like this:
private void enableFinish(){ IWizard w = this.getWizard(); IWizardPage [] pages = w.getPages(); for(int i = 0; i < pages.length; i++){ ((WizardPage) pages[i]).setPageComplete(true); } this.setPageComplete(true); // this is needed. }
The last line is needed because the finish button will not be enabled if setComplete is called on the current page without all other pages being flagged as completed. Since there are no guarantees about page ordering in the pages array, without this final line the finished button will be enabled at random (only when the current page is the last one to receive a call to setPageComplete) and --once again-- this will not be easy to debug.
The JFace Wizard API works, but it has a lot of room for improvement.
Override performFinish()
To perform final tasks or clean-up before the Wizard closes, override performFinish(). This method should return true if the Wizard should close. If the method returns false, the only way to close the wizard is by clicking the cancel button.
public boolean performFinish() {
//some final tasks or cleanup here.
return false;
}
Launching the Wizard
NewSomethingWizard wiz = new NewSomethingWizard();
WizardDialog dlg = new WizardDialog(getSite().getShell(), wiz);
int rc = dlg.open();
if(rc == Window.OK){
something = wiz.getSomething();
persistSomething(something);
}