<!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 IX&#8212;Build Support</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 IX&#8212;Adding Project Build Support and Some Finishing Touches"/>
        <!--      Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. -->
        <!--     Use is subject to license terms.-->

    </head>

    <body>

        <h1>Writing POV-Ray Support for NetBeans IX&#8212;Build Support</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>, <a href="nbm-povray-5.html">fifth</a>
            <a href="nbm-povray-6.html">sixth</a>, <a href="nbm-povray-7.html">seventh</a>,
            and <a href="nbm-povray-8.html">eighth</a>
            parts of this tutorial, you may want to start there.</p>

        <h2 class="tutorial"><a name="spit-and-polish"></a>Project Action Support</h2>

        <p>You may recall that early on, when we were writing <code>PovrayProject</code>,
            we stubbed out the implementation of <code>PovrayProject.ActionsProviderImpl</code>&#8212;so
            in fact the build, clean and run actions are all disabled when a POV-Ray
            project is active.  We should quickly implement them.</p>

	<p>Open <code>PovrayProject</code> in the code editor, and implement
	    the methods of <code>ActionProviderImpl</code> as follows:</p>

	<pre class="examplecode">private final class ActionProviderImpl implements ActionProvider {

    @Override
    public String[] getSupportedActions() {
        return new String[]{
                    ActionProvider.COMMAND_BUILD,
                    ActionProvider.COMMAND_CLEAN,
                    ActionProvider.COMMAND_COMPILE_SINGLE
        };
    }

    @Override
    public void invokeAction(String string, Lookup lookup) throws IllegalArgumentException {
        int idx = Arrays.asList(getSupportedActions()).indexOf(string);
        switch (idx) {
            case 0: //build
                final RendererService ren = (RendererService) getLookup().lookup(RendererService.class);
                RequestProcessor.getDefault().post(new Runnable() {
                    @Override
                    public void run() {
                        FileObject image = ren.render();
                        //If we succeeded, try to open the image
                        if (image != null) {
                            DataObject dob;
                            try {
                                dob = DataObject.find(image);
                                OpenCookie open = (OpenCookie) dob.getNodeDelegate().getLookup().lookup(OpenCookie.class);
                                if (open != null) {
                                    open.open();
                                }
                            } catch (DataObjectNotFoundException ex) {
                                Exceptions.printStackTrace(ex);
                            }
                        }
                    }
                });
                break;
            case 1: //clean
                FileObject fob = getImagesFolder(false);
                if (fob != null) {
                    DataFolder fld = DataFolder.findFolder(fob);
                    for (Enumeration en = fld.children(); en.hasMoreElements();) {
                        DataObject ob = (DataObject) en.nextElement();
                        try {
                            ob.delete();
                        } catch (IOException ioe) {
                            Exceptions.printStackTrace(ioe);
                        }
                    }
                }
                break;
            case 2: //compile-single
                final DataObject ob = (DataObject) lookup.lookup(DataObject.class);
                if (ob != null) {
                    final RendererService ren1 = (RendererService) getLookup().lookup(RendererService.class);
                    RequestProcessor.getDefault().post(new Runnable() {
                        @Override
                        public void run() {
                            if (ob.isValid()) { //Could theoretically change before we run
                                ren1.render(ob.getPrimaryFile());
                            }
                        }
                    });
                }
                break;
            default:
                throw new IllegalArgumentException(string);
        }
    }

    @Override
    public boolean isActionEnabled(String string, Lookup lookup) throws IllegalArgumentException {
        int idx = Arrays.asList(getSupportedActions()).indexOf(string);
        boolean result;
        switch (idx) {
            case 0: //build
                result = true;
                break;
            case 1: //clean
                result = getImagesFolder(false) != null
                        && getImagesFolder(false).getChildren().length > 0;
                break;
            case 2: //compile-single
                DataObject ob = (DataObject) lookup.lookup(DataObject.class);
                if (ob != null) {
                    FileObject file = ob.getPrimaryFile();
                    result = "text/x-povray".equals(file.getMIMEType());
                } else {
                    result = false;
                }
                break;
            default:
                result = false;
        }
        return result;
    }

}</pre>


        </div>

        <h2 class="tutorial"><a name="ensure-main-file"></a>Ensuring There Is A Main File</h2>

        <p>We now have handling implemented for all of the standard project actions that make
            sense for a POV-Ray project.  Now, if you've been following very carefully,
            you may have noticed that there is one bug we need to fix:
            <code>isActionEnabled()</code> will always return true for build.  But we
            implemented the following code in <code>Povray.getFileToRender()</code>:</p>

        <pre class="examplecode">render = provider.getMainFile();
if (render == null) {
    ProjectInformation info = (ProjectInformation) proj.getLookup().lookup(ProjectInformation.class);
    //XXX let the user choose
    throw new IOException(NbBundle.getMessage(Povray.class, "MSG_NoMainFile", info.getDisplayName()));
}</pre>

        <p>So if there is no main file set for a project, the build action will be
            enabled, but if it is invoked, it will throw an exception!  The simple
            choice would be to test if there is a main file, and if not, disable the
            build action&#8212;but this would be rather non-intuitive to the user who
            might not be able to figure out what is wrong with the project.
            And we would miss an opportunity to explore the Explorer & Property Sheet API,
            together with the Dialogs APIs!</p>

        <p>So instead, we will post a dialog which will allow the user to choose
            which file should be the main file, if none is set when build is called:</p>

        <div class="indent">

            <ol>

                <li>On the Povray Project module,
		    following the procedure outlined in previous sections of this tutorial,
                    add a module dependency on the Explorer &
                    Property Sheet API.</li>

                <li>Right-click the <code>org.netbeans.examples.modules.povproject</code>
                    package and chose New &gt; Other &gt; Swing GUI Forms &gt; JPanel Form.
		    Click Next. Name The JPanel &quot;MainFileChooser&quot; and click Finish.
                    The GUI Designer (Matisse)
                    will open.</li>

                <li>In the Palette (Ctrl-Shift-8), click the item for <code>JLabel</code> and drag
                    it to the top of the <code>JPanel</code>.
                    Drag the right-hand edge of the <code>JLabel</code> to the right edge of the
                    <code>JPanel</code> so that the <code>JLabel</code> will
		    resize automatically at runtime.</li>

                <li><p>In the Palette, click the item for <code>JScrollPane</code> and drag
                        it to the <code>JPanel</code> below the <code>JLabel</code>.
                        Drag the bottom right corner of the <code>JScrollPane</code> down
                        and to the right until the bottom and right edge alignment guidelines
                        appear. The result should look like this:</p>
                    <p><img alt="" src="../../images/tutorials/povray/71/ch9/pic1.png"/></p>
                </li>

                <li><p>Make sure the Properties window (Ctrl-Shift-7) is open.
			Select the <code>JLabel</code> and and then click the [...] button for its
                        <code>text</code> property in the Properties window.  A custom editor
                        will open:</p>
                    <p><img alt="" src="../../images/tutorials/povray/71/ch9/pic2.png"/></p>
                </li>

                <li><p>Change the drop-down at the top of the dialog to "Custom code", as
			shown below, and then type <tt>Bundle.LBL_ChooseMainFile()</tt>:</p>
                    <p><img alt="" src="../../images/tutorials/povray/71/ch9/pic3.png"/></p>
		    <p>Click OK. Now add this annotation above the class signature:</p>

		    <pre class="examplecode"><b>@NbBundle.Messages("LBL_ChooseMainFile=Select Main File")</b>
public class MainFileChooser extends javax.swing.JPanel {</pre>

		    <p>Save the file. Now the annotation is converted to a String constant in a <tt>Bundle</tt>
			class and the reference to this class in the <tt>initComponents</tt> block
			should not show an error anymore.</p>

                </li>

                <li>Edit the signature of the class so that it implements the interface
                    <code>ExplorerManager.Provider</code>:
                    <pre class="examplecode">public class MainFileChooser extends javax.swing.JPanel implements ExplorerManager.Provider {</pre></li>

                <li>Add the following code to implement <code>ExplorerManager.Provider</code>:
                    <pre class="examplecode">private final ExplorerManager mgr = new ExplorerManager();

public ExplorerManager getExplorerManager() {
    return mgr;
}</pre>
                </li>

                <li>
                    <p>Modify the constructor so it reads as follows:</p>

                    <pre class="examplecode">public MainFileChooser(PovrayProject proj) {

    initComponents();

    setLayout(new BorderLayout());

    LogicalViewProvider logicalView = (LogicalViewProvider) proj.getLookup().lookup(LogicalViewProvider.class);

    Node projectNode = logicalView.createLogicalView();

    mgr.setRootContext(new FilterNode(projectNode, new ProjectFilterChildren(projectNode)));

    BeanTreeView btv = new BeanTreeView();

    jScrollPane1.setViewportView(btv);

    btv.setPopupAllowed(false);

    btv.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

    add(btv, BorderLayout.CENTER);

}</pre>
                    <p>The <code>BeanTreeView</code> we are showing is a UI class from the
                        Explorer API&#8212;in fact, it is the very same component that you see in
                        the Projects, Files, Runtime and Favorites tabs in the NetBeans IDE.</p>
                    <p>
                        What it will do is, when it is added to a component, search through
                        the hierarchy of parent components until it finds one that implements
                        <code>ExplorerManager.Provider</code>.  That component's <code>ExplorerManager</code>
                        will then become the place where the tree view gets its root node to
                        display, and will be what it notifies when the selection changes.</p>

		    <p class="notes"><b>Note:</b> An error mark will remain
			for <code>ProjectFilterNode</code> because we have not yet
			written it.</p></li>

                <li><p>Now we need to implement <code>ProjectFilterNode</code>.  The
                        Nodes API contains a class, <code>FilterNode</code>, which makes it
                        possible to take one <code>Node</code>, and create another <code>Node</code>
                        which &quot;filters&quot; the original <code>Node</code>&#8212;providing
                        different children, actions, properties or whatever it chooses to.</p>

                    <p>In our case, we want a <code>FilterNode</code> that will filter out
                        any files that do not have the MIME type <code>text/x-povray</code>&#8212;so
			that, if the user has a text file or an image file or such in their
                        project, they cannot set that to be the main file and try to pass it
                        to POV-Ray.</p>

                    <p>We don't actually need to implement <code>FilterNode</code>, we
                        simply need to provide an alternate <code>Children</code> object
                        which filters out files we don't want.  Implement this as a nested
                        class inside <code>MainFileChooser</code>:</p>

                    <pre class="examplecode">private static final class ProjectFilterChildren extends FilterNode.Children {

    ProjectFilterChildren(Node projectNode) {
	super(projectNode);
    }

    @Override
    protected Node[] createNodes(Node object) {
	Node origChild = (Node) object;
	DataObject dob = (DataObject) origChild.getLookup().lookup(DataObject.class);
	if (dob != null) {
	    FileObject fob = dob.getPrimaryFile();
	    if ("text/x-povray".equals(fob.getMIMEType())) {
		return super.createNodes(object);
	    } else if (dob instanceof DataFolder) {
		//Allow child folders of the scenes/ dir
		return new Node[]{
			    new FilterNode(origChild,
			    new ProjectFilterChildren(origChild))
			};
	    }
	}
	//Don't create any nodes for non-povray files
	return new Node[0];
    }

}</pre>
                </li>

                <li>

                    <p>Now we just need some code to use this panel.  That code will
                        go in <code>RenderServiceImpl</code>, before we call
                        <code>Povray.render()</code>.  Reimplement the no-argument version
                        of the <code>render()</code> method as follows:</p>

                    <pre class="examplecode">@Override
public FileObject render() {
    MainFileProvider mfp = (MainFileProvider) proj.getLookup().lookup(MainFileProvider.class);
    assert mfp != null;
    if (mfp.getMainFile() == null) {
	showChooseMainFileDlg(mfp);
    }
    if (mfp.getMainFile() != null) {
	return render(null);
    } else {
	return null;
    }
}</pre>

                </li>

                <li><p>Now we need to implement the method we are calling above,
                        <code>showChooseMainFileDlg()</code>.  This is the method which
                        will ask the user to pick a main file.  It will use the Dialogs API
                        to show a dialog containing an instance of <code>MainFileChooser</code>,
                        and enable the OK button once a file is selected.  If the user
                        selects a POV-Ray file, it will be stored in <code>MainFileProvider</code>,
                        and so it will be non-null when we return to the <code>render()</code>
                        method, and so <code>render()</code> will proceed:</p>

                    <pre class="examplecode">@NbBundle.Messages("TTL_ChooseMainFile=Choose Main File")
private void showChooseMainFileDlg(final MainFileProvider mfp) {

    final MainFileChooser chooser = new MainFileChooser(proj);

    String title = Bundle.TTL_ChooseMainFile();

    //Create a simple dialog descriptor describing what kind of dialog
    //we want and its title and contents
    final DialogDescriptor desc = new DialogDescriptor(chooser, title);

    //The OK button should be disabled initially
    desc.setValid(false);

    //Create a property change listener.  It will listen on the selection
    //in our MainFileChooser, and enable the OK button if an appropriate
    //node is selected:
    PropertyChangeListener pcl = new PropertyChangeListener() {
	@Override
	public void propertyChange(PropertyChangeEvent pce) {
	    String propName = pce.getPropertyName();
	    if (ExplorerManager.PROP_SELECTED_NODES.equals(propName)) {
		Node[] n = (Node[]) pce.getNewValue();
		boolean valid = n.length == 1;
		if (valid) {
		    DataObject ob = (DataObject) n[0].getLookup().lookup(DataObject.class);
		    valid = ob != null;
		    if (valid) {
			FileObject selectedFile = ob.getPrimaryFile();
			String mimeType = selectedFile.getMIMEType();
			valid = "text/x-povray".equals(mimeType);
		    }
		}
		desc.setValid(valid);
	    }
	}
    };
    chooser.getExplorerManager().addPropertyChangeListener(pcl);

    //Show the dialog—dialogResult will be OK or Cancel
    Object dialogResult = DialogDisplayer.getDefault().notify(desc);

    //If the user clicked OK, try to set the main file
    //from the selection
    if (DialogDescriptor.OK_OPTION.equals(dialogResult)) {

	//Get the selected Node
	Node[] n = chooser.getExplorerManager().getSelectedNodes();

	//If it's > 1, explorer is broken—we set
	//single selection mode
	assert n.length <= 1;
	DataObject ob = (DataObject) n[0].getLookup().lookup(
		DataObject.class);

	//Get the file from the data object
	FileObject selectedFile = ob.getPrimaryFile();

	//And save it as the main file
	mfp.setMainFile(selectedFile);

    }

}</pre>
                </li>

            </ol>

        </div>

	<h2 class="tutorial"><a name="project-popup"></a>Extending the Project Popup Menu</h2>

	<p>Right now, if you run the application and open a new POV-Ray project
	    and right-click on it, there are no render or clean actions.
	    The first thing we can do is improve the popup menu for POV-Ray
	    projects&#8212;we need to add a couple of menu items to those already returned.</p>

        <ol>

            <li>Open <code>PovrayLogicalView</code> in the editor, and find the
                inner <code>ScenesNode</code> class.</li>

            <li><p>Override <code>getActions()</code> as follows:</p>

                <pre class="examplecode">@NbBundle.Messages({
    "LBL_Build=Render Project",
    "LBL_Clean=Clean Project"
})
@Override
public Action[] getActions(boolean popup) {
    Action[] result = new Action[]{
	new ProjectAction(ActionProvider.COMMAND_BUILD, Bundle.LBL_Build(), project),
	new ProjectAction(ActionProvider.COMMAND_CLEAN, Bundle.LBL_Clean(), project),
	new OtherProjectAction(project, false),
	SystemAction.get(NewTemplateAction.class),
	SystemAction.get(FileSystemAction.class),
	new OtherProjectAction(project, true),
    };
    return result;
}</pre>
                <p>This gives us two classes to implement&#8212;<code>ProjectAction</code> and
                    <code>OtherProjectAction</code>.
                    The former will simply be an action class which delegates to the action
                    provider of the project, and the other will use the <code>OpenProjects</code>
                    class from the Project UI API to close the project.</p>

            </li>

            <li><p>Implement <code>ProjectAction</code> as follows:</p>

		<pre class="examplecode">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;
    }

    @Override
    public void actionPerformed(ActionEvent actionEvent) {
	ActionProvider prov = (ActionProvider) project.getLookup().lookup(ActionProvider.class);
	prov.invokeAction(command, null);
    }

    @Override
    public boolean isEnabled() {
	ActionProvider prov = (ActionProvider) project.getLookup().lookup(ActionProvider.class);
	return prov.isActionEnabled(command, null);
    }

}</pre>
            </li>

            <li><p>Then implement the brilliantly named <code>OtherProjectAction</code>
                    this way, also as a 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&#8212;and additional classes do come with a
                    memory penalty, so for trivial things, this approach is not necessarily
                    a bad idea&#8212;as long as the result is readable:</p>

                <pre class="examplecode">@NbBundle.Messages({
    "LBL_CloseProject=Close Project",
    "LBL_SetMainProject=Set Main Project"
})
private static class OtherProjectAction extends AbstractAction {

    private final PovrayProject project;
    private final boolean isClose;

    OtherProjectAction(PovrayProject project, boolean isClose) {
	putValue(NAME, isClose ? Bundle.LBL_CloseProject() : Bundle.LBL_SetMainProject());
	this.project = project;
	this.isClose = isClose;
    }

    @Override
    public void actionPerformed(ActionEvent actionEvent) {
	if (isClose) {
	    OpenProjects.getDefault().close(new Project[]{project});
	} else {
	    OpenProjects.getDefault().setMainProject(project);
	}
    }

}</pre>
            </li>


	    <li><p>Run the application and right-click on a POV-Ray project
		    node. Notice that we now have a much improved popup menu:</p>
		<p><img alt="" src="../../images/tutorials/povray/71/ch9/pic4.png"/></p>
		<p>If "Render Project" is chosen while no main file has been set, you will
		    see this dialog, where you can set a main file, which will
		    immediately result in the file being rendered:</p>
		<p><img alt="" src="../../images/tutorials/povray/71/ch9/pic5.png"/></p>
	    </li>

        </ol>

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

        <p>Congratulations! You have completed the POV-Ray tutorial.
	    The <a href="nbm-povray-10.html">next step</a> is to
	    review the concepts you've learned and then continue
	    your journey on the NetBeans Platform.</p>

    </body>

</html>
