A nature is created by implementing the IProjectNature
interface. This will be used to create a MinimarkNature
, which will allow projects to be associated with the MinimarkBuilder
. Perform the following steps:
MinimarkNature
in the com.packtpub.e4.minimark.ui
package: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
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 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
of the 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. (It's best practice to add these to version control.)
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. 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 menu popup org.eclipse.ui.projectConfigure?after=additions
, 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 actions. The advantage of the separate Add/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; though 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 MinimarkNature
, we should not show the command. Use the visibleWhen
property to target the selection and only enable it if the projectNature
of the selected object is that of the minimark
builder.