Chapter 19. Auto-Test Property

We don't want auto-testing for all projects. We would like to switch it off and on for individual projects. In this chapter we will

  • Create a project property page with a checkbox for auto testing so that the user can turn on and off the auto-test builder

  • Call the methods that add or remove a nature

First, we need to get the property page to appear when we bring up the properties of a Java project. Eclipse can attach properties to any object. As a developer, you can allow a user to edit the properties of anything. To do so you provide property pages though an extension point. In the property page, you decide how to store and retrieve the property values. For example, Eclipse already supports attaching persistent properties to a resource.

We can copy the declaration from one of the other project property pages (see Figure 19.1).

Auto-Test Property
Auto-Test Property
Auto-Test Property

Clicking on org.eclipse.jdt.ui, we see many property pages. Here's one:

Example . org.eclipse.jdt.ui/plugin.xml

org.eclipse.jdt.ui/plugin.xml
<extension point="org.eclipse.ui.propertyPages">
  <page
    name="%buildPathPageName"
    id="org.eclipse.jdt.ui.propertyPages.BuildPathsPropertyPage"
    objectClass="org.eclipse.core.resources.IProject"
    class="org.eclipse.jdt.internal.ui.preferences.
      BuildPathsPropertyPage">
    <filter name="nature" value="org.eclipse.jdt.core.
      javanature"/>
  </page>
</extension>

The Relevance Rule is in action in this declaration. The filter element has a predefined set of possible keys: nature and persistent property. The declaration above says only projects having the Java nature will show this property page. Copying this into our manifest, we get:

Example . org.eclipse.contribution.junit/plugin.xml

<extension point="org.eclipse.ui.propertyPages">
  <page
    id="org.eclipse.contribution.junit.autotestproperty"
    name="Auto-test"
    objectClass="org.eclipse.jdt.core.IJavaProject"
    class="org.eclipse.contribution.junit.ui.
      AutoTestPropertyPage">
    <filter name="nature" value="org.eclipse.jdt.core.
      javanature"/>
  </page>
</extension>

In the run-time workbench, we can create a Java project. When we look at the project's properties, we see the name of the property page, as shown in Figure 19.3, but when we select it, we get an error because the class hasn't been implemented yet.

org.eclipse.contribution.junit/plugin.xml

If we show the project in the Navigator (instead of the Package Explorer in the Java perspective), the property page doesn't appear. Why not? The object class specified in the declaration is checked against the type of the currently selected element. In the Package Explorer, the elements are IJavaProjects. The Navigator shows IProjects. How can we make our property page appear in both places?

One solution used occasionally in Eclipse is to declare the property page twice, once for an IProject and once for an IJavaProject. This is not an elegant solution. A better solution, also used in Eclipse, is to enable the resource adapter for the contribution (Chapter 31). Applying the resource adapter to an IJavaProject will reveal its IProject.

Example . org.eclipse.contribution.junit/plugin.xml

<extension point="org.eclipse.ui.propertyPages">
  <page
    id="org.eclipse.contribution.junit.autotestproperty"
    name="Auto-test"
    objectClass="org.eclipse.core.resources.IProject"
    adaptable="true"
    class="org.eclipse.contribution.junit.ui.
      AutoTestPropertyPage">
    <filter name="nature" value="org.eclipse.jdt.core.
      javanature"/>
  </page>
</extension>

At runtime, Eclipse will look at the selection. If it's an IProject, no problem. The property page sticks. If the selection is anything else, Eclipse will ask to see if the selection can be adapted to an IProject (for more on adapters, see Chapter 31). IJavaProjects are adaptable to IProjects, so the page sticks. Other elements are not adaptable to IProjects, so the page will not stick to, for example, compilation units.

To implement the property page, we can look at an example. BuildPathsPropertyPage extends PropertyPage, so we will, too:

Example . org.eclipse.contribution.junit/AutoTestPropertyPage

public class AutoTestPropertyPage extends PropertyPage {
  public AutoTestPropertyPage() {
  }
  protected Control createContents(Composite parent) {
    return null;
  }
}

Notice that, as usual, we have to implement the default constructor. Because AutoTestPropertyPage is an extension class it will be created via reflection.

Now when we select the auto-test property page, we get a page with no contents, as shown in Figure 19.4.

org.eclipse.contribution.junit/AutoTestPropertyPage

Just as we did with the JUnit view, we need to add controls to the page. In our case, we want to add a checkbox with the label Auto-test. Looking at all the other implementors of createContents() (there are more than 100 of them), it looks like we only need to add a Button and return it as the value of the method:

Example . org.eclipse.contribution.junit/AutoTestPropertyPage

Button autoTest;
protected Control createContents(Composite parent) {
  Button autoTest= new Button(parent, SWT.CHECK);
  autoTest.setText("Auto-test");
  return autoTest;
}

Figure 19.5 shows the new page.

org.eclipse.contribution.junit/AutoTestPropertyPage

We would like a more attractive layout than this and we need to connect our property page to the JUnitPlugin methods for adding and removing the auto-test nature.

To improve the appearance, we'll first extract a method to create the widgets:

Example . org.eclipse.contribution.junit/AutoTestPropertyPage

protected Control createContents(Composite parent) {
  noDefaultAndApplyButton();
  Control composite= addControl(parent);
  try {
    boolean hasNature= getProject().hasNature(
      JUnitPlugin.AUTO_TEST_NATURE);
    autoTest.setSelection(hasNature);
  } catch (CoreException e) {
    // TODO Error dialog
  }
  return composite;
}

Notice that we've hidden the Restore Defaults and Apply buttons. These only make sense for complicated property pages where you want to preview the effects of your choices. The method getProject() retrieves the input to the property page, which is an IProject:

Example . org.eclipse.contribution.junit/AutoTestPropertyPage

private IProject getProject() {
  return (IProject) getElement();
}

We would like to have a short description of the auto-test property above the checkbox. GridLayout provides a way to arrange widgets in a grid.

Example . org.eclipse.contribution.junit/AutoTestPropertyPage

private Control addControl(Composite parent) {
  Composite composite= new Composite(parent, SWT.NULL);
  GridLayout layout= new GridLayout();
  layout.numColumns= 1;
  composite.setLayout(layout);
  GridData data= new GridData();
  data.verticalAlignment= GridData.FILL;
  data.horizontalAlignment= GridData.FILL;
  composite.setLayoutData(data);

  Font font= parent.getFont();
  Label label= new Label(composite, SWT.NONE);
  label.setText("When auto-testing, after every build all "+
    "tests in this project will be run.");
  label.setFont(font);
  autoTest= new Button(composite, SWT.CHECK);
  autoTest.setText("Auto-test");
  autoTest.setFont(font);
  return composite;
}

Because we want to add several controls, we need to put them together in a Composite, for which we define a GridLayout. The new page is shown in Figure 19.6.

org.eclipse.contribution.junit/AutoTestPropertyPage

Notice that we must separately set the parent's font for each control. Without this, our controls would not appear in the user's preferred dialog font.

All that's left is to install (or uninstall) the auto-test nature when the user clicks OK. We override the hook method performOk() to do this:

Example . org.eclipse.contribution.junit/AutoTestPropertyPage

public boolean performOk() {
  try {
    JUnitPlugin plugin= JUnitPlugin.getPlugin();
    if (autoTest.getSelection())
      plugin.addAutoBuildNature(getProject());
    else
      plugin.removeAutoBuildNature(getProject());
  } catch (CoreException e) {
    // TODO Error dialog
  }
  return true;
}

We return true because we don't ever want to veto the acceptance of the changes. We can run a run-time workspace to see the auto-test feature in action. Once we've selected auto-test and clicked OK, the auto-test builder appears in our project's properties, as shown in Figure 19.7.

org.eclipse.contribution.junit/AutoTestPropertyPage

To further confirm that we are getting the expected results, we can start a run-time workbench. There we can create a project, set the auto-test property, look at the contents of the .project file, and see the auto-test nature and builder attached to our project.

<projectDescription>
  <name>Java Project</name>
  <comment></comment>
  <projects>
  </projects>
  <buildSpec>
    <buildCommand>
      <name>org.eclipse.jdt.core.javabuilder</name>
      <arguments>
      </arguments>
    </buildCommand>
    <buildCommand>
      <name>org.eclipse.contribution.junit.autoTestBuilder</name>
      <arguments>
      </arguments>
    </buildCommand>
  </buildSpec>
  <natures>
    <nature>org.eclipse.jdt.core.javanature</nature>
    <nature>org.eclipse.contribution.junit.autoTestNature</nature>
  </natures>
</projectDescription>

The main development of the auto-test feature is complete. However, we still have a lot of polishing to do, starting with handling errors gracefully, whether we notify the user or just log the problem. Reviewing this chapter, we

  • Declared AutoTestPropertiesPage in the manifest. We made sure it appeared in the Navigator and the Package Explorer by attaching it to IProjects and making it adaptable. We made sure it only attached to Java projects by specifying a filter requiring the presence of the Java nature.

  • Implemented the AutoTestPropertiesPage, including using a GridLayout to enhance the appearance of the controls.

  • Implemented performOk() to install or uninstall the auto-test nature.

Forward Pointers

  • Preference pages—the implementation of a preference page is very similar to the implementation of a property page. In fact, the class PropertyPage extends PreferencePage and adds the notion of an input. When implementing a preference page you can also use field editors. A field editor helps you manage and validate preference settings. See www.eclipse.org/articles/Article-Field-Editors/field_editors.html for more details.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset