NetBeans Component Palette Module Tutorial
This tutorial demonstrates how to create a component palette that provides drag-and-drop code snippets
for a new file type. Code snippets serve to speed up coding. The IDE provides a component palette for JSP files,
HTML files, and Form files. In this tutorial, you learn how to create a component palette for a different file type—one
that is not recognized by the IDE by default. First, you use the New File Type wizard to enable the IDE to recognize
the new file type. Then, you implement several classes provided by the
NetBeans Palette API.
Finally, you register the new component palette in the layer.xml file.
The component palette that you create in this tutorial will be used by the JBoss deployment descriptor file (jboss-web.xml).
The jboss-web.xml file is distinguished from all other XML files by its namespace:
<!DOCTYPE jboss-web
PUBLIC "-//JBoss//DTD Web Application 2.3//EN"
"http://www.jboss.org/j2ee/dtd/jboss-web_3_0.dtd">
The component palette that you create in this tutorial will only be visible when a file with the namespace above
is open in the IDE's Source Editor. For these files only, the component palette will include code snippets for three typical elements in
a jboss-web.xml file: "Context Root", "Security Domain",
and "Resource Reference". As shown below, the tooltip will display the tags that will be inserted at the cursor in the Source Editor
when the code snippet is dragged-and-dropped:
If you do not want to create a new component palette, but only want to add a code snippet to an existing component palette,
see the NetBeans Code Snippet Module Tutorial.
The following topics are covered below:
Once the software is installed, this tutorial can be completed in 45 minutes.
For more information on working with modules, see the
NetBeans Development Project home on the NetBeans website. If you have questions, visit the
NetBeans Developer FAQ or use the feedback link
at the top of this page.
Installing the Software
Before you begin, you need to install the following software on your
computer:
Installing the Sample
Take the following steps to install the sample:
- Unzip the attached file.
- In the IDE, choose File > Open Project and browse to the folder that contains the unzipped file.
Open the module project. It should look as follows:
- Right-click the project node and choose Install/Reload in Target Platform. The target
platform opens and the module is installed.
- Verify that the module is correctly installed by opening the Files window (Ctrl-2) and
double-clicking the test-jboss-web.xml file that you find there:
The file opens in the Source Editor and the component palette opens, and displays three code snippets, as
in the screenshot shown in the introduction of this tutorial.
If the component palette does not open automatically, press Ctrl-Shift-8 to open it manually.
- Choose Tools > Palette Manager from the main menu bar, as shown below:
The Palette Manager appears, containing your new code snippets, as shown below:
Now that you know what the end result looks like, you will create the module from scratch and learn about each part
while creating it.
Setting up the Module Project
Before you start writing the module, you have to make sure you
that your project is set up correctly. NetBeans IDE 5.x provides a wizard that sets up all the basic files
needed for a module.
- Choose File > New Project (Ctrl-Shift-N). Under Categories, select NetBeans Plug-in Modules. Under projects,
select Module Project and click Next.
- In the Name and Location panel, type jbosswebxml in Project Name.
Change the
Project Location to any directory on your computer, such as c:\mymodules. Leave the Standalone Module radiobutton
and the Set as Main Project checkbox selected.
Click Next.
- In the Basic Module Configuration panel, replace yourorghere in Code Name Base with org.netbeans.modules,
so that the whole code name base is org.netbeans.modules.jbosswebxml.
Leave the location of the localizing bundle and XML layer, so that they will be stored in a
package with the name org/netbeans/modules/jbosswebxml. Click Finish.
The IDE creates the jbosswebxml
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).
Recognizing the New File Type
- Right-click the project node and
choose New > File/Folder and then, in the NetBeans Module Development
category, choose File Type. Click Next.
- In the File Recognition panel, do the following:
- Type text/x-jboss+xml in the MIME Type edit box.
- Type public-id="-//JBoss//DTD Web Application 2.3//EN" in the by XML Root Element edit box.
The File Recognition panel should now look as follows:
Note the following about the fields in the File Recognition panel:
Click Next.
- In the Name and Location panel, type jbossdd as the Class Name Prefix
and browse to any 16x16 pixel image file as the new file type's icon, as shown below.
Note that several
16x16 pixel image files are found within your NetBeans installation directory, for example, in this
location:
enterprise2\jakarta-tomcat-5.5.7\server\webapps\admin\images.
For example, you could use the Datasource.gif image in the above directory.
This is what it looks like:
- Click Finish.
The Projects window should now look as follows:

Each of the newly generated files is briefly introduced:
Creating the Component Palette and Code Snippets
Specifying the Module's Dependencies
You will need to subclass several classes that belong to NetBeans APIs.
Each has to be declared as a Module dependency. Use the Project Properties dialog box for this purpose.
- In the Projects window, right-click the jbosswebxml project node and choose Properties.
In the Project Properties dialog box, click Libraries.
- For each of the following APIs, click "Add...",
select the name from the Module list, and then click OK to confirm it:
- Click OK to exit the Project Properties dialog box.
- In the Projects window, expand the Important Files node, double-click the Project Metadata node, and note that the APIs you selected have been
declared as Module dependencies:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.apisupport.project</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/nb-module-project/2">
<code-name-base>org.netbeans.modules.jbosswebxml</code-name-base>
<standalone/>
<module-dependencies>
<dependency>
<code-name-base>org.netbeans.modules.editor.lib</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.9.0.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.modules.projectapi</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.9</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.spi.palette</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>0</release-version>
<specification-version>1.5</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.dialogs</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.4</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.filesystems</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.4</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.loaders</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>5.9</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.nodes</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.7</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.text</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.9</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.util</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.8</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.windows</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.5</specification-version>
</run-dependency>
</dependency>
</module-dependencies>
<public-packages/>
</data>
</configuration>
</project>
Creating the Component Palette
Component Palettes are defined
by the NetBeans Palette API.
Implementing the NetBeans Palette API for this tutorial means implementing the following NetBeans Palette API classes:
|
File
|
Description
|
| PaletteFactory |
Creates a new instance of the Component Palette. To do so, it invokes
the createPalette method which creates a new palette from the JBOSSPalette folder, which is defined
in the layer.xml file. |
| PaletteController |
Provides access to data in the Component Palette. |
| PaletteActions |
(to be done)
|
In addition, you will also create the following supporting classes:
|
File
|
Description
|
| jbossddPaletteUtilities |
Handles insertion and formatting of the dropped code snippet, by implementing two NetBeans API classes:
|
| jbossddPaletteCustomizerAction |
Provides the menu item that opens the Palette Manager:
|
| jbossddPaletteDropDefault |
(to be done)
|
To implement the NetBeans Palette API,
take the following steps:
- Right-click the org.netbeans.modules.jbosswebxml project node and
choose New > Java Class. Create the first of the following files, type
org.netbeans.modules.jbosswebxml.palette in the package drop-down list,
click Finish, and then repeat the process to create the others:
- jbossddPaletteActions
- jbossddPaletteCustomizerAction
- jbossddPaletteDropDefault
- jbossddPaletteFactory
- jbossddPaletteUtilities
You should now have the following files (highlighted in the screenshot below):
- Replace the default content of the jbossddPaletteFactory.java file with the following:
package org.netbeans.modules.jbosswebxml.palette;
import java.io.IOException;
import org.netbeans.spi.palette.PaletteController;
import org.netbeans.spi.palette.PaletteFactory;
public class jbossddPaletteFactory {
public static final String JBOSS_PALETTE_FOLDER = "JBOSSPalette";
private static PaletteController palette = null;
public static PaletteController getPalette() throws IOException {
if (palette == null)
palette = PaletteFactory.createPalette(JBOSS_PALETTE_FOLDER, new jbossddPaletteActions());
return palette;
}
}
- Replace the default content of the jbossddPaletteActions.java file with the following:
package org.netbeans.modules.jbosswebxml.palette;
import java.awt.event.ActionEvent;
import java.io.IOException;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.text.JTextComponent;
import org.netbeans.editor.Utilities;
import org.netbeans.spi.palette.PaletteActions;
import org.netbeans.spi.palette.PaletteController;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.text.ActiveEditorDrop;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
public class jbossddPaletteActions extends PaletteActions {
/** Creates a new instance of jbossddPaletteActions */
public jbossddPaletteActions() {
}
public Action[] getImportActions() {
return new Action[0]; //TODO implement this
}
public Action[] getCustomCategoryActions(Lookup category) {
return new Action[0]; //TODO implement this
}
public Action[] getCustomItemActions(Lookup item) {
return new Action[0]; //TODO implement this
}
public Action[] getCustomPaletteActions() {
return new Action[0]; //TODO implement this
}
public Action getPreferredAction( Lookup item ) {
return new MFPaletteInsertAction(item);
}
private static class MFPaletteInsertAction extends AbstractAction {
private Lookup item;
MFPaletteInsertAction(Lookup item) {
this.item = item;
}
public void actionPerformed(ActionEvent e) {
ActiveEditorDrop drop = (ActiveEditorDrop) item.lookup(ActiveEditorDrop.class);
JTextComponent target = Utilities.getFocusedComponent();
if (target == null) {
String msg = NbBundle.getMessage(jbossddPaletteActions.class, "MSG_ErrorNoFocusedDocument");
DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(msg, NotifyDescriptor.ERROR_MESSAGE));
return;
}
try {
drop.handleTransfer(target);
}
finally {
Utilities.requestFocus(target);
}
try {
PaletteController pc = jbossddPaletteFactory.getPalette();
pc.clearSelection();
}
catch (IOException ioe) {
} //should not occur
}
}
}
- Replace the default content of the jbossddPaletteUtilities.java file with the following:
package org.netbeans.modules.jbosswebxml.palette;
import java.awt.Component;
import java.awt.Container;
import java.util.StringTokenizer;
import javax.swing.JTree;
import javax.swing.text.BadLocationException;
import javax.swing.text.Caret;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.Sources;
import org.netbeans.editor.BaseDocument;
import org.netbeans.editor.Formatter;
import org.openide.filesystems.FileObject;
public class jbossddPaletteUtilities {
/** Creates a new instance of jbossddPaletteUtilities */
public jbossddPaletteUtilities() {
}
public static void insert(String s, JTextComponent target)
throws BadLocationException {
insert(s, target, true);
}
public static void insert(String s, JTextComponent target, boolean reformat)
throws BadLocationException {
if (s == null)
s = "";
Document doc = target.getDocument();
if (doc == null)
return;
if (doc instanceof BaseDocument)
((BaseDocument)doc).atomicLock();
int start = insert(s, target, doc);
if (reformat && start >= 0 && doc instanceof BaseDocument) { // format the inserted text
int end = start + s.length();
Formatter f = ((BaseDocument)doc).getFormatter();
f.reformat((BaseDocument)doc, start, end);
}
if (doc instanceof BaseDocument)
((BaseDocument)doc).atomicUnlock();
}
private static int insert(String s, JTextComponent target, Document doc)
throws BadLocationException {
int start = -1;
try {
//at first, find selected text range
Caret caret = target.getCaret();
int p0 = Math.min(caret.getDot(), caret.getMark());
int p1 = Math.max(caret.getDot(), caret.getMark());
doc.remove(p0, p1 - p0);
//replace selected text by the inserted one
start = caret.getDot();
doc.insertString(start, s, null);
} catch (BadLocationException ble) {}
return start;
}
}
- Replace the default content of the jbossddPaletteCustomizerAction.java file with the following:
package org.netbeans.modules.jbosswebxml.palette;
import java.io.IOException;
import org.openide.ErrorManager;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
public class jbossddPaletteCustomizerAction extends CallableSystemAction {
private static String name;
public jbossddPaletteCustomizerAction () {
putValue("noIconInMenu", Boolean.TRUE); // NOI18N
}
protected boolean asynchronous() {
return false;
}
/** Human presentable name of the action. This should be
* presented as an item in a menu.
* @return the name of the action
*/
public String getName() {
if (name == null)
name = NbBundle.getBundle(jbossddPaletteCustomizerAction.class).getString("ACT_OpenjbossddCustomizer"); // NOI18N
return name;
}
/** Help context where to find more about the action.
* @return the help context for this action
*/
public HelpCtx getHelpCtx() {
return null;
}
/** This method is called by one of the "invokers" as a result of
* some user's action that should lead to actual "performing" of the action.
*/
public void performAction() {
try {
jbossddPaletteFactory.getPalette().showCustomizer();
}
catch (IOException ioe) {
ErrorManager.getDefault().notify(ErrorManager.EXCEPTION, ioe);
}
}
}
- Replace the default content of the jbossddPaletteDropDefault.java file with the following:
package org.netbeans.modules.jbosswebxml.palette;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import org.openide.text.ActiveEditorDrop;
public class jbossddPaletteDropDefault implements ActiveEditorDrop {
String body;
public jbossddPaletteDropDefault(String body) {
this.body = body;
}
public boolean handleTransfer(JTextComponent targetComponent) {
if (targetComponent == null)
return false;
try {
jbossddPaletteUtilities.insert(body, (JTextComponent)targetComponent);
}
catch (BadLocationException ble) {
return false;
}
return true;
}
}
- Right-click the org.netbeans.modules.jbosswebxml.palette node, choose New > File/Folder,
and select Properties File from the Other category. Click Next. Name the file Bundle and then click Finish.
Add the following keys to the new Bundle.properties file:
MSG_ErrorNoFocusedDocument=No document selected. Please select a document to insert the item into.
ACT_OpenJbossddCustomizer=&JBoss Code Clips
Creating the Code Snippets
Each code snippet requires the following files:
- A Java class that defines the piece of code to be dragged into the Source Editor. This Java class
must refer to jbossddPaletteUtilities.java, which defines how the piece of code should be
inserted. For example, indentation and formatting are defined here.
- A properties file that defines the labels and tooltips.
- A 16x16 pixel image for the 'Small Icon' display.
- A 32x32 pixel image for the 'Big Icon' display.
After you have created or added the above files to the NetBeans module, you declare them in a resource declaration XML file,
which you register in the NetBeans System Filesystem by using the layer.xml file.
For details on all of the items above, work through the NetBeans Code Snippet Module Tutorial.
As an example,
when you create three code snippets called ContextRoot.java, ResourceReference.java, and
SecurityDomain.java, the result might be as follows (the highlighted packages below contain the code snippets and
their supporting resources):
Registering the Module
- Add the following tags to the layer.xml file:
<folder name="Menu">
<folder name="Tools">
<folder name="PaletteManager">
<file name="org-netbeans-modules-jbosswebxml-palette-jbossddPaletteCustomizerAction.instance"/>
</folder>
</folder>
</folder>
<folder name="JBOSSPalette">
<folder name="JBoss">
<attr name="SystemFileSystem.localizingBundle"
stringvalue="org.netbeans.modules.jbosswebxml.palette.Bundle"/>
<file name="ContextRoot.xml"
url="nbresloc:/org/netbeans/modules/jbosswebxml/palette/items/resources/ContextRoot.xml"/>
<file name="SecurityDomain.xml"
url="nbresloc:/org/netbeans/modules/jbosswebxml/palette/items/resources/SecurityDomain.xml"/>
<file name="ResourceReference.xml"
url="nbresloc:/org/netbeans/modules/jbosswebxml/palette/items/resources/ResourceReference.xml"/>
</folder>
</folder>
- Add the following to the Bundle.properties file that is in the same package as
the layer.xml file:
JBOSSPalette/JBoss=JBoss Deployment Descriptor
JBOSSPalette/JBoss/ContextRoot.xml=Context Root
JBOSSPalette/JBoss/ResourceReference.xml=Resource Reference
JBOSSPalette/JBoss/SecurityDomain.xml=Security Domain
The key-value pairs listed above localize the items registered in the layer.xml file.
- Optionally, you can merge your collection of code snippets with the code snippets provided
by other modules. For example, if you want to merge your code snippets so that the jboss-web.xml file has
access to the code snippets provided by the JSP module and the HTML module, do the following:
- In org.netbeans.modules.jbosswebxml.palette, change the value for
the ACT_OpenJbossddCustomizer so that it matches the names of the same action
provided by the HTML module and the JSP module:
ACT_OpenJbossddCustomizer=&HTML/JSP Code Clips
- Hide the other two actions (the action in the
HTML module and the JSP module that displays the JSP/HTML Code Clips
Palette Manager) by adding the two lines in bold below to the layer.xml file:
<folder name="Menu">
<folder name="Tools">
<folder name="PaletteManager">
<file name="org-netbeans-modules-jbosswebxml-palette-jbossddPaletteCustomizerAction.instance"/>
<file name="org-netbeans-modules-html-palette-HTMLPaletteCustomizerAction.instance_hidden"/>
<file name="org-netbeans-modules-web-core-palette-JSPPaletteCustomizerAction.instance_hidden"/>
</folder>
</folder>
</folder>
- Finally, declare the resource declaration XML files of the HTML module and the JSP module as
shadow files:
<folder name="JBOSSPalette">
<folder name="JBoss">
<attr name="SystemFileSystem.localizingBundle"
stringvalue="org.netbeans.modules.jbosswebxml.Bundle"/>
<file name="ContextRoot.xml"
url="ContextRoot.xml"/>
<file name="ResourceReference.xml"
url="ResourceReference.xml"/>
<file name="SecurityDomain.xml"
url="SecurityDomain.xml"/>
</folder>
<folder name="HTML.shadow">
<attr name="SystemFileSystem.localizingBundle"
stringvalue="org.netbeans.modules.web.core.palette.Bundle"/>
<attr name="originalFile"
stringvalue="HTMLPalette/HTML"/>
</folder>
<folder name="HTML_Forms.shadow">
<attr name="SystemFileSystem.localizingBundle"
stringvalue="org.netbeans.modules.web.core.palette.Bundle"/>
<attr name="originalFile"
stringvalue="HTMLPalette/HTML_Forms"/>
</folder>
<folder name="JSP.shadow">
<attr name="SystemFileSystem.localizingBundle"
stringvalue="org.netbeans.modules.web.core.palette.Bundle"/>
<attr name="originalFile"
stringvalue="JSPPalette/JSP"/>
</folder>
<folder name="Database.shadow">
<attr name="SystemFileSystem.localizingBundle"
stringvalue="org.netbeans.modules.web.core.palette.Bundle"/>
<attr name="originalFile"
stringvalue="JSPPalette/Database"/>
</folder>
</folder>
Now, when you build and install the module, as described in the next section, the Component Palette for
jboss-web.xml files will contain all the code snippets provided by the JSP module
as well as all the code snippets provided by the HTML module.
Building and Installing the Module
The IDE uses an Ant build script to build and install your module. The build script is created for you
when you create the module project.
Installing and Using the Module
- In the Projects window, right-click the jbosswebxml project and choose Install/Reload
in Target Platform.
The module is built and installed in the target platform. The target platform opens so that you
can try out your new module. The default target platform is the
installation used by the current instance of the development IDE.
- Verify that the module is correctly installed by using it as
shown in Installing the Sample.
Creating a Shareable Module Binary
- In the Projects window, right-click the newhtmlsnippet project and choose Create NBM.
The NBM file is created and you can view it in the Files window (Ctrl-2):
- Make the module available to others via, for example, e-mail.
- The recipient can install the module by using the Update Center. Choose Tools > Update Center
from the main menu.
Next Steps
For more information about creating and developing NetBeans modules, see the following resources:
Versioning
|
Version
|
Date
|
Changes
|
Open Issues
|
|
1
|
29 November 2005
|
Initial version
|
- Needs to be reviewed! Use at your own risk!
- Need to add explanation for adding own dialog box for predefining values.
- Explanatory text for the use of the NetBeans APIs to be added.
- Check for copy-paste errors.
- Need to add more Javadoc links, for NetBeans API classes in the code.
|
|
2
|
30 November 2005
|
Changed the ZIP file because of problems (see Issue 69571).
Removed hyphens and changed screenshots.
|
All other issues from above must still be done.
|
|
3
|
8 December 2005
|
Fixed reopened issue Issue 69571
|
All other issues from above must still be done.
|
|
|
4
|
22 August 2006
|
Minor tweaks.
All other issues from above must still be done.
Discovered that the editor support file is missing in the tutorial,
but not in the module that you can download from the top of the file.
Discovered that there are several gaps and tbds in this tutorial.
|
|
|
|