Section 11.2. Wizards


11.2. Wizards

org.eclipse.jface.wizard.WizardDialog is a specialized subclass of Dialog (see Figure 11-6) that is used when a modal operation requires a particular sequence for its information collection or when a single screen has too many fields. Wizards have a title area along the top; a content area in the middle showing the wizard pages; a progress bar as needed; and Help, Next, Back, Finish, and Cancel buttons (or some subset) along the bottom (see Figure 11-7). The title area contains the wizard's title, description, an optional image, and an error, warning, or informational message as required.

Figure 11-6. Wizard class hierarchy.


Figure 11-7. Default wizard dialog structure.


11.2.1. IWizard

Rather than subclass WizardDialog, you should subclass org.eclipse.jface.wizard.Wizard, which implements the org.eclipse.jface.wizard.IWizard interface for use with WizardDialog. The WizardDialog uses the IWizard interface to obtain the pages to be displayed and to notify the wizard of user interaction. The concrete wizard class provides much of the IWizard behavior, allowing you to focus on a subset of the IWizard interface. The wizard's task is to create and initialize the pages it contains, handle any special customized flow and information between pages, and execute the operation when the Finish button is pressed.

addPages() Subclasses should override this method to add the appropriate pages by calling addPage().

canFinish() Returns whether this wizard could be finished without further user interaction. Typically, this is used by the wizard container to enable or disable the Finish button.

createPageControls(Composite) Creates this wizard's controls in the given parent control.

dispose() Cleans up any native resources, such as images, clipboard, and so on, that were created by this class. This follows the if you create it, you destroy it theme that runs throughout Eclipse.

getContainer() Returns the wizard container in which this wizard is being displayed.

getdefaultPageImage() Returns the default page image for this wizard.

geTDialogSettings() Returns the dialog settings for this wizard page.

getNextPage(IWizardPage) Returns the wizard page to be shown after the specified wizard page, or null if none. The default implementation shows pages in the order in which they were added to the wizard, so subclasses need only to override this method to implement a custom page flow.

getPreviousPage(IWizardPage) Returns the wizard page to be shown before the specified wizard page, or null if none. The default implementation shows pages in the order in which they were added to the wizard, so subclasses need only to override this method to implement a custom page flow.

getStartingPage() Answers the first page to be displayed in the wizard. The default implementation answers the first wizard page added to the wizard, so subclasses need only to override this method if the starting page is not the first page added.

performCancel() Called by the wizard container if the wizard is canceled. Subclasses need only to override this method to provide any custom cancel processing. Return TRue if the wizard container can be closed, or false if it should remain open.

performFinish() Called by the wizard container when the Finish button is pressed. Subclasses should override this method to perform the wizard operation and return true to indicate that the wizard container should be closed, or false if it should remain open.

setDefaultPageImageDescriptor(ImageDescriptor) Sets the image displayed in the wizard's title area if the current wizard page does not specify an image.

setHelpAvailable(boolean) Sets whether help is available and whether the Help button is visible.

setNeedsProgressMonitor(boolean) Sets whether this wizard needs a progress monitor. If true, then space is reserved below the page area and above the buttons for a progress bar and progress message to be displayed (see Section 9.4, Progress Monitor, on page 383).

setTitleBarColor(RGB) Sets the color of the title area.

setWindowTitle(String) Sets the window title.

11.2.2. IWizardPage

Wizards use the org.eclipse.jface.wizard.IWizardPage interface to communicate with the pages they contain. Typically, you will subclass the org.eclipse.jface.wizard.WizardPage class, accessing and overriding the following methods, rather than implementing the IWizardPage interface. The wizard page's task is to present a page of information to the user, validate any information entered by the user on that page, and provide accessors for the wizard to gather the information entered.

createControl(Composite) Creates the controls comprising this wizard page.

dispose() Cleans up any native resources, such as images, clipboard, and so on, that were created by this class. This follows the if you create it, you destroy it theme that runs throughout Eclipse.

getContainer() Returns the wizard container for this wizard page.

getdialogSettings() Returns the dialog settings for this wizard page.

getWizard() Returns the wizard that hosts this wizard page.

setDescription(String) Sets the descriptive text appearing in the wizard's title area.

setErrorMessage(String) Sets or clears the error message for this page.

setImageDescriptor(ImageDescriptor) Sets the image that appears in the wizard's title area.

setMessage(String) Sets or clears the message for this page.

setPageComplete(boolean) Sets whether this page is complete. This forms the basis for determining whether the Next and Finish buttons are enabled.

setTitle(String) Sets the title that appears in the title area of the wizard, not the title on the shell.

setVisible(boolean) Sets the visibility of this dialog page. Subclasses can extend this method (being sure to call the superclass method) to detect when a page becomes the active page.

One approach for validating information entered by a user on a wizard page is for each field to have a listener that calls an updatePageComplete() method in the wizard page (snipped from Section 11.2.8, Page content based on selection, on page 441).

sourceFileField = new Text(container, SWT.BORDER); sourceFileField.addModifyListener(new ModifyListener()  {    public void modifyText(ModifyEvent e) {       updatePageComplete();    } }); 


This updatePageComplete() method would be responsible for checking the content in each field, displaying an error message as appropriate, and calling the setPageComplete() method (see Section 11.2.8, Page content based on selection, on page 441 for an example). The pageComplete attribute is used by the wizard container to determine whether the Next and Finish buttons should be enabled.

New in Eclipse 3.2

The org.eclipse.jface.fieldassist package adds images, hover text, content proposals, and auto type-ahead to fields in forms, dialogs, and wizards. This functionality can help a user understand and enter information into a form-based user interface.


11.2.3. IWizardContainer

The wizard uses the org.eclipse.jface.wizard.IWizardContainer interface to communicate with the context in which it is being displayed.

getCurrentPage() Returns the current page being displayed.

getShell() Returns the shell for this wizard container.

run(boolean, boolean, IRunnableWithProgress) Runs the given runnable in the context of the wizard dialog. The first argument "fork" indicates whether the runnable should be executed in a separate thread. The second argument "cancelable" indicates whether the user should be allowed to cancel the operation while it is in progress (see Section 4.2.5.1, Display, on page 140 for more on the UI thread).

showPage(IWizardPage) Shows the specified wizard page. This should not be used for normal next/back page flow, but exists for custom page flow such as double-clicking in a list.

updateButtons() Adjusts the enable state of the Back, Next, and Finish buttons to reflect the state of the active page in this container.

updateMessage() Updates the message shown in the message line to reflect the state of the currently active page in this container.

updateTitleBar() Updates the title bar (title, description, and image) to reflect the state of the active page in this container.

updateWindowTitle() Updates the window title to reflect the state of the wizard.

In addition to IWizardContainer, WizardDialog implements both IWizardContainer2 and IPageChangeProvider. In your wizard, you can obtain the container using getContainer() and then test to see whether it implements either of these interfaces to access additional functionality.

addPageChangedListener(IPageChangedListener) Adds a listener for page changes in this page change provider.

getSelectedPage() Returns the currently selected page in the dialog.

removePageChangedListener(IPageChangedListener) Removes the given page change listener from this page change provider.

updateSize() Updates the window size to reflect the state of the current wizard.

11.2.4. Nested wizards

One wizard can contain one or more nested wizards such as the Import and Export wizards. The org.eclipse.jface.wizard.WizardSelectionPage class provides behavior for managing one or more nested wizards. When a nested wizard can be determined, a WizardSelectionPage subclass calls the setSelectedNode() method. When a user clicks the Next button, the WizardSelectionPage class uses that information via the org.eclipse.jface.wizard.IWizardNode interface to create and manage the nested wizard.

11.2.5. Launching a wizard

You can hook a wizard into the Eclipse framework using one of the predefined wizard extension points, or you can manually launch a wizard as a result of a user action.

11.2.5.1. Wizard extension points

If you want Eclipse to automatically provide an action delegate and display your wizard in a predefined location, you can extend one of the following wizard extension points.

org.eclipse.ui.exportWizards Adds a nested wizard in the Export wizard, which is displayed by selecting the File > Export... command. Wizard classes associated with this extension point must implement the org.eclipse.ui.IExportWizard interface.

org.eclipse.ui.importWizards Adds a nested wizard in the Import wizard, which is displayed by selecting File > Import.... Wizard classes associated with this extension point must implement the org.eclipse.ui.IImportWizard interface.

org.eclipse.ui.newWizards Adds a nested wizard in the New wizard, which is displayed by selecting File > New > Other.... Wizard classes associated with this extension point must implement the org.eclipse.ui.INewWizard interface.

These three extension points share several common attributes:

class The wizard class to be launched by the parent wizard. This wizard must implement the appropriate interface for the extension point as outlined earlier. The class is instantiated using its no argument constructor, but can be parameterized using the IExecutableExtension interface (see Section 20.5, Types Specified in an Extension Point, on page 723).

icon The icon associated with this wizard, similar to action images (see Section 6.2.4, Action images, on page 214).

id The unique identifier for the wizard.

name The human-readable name for the wizard.

You can specify a filter for both org.eclipse.ui.exportWizards and org.eclipse.ui.importWizards extension points using the selection subelement. By using a filter, your export or import wizard only appears when the appropriately named or typed element is selected.

The org.eclipse.ui.newWizards extension point requires an additional category attribute to identify how wizards are to be hierarchically organized. This category is declared using the same extension point with the following attributes:

id The unique identifier for the category.

name The human-readable name for the category.

parentCategory The unique identifier for the category in which the category will appear, if there is one.

The org.eclipse.ui.newWizards extension point also allows you to specify a primaryWizard. A primary wizard is emphasized in the new wizard dialog and exists so that product managers can emphasize a set of wizards for their products. This element is not intended to be used by plug-in developers.

If a wizard declared using one of the aforementioned extension points implements the IExecutableExtension interface, then Eclipse will communicate additional initialization information encoded in the declaration to the wizard using that interface (see Section 20.5, Types Specified in an Extension Point, on page 723).

You can use the plug-in manifest editor to quickly create a wizard class with stub methods that is hooked into one of the wizard extension points. In the plug-in manifest editor, navigate to the Extensions page and click the Add... button to add, for example, an org.eclipse.ui.newWizards extension (see Section 6.2.1, Defining a workbench window menu, on page 209 for an example of adding extensions). Then, right-click on the org.eclipse.ui.newWizards extension in the plug-in manifest editor and select New > wizard. Select the wizard extension that was added to edit its properties (see Figure 11-8).

Figure 11-8. The extension element details showing newWizard extension.


Clicking on the class: label to the right of the class field will open a Java Attribute Editor dialog in which a new class can be created (see Figure 11-9).

Figure 11-9. Java Attribute Editor dialog showing class creation.


Completing the required fields generates a new Java class and hooks that class into the plug-in manifest. The folowing are the generated plug-in manifest entry and stub Java wizard class.

<extension point="org.eclipse.ui.newWizards">    <wizard       name="com.qualityeclipse.favorites.wizard1"              >    </wizard> </extension> package com.qualityeclipse.favorites; import ... public class NewWizard1 extends Wizard    implements INewWizard {    public void init(       IWorkbench workbench, IStructuredSelection selection    ) {       // Initialization code here.    }    public boolean performFinish() {       // Perform operation here.       return false;    } } 


11.2.5.2. Manually launching a wizard

Alternatively, you can launch a wizard from an action delegate. In this case, implement an IObjectActionDelegate (see Section 6.3.3, IObjectActionDelegate, on page 233) with a run() method that launches the Extract Strings wizard (see next section).

public void setActivePart(IAction action, IWorkbenchPart targetPart) {    this.targetPart = targetPart; } public void selectionChanged(IAction action, ISelection selection) {    this.selection =       selection instanceof IStructuredSelection          ? (IStructuredSelection) selection          : null; } public void run(IAction action) {    IWorkbenchPartSite site = targetPart.getSite();    IWorkbenchWindow window = site.getWorkbenchWindow();    ExtractStringsWizard wizard = new ExtractStringsWizard();    wizard.init(window.getWorkbench(), selection);    WizardDialog dialog = new WizardDialog(window.getShell(), wizard);    dialog.open(); } 


11.2.6. Wizard example

For the example, you will create a two-page wizard for extracting strings from a plugin.xml file and placing those strings into a separate plugin.properties file as specified by the RFRS requirements. The wizard is responsible for instantiating the two pages, facilitating communication from the first page to the second, and gathering information from the two pages and performing the operation when the user presses the Finish button. The operation is performed in a separate thread so that the user can cancel the operation (see Section 9.4, Progress Monitor, on page 383 and Section 4.2.5.1, Display, on page 140 for more about the UI thread).

In the following code example, the init() method is called directly by the action delegate, while the addPages() method is called indirectly by the dialog framework when the wizard dialog is created and opened. This approach parallels the INewWizard interface so that this wizard can easily implement that interface and thus be launched by File > New > Other....

package com.qualityeclipse.favorites.wizards; import ... public class ExtractStringsWizard extends Wizard       implements INewWizard {    private IStructuredSelection initialSelection;    private SelectFilesWizardPage selectFilesPage;    private SelectStringsWizardPage selectStringsPage;    public void init(       IWorkbench workbench, IStructuredSelection selection    ) {       initialSelection = selection;    }    public void addPages() {       setWindowTitle("Extract");       selectFilesPage = new SelectFilesWizardPage();       addPage(selectFilesPage);       selectStringsPage = new SelectStringsWizardPage();       addPage(selectStringsPage);       selectFilesPage.init(initialSelection);    } 


When the user has finished entering information and clicks the Finish button, the performFinish() method is called to perform the operation. In this example, the finish method uses functionality provided by the wizard container to perform the operation on a separate thread so that the UI stays responsive during the operation and so that the user can cancel the operation.

public boolean performFinish() {    try {       getContainer().run(true, true, new IRunnableWithProgress() {          public void run(IProgressMonitor monitor)             throws InvocationTargetException, InterruptedException          {             performOperation(monitor);          }       });    }    catch (InvocationTargetException e) {       FavoritesLog.logError(e);       return false;    }    catch (InterruptedException e) {       // User canceled, so stop but don't close wizard.       return false;    }    return true; } private void performOperation(IProgressMonitor monitor) {    ExtractedString[] extracted = selectStringsPage.getSelection();    // Perform the operation here. } 


11.2.7. Dialog settings

Dialog settings can be used to store current values for a wizard or dialog to use the next time the wizard or dialog is opened. In this case, instantiate and cache the dialog settings object in the wizard's constructor for use by the various wizard pages. The getSection() call is used to isolate settings for this wizard from settings for other wizards. Each page can then use the various IDialogSetting get() and put() methods to load and save values across sessions.

public ExtractStringsWizard() {    IDialogSettings favoritesSettings =       FavoritesPlugin.getDefault().getDialogSettings();    IDialogSettings wizardSettings =       favoritesSettings.getSection("ExtractStringsWizard");    if (wizardSettings == null)       wizardSettings =          favoritesSettings.addNewSection("ExtractStringsWizard");    setDialogSettings(favoritesSettings); } 


11.2.8. Page content based on selection

The first page of the Extract Strings wizard displays Source File and Destination File text fields, each with a Browse... button to the right (see Figure 11-10). The createControl() method creates and aligns each of the wizard page controls.

package com.qualityeclipse.favorites.wizards; import ... public class SelectFilesWizardPage extends WizardPage {    private Text sourceFileField;    private Text destinationFileField;    private IPath initialSourcePath;    public SelectFilesWizardPage() {       super("selectFiles");       setTitle("Select files");       setDescription(          "Select the source and destination files");    }    public void createControl(Composite parent) {       Composite container = new Composite(parent, SWT.NULL);       final GridLayout gridLayout = new GridLayout();       gridLayout.numColumns = 3;       container.setLayout(gridLayout);       setControl(container);       final Label label = new Label(container, SWT.NONE);       final GridData gridData = new GridData();       gridData.horizontalSpan = 3;       label.setLayoutData(gridData);       label.setText(          "Select the plugin.xml file " +          "from which strings will be extracted.");       final Label label_1 = new Label(container, SWT.NONE);       final GridData gridData_1 =          new GridData(GridData.HORIZONTAL_ALIGN_END);       label_1.setLayoutData(gridData_1);       label_1.setText("Source File:");       sourceFileField = new Text(container, SWT.BORDER);       sourceFileField.addModifyListener(new ModifyListener() {          public void modifyText(ModifyEvent e) {             updatePageComplete();          }       });       sourceFileField.setLayoutData(          new GridData(GridData.FILL_HORIZONTAL));       final Button button = new Button(container, SWT.NONE);       button.addSelectionListener(new SelectionAdapter() {          public void widgetSelected(SelectionEvent e) {             browseForSourceFile();          }       });       button.setText("Browse...");        final Label label_2 = new Label(container, SWT.NONE);        final GridData gridData_2 = new GridData();        gridData_2.horizontalSpan = 3;        label_2.setLayoutData(gridData_2);        final Label label_3 = new Label(container, SWT.NONE);        final GridData gridData_3 = new GridData();        gridData_3.horizontalSpan = 3;        label_3.setLayoutData(gridData_3);        label_3.setText(           "Select the plugin.properties file " +           "into which strings will be placed.");        final Label label_4 = new Label(container, SWT.NONE);        final GridData gridData_4 = new GridData();        gridData_4.horizontalIndent = 20;        label_4.setLayoutData(gridData_4);        label_4.setText("Destination File:");        destinationFileField =           new Text(container, SWT.BORDER);        destinationFileField.addModifyListener(           new ModifyListener() {              public void modifyText(ModifyEvent e) {                 updatePageComplete();              }           });        destinationFileField.setLayoutData(           new GridData(GridData.HORIZONTAL_ALIGN_FILL));        final Button button_1 =           new Button(container, SWT.NONE);        button_1           .addSelectionListener(new SelectionAdapter() {           public void widgetSelected(SelectionEvent e) {              browseForDestinationFile();           }        });        button_1.setText("Browse...");        initContents();    } } 


Figure 11-10. The Extract Strings wizard.


As always, the goal is to save time for the user. If the user has already selected something in the workbench, you want to populate the wizard page based on that information. For this wizard page, the init() method analyzes the current selection and caches the result, while the initContents() method initializes the field content based on that cached result.

public void init(ISelection selection) {    if (!(selection instanceof IStructuredSelection))        return;    // Find the first plugin.xml file.    Iterator iter = ((IStructuredSelection) selection).iterator();    while (iter.hasNext()) {       Object item = (Object) iter.next();       if (item instanceof IJavaElement) {          IJavaElement javaElem = (IJavaElement) item;          try {             item = javaElem.getUnderlyingResource();          }          catch (JavaModelException e) {             // Log and report the exception.             e.printStackTrace();             continue;          }       }       if (item instanceof IFile) {          IFile file = (IFile) item;          if (file.getName().equals("plugin.xml")) {             initialSourcePath = file.getLocation();             break;          }          item = file.getProject();       }       if (item instanceof IProject) {          IFile file = ((IProject) item).getFile("plugin.xml");          if (file.exists()) {             initialSourcePath = file.getLocation();             break;          }       }    } } private void initContents() {    if (initialSourcePath == null)       return;    IPath rootLoc = ResourcesPlugin.getWorkspace()       .getRoot().getLocation();    IPath path = initialSourcePath;    if (rootLoc.isPrefixOf(path))       path = path          .setDevice(null)          .removeFirstSegments(rootLoc.segmentCount());    sourceFileField.setText(path.toString());    destinationFileField.setText(       path          .removeLastSegments(1)          .append("plugin.properties")          .toString());    updatePageComplete();    setMessage(null);    setErrorMessage(null); } 


Wizards provide a message area just below the title in which feedback can be provided. Generally, this area is used to indicate to the user that additional information needs to be entered before proceeding to the next wizard page or performing the operation. In this case, the updatePageComplete() method is called once after initial contents are determined and again by various text field listeners anytime the content changes. This method then inspects the current text field contents, displays an error or warning message, and enables or disables the Next and Finish buttons as appropriate.

private void updatePageComplete() {    setPageComplete(false);    IPath sourceLoc = getSourceLocation();    if (sourceLoc == null || !sourceLoc.toFile().exists()) {       setMessage(null);       setErrorMessage("Please select an existing plugin.xml file");       return;    }    IPath destinationLoc = getDestinationLocation();    if (destinationLoc == null) {       setMessage(null);       setErrorMessage(          "Please specify a plugin.properties file"             + " to contain the extracted strings");       return;    }    setPageComplete(true);    IPath sourceDirPath = sourceLoc.removeLastSegments(1);    IPath destinationDirPath = destinationLoc.removeLastSegments(1);    if (!sourceDirPath.equals(destinationDirPath)) {       setErrorMessage(null);       setMessage(          "The plugin.properties file is typically"             + " located in the same directory"             + " as the plugin.xml file",          WARNING);       return;    }    if (!destinationLoc.lastSegment().equals("plugin.properties")) {       setErrorMessage(null);       setMessage(         "The destination file is typically"            + " named plugin.properties",          WARNING);       return;    }    setMessage(null);    setErrorMessage(null); } 


When the user clicks the Browse button, the selection listener calls the browseForSourceFile() method to prompt the user for a source file. You also need a similar method called browseForDestinationFile() to be called when the other Browse button is clicked, plus accessors for source and destination locations.

protected void browseForSourceFile() {    IPath path = browse(getSourceLocation(), false);    if (path == null)       return;     IPath rootLoc = ResourcesPlugin.getWorkspace()        .getRoot().getLocation();    if (rootLoc.isPrefixOf(path))       path = path          .setDevice(null)          .removeFirstSegments(rootLoc.segmentCount());    sourceFileField.setText(path.toString()); } private IPath browse(IPath path, boolean mustExist) {    FileDialog dialog = new FileDialog(getShell(),          mustExist ? SWT.OPEN : SWT.SAVE);     if (path != null) {       if (path.segmentCount() > 1)          dialog.setFilterPath(path.removeLastSegments(1)                .toOSString());       if (path.segmentCount() > 0)          dialog.setFileName(path.lastSegment());    }    String result = dialog.open();     if (result == null)        return null;    return new Path(result); } public IPath getSourceLocation() {    String text = sourceFileField.getText().trim();    if (text.length() == 0)        return null;    IPath path = new Path(text);    if (!path.isAbsolute())       path = ResourcesPlugin.getWorkspace().getRoot().getLocation()              .append(path);    return path; } 


11.2.9. Page content based on previous page

The second page of the wizard contains a checkbox list of key/value pairs that can be extracted from the source file (see Figure 11-11).

package com.qualityeclipse.favorites.wizards; import ... public class SelectStringsWizardPage extends WizardPage {    private CheckboxTableViewer checkboxTableViewer;    private IPath sourceLocation;    private ExtractedStringsModel stringModel;    public SelectStringsWizardPage() {       super("selectStrings");       setTitle("Extract Strings");       setDescription("Select the strings to be extracted");    }    public void createControl(Composite parent) {       Composite container = new Composite(parent, SWT.NULL);       container.setLayout(new FormLayout());       setControl(container);       checkboxTableViewer =          CheckboxTableViewer.newCheckList(container, SWT.BORDER);       checkboxTableViewer.setContentProvider(          new ExtractedStringsContentProvider());       checkboxTableViewer.setLabelProvider(          new ExtractedStringsLabelProvider());        final Table table = checkboxTableViewer.getTable();        final FormData formData = new FormData();        formData.bottom = new FormAttachment(100, 0);        formData.right = new FormAttachment(100, 0);        formData.top = new FormAttachment(0, 0);        formData.left = new FormAttachment(0, 0);        table.setLayoutData(formData);        table.setHeaderVisible(true);        final TableColumn tableColumn =           new TableColumn(table, SWT.NONE);        tableColumn.setWidth(200);        tableColumn.setText("Key");        final TableColumn tableColumn_1 =           new TableColumn(table, SWT.NONE);        tableColumn_1.setWidth(250);        tableColumn_1.setText("Value");    } 


Figure 11-11. Second page of the Extract Strings wizard.


Rather than initializing its contents when first created, this page updates its contents whenever it becomes visible by overriding the setVisible() method. You also need an accessor method to return the selected strings.

public void setVisible(boolean visible) {    if (visible) {       IPath location =          ((ExtractStringsWizard) getWizard()).getSourceLocation();       if (!location.equals(sourceLocation)) {          sourceLocation = location;          stringModel = new ExtractedStringsModel(sourceLocation);          checkboxTableViewer.setInput(stringModel);       }    }    super.setVisible(visible); } public ExtractedString[] getSelection() {    Object[] checked = checkboxTableViewer.getCheckedElements();    int count = checked.length;    ExtractedString[] extracted = new ExtractedString[count];    System.arraycopy(checked, 0, extracted, 0, count);    return extracted; } 


There are also two model classes, ExtractedString and ExtractedStringsModel, and two viewer helper classes, ExtractedStringsContentProvider and ExtractedStringsLabelProvider, similar to classes already covered earlier in the book. This classes can be found as part of the example code that is downloadable from the QualityEclipse Web site (www.qualityeclipse.com). For more on these types of classes, see the following:

  • Section 7.2.3, View model, on page 265

  • Section 7.2.4, Content provider, on page 276

  • Section 7.2.5, Label provider, on page 277



Eclipse(c) Building Commercial-Quality Plug-ins
Eclipse: Building Commercial-Quality Plug-ins (2nd Edition)
ISBN: 032142672X
EAN: 2147483647
Year: 2004
Pages: 200

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net