This tutorial lets you create a module which adds a new template to the New wizard, including a custom wizard and a custom internal executor. The template will be of a class implementing Runnable and the executor will run it. The custom wizard will add a panel permitting the user to add code to the run() method in advance. The template will also have a pleasant display name and icon.

  1. Create a module JAR and prepare a package for it as described above.
  2. Create an XML Layer (Empty) from template and place in your module package. Copy it and then Paste it beneath Layer in your module JAR to add it to the module manifest.
  3. Right-click <root folder> inside the new layer and create a new package named Templates, then a subpackage named Classes. Right-click Classes and select New | Classes | Empty to make a new Java class inside the layer, named for example RunnableImpl. It should open in the Editor.
  4. Make the Java class implement Runnable like so:
    package Templates.Classes;
    /** A class which may be run.
      * @author __USER__
      */
    public class RunnableImpl
            implements Runnable {
        public RunnableImpl() {
        }
        public void run() {
        }
    }
    
    (Note: due to problems with source synchronization inside layers, you may need to write the run() first, then make the class implement Runnable later.)

    Save the class. You should see it quoted inside the XML layer.

  5. Select the class in the Explorer and change Template to True.
  6. Create a new Internal Executor from template in your module package, named RunRunnable.
  7. Change the Bean property myProp to be named count and make it an int, default value 1. Correspondingly change the name of the descriptor in RunRunnableExecutorBeanInfo. Edit the bundle and make sure the property is labelled Count, and the executor Run Runnables.
  8. In RunRunnableExecutor, change MyInterface to Runnable in checkClass(). In executeClass(), do the same and change the work code to:
    for (int i = 0; i < count; i++) {
        thing.run();
    }
    
  9. Compile the executor classes. Copy RunRunnableExecutor and Paste beneath Service Types in the module JAR to add it to the module manifest.
  10. Save everything, and compile and execute your module right now so that the executor is registered into the system.
  11. Select RunnableImpl inside the layer and on its Execution tab set Executor to Run Runnables. You will see some odd-looking code generated in the XML layer; this associates the executor to the template. (You can also achieve the same effect manually by using methodvalue in the XML attribute; this is a shortcut.)
  12. Create a new Template Wizard from template, named RunnableTemplate. Also create a new Wizard Panel from template, named ImplementRun. Place both in your module package.
  13. Give RunnableTemplateIterator some arbitrary serialVersionUID (just pick up a big long number at random).
  14. In createPanels(), keep wiz.targetChooser() and also add a second panel, new ImplementRunPanel().
  15. In createSteps(), keep null for the standard second panel and add a second step name, NbBundle.getMessage(RunnableTemplateIterator.class, "LBL_step_run"). Make sure this step name exists in the bundle file, say Implement run().
  16. For ImplementRunPanel, make sure TITLE_WizardPanel is defined in the bundle, say Implement the run() method.
  17. We will add a text pane to the run panel to let the user enter code. You may use the Form Editor to build up the GUI; the final code should include a variable of type JEditorPane named pane and the initialization code should read something like this:
    pane = new JEditorPane();
    pane.setContentType("text/x-java");
    // This key in the bundle should say e.g.:
    // "Implement your run() method here:"
    label = new JLabel(NbBundle.getMessage
        (ImplementRunPanel.class,
         "LBL_implement_run_here"));
    add(label, BorderLayout.NORTH);
    scrollPane = new JScrollPane(pane);
    add(scrollPane, BorderLayout.CENTER);
    
    (If using the Form Editor, note that the I18N module has a setting which helps you internationalize text labels using NbBundle.)
  18. Still in ImplementRunPanel, make sure the contents of the pane are stored in the wizard, e.g.:
    private static final String PROP = "runBody";
    public void readSettings(Object o) {
        TemplateWizard wiz = (TemplateWizard)o;
        String s = (String)wiz.getProperty(PROP);
        if (s != null) pane.setText(s);
    }
    public void storeSettings(Object o) {
        TemplateWizard wiz = (TemplateWizard)o;
        wiz.putProperty(PROP, pane.getText());
    }
    
  19. Now in RunnableTemplateIterator.instantiate(), right before the code using OpenCookie, insert code like this:
    try {
        SourceCookie source = (SourceCookie)
            result.getCookie(SourceCookie.class);
        ClassElement clazz =
            source.getSource().getClasses()[0];
        MethodElement run = clazz.getMethod
            (Identifier.create("run"), new Type[0]);
        run.setBody
            ((String)wiz.getProperty("runBody"));
        SaveCookie save = (SaveCookie)
            result.getCookie(SaveCookie.class);
        save.save();
    } catch (IOException ioe) {
        throw ioe;
    } catch (Exception e) {
        IOException ioe =
            new IOException(e.toString());
        TopManager.getDefault().getErrorManager().
            annotate(ioe, e);
        throw ioe;
    }
    
  20. Compile the wizard classes.
  21. Select RunnableImpl inside the layer and switch to the Extra tab in the property sheet.
  22. Click ... on Sequence of Panels and choose RunnableTemplateIterator.
  23. Make a new HTML page in your module package. Enter some text into it like:
    Class implementing <code>Runnable</code>.
    You will be prompted to fill in its
    <code>run</code> method.
    Hit <b>Execute</b> to run it.
    
    Click ... on the template's Description URL property and select this HTML file.
  24. Replace RunRunnableExecutorIcon with an icon you like. Click ... on the template's Custom Icon property and select this icon.
  25. Click ... on the Localizing Bundle property and select the Bundle in your module's package. Select Populate Bundle... from the template's context menu. Edit the bundle key Templates/Classes/RunnableImpl.java to say Runnable Implementation.
  26. Save everything, compile and execute your module.
  27. Select File | New and under Templates | Classes you should see Runnable Implementation with your icon. Click it; you should see your HTML description. Click Next and choose a package and name for the template. Click Next and type some Java code like:
    System.out.println("Hi mom!");
    
    in the editor pane. Click Finish.
  28. You should have a class looking like this:
    package pkg.you.chose;
    /** A class which may be run.
      * @author myself
      */
    public class NameYouChose
            implements Runnable {
        public NameYouChose() {
        }
        public void run() {
            System.out.println("Hi mom!");
        }
    }
    
  29. Check that on its property sheet, Executor is set to Run Runnables. Click ... on the Executor property and with Run Runnables selected, change Count to 3. Click Execute. Hi mom! should be printed to the Output Window three times.