<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

    <head>

        <title>Writing POV-Ray Support for NetBeans VI&#8212;Implementing the API</title>

        <link rel="stylesheet" type="text/css" href="https://netbeans.org/netbeans.css"/>
        <meta name="AUDIENCE" content="NBUSER"/>
        <meta name="TYPE" content="ARTICLE"/>
        <meta name="EXPIRES" content="N"/>
        <meta name="developer" content="geertjan.wielenga@oracle.com"/>
        <meta name="indexed" content="y"/>
        <meta name="description"
              content="NetBeans POV-Ray Support Tutorial Part VI&#8212;Implementing our API and making implementations of it available from our custom project type"/>
        <!--      Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. -->
        <!--     Use is subject to license terms.-->

    </head>

    <body>

        <h1>Writing POV-Ray Support for NetBeans VI&#8212;Implementing the API</h1>

	<p>This is a continuation of the tutorial for building a POV-Ray rendering application on
            the NetBeans Platform.  If you have not read the <a href="nbm-povray-1.html">first</a>,
            <a href="nbm-povray-2.html">second</a>, <a href="nbm-povray-3.html">third</a>,
            <a href="nbm-povray-4.html">fourth</a>, and <a href="nbm-povray-5.html">fifth</a>
            parts of this tutorial, you may want to start there.</p>

        <h2 class="tutorial"><a name="setup"></a>Implementing MainFileProvider</h2>

        <p>The first class we will implement is <code>MainFileProvider</code>.  This
            is the class that our <code>Node</code>s for POV-Ray files will look up,
            to see if they represent the main scene file of the project (if so, they will
            display their name in boldface text, and later this will be used to provide
            actions to set which file is the main file).</p>

        <div class="indent">

            <ol>
                <li><p>In the Povray Project module, add the key for the main file to the top of the <tt>PovrayProject</tt>
                        class:</p>
                    <pre class="examplecode">public static final String KEY_MAINFILE = "main.file";</pre>
                </li>

                <li><p>In the Povray Project module, create a new Java class in the package
                        <code>org.netbeans.examples.modules.povproject</code>, and call it
                        "MainFileProviderImpl".</p></li>

                <li>Implement it as follows:
                    <pre class="examplecode">class MainFileProviderImpl extends MainFileProvider {

    private final PovrayProject proj;

    private FileObject mainFile = null;

    private boolean checked = false;

    MainFileProviderImpl(PovrayProject proj) {
        this.proj = proj;
    }

    @Override
    public FileObject getMainFile() {
        //Try to look up the main file in the project properties
        //the first time this is called;  no need to look it up every
        //time, either it's there or it's not and when the user sets it
        //we'll save it when the project is closed
        if (mainFile == null && !checked) {
            checked = true;
            Properties props = (Properties) proj.getLookup().lookup(Properties.class);
            String path = props.getProperty(PovrayProject.KEY_MAINFILE);
            if (path != null) {
                FileObject projectDir = proj.getProjectDirectory();
                mainFile = projectDir.getFileObject(path);
            }
        }
        if (mainFile != null && !mainFile.isValid()) {
            return null;
        }
        return mainFile;
    }

    @Override
    public void setMainFile(FileObject file) {
        String projPath = proj.getProjectDirectory().getPath();
        assert file == null ||
                file.getPath().startsWith(projPath) :
                "Main file not under project";
        boolean change = ((mainFile == null) != (file == null)) ||
                (mainFile != null && !mainFile.equals(file));
        if (change) {
            mainFile = file;
            //Get the project properties (loaded from
            //$PROJECT/pvproject/project.properties)
            Properties props = (Properties) proj.getLookup().lookup(
                    Properties.class);
            //Store the relative path from the project root as the main file
            String relPath = file.getPath().substring(projPath.length());
            props.put(PovrayProject.KEY_MAINFILE, relPath);
        }
    }

}</pre>

                    <p class="notes">The code above is simple and quite straightforward&#8212;it will look for
                        a <code>Properties</code> object in the <code>Lookup</code> of the
                        project.  The getter will look for the value of "main.file"
                        from the <code>Properties</code> object (which was loaded from
                        <code>$PROJECT/pvproject/project.properties</code>), which will be
                        a relative path to the main file.  If there is a value for that key, try
                        to find the corresponding file and return it.  The setter, in turn, will
                        write a new relative path to the <code>Properties</code> object.  That
                        in turn, will cause the project to be marked as modified, so the system
                        will call <code>PovProjectFactory.saveProject()</code> if it is unloading
                        the project, causing the <code>Properties</code> to be written out to
                        disk in <code>$PROJECT/pvproject/project.properties</code>.</p>

                </li>

                <li><p>Add <code>new MainFileProviderImpl(this)</code> to the implementation
                        of <code>getLookup()</code> in <code>PovrayProject</code>, so that it
                        is included in the array of objects that make up the lookup contents:</p>

                    <pre class="examplecode">@Override
public Lookup getLookup() {
    if (lkp == null) {
        lkp = Lookups.fixed(new Object[]{
                    this, //handy to expose a project in its own lookup
                    state, //allow outside code to mark the project as needing saving
                    new ActionProviderImpl(), //Provides standard actions like Build and Clean
                    loadProperties(), //The project properties
                    new Info(), //Project information implementation
                    logicalView, //Logical view of project implementation
                    <b>new MainFileProviderImpl(this)</b>
                });
    }
    return lkp;
}</pre>

                </li>
            </ol>

        </div>

        <h2 class="tutorial"><a name="setup"></a>Implementing RendererService&#8212;Providing Default Renderer Settings</h2>

        <p>The next class to implement is <code>RendererService</code>&#8212;this is the
            service, belonging to the project, by which a project will be "compiled"
            into an image (by executing the POV-Ray program and passing it arguments).</p>

        <p>
            As we discussed <a href="nbm-povray-2.html">earlier</a>, we are not going to
            try to implement a complicated dialog that makes every possible POV-Ray
            setting adjustable via a GUI widget&#8212;this would add a lot of complexity
            when many users would be satisfied with a reasonable set of defaults.  So
            we will have a set of different default combinations of settings that should
            satisfy most users.  Later we will add the ability to create completely
            customized settings by editing the <code>project.properties</code> of a
            POV-Ray project, to satisfy the needs of power users.</p>

        <p>
            Right now, we will not worry about the execution part&#8212;<code>RendererService</code>
            also provides for named sets of settings&#8212;combinations of line switches
            which should be passed to POV-Ray to determine rendering quality, image size
            and speed.  Right now we will only implement that part of <code>RendererService</code>.</p>

        <p>
            This is where we will begin dealing directly with the System
            Filesystem&#8212;the registry of runtime data supplied by modules.  What we
            will do is create <code>.properties</code> files for each set of standard
            settings we will supply.  We will start by creating <code>.properties</code>
            files for each set of settings in our module.</p>

        <div class="indent">

            <ol>

                <li>Create a new Java Package in the Povray Project project,
                    <code>org.netbeans.examples.modules.povproject.defaults</code>.  This
                    is where we will put our properties files.
                </li>

                <li>
                    <p>Create six properties files with the following contents in that package:</p>
                    <ul>
                        <li>160x100.properties
                            <pre class="examplecode">
W=160
H=100
Q=4
FN=8
A=0.0
                            </pre>
                        </li>
                        <li>320x200.properties
                            <pre class="examplecode">
W=320
H=200
Q=4
FN=8
A=0.0
                            </pre>
                        </li>
                        <li>640x480.properties
                            <pre class="examplecode">
W=640
H=480
Q=4
FN=8
A=0.0
                            </pre>
                        </li>
                        <li>640x480hq.properties
                            <pre class="examplecode">
W=640
H=480
Q=R
FN=8
A=0.9
                            </pre>
                        </li>
                        <li>1024x768.properties
                            <pre class="examplecode">
W=1024
H=768
Q=4
FN=9
A=0.0
                            </pre>
                        </li>
                        <li>1024x768hq.properties
                            <pre class="examplecode">
W=1024
H=768
Q=R
FN=8
A=0.9
                            </pre>
                        </li>
                    </ul></li>

                <li><p>Next, we will want to actually add these to the
                        System Filesystem, so our module can find them at runtime, and more
                        importantly, so other modules can modify and save, or add additional,
                        sets of default settings by adding more properties files to the
                        same folder we put these files in, in the System Filesystem.</p>
                    <p>Right-click the Povray Project project and choose
                        New | Other | Module Development | XML Layer. Then click
                        Next and Finish. The IDE creates the <tt>layer.xml</tt> file
                        and registers it in the project's manifest. Open the newly created
                        <tt>layer.xml</tt> file in the code editor.</p>
                </li>

                <li>

                    <p>Replace the content of the <tt>layer.xml</tt> file with the content below.</p>

                    <pre class="examplecode">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "https://netbeans.org/dtds/filesystem-1_2.dtd"&gt;
&lt;filesystem&gt;

    &lt;folder name="Povray"&gt;

        &lt;folder name="RendererSettings"&gt;

        &lt;!-- Declare a file, with its content provided by the URL.  This
                 will be the command line arguments for 1024x768 high quality
                 rendering --&gt;
            &lt;file name="1024x768hq.properties" url="defaults/1024x768hq.properties"&gt;
                &lt;attr name="SystemFileSystem.localizingBundle"
                  stringvalue="org.netbeans.examples.modules.povproject.defaults.Bundle"/&gt;
            &lt;/file&gt;
        &lt;!-- This is an ordering attribute, it determines that the
                 DataFolder (but *not* the FileObject) for this folder will return
                 its child DataObjects (and thus also its Node's children) in
                 a specific order—in this case we are specifying that
                 1024x768hq must come before 1024x768.properties. --&gt;
            &lt;attr name="1024x768hq.properties/1024x768.properties" boolvalue="true"/&gt;

            &lt;file name="1024x768.properties" url="defaults/1024x768.properties"&gt;
                &lt;attr name="SystemFileSystem.localizingBundle"
                  stringvalue="org.netbeans.examples.modules.povproject.defaults.Bundle"/&gt;
            &lt;/file&gt;

            &lt;attr name="1024x768.properties/640x480hq.properties" boolvalue="true"/&gt;
            &lt;file name="640x480hq.properties" url="defaults/640x480hq.properties"&gt;
                &lt;attr name="SystemFileSystem.localizingBundle"
                  stringvalue="org.netbeans.examples.modules.povproject.defaults.Bundle"/&gt;
            &lt;/file&gt;

            &lt;attr name="640x480hq.properties/640x480.properties" boolvalue="true"/&gt;
            &lt;file name="640x480.properties" url="defaults/640x480.properties"&gt;
                &lt;attr name="SystemFileSystem.localizingBundle"
                  stringvalue="org.netbeans.examples.modules.povproject.defaults.Bundle"/&gt;
            &lt;/file&gt;

            &lt;attr name="640x480.properties/320x200.properties" boolvalue="true"/&gt;
            &lt;file name="320x200.properties" url="defaults/320x200.properties"&gt;
                &lt;attr name="SystemFileSystem.localizingBundle"
                  stringvalue="org.netbeans.examples.modules.povproject.defaults.Bundle"/&gt;
            &lt;/file&gt;

            &lt;attr name="320x200.properties/160x100.properties" boolvalue="true"/&gt;
            &lt;file name="160x100.properties" url="defaults/160x100.properties"&gt;
                &lt;attr name="SystemFileSystem.localizingBundle"
                  stringvalue="org.netbeans.examples.modules.povproject.defaults.Bundle"/&gt;
            &lt;/file&gt;

        &lt;/folder&gt;

    &lt;/folder&gt;

&lt;/filesystem&gt;</pre>

                    <p class="notes">What this XML does is map the properties files we just created into
                        the system filesystem in the folder <code>Povray/RendererSettings</code>,
                        which is where our code will look for them.  Additionally, it specifies
                        <i>ordering attributes</i>, which are attributes we are adding to the
                        folder <code>RendererSettings/</code>, which will determine what order
                        the files will appear in when code asks for the array of children of
                        the <code>DataFolder</code> (<code>DataObject</code> subclass for
                        folders) or its Node for this folder.</p>

                </li>

                <li>
                    <p>You may have noticed the attribute <code>SystemFilesystem.localizingBundle</code>
                        which we added to the <code>RendererSettings</code> folder.  NetBeans
                        <code>FileObject</code>s (which is what the "files" in the
                        System Filesystem are) can have ad-hoc key-value pairs associated
                        with them.  <code>SystemFilesystem.localizingBundle</code> is a magic
                        attribute which the system will use to localize the names of files&#8212;all
                        you have to do is get the <code>DataObject</code> for a file in
                        the system filesystem, get the <code>Node</code> for that <code>DataObject</code>,
                        and the return value of <code>Node.getDisplayName()</code> for that
                        <code>Node</code> will look up its localized display name in the
                        requested resource bundle&#8212;this is how file names for things declared
                        in the System Filesystem are localized.</p>
                    <p>
                        So we need one <i>more</i> properties file in
                        <code>org.netbeans.examples.modules.povproject.defaults</code>&#8212;create
                        one called "Bundle".  This one won't contain renderer
                        defaults, it will contain mappings from the file names of the files
                        we declared above, to their localized, human friendly names.</p>
                </li>

                <li>
                    <p>Add the following contents to <code>Bundle.properties</code>:</p>
                    <p><pre class="examplecode">Povray/RendererSettings/1024x768.properties=1024 x 768
Povray/RendererSettings/1024x768hq.properties=1024 x 768 High Quality
Povray/RendererSettings/640x480hq.properties=640 x 480 High Quality
Povray/RendererSettings/640x480.properties=640 x 480
Povray/RendererSettings/320x200.properties=320 x 200
Povray/RendererSettings/160x100.properties=160 x 100</pre></p>
                </li>

                <li><p>Make sure that you have the new files in the correct places, reflecting
                        the structure in the image below:</p>
                    <p><img alt="" src="../images/tutorials/povray/71/ch6/pic1.png"/></p>
                </li>

            </ol>

        </div>

        <h2 class="tutorial"><a name="rendererservice1"></a>Implementing RendererService&#8212;Basic Implementation</h2>

        <p>Now we have a set of default settings to show, so we can implement the methods of
            <code>RendererService</code> that will expose them.</p>

        <div class="indent">

            <ol>

                <li>Create a new class, <code>RendererServiceImpl</code>, in
                    <code>org.netbeans.examples.modules.povproject</code>.</li>

                <li>Modify the class declaration to say that it extends <code>RendererService</code>
                    and press Ctrl-Shift-I to fix imports and to generate stub implementations
                    of the abstract methods. The result should be as follows:

                    <pre class="examplecode">package org.netbeans.examples.modules.povproject;

import java.util.Properties;
import org.netbeans.examples.api.povray.RendererService;
import org.openide.filesystems.FileObject;

public class RendererServiceImpl extends RendererService {

    @Override
    public FileObject render(FileObject scene, String propertiesName) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public FileObject render(FileObject scene, Properties renderSettings) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public FileObject render(FileObject scene) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public FileObject render() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String[] getAvailableRendererSettingsNames() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Properties getRendererSettings(String name) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getPreferredRendererSettingsNames() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getDisplayName(String settingsName) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

}</pre>

                </li>

                <li>The first things we will do are implement the constructor and
                    leave the render methods stubbed out&#8212;we will implement these later:
                    <pre class="examplecode">private PovrayProject proj;

    public RendererServiceImpl(PovrayProject proj) {
        this.proj = proj;
    }

    PovrayProject getProject() {
        return proj;
    }</pre>
                </li>

                <li><p>Next, we will implement some private utility methods that the other
                        methods will do.  This should help to give some of the flavor of working
                        with things in the system filesystem.</p>

                    <pre class="examplecode">    private FileObject getRendererSettingsFolder() {
        String folderName = "Povray/RendererSettings";
        FileObject result = FileUtil.getConfigFile(folderName);
        if (result == null && !logged) {
            //Corrupted userdir or something is very very wrong.
            //Log it and move on.
            Exceptions.printStackTrace(new IllegalStateException("Renderer settings dir missing!"));
            logged = true;
        }
        return result;
    }

    private static boolean logged = false;

    private FileObject fileFor (String settingsName) {
        FileObject settingsFolder = getRendererSettingsFolder();
        FileObject result;
        if (settingsFolder != null) { //should never be null
            result = settingsFolder.getFileObject(settingsName);
        } else {
            result = null;
        }
        return result;
    }

    private void setPreferredRendererSettingsName(String val) {
        getPreferences().put(KEY_PREFERRED_SETTINGS, val);
    }

    private static final String KEY_PREFERRED_SETTINGS = "preferredSettings";

    static Preferences getPreferences() {
        return Preferences.userNodeForPackage(RendererServiceImpl.class);
    }</pre>

                    <p>The first thing we have is a utility method that finds the folder we
                        declared in our XML layer, in the System Filesystem&#8212;that is what
                        <code>getRendererSettingsFolder()</code> does.  You'll note that there
                        is a null check.  This folder *should* not be null, since we are declaring
                        it in our layer.  But it conceivably could be (a corrupted settings
                        directory or a module that for some reason hides the settings directory -
                        it should not happen, but it is theoretically possible), so we log an
                        exception if so, rather than throwing exceptions every time something goes
                        and looks for a display name for a menu item or similar.</p>

                    <p>The next method is a utility method that just fetches the file corresponding
                        to a file name&#8212;we are returning the names of all files in the settings
                        folder, so this will allow us to find a corresponding properties file.</p>

                    <p>The last two methods are simply for saving the last-used set of renderer
                        settings, and simply use the standard Java Preferences API.</p>
                </li>

                <li>
                    <p>The next method we want to implement is
                        <code>getAvailableRendererSettingsNames()</code>.  This method will
                        return an array of <code>String</code>s&#8212;the localized, human-friendly
                        names of all of the files which we declared above:</p>

                    <pre class="examplecode">    @Override
    public String[] getAvailableRendererSettingsNames() {
        FileObject settingsFolder = getRendererSettingsFolder();
        String[] result;
        if (settingsFolder != null) {
            //Use a DataFolder here, so our ordering attributes in the layer
            //file are applied, and our returned String array will be in the
            //order we want
            DataFolder fld = DataFolder.findFolder(settingsFolder);
            DataObject[] kids = fld.getChildren();
            result = new String[ kids.length ];
            for (int i = 0; i < kids.length; i++) {
                result[i] = kids[i].getPrimaryFile().getNameExt();
            }
        } else {
            result = new String[0];
        }
        return result;
    }</pre>

                    <p>This is quite straightforward&#8212;we just iterate all of the files in the
                        folder, and return an array of <code>String</code>s with their names.  The
                        one twist to it is that we don't iterate the <i><code>FileObject</code></i>'s
                        children, but rather we get a <code>DataFolder</code> (the <code>DataObject</code>
                        type for filesystem folders), and iterate its children.  The reason we do
                        it this way is that the order of children of <code>FileObjects</code> is
                        undefined&#8212;we might get the files we declared in any order.  The
                        <code>DataFolder</code>, however, understands <i>ordering attributes</i> -
                        attributes we can declare in the XML of our layer file, which will determine
                        what order a folder's children are returned in.  So this enables us to sort
                        our settings files in an intuitive way&#8212;yet other modules could still insert
                        additional settings, with their own ordering attributes, and they would be
                        included in the sort (for more info on how and why this works, see the
                        javadoc for
                        <a href="https://netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/Utilities.html#topologicalSort(java.util.Collection,%20java.util.Map)">Utilities.topologicalSort()</a>).</p>

                </li>

                <li><p>Next we will implement <code>getRendererSettings(name)</code>&#8212;this method
                        will actually get a <code>Properties</code> object with the contents of
                        whichever file name was passed to it:</p>

                    <pre class="examplecode">    @Override
    public Properties getRendererSettings(String name) {
        Properties result = new Properties();
        FileObject settingsFile = fileFor (name);
        if (settingsFile != null) {
            try {
                result.load(new BufferedInputStream(settingsFile.getInputStream()));
            } catch (FileNotFoundException ex) {
                Exceptions.printStackTrace(ex);
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            }
        } else {
            Exceptions.printStackTrace(
		    new NullPointerException("Requested non-existent settings " +
                    "file " + name));
        }
        return result;
    }</pre>

                    <p>The code here is also quite straightforward&#8212;it simply tries to load a
                        <code>Properties</code> object from the input stream of the file in question.</p>

                </li>

                <li>
                    <p>Next we will implement the method that fetches the name of the preferred
                        set of settings&#8212;this will be the most recently used settings, fetched from
                        the Preferences API, with a fallback if none has yet been chosen:</p>

                    <pre class="examplecode">    @Override
    public String getPreferredRendererSettingsName() {
        String result = getPreferences().get(KEY_PREFERRED_SETTINGS, null);
        if (result == null) {
            result = "640x480.properties";
        }
        return result;
    }</pre>

                </li>

                <li>

                    <p>The last method we will implement takes a settings <i>file name</i> and
                        converts it to a localized, human-readable name:</p>

                    <pre class="examplecode">    @Override
    public String getDisplayName(String settingsName) {
        FileObject file = fileFor (settingsName);
        String result;
        if (file != null) {
            DataObject dob;
            try {
                dob = DataObject.find(file);
                result = dob.getNodeDelegate().getDisplayName();
            } catch (DataObjectNotFoundException ex) {
                Exceptions.printStackTrace(ex);
                result = "[error]";
            }
        } else {
            result = "";
        }
        return result;
    }</pre>

                    <p>Human-readable display names are provided by <code>Nodes</code>&#8212;a
                        <code>FileObject</code> is simply a file on disk (or similar storage such
                        as the System Filesystem via our <code>layer.xml</code> file)&#8212;it has
                        no notion of human readability.  So if we want the <i>localized</i> name
                        for a <code>FileObject</code>, we need to get the <code>Node</code> for it.
                        In this case, the <code>Node</code> will use the hint we provided
                        in the <code>layer.xml</code> file:</p>

                    <pre class="examplecode">&lt;attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.povproject.defaults.Bundle"/&gt;</pre>

                    <p>and look up its localized name in
                        <code>org.netbeans.examples.modules.povproject.defaults.Bundle.properties</code>.</p>

                </li>

                <li><p>As we did earlier with the <tt>MainFileProviderImpl</tt>, we now need to
                        expose our implementation of <tt>RendererService</tt> via the
                        project's lookup. Modify <tt>PovrayProject.getLookup()</tt> as follows: </p>

                    <pre class="examplecode">public Lookup getLookup() {
    if (lkp == null) {
        lkp = Lookups.fixed(new Object[] {
            this,  //handy to expose a project in its own lookup
            state, //allow outside code to mark the project as needing saving
            new ActionProviderImpl(), //Provides standard actions like Build and Clean
            loadProperties(), //The project properties
            new Info(), //Project information implementation
            logicalView, //Logical view of project implementation
            new MainFileProviderImpl(this), //So things can set the main file
            <b>new RendererServiceImpl(this), //Renderer Service Implementation</b>
        });
    }
    return lkp;
}</pre>

                </li>


            </ol>

        </div>

        <h2 class="tutorial"><a name="setup"></a>Providing Render Actions on POV-Ray Files</h2>

        <p>Now we have an implementation of some of our API, the next step is to use it.
            As <a href="nbm-povray-2.html">discussed earlier</a>, we want a user to be
            able to right-click and choose to render any file, not just the main file
            of the project.  So there should be some menu items available from our
            <code>PovrayDataNode</code>s which will allow the user to render the file
            with one of our sets of settings.</p>

        <div class="indent">

            <ol>

                <li>Open <code>PovrayDataNode</code>, from the Povray File Support project,
                    in the code editor</li>

                <li><p>Press Ctrl-I (Command-I on Macintosh) and override the
                        <code>getActions(boolean)</code> method.  Implement it as follows:</p>

                    <pre class="examplecode">@Override
public Action[] getActions (boolean popup) {
    Action[] actions = super.getActions(popup);
    RendererService renderer =
        (RendererService)getFromProject (RendererService.class);
    Action[] result;
    if (renderer != null && actions.length > 0) { //should always be > 0
        Action rendererAction = new RendererAction (renderer, this);
        result = new Action[ actions.length + 2 ];
        result[0] = actions[0];
        result[1] = new SetMainFileAction();
        result[2] = rendererAction;
    } else {
        //Isolated file in the favorites window or something
        result = actions;
    }
    return result;
}</pre>

                    <p>This method will add two (yet to be implemented) actions into the array
                        of actions, if a renderer service for this file can be found.  It positions
                        them as the second and third elements in the array, since the first element is
                        what will be invoked when you double click the file, and we want that
                        to remain opening the file (we could also override
                        <code>getPreferredAction()</code> to determine what happens when
                        the node is doubled clicked).</p>

                </li>

                <li><p>Now we need to implement RendererAction.  Right-click the
                        <code>org.netbeans.examples.modules.povfile</code> package, and create
                        a new Java Class called <code>RendererAction</code>.  Define it
                        as follows:
                        <pre class="examplecode">public class RendererAction extends AbstractAction implements Presenter.Popup {</pre></p>

                    <p>Implementing <code>Presenter.Popup</code> is an important step&#8212;this
                        is a way in which an action can actually provide whatever component it
                        wants to insert into the popup menu.  It is a one-method interface, with
                        the method <code>getPopupPresenter</code> which returns a JMenuItem
                        (remember that in Swing, JMenu is a subclass of JMenuItem, so it's
                        legal to return whole submenu here).
                        In our case, we want a submenu:</p>

                    <ul>
                        <li>Render
                            <ul>
                                <li>1024 x 768 High Quality</li>
                                <li>1024 x 768</li>
                                <li>640 x 480 High Quality</li>
                                <li>640 x 480 High Quality</li>
                                <li>320 x 200</li>
                                <li>160 x 120</li>
                            </ul>
                        </li>
                        <li>Standard file menu items...</li>
                    </ul>

                </li>

                <li><p>Now we will provide the body of <code>RendererAction</code>:</p>

                    <pre class="examplecode">package org.netbeans.examples.modules.povfile;

import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import org.netbeans.examples.api.povray.RendererService;
import org.openide.util.NbBundle;
import org.openide.util.actions.Presenter;

public class RendererAction extends AbstractAction implements Presenter.Popup {

    private final RendererService renderer;
    private final PovrayDataNode node;

    public RendererAction(RendererService renderer, PovrayDataNode node) {
        this.renderer = renderer;
        this.node = node;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        assert false;
    }

    @NbBundle.Messages("LBL_Render=Render")
    @Override
    public JMenuItem getPopupPresenter() {

        JMenu result = new JMenu();

        //Set the menu's label
        result.setText(Bundle.LBL_Render());

        //Get the names of all available settings sets:
        String[] availableSettings =
                renderer.getAvailableRendererSettingsNames();

        //Get the name of the most recently used setting set:
        String preferred = renderer.getPreferredRendererSettingsNames();

        for (int i = 0; i < availableSettings.length; i++) {

            String currName = availableSettings[i];

            RenderWithSettingsAction action =
                    new RenderWithSettingsAction(currName);

            JCheckBoxMenuItem itemForSettings = new JCheckBoxMenuItem(action);

            //Show our menu item checked if it is the most recently used set
            //of settings:
            itemForSettings.setSelected(preferred != null
                    && preferred.equals(currName));

            result.add(itemForSettings);

        }

        return result;

    }

}</pre>

                </li>

                <li><p>The one thing missing here, of course, is the individual actions
                        that will run the renderer with different sets of settings.  Create an
                        inner class of <code>RendererAction</code> called
                        <code>RenderWithSettingsAction</code>, and implement it as follows:</p>

                    <pre class="examplecode">private class RenderWithSettingsAction extends AbstractAction implements Runnable {

    private final String name;

    public RenderWithSettingsAction(String name) {
        this.name = name;
        putValue(NAME, renderer.getDisplayName(name));
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        RequestProcessor.getDefault().post(this);
    }

    @Override
    public void run() {
        DataObject ob = node.getDataObject();
        FileObject toRender = ob.getPrimaryFile();
        FileObject image = renderer.render(toRender, name);
        if (image != null) {
            try {
                //Try to open the file:
                DataObject dob = DataObject.find(image);
                Node n = dob.getNodeDelegate();
                OpenCookie ck = (OpenCookie) n.getLookup().lookup(OpenCookie.class);
                if (ck != null) {
                    ck.open();
                }
            } catch (DataObjectNotFoundException e) {
                //Should never happen
                Exceptions.printStackTrace(e);
            }
        }
    }

}</pre>

                    <p>This is relatively straightforward as well.  We are using the
                        <code>renderer</code> field of the outer class, and only storing the
                        name of which specific properties file should be used to provide
                        settings for this class, which we will pass to <code>renderer.render()</code>.</p>

                    <p>The two interesting areas are how we find the file, and how we actually
                        perform the rendering.  We have the instance of <code>PovRayDataNode</code>
                        that we are operating against.  It is a subclass of <code>DataNode</code>,
                        so we can call its <code>getDataObject()</code> method (another way
                        would be to call <code>node.getLookup().lookup(DataObject.class)</code>,
                        but since we know its type, calling <code>getDataObject()</code> is
                        more efficient).  From that we may call <code>getPrimaryFile()</code> to
                        actually get the <code>FileObject</code> that should be rendered into
                        an image by POV-Ray.</p>

                    <p>The other item of interest is how we do our rendering.  Notice
                        that we implement Runnable.  Our action will be, by default, called
                        from the event dispatch thread when the user clicks it in a menu.
                        It would not be good at all if running the action blocked the UI from
                        repainting or anything else until the external POV-Ray process was
                        completed.  So instead, we use a handy thread pool NetBeans provides
                        for us, and simply post the work to be done on another thread off of
                        the event queue.</p>

                </li>

            </ol>

        </div>

        <h2 class="tutorial"><a name="pov-exe"></a>Implementing SetMainFileAction</h2>

        <p>The other action we added to the array of actions on the popup menu for
            POV-Ray files will set the main file of the project to be whatever file
            was clicked.</p>

        <div class="indent">

            <ol>

                <li>We will simply implement this as an inner class of <code>PovrayDataNode</code>.
                    Open <code>PovrayDataNode</code> in the code editor.</li>

                <li>Implement it as follows.  The only twist is that if our <code>Node</code>
                    becomes the main file, it needs to tell the former main file that it is
                    not the main file anymore&#8212;more specifically, it needs to force it to
                    fire a property change in its display name so that it gets redrawn as
                    non-bold:
                    <pre class="examplecode">@NbBundle.Messages("CTL_SetMainFile=Set Main File")
private final class SetMainFileAction extends AbstractAction {

    public SetMainFileAction() {
        putValue(NAME, Bundle.CTL_SetMainFile());
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
        MainFileProvider provider = (MainFileProvider) getFromProject(MainFileProvider.class);
        FileObject oldMain = provider.getMainFile();
        provider.setMainFile(getFile());
        fireDisplayNameChange(getDisplayName(), getHtmlDisplayName());
        if (oldMain != null) {
            try {
                Node oldMainFilesNode = DataObject.find(oldMain).getNodeDelegate();
                if (oldMainFilesNode instanceof PovrayDataNode) {
                    ((PovrayDataNode) oldMainFilesNode).fireDisplayNameChange(null, oldMainFilesNode.getDisplayName());
                }
            } catch (DataObjectNotFoundException donfe) { //Should never happen
                Exceptions.printStackTrace(donfe);
            }
        }
    }

    @Override
    public boolean isEnabled() {
        return !isMainFile() && getFromProject(MainFileProvider.class) != null;
    }

}</pre>
                </li>

                <li><p>Run the application, create or open a POV-Ray project,
                        right-click on a .pov file, and you should see your
                        new Actions on the Node:</p>
                    <p><img alt="" src="../images/tutorials/povray/71/ch6/pic2.png"/></p>
                    <p class="notes"><b>Note:</b> Though the Set Main File
                        action should work correctly, the rendering Actions
                        do not work yet because we have not implemented them
                        yet. That will be done later in this tutorial.</p>
                </li>

            </ol>

        </div>

        <h2 class="tutorial"><a name="pov-exe"></a>Locating the POV-Ray Executable</h2>

        <p>The next step is to write the code that will actually run POV-Ray and send
            its text output to the output window, and eventually open a rendered image.
            Since this involves some complicated code, we will create a separate
            utility class that will do the actual rendering.</p>

        <div class="indent">

            <ol>

                <li>Create a new Java class in the Povray Project project, in
                    <code>org.netbeans.examples.modules.povproject</code>, called
                    "Povray".</li>

                <li>
                    <p>First we need to implement support for finding the POV-Ray
                        executable, so that we have something to run.  This will simply
                        be a matter of popping up a <code>JFileChooser</code> to let the
                        user locate the POV-Ray executable and the directory with the standard
                        POV-Ray include files&#8212;once this has been done once, we will store
                        the result so we do not have to ask again unless it is deleted.</p>

                    <p>Since we may need a file chooser twice, once to locate the
                        executable, and once to locate the standard include file directory
                        (which contains files that define standard colors, shapes, etc. that
                        can be used in POV-Ray files), we should provide one method that shows
                        a file chooser for both cases.  Add the following method to <code>Povray</code>:
                        <pre class="examplecode">private static File locate(String key) {
    JFileChooser jfc = new JFileChooser();
    jfc.setDialogTitle(NbBundle.getMessage(Povray.class, key));
    jfc.setFileSelectionMode (JFileChooser.FILES_ONLY);
    jfc.showOpenDialog(WindowManager.getDefault().getMainWindow());
    File result = jfc.getSelectedFile();
    return result;
}</pre>
                        <p class="notes">At this point we need to add another dependency, because we are calling
                            <code>WindowManager</code> above.  That is part of the Window System API.
                            We could pass null here, but then there is the risk that on some window
                            managers, our file chooser would pop up <i>behind</i> the main window.
                            This makes sure it stays on top. Add a dependency on the Window System API to Povray Project, by
                            right-clicking the project's Libraries node and choosing
                            Add Module Dependency.</p>
                </li>

                <li><p>As you can see in the above code, we will be fetching a localized
                        string from a resource bundle&#8212;a different one depending on whether
                        we're looking for the executable or include directory.  So let's add
                        those strings to the resource bundle for this package via Bundle
                        annotations.  We will also
                        add one warning message we will need later.</p>

                    <p>Next, we will add the two methods for fetching the POV-Ray executable
                        and the include directory, which will automatically ask the user if they
                        are unknown or unavailable.  Add the following two methods, and their
                        associated fields to
                        <code>Povray</code>:</p>

                    <pre class="examplecode">private static File povray = null;
private static File include = null;

/**
 * Preferences key for the povray executable
 */
private static final String KEY_POVRAY_EXEC = "povray";

/**
 * Preferences key for the povray standard includes dir
 */
private static final String KEY_POVRAY_INCLUDES = "include";

@NbBundle.Messages({"TTL_FindPovray=Locate POV-Ray Executable",
    "MSG_WindowsWarning="
    + "<html>POV-Ray for Windows always displays its graphical"
    + "user interface when it runs. You can get a command-line "
    + "version of POV-Ray at &lt;a href=\"http://www.imagico.de/files/povcyg_350c.zip\"&gt;"
    + "http://www.imagico.de/files/povcyg_350c.zip&lt;/a&gt;</html>"
})
private static File getPovray() {
    if (povray == null || !povray.exists()) {
        Preferences prefs = RendererServiceImpl.getPreferences();
        String loc = prefs.get(KEY_POVRAY_EXEC, null);
        if (loc != null) {
            povray = new File(loc);
        }
        if (povray == null || !povray.exists()) {
            File maybePov = locate(Bundle.TTL_FindPovray());
            if (maybePov.getPath().endsWith("pvengine.exe")) {
                //Warn the user to get a command line build:
                NotifyDescriptor msg = new NotifyDescriptor.Confirmation(
                        NbBundle.getMessage(RendererServiceImpl.class,
                        Bundle.MSG_WindowsWarning()),
                        NotifyDescriptor.WARNING_MESSAGE);
                Object result = DialogDisplayer.getDefault().notify(msg);
                if (result == NotifyDescriptor.CANCEL_OPTION) {
                    return null;
                }
            }
            povray = maybePov;
            if (povray != null) {
                prefs.put(KEY_POVRAY_EXEC, povray.getPath());
            }
        }
    }
    return povray;
}

@NbBundle.Messages("TTL_FindIncludeDir=Find POV-Ray Standard Include File Dir")
private static File getStandardIncludeDir(File povray) {
    if (include != null) {
        return include;
    }
    Preferences prefs = RendererServiceImpl.getPreferences();
    String loc = prefs.get(KEY_POVRAY_INCLUDES, null);
    if (loc != null) {
        include = new File(loc);
        if (!include.exists()) {
            include = null;
        }
    }
    if (include == null) {
        include = new File(povray.getParentFile().getParent()
                + File.separator + "include");
        if (!include.exists()) {
            include = locate(Bundle.TTL_FindIncludeDir());
            if (include != null) {
                prefs.put(KEY_POVRAY_INCLUDES, include.getPath());
            } else {
                include = null;
            }
        }
    }
    return include;
}</pre>

                </li>

            </ol>

        </div>

        <h2 class="tutorial"><a name="executing"></a>Next Steps</h2>

        <p>The <a href="nbm-povray-7.html">next section</a> will cover actually
            executing POV-Ray and piping its output to the Output window of our application.</p>

    </body>

</html>
