<!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> | |
<!-- -*- xhtml -*- --> | |
<title>NetBeans Project Type Extension Module Tutorial for NetBeans Platform 6.9</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="gwielenga@netbeans.org"/> | |
<meta name="indexed" content="y"/> | |
<meta name="description" | |
content="A short guide to using the APIs for extending project types."/> | |
<!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. --> | |
<!-- Use is subject to license terms.--> | |
</head> | |
<body> | |
<h1>NetBeans Project Type Extension Module Tutorial</h1> | |
<p>This tutorial demonstrates how to extend an existing project type.</p> | |
<p><strong class="notes">Note: </strong>This document uses the NetBeans IDE 6.9 Release or above. If you | |
are using an earlier version, see <a href="60/nbm-projectextension.html">the 6.0/6.1 version | |
of this document</a>.</p> | |
<p><b>Contents</b></p> | |
<p><img src="../../images/articles/69/netbeans-stamp-69-70.png" class="stamp" width="114" height="114" alt="Content on this page applies to NetBeans IDE 6.9" title="Content on this page applies to NetBeans IDE 6.9"/></p> | |
<ul class="toc"> | |
<li><a href="#intro">Introduction to Project Extensions</a></li> | |
<li><a href="#creatingthemoduleproject">Creating the Module Project</a></li> | |
<li><a href="#settingdependencies">Setting Dependencies</a></li> | |
<li><a href="#extendingthelookup">Extending the Lookup</a></li> | |
<li><a href="#extendingthelogicalview">Extending the Logical View</a></li> | |
<li><a href="#extendingthecustomizer">Extending the Project Customizer</a></li> | |
<li><a href="#building">Installing the Module</a></li> | |
</ul> | |
<p><b>To follow this tutorial, you need the software and resources listed in the following | |
table.</b></p> | |
<table> | |
<tbody> | |
<tr> | |
<th class="tblheader" scope="col">Software or Resource</th> | |
<th class="tblheader" scope="col">Version Required</th> | |
</tr> | |
<tr> | |
<td class="tbltd1"><a href="https://netbeans.org/downloads/index.html">NetBeans IDE</a></td> | |
<td class="tbltd1">version 6.9 or above</td> | |
</tr> | |
<tr> | |
<td class="tbltd1"><a href="http://java.sun.com/javase/downloads/index.jsp">Java Developer Kit (JDK)</a></td> | |
<td class="tbltd1">Version 6</td> | |
</tr> | |
</tbody> | |
</table> | |
<p>You will also make use of this icon, which you | |
can right-click here and download: <img alt="" src="../../images/tutorials/projectextensions/webPagesBadge.gif" /></p> | |
<p class="tips">Optionally, for troubleshooting purposes, you can <a href="http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=14034">download the | |
completed sample</a> and inspect the sources.</p> | |
<h2 class="tutorial"><a name="intro"></a>Introduction to Project Extensions</h2> | |
<p>New NetBeans IDE APIs since NetBeans IDE 6.0 | |
enable you to add new nodes to an existing project type's logical view, new objects to an | |
existing project type's lookup, and new panels to an existing project type's Project | |
Properties dialog box. For example, in this tutorial, | |
to illustrate these extensions, we extend the web application | |
project type, by adding a new 'Important Files' node, exposing the content of the | |
project's 'nbproject' folder, as shown here:</p> | |
<p><img src="../../images/tutorials/projectextensions/result-69.png" alt="New node"/></p> | |
<p>Prior to NetBeans IDE 6.0, no NetBeans IDE APIs existed for extending existing project types. | |
Instead, you would need to create new project types from scratch. From 6.0 onwards, you are | |
recommended to extend existing project types rather than create new ones. This will | |
keep the number of project types to a minimum and avoid a large number of project | |
types with very small differences. However, it is still possible to create project | |
types from scratch, as before.</p> | |
<p>Annotations are used throughout this tutorial to register the lookup extension, | |
logical view extension, and project customizer extension. As you will see | |
below, the extensions will be registered for the project type | |
"org-netbeans-modules-web-project", which is the web application project type. | |
Here is a list of strings representing other project types supported by | |
NetBeans IDE:</p> | |
<ul> | |
<li>org-netbeans-modules-ant-freeform</li> | |
<li>org-netbeans-modules-apisupport-project</li> | |
<li>org-netbeans-modules-apisupport-project-suite</li> | |
<li>org-netbeans-modules-j2ee-archiveproject</li> | |
<li>org-netbeans-modules-j2ee-clientproject</li> | |
<li>org-netbeans-modules-j2ee-earproject</li> | |
<li>org-netbeans-modules-j2ee-ejbjarproject</li> | |
<li>org-netbeans-modules-java-j2seproject</li> | |
</ul> | |
<p>Other project types may be available, depending on the modules that are part | |
of your specific installation of NetBeans IDE or other application on the | |
NetBeans Platform.</p> | |
<h2 class="tutorial"><a name="creatingthemoduleproject"></a>Creating the Module Project</h2> | |
<p>We begin by working through the New Module Project | |
wizard. At the end of it, we will have a basic | |
source structure, with some default files, that | |
every NetBeans module requires.</p> | |
<ol> | |
<li>Choose File > New Project (Ctrl+Shift+N). Under Categories, select NetBeans Modules. | |
Under Projects, select Module. Click Next.</li> | |
<li>In the Name and Location panel, type <tt>ImportantWebFiles</tt> in the Project Name field. | |
Change the Project Location to any directory on your computer. Leave the Standalone Module option | |
and Set as Main Project checkbox selected. Click Next.</li> | |
<li>In the Basic Module Configuration panel, type <tt>org.netbeans.modules.importantwebfiles</tt> | |
in Code Name Base.</li> | |
<li>Select "Generate XML Layer". Leave the | |
locations of both the localizing bundle and the XML layer file | |
so that they will be stored in a package with | |
the name <tt>org/netbeans/modules/importantwebfiles</tt>. Click Finish.</li> | |
</ol> | |
<p> The IDE creates the <tt>ImportantWebFiles</tt> | |
project. The project contains all of your sources and | |
project metadata, such as the project's Ant build script. The project | |
opens in the IDE. You can view its logical structure in the Projects window (Ctrl-1) and its | |
file structure in the Files window (Ctrl-2).</p> | |
<!-- ===================================================================================== --> | |
<h2><a name="settingdependencies"></a>Setting Dependencies</h2> | |
<p>We will need to make use of several NetBeans APIs. In this | |
step, we select the modules that provide the NetBeans APIs | |
that we will need.</p> | |
<ol> | |
<li>Right-click the project node and | |
choose Properties. The Project Properties dialog box opens.</li> | |
<li>In the Libraries panel, add dependencies on the | |
following modules: | |
<ul> | |
<li>Datasystems API</li> | |
<li>File System API</li> | |
<li>Nodes API</li> | |
<li>Project API</li> | |
<li>Project UI API</li> | |
<li>Utilities API</li> | |
<li>Web APIs</li> | |
</ul> | |
<p>The Libraries panel should now look as follows:</p> | |
<p><img src="../../images/tutorials/projectextensions/add-deps-69.png" alt="Select Project panel."/></p> | |
</li> | |
<li>Click OK.</li> | |
</ol> | |
<!-- ===================================================================================== --> | |
<h2><a name="extendingthelookup"></a>Extending the Lookup</h2> | |
<p>We start by implementing the <tt>LookupProviderImpl</tt> | |
class, which we will register via an annotation.</p> | |
<ol> | |
<li><p>Create a Java class called <tt>LookupProviderImpl</tt>.</p></li> | |
<li><p>Change the default code to the following:</p> | |
<pre class="examplecode">@LookupProvider.Registration(projectType = "org-netbeans-modules-web-project") | |
public class LookupProviderImpl implements LookupProvider { | |
public Lookup createAdditionalLookup(Lookup lookup) { | |
Project prj = lookup.lookup(Project.class); | |
<b>//If there is a web module provider in the | |
//project's lookup, add a new lookup item to | |
//the lookup, which we will look for to determine | |
//whether a node should be created:</b> | |
WebModuleProvider wmp = lookup.lookup(WebModuleProvider.class); | |
if (wmp != null) { | |
return Lookups.fixed(new MyCoolLookupItem(prj)); | |
} | |
<b>//If there is no web module in the lookup, | |
//we do not add a new item to our lookup, | |
//so that later a node will not be created:</b> | |
return Lookups.fixed(); | |
} | |
}</pre> </li> | |
<li>Create a new Java class called <tt>MyCoolLookupItem</tt>.</li> | |
<li><p>Change the default code to the following:</p> | |
<pre class="examplecode">public class MyCoolLookupItem { | |
public MyCoolLookupItem(Project prj) { | |
} | |
}</pre> </li> | |
</ol> | |
<!-- ===================================================================================== --> | |
<h2><a name="extendingthelogicalview"></a>Extending the Logical View</h2> | |
<p>We start by implementing the <tt>ImportantFilesNodeFactoryImpl</tt> | |
class, which we will register via an annotation.</p> | |
<ol> | |
<li><p>Create a Java class called <tt>ImportantFilesNodeFactoryImpl</tt>.</p></li> | |
<li><p>Change the default code to the following:</p> | |
<pre class="examplecode">@NodeFactory.Registration(projectType = "org-netbeans-modules-web-project") | |
public class ImportantFilesNodeFactoryImpl implements <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-projectuiapi/org/netbeans/spi/project/ui/support/NodeFactory.html">NodeFactory</a> { | |
Project proj; | |
public <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-projectuiapi/org/netbeans/spi/project/ui/support/NodeList.html">NodeList</a> createNodes(Project project) { | |
this.proj = project; | |
<b>//If there is no 'nbproject' folder, | |
//return an empty list of nodes:</b> | |
if (proj.getProjectDirectory().getFileObject("nbproject") == null) { | |
return NodeFactorySupport.fixedNodeList(); | |
} | |
<b>//If our item is in the project's lookup, | |
//return a new node in the node list:</b> | |
MyCoolLookupItem item = project.getLookup().lookup(MyCoolLookupItem.class); | |
if (item != null) { | |
try { | |
ImportantFilesNode nd = new ImportantFilesNode(proj); | |
return NodeFactorySupport.fixedNodeList(nd); | |
} catch (DataObjectNotFoundException ex) { | |
Exceptions.printStackTrace(ex); | |
} | |
} | |
<b>//If our item isn't in the lookup, | |
//then return an empty list of nodes:</b> | |
return NodeFactorySupport.fixedNodeList(); | |
} | |
}</pre></li> | |
<li>Create a new Java class called <tt>ImportantFilesNode</tt>.</li> | |
<li><p>Change the default code to the following:</p> | |
<pre class="examplecode">public class ImportantFilesNode extends <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/FilterNode.html">FilterNode</a> { | |
private static Image smallImage = | |
ImageUtilities.loadImage("/org/netbeans/modules/importantwebfiles/webPagesBadge.gif"); // NOI18N | |
public ImportantFilesNode(Project proj) throws DataObjectNotFoundException { | |
super(DataObject.find(proj.getProjectDirectory().getFileObject("nbproject")).getNodeDelegate()); | |
} | |
public String getDisplayName() { | |
return "Important Files"; | |
} | |
<b>//Next, we add icons, for the default state, which is | |
//closed, and the opened state; we will make them the same. | |
//Icons in project logical views are | |
//based on combinations--you must combine the node's own icon | |
//with a distinguishing badge that is merged with it. Here we | |
//first obtain the icon from a data folder, then we add our | |
//badge to it by merging it via a NetBeans API utility method:</b> | |
public Image getIcon(int type) { | |
DataFolder root = DataFolder.findFolder(FileUtil.getConfigRoot()); | |
Image original = root.getNodeDelegate().getIcon(type); | |
return ImageUtilities.mergeImages(original, smallImage, 7, 7); | |
} | |
public Image getOpenedIcon(int type) { | |
DataFolder root = DataFolder.findFolder(FileUtil.getConfigRoot()); | |
Image original = root.getNodeDelegate().getIcon(type); | |
return ImageUtilities.mergeImages(original, smallImage, 7, 7); | |
} | |
}</pre> </li> | |
<li>Right-click this icon and save it in the main package of your module: <img alt="" src="../../images/tutorials/projectextensions/webPagesBadge.gif" /></li> | |
</ol> | |
<!-- ======================================================================================= --> | |
<h2><a name="extendingthecustomizer"></a>Extending the Project Customizer</h2> | |
<p>Finally, we create two new tabs in the Project Properties dialog of the web application project type.</p> | |
<ol> | |
<li><p>Create a Java class called <tt>ImportantFilesCustomizerTab</tt>.</p></li> | |
<li><p>Change the default code to the following:</p> | |
<pre class="examplecode">public class ImportantFilesCustomizerTab implements ProjectCustomizer.CompositeCategoryProvider { | |
private static final String MURPHY1 = "Murphy1"; | |
private static final String MURPHY2 = "Murphy2"; | |
private ResourceBundle bundle = NbBundle.getBundle(ImportantFilesCustomizerTab.class); | |
private String name; | |
@ProjectCustomizer.CompositeCategoryProvider.Registration(projectType = "org-netbeans-modules-web-project", position = 100) | |
public static ImportantFilesCustomizerTab createMurphy1() { | |
return new ImportantFilesCustomizerTab(MURPHY1); | |
} | |
@ProjectCustomizer.CompositeCategoryProvider.Registration(projectType = "org-netbeans-modules-web-project", position = 110) | |
public static ImportantFilesCustomizerTab createMurphy2() { | |
return new ImportantFilesCustomizerTab(MURPHY2); | |
} | |
private ImportantFilesCustomizerTab(String name) { | |
this.name = name; | |
} | |
@Override | |
public Category createCategory(Lookup lkp) { | |
ProjectCustomizer.Category toReturn = null; | |
if (MURPHY1.equals(name)) { | |
toReturn = ProjectCustomizer.Category.create( | |
MURPHY1, | |
bundle.getString("LBL_Config_Murphy1"), | |
null); | |
} else { | |
toReturn = ProjectCustomizer.Category.create( | |
MURPHY2, | |
bundle.getString("LBL_Config_Murphy2"), // NOI18N | |
null); | |
} | |
return toReturn; | |
} | |
@Override | |
public JComponent createComponent(Category category, Lookup lkp) { | |
String nm = category.getName(); | |
if (MURPHY1.equals(nm)) { | |
JPanel jPanel1 = new JPanel(); | |
jPanel1.setLayout(new BorderLayout()); | |
jPanel1.add(new JLabel(bundle.getString("LBL_Config_Murphy1")), BorderLayout.CENTER); | |
return jPanel1; | |
} else { | |
JPanel jPanel2 = new JPanel(); | |
jPanel2.setLayout(new BorderLayout()); | |
jPanel2.add(new JLabel(bundle.getString("LBL_Config_Murphy2")), BorderLayout.CENTER); | |
return jPanel2; | |
} | |
} | |
}</pre> </li> | |
<li><p>Add the keys referred to above to the <tt>Bundle.properties</tt> | |
file in the main package of your module:</p> | |
<pre class="examplecode">LBL_Config_Murphy1=Murphy 1 | |
LBL_Config_Murphy2=Murphy 2 </pre> </li> | |
</ol> | |
<!-- ===================================================================================== --> | |
<h2><a name="building"></a>Installing the Module</h2> | |
<p>Finally, we install the module and make use of the result.</p> | |
<div class="indent"> | |
<ol> | |
<li><p>Check that the module looks as follows | |
in the Projects window:</p> | |
<p><img src="../../images/tutorials/projectextensions/proj-window-69.png" alt="finished project"/></p></li> | |
<li>Right-click the module project and install it.</li> | |
<li><p>Create a new web application, or open an | |
existing one, and notice that it | |
has an Important Files node, containing the files | |
from the 'nbproject' folder:</p> | |
<p><img src="../../images/tutorials/projectextensions/result-69.png" alt="installed result"/></p></li> | |
<li><p>Right-click the web application project and choose Properties. | |
In the Project Properties dialog box, notice your new tabs:</p> | |
<p><img src="../../images/tutorials/projectextensions/proj-props-69.png" alt="installed result"/></p></li> | |
</ol> | |
</div> | |
<div class="feedback-box"><a href="https://netbeans.org/about/contact_form.html?to=3&subject=Feedback:%20Project%20Extension%20Module%20Tutorial">Send Us Your Feedback</a></div> | |
<!-- ======================================================================================== --> | |
<h2><a name="nextsteps"></a>Next Steps</h2> | |
<p>For more information about creating and developing NetBeans modules, see the following resources: </p> | |
<ul> | |
<li><a href="https://netbeans.org/kb/trails/platform.html">Other Related Tutorials</a></li> | |
<li><a href="https://netbeans.org/download/dev/javadoc/">NetBeans API Javadoc</a></li> | |
</ul> | |
</body> | |
</html> |