NetBeans Editor 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.

Note: This is not the latest version of this document. It applies to NetBeans IDE 6.0/6.1 only. Click here to see the most up to date version.

Contents

Content on this page applies to NetBeans IDE 6.1

To follow this tutorial, you need the software and resources listed in the following table.

Software or Resource Version Required
NetBeans IDE version version 6.1 or
version 6.0
Java Developer Kit (JDK) version 6 or
version 5

Introduction to Component Palettes

In this tutorial, you first use the New File Type wizard to create the classes that enable the IDE to recognize a 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:

Completed module.

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.

Getting to Know the Sample

Take the following steps to install the sample:

  1. Unzip the attached file.

  2. 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:

    Completed projects window.

  3. Right-click the project node and choose Install/Reload in Target Platform. The target platform opens and the module is installed.

  4. 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:

    Test file.

    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.

  5. Choose Tools > Palette > JBoss Code Clips from the main menu bar, as shown below:

    New menu item.

    The Palette Manager appears, containing your new code snippets, as shown below:

    New palette manager.

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. The IDE provides a wizard that sets up all the basic files needed for a module.

  1. Choose File > New Project (Ctrl-Shift-N). Under Categories, select NetBeans 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

    In order to treat JBoss deployment descriptor files differently to all other types of files, we need to create a NetBeans data object specifically for this type of file, as well as a loader for loading our new data object.

    1. Right-click the project node and choose New > Other 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:

    Step 1 of New File wizard.

    Note the following about the fields in the File Recognition panel:

    • MIME Type. Specifies the data object's unique MIME type.
    • by
      • Filename Extension. Specifies one or more file extensions that the IDE will recognize as belonging to the specified MIME type. The file extension can optionally be preceded by a dot. Separators are commas, spaces, or both. Therefore, all of the following are valid:

        • .abc,.def
        • .abc .def
        • abc def
        • abc,.def ghi, .wow

        Note that manifests in JAR files are "MANIFEST.MF" and can be case-sensitive (at least on Unix). For this reason, you specify two MIME types in this tutorial—.mf and .MF.

      • XML Root Element. Specifies a unique namespace that distinguishes the XML file type from all other XML file types. Since many XML files have the same extension (xml), the IDE distinguishes between XML files via their XML root elements. More specifically, the IDE can distinguish between namespaces and the first XML element in XML files. In this tutorial, the distinction will be based on the XML file's doctype element.

    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.

    Step 2 of New File wizard.

    Note: If you do not have a suitable 16x16 pixel image file, you can right-click on this image, download it, and access it in the wizard above: Datasource.gif

  • Click Finish.
  • The Projects window should now look as follows:

    Final Projects window.

    Each of the newly generated files is briefly introduced:

  • JbossddDataLoader.java. Recognizes the text/x-jboss+xml MIME type. Functions as a factory for the DataObject. For more information, see What is a DataLoader?.

  • JbossddResolver.xml. Maps the MIME type to an <xml-rule> that restricts the DataLoader to only recongize XML files that match the <xml-rule>. Change the rule so that a <doc-type> defines it, as shown below (the line to be changed is highlighted below):

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE MIME-resolver PUBLIC "-//NetBeans//DTD MIME Resolver 1.0//EN" 
     "https://netbeans.org/dtds/mime-resolver-1_0.dtd">
    <MIME-resolver>
        <file>
            <ext name="xml"/>
            <resolver mime="text/x-jboss+xml">
                <xml-rule>
    		<doctype public-id="-//JBoss//DTD Web Application 2.3//EN"/>
                </xml-rule>
            </resolver>
    
        </file>
    </MIME-resolver>

  • JbossddDataObject.java. Wraps a FileObject. DataObjects are produced by DataLoaders. For more information, see What is a DataObject?.

  • JbossddDataNode.java. Provides what you see in the IDE—functionality like actions, icons, and localized names.

  • JbossddDataLoaderBeanInfo.java. Controls the appearance of the DataLoader in the Object Types section of the Options window.

  • 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.

    1. 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:
  • All source files.

  • 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 the long list of APIs that you selected have been declared as module dependencies.
  • 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 of the dropped code snippet.
    JbossddPaletteCustomizerAction Provides the menu item that opens the Palette Manager.
    JbossddPaletteDropDefault (to be done)

    To implement the NetBeans Palette API, take the following steps:

    1. 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):

      Main palette files.

    2. 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;
          }
      }

    3. 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
      
              }
          }
          
      }

    4. 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;
          }
      }

    5. 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);
              }
          }
      
      }

    6. 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;
          }
      
      }

    7. 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):

    Main palette files.


    Registering the Module

    In this section, we register the menu item and code snippets in the layer.xml file and in the Bundle.properties file.

    1. 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>

    2. 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.

    Reusing Code Snippets from Other Palettes

    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, take the steps below.

    1. 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
    2. 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>
    3. 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

    1. 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.

    2. Verify that the module is correctly installed by using it as shown in Installing the Sample.

    Creating a Shareable Module Binary

    1. In the Projects window, right-click the the project node and choose Create NBM.

    The NBM file is created and you can view it in the Files window (Ctrl-2):

    Shareable NBM.

  • Make the module available to others via, for example, e-mail.

  • The recipient can install the module by using the Plugin Manager. Choose Tools > Plugins from the main menu.


    Next Steps

    For more information about creating and developing NetBeans modules, see the following resources:

  • Other Related Tutorials
  • NetBeans API Javadoc

  • 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.
    5 30 May 2007 Began updating this tutorial for 6.0.

    Project Features

    Project Links

    About this Project

    Platform was started in November 2009, is owned by Antonin Nebuzelsky, and has 138 members.
    By use of this website, you agree to the NetBeans Policies and Terms of Use (revision 20131025.e7cbc9d). © 2013, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo
     
     
    Close
    loading
    Please Confirm
    Close