Writing POV-Ray Support for NetBeans X - Finishing Touches
Tim Boudreau
10 June 2006
Feedback
This is a DRAFT!
This is a continuation of the tutorial for building POV-Ray support for
NetBeans. If you have not read the
first
or
second,
third,
fourth fifth
sixth,
seventh,
and
eighth
parts of this tutorial, you may want to start there.
Spit and Polish
We now have POV-Ray support working fairly well - you can create a new
project, render it, settings are remembered, images are opened and output
goes to the output window. There are just a few remaining problems - these
are details, but small details are sometimes the most important ones:
- When you right click a project, there are no render or clean actions
- Our project templates are mixed in with Java project templates, and
don't have human-friendly names ("SamplePovrayProject.zip").
- We said power users would be able to
write their own settings into the project properties file to customize
any aspect of rendering not directly supported by the GUI
- POV-Ray file templates should be the first items on the New submenu
of POV-Ray projects
These are things we should take care of now.
Improving the Project Popup Menu
The first thing we can do is improve the popup menu for POV-Ray projects -
we just need to add a couple of menu items to those already returned.
- Right click the Povray Projects project, and bring up the Project
Properties dialog, and add a dependency on the Actions API by searching
for
NewAction on the Libraries tab. Rather than just use
the array of standard folder actions we are getting from the parent
folder, we will provide just those actions that we want.
- Open
PovrayLogicalView in the editor, and find the
inner ScenesNode class.
- Override
getActions() as follows:
public Action[] getActions (boolean popup) {
Action[] result = new Action[] {
new ProjectAction (ActionProvider.COMMAND_BUILD,
NbBundle.getMessage(PovrayLogicalView.class, "LBL_Build"),
project),
new ProjectAction (ActionProvider.COMMAND_CLEAN,
NbBundle.getMessage(PovrayLogicalView.class, "LBL_Clean"),
project),
new OtherProjectAction (project, false),
SystemAction.get (NewTemplateAction.class),
SystemAction.get (FileSystemAction.class),
new OtherProjectAction(project, true),
};
return result;
}
This gives us two classes to implement - ProjectAction and
CloseProjectAction.
The former will simply be an action class which delegates to the action
provider of the project, and the latter will use the OpenProjects
class from the Project UI API to close the project.
- Implement
ProjectAction as follows:
private static class ProjectAction extends AbstractAction {
private final PovrayProject project;
private final String command;
public ProjectAction (String cmd, String displayName, PovrayProject prj) {
this.project = prj;
putValue (NAME, displayName);
this.command = cmd;
}
public void actionPerformed(ActionEvent actionEvent) {
ActionProvider prov = (ActionProvider)
project.getLookup().lookup(ActionProvider.class);
prov.invokeAction(command, null);
}
public boolean isEnabled() {
ActionProvider prov = (ActionProvider)
project.getLookup().lookup(ActionProvider.class);
return prov.isActionEnabled(command, null);
}
}
- Then implement the brilliantly named
OtherProjectAction
this way, also as an nested class inside PovrayLogicalView. What we're
doing here is saving the overhead of one more class to do something
simple, and writing one action that either closes the project or makes
it the main project, depending on a flag. While not beautiful, it is
short enough to be readable - and additional classes to come with a
memory penalty, so for trivial things, this approach is not necessarily
a bad idea - as long as the result is readable:
private static class OtherProjectAction extends AbstractAction {
private final PovrayProject project;
private final boolean isClose;
OtherProjectAction(PovrayProject project, boolean isClose) {
putValue (NAME, NbBundle.getMessage (PovrayLogicalView.class,
isClose ? "LBL_CloseProject" : "LBL_SetMainProject"));
this.project = project;
this.isClose = isClose;
}
public void actionPerformed(ActionEvent actionEvent) {
if (isClose) {
OpenProjects.getDefault().close (new Project[] { project });
} else {
OpenProjects.getDefault().setMainProject(project);
}
}
}
- Lastly we need to add the necessary localized strings to the resource
bundle for the povray projects package:
LBL_Build=Render Project
LBL_Clean=Clean Project
LBL_CloseProject=Close Project
LBL_SetMainProject=Set Main Project
And we now have a much improved popup menu:
Human-Friendly Template Names and Categories
Next, we will makes some minor improvements in the way our project templates
are presented. They are declared in the layer file for our project, and
remain as they were
when we created them.
Open the
layer.xml file for the Povray Projects project.
- The first thing to change is simply the folder, so that our templates
will have their own category. So change the third level of folder name,
so that instead of going into
Templates/Project/Standard,
our project templates will go into Templates/Project/Povray.
Copy the SystemFilesystem.localizingBundle entry from the
zip file, and paste a copy of it inside the folder tags for the
Povray folder. The end result should look like this:
<folder name="Templates">
<folder name="Project">
<folder name="Povray">
<attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.examples.modules.povproject.templates.Bundle"/>
<file name="EmptyPovrayProjectProject.zip" url="EmptyPovrayProjectProject.zip">
<attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.examples.modules.povproject.templates.Bundle"/>
<attr name="instantiatingIterator" methodvalue="org.netbeans.examples.modules.povproject.templates.EmptyPovrayProjectWizardIterator.createIterator"/>
<attr name="instantiatingWizardURL" urlvalue="nbresloc:/org/netbeans/examples/modules/povproject/templates/EmptyPovrayProjectDescription.html"/>
<attr name="template" boolvalue="true"/>
</file>
<file name="SamplePovrayProjectProject.zip" url="SamplePovrayProjectProject.zip">
<attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.examples.modules.povproject.templates.Bundle"/>
<attr name="instantiatingIterator" methodvalue="org.netbeans.examples.modules.povproject.templates.EmptyPovrayProjectWizardIterator.createIterator"/>
<attr name="instantiatingWizardURL" urlvalue="nbresloc:/org/netbeans/examples/modules/povproject/templates/SamplePovrayProjectDescription.html"/>
<attr name="template" boolvalue="true"/>
</file>
</folder>
</folder>
</folder>
- The next thing to notice is that, although all of our templates are
pointing at
org/netbeans/examples/modules/povproject/templates/Bundle.properties,
there are actually no localized file names in defined in that file. So
one other thing we need to do is define them:
Templates/Project/Povray=POV-Ray
Templates/Project/Povray/EmptyPovrayProjectProject.zip=Empty Povray Project
Templates/Project/Povray/SamplePovrayProjectProject.zip=Sample Povray Project
- As a last step, we can edit the two HTML files in
org.netbeans.examples.modules.povproject.templates to
provide better descriptions.
Power-User Renderer Settings
[pending]
Adding POV-Ray Templates to the New Popup Menu
[pending]