Creating Orana Wizards
Warning: This document is incomplete and is a work-in-progress.
This documentation is based on the 'Creating JFace Wizards' Eclipse article which can be found at http://www.eclipse.org/articles/Article-JFace%20Wizards/wizardArticle.html
Wizard Sample
This page will document the process of porting the wizard sample in the JFace article to Orana.
Creating a Moomba project
To make life simpler we will base this project on the simple Moomba plugin archetype described here. Once this project has been created import the project into Eclipse.
Adding the article files to the mix
Download the wizard sample code from the Eclipse article and unzip the project into a temporary directory.
Create a new package in the wizard project called 'com.xyz.article.wizards' and add all the source files to this package. You might aswell add the 2 image files to 'src/main/resource/image' also - we'll need them later.
Refactoring the JFace code to Orana
This section concentrates on refactoring the code to use Orana and Cooee instead of JFace and SWT so that it compiles properly.
HolidayModel.java
Luckily, because this is just a model and has no GUI references, no changes are required for this file.
HolidayAction.java
We're going to change this quite a bit because, unlike the example, we're going to add a simple Action to the Moomba workbench. The wizard example contributes a 'newWizard' to the Eclipse workbench which is something yet to be implemented in Moomba.
All we're interested in is an action that can display the wizard.
Replace the entire code with the following:
package com.xyz.article.wizards; import org.karora.cooee.app.ImageReference; import org.karora.cooee.app.ResourceImageReference; import org.karora.moomba.ui.PlatformUI; import org.karora.orana.action.Action; import org.karora.orana.wizard.WizardDialog; /** * Class associated with the popupMenu for the folder * Start the wizard in the run method */ public class HolidayAction extends Action { // Action unique ID public static final String ID = "org.karora.orana.wizard.HolidayAction"; public String getActionDefinitionId() { return null; } public int getStyle() { return 0; } public boolean isToolBarAction() { return true; } public void setActionDefinitionId(String id) { } @Override public String getToolTipText() { return "Click me to go on holiday!!!"; } @Override public ImageReference getImageDescriptor() { return new ResourceImageReference("image/wizard.gif"); } @Override public void run() { // Instantiates and initializes the wizard HolidayWizard wizard = new HolidayWizard(); // Instantiates the wizard container with the wizard and opens it WizardDialog dialog = new WizardDialog( PlatformUI.getWorkbench().getActiveWorkbenchWindow().getWindow(), wizard); dialog.create(); dialog.open(null); } @Override public String getText() { return "Wizard"; } @Override public String getId() { return HolidayAction.ID; } }
CarPage.java
The changes required in this file are all due to the differences between SWT and Cooee
- Remove implements Listener from the class declaration.
- Change the Combo, Text, and Button widgets to a SelectFieldEx, TextFieldEx, and CheckBoxEx respectively.
- Remove the handleEvent method completely. We'll attach listeners directly to the controls.
- Replace all occurrences of companyCombo.getText() with companyCombo.getSelectedItem().toString()
- Replace insuranceButton.getSelection() with insuranceButton.isSelected()
- Replace the createControl method with:
public void createControl(Component parent) { Grid gl = new Grid(2); parent.add(gl); // create the widgets. If the appearance of the widget is different from the default, // create a GridData for it to set the alignment and define how much space it will occupy // rental company gl.add(new Label ("Rental company")); companyCombo = new SelectFieldEx(rentalCompanyNames); gl.add(companyCombo); companyCombo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { if (companyCombo.getSelectedIndex() >=0) priceText.setText("£"+prices[companyCombo.getSelectedIndex()]); setPageComplete(isPageComplete()); getWizard().getContainer().updateButtons(); } }); gl.add(new Label ("Price:")); priceText = new TextFieldEx(); // insurance button insuranceButton = new CheckBoxEx("Buy insurance"); gl.add(insuranceButton); insuranceButton.setSelected(true); // set the composite as the control for this page setControl(gl); }
- Remove all imports and then select 'Source/Organize Imports' from the editor popup menu.
PlanePage.java
Similarly to above, the changes required in this file are due to differences between SWT and Cooee
- Remove implements Listener from the class declaration.
- Change the List and Text widgets to a ListBoxEx and TextFieldEx respectively.
- Remove the handleEvent method completely. We'll attach listeners directly to the controls.
- Replace all occurrences of seatCombo.getText() with seatCombo.getSelectedItem().toString()
- Replace the createControl method with:
public void createControl(Component parent) { // create the desired layout for this wizard page Grid gl = new Grid(2); parent.add(gl); // create the widgets. If the appearance of the widget is different from the default, // create a GridData for it to set the alignment and define how much space it will occupy // flights list Label label = new Label(); gl.add(label); label.setText("Flights:"); // price button priceButton = new PushButton(); gl.add(priceButton); priceButton.setText("Get price"); priceButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { if (flightsList.getSelectedIndices().length >0) { if (((HolidayWizard)getWizard()).model.discounted) price *= discountRate; MessageDialog.openInformation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getWindow(),"", "Flight price "+ price, null); } setPageComplete(isPageComplete()); getWizard().getContainer().updateButtons(); } }); flightsList = new ListBoxEx(); GridLayoutData layoutData = new GridLayoutData(); layoutData.setColumnSpan(2); flightsList.setLayoutData(layoutData); gl.add(flightsList); // seat choice gl.add(new Label ("Seat choice:")); seatCombo = new SelectFieldEx(seatChoices); seatCombo.setSelectedIndex(0); gl.add(seatCombo); // set the composite as the control for this page setControl(gl); setPageComplete(true); }
- In isPageComplete replace:
flightsList.getSelectionCount() == 0
with
flightsList.getSelectedIndices().length == 0
- In saveDataToModel replace:
flightsList.getSelection()[0];
with
flightsList.getSelectedValue().toString();
- In onEnterPage replace:
flightsList.removeAll(); flightsList.add(text1); flightsList.add(text2);
with
DefaultListModel listModel = (DefaultListModel)flightsList.getModel(); listModel.removeAll(); listModel.add(text1); listModel.add(text2);
- Remove all imports and then select 'Source/Organize Imports' from the editor popup menu.
HolidayMainPage.java
- Remove implements Listener from the class declaration.
- Change all occurrences of the Combo, Text, and planeButton/carButton Button widgets to a SelectFieldEx, TextFieldEx, and RadioButtonEx respectively.
- Replace all occurrences of getSelectionIndex to getSelectedIndex
- Replace all occurrences of getText for SelectFieldEx components to getSelectedIndex.toString()
- Replace all occurrences of getSelection with isSelected for the RadioButtonEx
- Remove the handleEvent method completely. And replace with the following ActionListener:
private ActionListener actionListener = new ActionListener() { public void actionPerformed(ActionEvent arg0) { // Initialize a variable with the no error status Status status = new Status(IStatus.OK, "not_used", 0, "", null); String command = arg0.getActionCommand(); if(command.equals("travelDate") || command.equals("travelMonth") || command.equals("travelYear") || command.equals("returnDate") || command.equals("returnMonth") || command.equals("returnYear")) { if(isReturnDateSet() && !validDates()) status = new Status(IStatus.ERROR, "not_used", 0, "Return date cannot be before the travel date", null); timeStatus = status; } else if(command.equals("fromText") || command.equals("toText")) { if (fromText.getText().equals(toText.getText()) && !"".equals(fromText.getText())) status = new Status(IStatus.ERROR, "not_used", 0, "Departure and destination cannot be the same", null); destinationStatus = status; } // Show the most serious error applyToStatusLine(findMostSevere()); getWizard().getContainer().updateButtons(); } };
- Also replace the contents of addListeners with:
planeButton.setActionCommand("planeButton"); planeButton.addActionListener(actionListener); carButton.setActionCommand("carButton"); carButton.addActionListener(actionListener); fromText.setActionCommand("fromText"); fromText.addActionListener(actionListener); toText.setActionCommand("toText"); toText.addActionListener(actionListener); travelDate.setActionCommand("travelDate"); travelDate.addActionListener(actionListener); travelMonth.setActionCommand("travelMonth"); travelMonth.addActionListener(actionListener); travelYear.setActionCommand("travelYear"); travelYear.addActionListener(actionListener); returnDate.setActionCommand("returnDate"); returnDate.addActionListener(actionListener); returnMonth.setActionCommand("returnMonth"); returnMonth.addActionListener(actionListener); returnYear.setActionCommand("returnYear"); returnYear.addActionListener(actionListener);
- Replace all occurrences of seatCombo.getText() with seatCombo.getSelectedItem().toString()
- Replace the createControl method with:
public void createControl(Component parent) { // create the composite to hold the widgets Grid gd = new Grid(); parent.add(gd); // create the desired layout for this wizard page Grid gl = new Grid(4); gd.add(gl); // initial value for date of travel, today's date Calendar cal = Calendar.getInstance(); cal.setTime(new Date()); int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH); int month = cal.get(Calendar.MONTH); int year = cal.get(Calendar.YEAR); // create the widgets. If the appearance of the widget is different from the default, // create a GridData for it to set the alignment and define how much space it will occupy // Date of travel gl.add(new Label ("Travel on:")); travelDate = new SelectFieldEx(dates); gl.add(travelDate); travelDate.setSelectedIndex(dayOfMonth -1); // 0 based indexes travelMonth = new SelectFieldEx(months); gl.add(travelMonth); travelMonth.setSelectedIndex(month); travelYear = new SelectFieldEx(years); gl.add(travelYear); travelYear.setSelectedIndex(year - startingYear); // Date of return gl.add(new Label ("Return on:")); returnDate = new SelectFieldEx(dates); gl.add(returnDate); returnMonth = new SelectFieldEx(months); gl.add(returnMonth); returnYear = new SelectFieldEx(years); gl.add(returnYear); createLine(gd, 4); // Departure gl.add(new Label ("From:")); fromText = new TextFieldEx(); gl.add(fromText); // Destination gl.add(new Label ("To:")); toText = new TextFieldEx(); gl.add(toText); createLine(gl, 4); // Choice of transport ButtonGroup bg = new ButtonGroup(); planeButton = new RadioButtonEx(); gl.add(planeButton); planeButton.setGroup(bg); planeButton.setText("Take a plane"); planeButton.setSelected(true); carButton = new RadioButtonEx(); gl.add(carButton); carButton.setGroup(bg); carButton.setText("Rent a car"); // set the composite as the control for this page setControl(gl); addListeners(); }
- Remove all imports and then select 'Source/Organize Imports' from the editor popup menu.
HolidayWizard.java
Remove all the imports from the top of the file and then select 'Source/Organize Imports' from the editor popup menu. This will replace all Eclipse/JFace/SWT imports with Moomba/Orana/Cooee imports. Clever eh?
There will still be a few errors because of some slight differences in the APIs of Eclipse and Moomba.
- MessageDialog.openInformation(workbench.getActiveWorkbenchWindow().getShell(), "Holiday info", summary);
with
MessageDialog.openInformation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getWindow(), "Holiday info", summary, null); - Remove the entire init method (this override is yet to be implemented in Orana)
Adding Spring-OSGi configuration
Add the following Spring bean configuration to the src/main/resources/META-INF/spring/bundle-context.xml file to declare the HolidayAction bean:
<bean name="HolidayAction" class="com.xyz.article.wizards.HolidayAction" singleton="false"/>
And then add the following Spring-OSGi service configuration to the src/main/resources/META-INF/spring/bundle-context-osgi.xml file to declare the bean as an Moomba IAction OSGi service.
<osgi:service ref="HolidayAction" interface="org.karora.orana.action.IAction" />
Configuring the MANIFEST.MF
Because the example wizard code has dependencies on some core equinox libraries, we'll have to add the required packages to the Import-Package section of the MANIFEST.MF file
org.eclipse.core.runtime org.eclipse.core.internal.runtime
Building and Deploying
Build the project using mvn package and copy the built jar into your runtime. You can find a pre-packaged runtime here

Add Comment