FeaturesPluginsDocs & SupportCommunityPartners

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.

  1. 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.
  2. Open PovrayLogicalView in the editor, and find the inner ScenesNode class.

  3. 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.
  4. 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);
        }
    }
  5. 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);
            }
        }
    }
  6. 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.
  1. 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>
            
  2. 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
            
  3. 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]

Companion
Projects:
MySQL Database Server   Open JDK: an Open SourceJDK   GlassFish Community: an Open Source Application Server    Mobile & Embedded Community    Open Solaris   java.net - The Source for Java Technology Collaboration   Virtual Box - full virtualizer  Open ESB - The Open Enterprise Service Bus Powered by