A nature is created by implementing the IProjectNature
interface. This will be used to create a MinimarkNature
class, which will allow projects to be associated with the MinimarkBuilder
class.
MinimarkNature
in the com.packtpub.e4.minimark.ui
package as follows:public class MinimarkNature implements IProjectNature { public static final String ID = "com.packtpub.e4.minimark.ui.MinimarkNature"; private IProject project; public IProject getProject() { return project; } public void setProject(IProject project) { this.project = project; } public void configure() throws CoreException { } public void deconfigure() throws CoreException { } }
MinimarkBuilder
class, which can be used to refer to it by the nature:public class MinimarkBuilder extends IncrementalProjectBuilder { public static final String ID = "com.packtpub.e4.minimark.ui.MinimarkBuilder";
Arrays
class takes away some of the pain. Implement the configure
method in the MinimarkNature
class as follows:public void configure() throws CoreException { IProjectDescription desc = project.getDescription(); List<ICommand> commands = new ArrayList<ICommand>( Arrays.asList(desc.getBuildSpec())); Iterator<ICommand> iterator = commands.iterator(); while (iterator.hasNext()) { ICommand command = iterator.next(); if (MinimarkBuilder.ID.equals(command.getBuilderName())) { return; } } ICommand newCommand = desc.newCommand(); newCommand.setBuilderName(MinimarkBuilder.ID); commands.add(newCommand); desc.setBuildSpec(commands.toArray(new ICommand[0])); project.setDescription(desc,null); }
deconfigure
method as follows:public void deconfigure() throws CoreException { IProjectDescription desc = project.getDescription(); List<ICommand> commands = new ArrayList<ICommand>( Arrays.asList(desc.getBuildSpec())); Iterator<ICommand> iterator = commands.iterator(); while (iterator.hasNext()) { ICommand command = iterator.next(); if (MinimarkBuilder.ID.equals(command.getBuilderName())) { iterator.remove(); } } desc.setBuildSpec(commands.toArray(new ICommand[0])); project.setDescription(desc, null); }
plugin.xml
file in the com.packtpub.e4.minimark.ui
project:<extension id="MinimarkNature" point="org.eclipse.core.resources.natures"> <runtime> <run class="com.packtpub.e4.minimark.ui.MinimarkNature"/> </runtime> </extension>
plugin.xml
file for the Add Minimark Nature
command, and put it in the projectConfigure
menu:<extension point="org.eclipse.ui.commands"> <command name="Add Minimark Nature" defaultHandler="com.packtpub.e4.minimark.ui.AddMinimarkHandler" id="com.packtpub.e4.minimark.ui.AddMinimarkNature"/> </extension> <extension point="org.eclipse.ui.menus"> <menuContribution allPopups="false" locationURI= "popup:org.eclipse.ui.projectConfigure?after=additions"> <command label="Add Minimark Nature" style="push" commandId="com.packtpub.e4.minimark.ui.AddMinimarkNature"/> </menuContribution> </extension>
com.packtpub.e4.minimark.ui
package called AddMinimarkNature
as follows:public class AddMinimarkHandler extends AbstractHandler { public Object execute(ExecutionEvent event) throws ExecutionException { ISelection sel = HandlerUtil.getCurrentSelection(event); if (sel instanceof IStructuredSelection) { Iterator<?> it = ((IStructuredSelection)sel).iterator(); while (it.hasNext()) { Object object = (Object) it.next(); if(object instanceof IProject) { try { addProjectNature((IProject)object,MinimarkNature.ID); } catch (CoreException e) { throw new ExecutionException("Failed to set nature on" + object,e); } } } } return null; } private void addProjectNature(IProject project, String nature) throws CoreException { IProjectDescription description = project.getDescription(); List<String> natures = new ArrayList<String>( Arrays.asList(description.getNatureIds())); if(!natures.contains(nature)) { natures.add(nature); description.setNatureIds(natures.toArray(new String[0])); project.setDescription(description, null); } } }
.project
file using the Navigator view. Now right-click on the project, and select Configure | Add Minimark Nature to add the nature. When the nature is added, it will add the commands automatically, and the changes will be visible in the .project
file.The MinimarkNature
class was created to inject a builder into the project description when added. Changing the .project
file manually does not add the builder, so an action to programmatically add the nature was created and added to the standard Configure menu.
Both the nature and the builder are referred to via IDs; these are stored in the .project
and .classpath
files. Since these may be checked into a version control system, the names of these IDs should be consistent between releases.
The project descriptor contains the content from the .project
file, and stores an array of nature IDs and commands. To add a nature to a project, its identifier is appended to this list—however, note that the change only takes effect when the updated project descriptor is set on the project.
Since the nature's modifications only take effect when set programmatically, the Add Minimark Nature
command was created to add the nature. The command was put into the popup:org.eclipse.ui.projectConfigure?after=additions
menu, which is the standard location for adding and configuring natures. Conventionally, either a separate command to Add Minimark Nature
and Remove Minimark Nature
is used, or a Toggle Minimark Nature
could be used for both menu items. The advantage of the separate add or remove menu items is that their visibility can be controlled based on whether the project already has the nature or not.
The handler class used HandlerUtil
to extract the current selection, although this just extracts the object from the parameter map via the variable name selection
.
To avoid spelling errors, it makes sense to define constants as static final
variables. If they are related with class names, it can be better to use class.getName()
as the identifier, so that if they are renamed then the identifiers are automatically updated as well. Alternatively, they can be created from a concatenation with the plug-in's ID (in this case, via Activator.ID
).
It is conventional to only show the Configure option if it is strictly necessary. In the case where projects already have a MinimarkNature
, the command should not be shown. Use the visibleWhen
property to target the selection and only enable it if the projectNature
of the selected object is that of the MinimarkNature
. Alternatively, implement another handler that performs the removal of the nature, and then use an expression to determine whether the handler should be shown based on whether the project already has the nature or not.
The handler here was implemented using Eclipse 3.x classes. Convert these to a handler using the E4 model, as shown in Chapter 4, Interacting with the User.
3.143.9.115