blob: 2b68e577608357b92057315a85d35d77da7da7a5 [file] [log] [blame]
<!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&#8212;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&#8212;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&#8212;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&#8212;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&#8212;data recognition
and project types are orthagonal&#8212;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 &quot;compiles&quot; 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&#8212;Don't Try to Save the World</h2>
<p>The biggest killer of projects is trying to &quot;save the world&quot; -
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&#8212;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&#8212;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&#8212;<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&#8212;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&#8212;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&#8212;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 &quot;main file&quot;.
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>&#8212;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>