| <!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 II—Project Type Design</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 II—designing a sane custom project type and structure"/> |
| <!-- Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. --> |
| <!-- Use is subject to license terms.--> |
| |
| </head> |
| |
| <body> |
| <h1>Writing POV-Ray Support for NetBeans II—Project Type Design</h1> |
| |
| <p>In this part of the tutorial, we will walk through how to create a basic |
| project type. It will be a project type that supports building 3D graphics |
| scenes using <a href="http://povray.org">POV-Ray</a>'s scene language, and |
| eventually, rendering them as images and displaying the result in NetBeans.</p> |
| |
| <p> |
| It is assumed you have completed the steps in the |
| <a href="nbm-povray-1.html">previous tutorial</a> for creating basic POV-Ray |
| support.</p> |
| |
| <p> |
| This tutorial will go through the up-front design and thinking through |
| needed to successfully implement a project type that will serve its users |
| well. The subsequent tutorial walks through the implementation of the basic |
| project.</p> |
| |
| <h2>Design and Coupling</h2> |
| |
| <p>A NetBeans project is a directory on disk; typically there is some signature, |
| such as having a subdirectory with a specific name, which identifies that |
| directory as being a project.</p> |
| |
| <p> |
| The major requirement of identifying a folder as being a project is that the |
| test fail quickly—the code that determines that a folder is <i>not</i> a |
| project must complete very quickly, because it is going to be called once |
| for every folder visible in the file chooser that lets users open projects. |
| We will stick with what works, and use a specific subdirectory name to |
| identify our POV-Ray projects.</p> |
| |
| <p> |
| Most Project types in NetBeans use <a href="http://ant.apache.org">Apache Ant</a> |
| as their build infrastructure, and there are APIs for building Ant-based |
| projects. This example does <i>not</i> use Ant, but implements a simple basic |
| project type. Even if you know you will use Ant, you will encounter all of |
| the concepts presented here in implementing an Ant-based project.</p> |
| |
| <p> |
| Notice that we implemented support for <code>.pov</code> and <code>.inc</code> |
| files in a <a href="nbm-povray-1.html">separate module</a>. Design-wise |
| this makes sense—data recognition |
| and project types are orthagonal—and it provides a good demonstration of |
| how to do loose coupling between modules.</p> |
| |
| <p> |
| So at this point we need to think about what we're designing, what functionality |
| belongs to which module, and what will serve our users' needs best. Before |
| we do any coding, some design has to happen. Here's what we know about |
| POV-Ray and its usage patterns:</p> |
| |
| <div class="indent"> |
| |
| <ol> |
| <li>POV-Ray has a scene language, and it "compiles" textual <code>.pov</code> files down |
| into image files.</li> |
| <li>A <code>.pov</code> file can reference other files, which typically get |
| the extension <code>.inc</code>.</li> |
| <li>POV-Ray has a huge number of options such as antialiasing, jitter, output |
| image size, quality, number of reflections, animation clock.</li> |
| <li>Users will render small test versions of a scene at low quality to check |
| their work as they go; large, high quality renders can take a long time.</li> |
| <li>Typically the user knows the size and aspect ratio they'll want for the |
| final output, but that's also <i>not</i> what most renders will use.</li> |
| <li>To save rendering time while working, a user may split individual objects |
| from a scene into separate files and render them individually as they work.</li> |
| </ol> |
| |
| </div> |
| |
| <h2 class="tutorial"><a name="choices"></a>Design Choices—Don't Try to Save the World</h2> |
| |
| <p>The biggest killer of projects is trying to "save the world" - |
| trying to provide every combination of every possible option to the user, such |
| that the user is confronted with a bewildering array of choices when most of |
| the time they want to do something very simple. Trying to support every |
| imaginable permutation of anything leads to projects |
| which are permanently six months from completion. So we need to limit the |
| scope while providing value to the user. But we also want to keep |
| power users happy and give them the ability to do what they need to do. So |
| we have some choices to make, and some hard thinking to do about what is the |
| right UI to balance the power of POV-Ray with the need to keep things simple |
| and easy to use for beginners.</p> |
| |
| <p> |
| The first question, from item 1, is, which module owns the rendering infrastructure? |
| Well, when you render an image, you need a place to put it. A project owns |
| a directory and its subdirectories. So we'll make an executive decision right |
| now that we don't render a random <code>.pov</code> file on disk—it must |
| belong to a project which can provide a place to put the result. So the |
| code that actually calls out to POV-Ray will be part of the project support |
| module, not the file support module.</p> |
| |
| <p> |
| A follow-on to this is, should it be possible to render absolutely any <code>.pov</code> |
| or <code>.inc</code> file? Probably yes, due to fact 6—but we'll only do |
| that if it belongs to a project.</p> |
| |
| <p> |
| Do we want to provide structure (subfolders, etc.) in POV-Ray projects? It |
| would probably be nice for the future, but to keep the scope of things manageable, |
| we're not going to do that now. In practice, POV-Ray projects can be just as |
| messy as projects written in C, with source files scattered hither and yon. |
| We are not going to try to solve all the world's problems here; but neither are |
| we going to impose our own idea of what a well structured POV-Ray project |
| looks like on the user.</p> |
| |
| <p> |
| How many of the myriad command-line options that POV-Ray supports should we |
| expose the user to? The real usage pattern here is that, for test renders, |
| any of a few sets of standard settings will do for almost all cases. So we |
| will provide a set of standard resolutions like 320x200, 640x480, 1024x768. |
| Those settings will be unmodifiable. But, associated with each project will |
| be a set of <i>production settings</i>, which are saved with the project, are |
| shareable and go with the project wherever it goes. We will provide a |
| basic GUI customizer for the production settings. |
| It will not cover every possible setting POV-Ray has—<i>however</i>, the |
| customizer will be writing into the project's <code>project.properties</code> file - |
| and a power user can edit in their own settings to do anything they want, so |
| the full power of POV-Ray stays available to power users—any desired line |
| switch can be encoded into the project's properties file and end up passed |
| on the command line to POV-Ray.</p> |
| |
| <p> |
| Because of item 6, we know there can be multiple files in a project, but only |
| one is the master scene that is the final output of the project. So we will |
| give our projects the concept of a <i>main file</i> which is what gets rendered |
| when they invoke Build, and we'll need a UI to select which file it is.</p> |
| |
| <h2><a name="phys">Physical Structure of a POV-Ray Project</a></h2> |
| |
| <p>We also need to make some decisions about what will be stored on disk and where. We know that |
| projects typically have Build and Clean actions, and these will be useful |
| for POV-Ray projects as well. Where should |
| scene files go? Well, we want to keep some flexibility for future versions, |
| so we don't want them in the root directory of our projects—we'll create a |
| <code>scenes/</code> folder for them.</p> |
| |
| <p> |
| We also know we will end up with image |
| files from rendering. The Clean operation will be much less complex to |
| implement if it just means deleting a directory. And the UI will |
| be less cluttered if we put images in their own |
| directory, so rendered images will go in an <code>images/</code> subdirectory |
| of the project. The project UI won't even show the <code>images/</code> |
| directory—you'll just right-click a scene file and select <i>View</i>, |
| to render and show a single file, or build the project to show the "main file". |
| As with compiling, we will do a date check to see if the source file is |
| newer than the image file, and if so, render it again.</p> |
| |
| <p>We also know we need to use a subdirectory to identify our project type, and |
| to store configuration data that should be saved, such as which file is the |
| main file and what are the production renderer settings. So we'll decide that every |
| POV-Ray project will have a <code>pvproject</code> subdirectory, and in |
| that directory will be a <code>properties</code> file. So on disk, |
| a typical POV-Ray project will look like:</p> |
| |
| <ul> |
| <li>Wonderland/ |
| <ul> |
| <li>images/ |
| <ul> |
| <li>Wonderland.png</li> |
| </ul> |
| </li> |
| <li>pvproject/ |
| <ul> |
| <li>project.properties</li> |
| </ul> |
| </li> |
| <li>scenes/ |
| <ul> |
| <li>Alice.inc</li> |
| <li><b>Wonderland.pov</b></li> |
| <li>LookingGlass.inc</li> |
| <li>MadQueen.inc</li> |
| <li>MockTurtle.inc</li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| |
| <h2>Coupling Between POV-Ray Files and POV-Ray Project</h2> |
| |
| <p>Typically a user is going to be dealing with files, and we already decided that |
| a user should be able to render any file in a project; and we know we are |
| going to have to give the user the ability to pick which file is the main file |
| for a project. That means our <code>Node</code>s for <code>.pov</code> files |
| will need to have <code>Action</code>s that will be invoking rendering and main-file-setting |
| code that belongs to the project module, not to their module. So we know we |
| that the project module will need to expose some API for doing these things, |
| and the <code>Node</code> of a POV-Ray file will need to be able to find the |
| project that owns it and call this code. But if a <code>.pov</code> is |
| orphaned on disk, or is inside, say, a J2EE project for some reason, it |
| must fail gracefully.</p> |
| |
| <p> |
| This gives a great opportunity to demonstrate how loose coupling between |
| modules is done. There are two simple mechanisms that will allow us to |
| easily do this: The first is <code>FileOwnerQuery</code>—this is a class |
| from the <code>Project</code> module, which allows one to find out what |
| project owns any file. The second is that <code>Project</code>, the interface |
| we implement to create our project type, has a method <code>getLookup()</code>. |
| So we will provide some interfaces in the POV-Ray project type which we'll |
| make available as API. When a node finds out what project its file belongs |
| to, it can simply request the implementation of one of those interfaces. |
| If it gets non-null, it can call the rendering or main-file-setting functionality; |
| if it gets null, or the project is null, those actions will just be disabled.</p> |
| |
| <h2>Summary</h2> |
| |
| <p>Design is an inescapable first-step in developing modules. It pays to think |
| hard about what functionality belongs where, and what the user experience |
| should be before starting to code.</p> |
| |
| <p><b><a href="nbm-povray-3.html">Next: Implementing POV-Ray Project Support</a></b></p> |
| |
| </body> |
| |
| </html> |