Exari XML Document Assembly
   
 

How to Develop Xerlin DTD Plug-ins Cookbook

Xerlin is an extensible XML editor. For a particular XML tag you can create a custom editor frame to be displayed to the user. Xerlin comes with its own default editor that allows modification of the attributes according to the DTD, this may be sufficient for your requirements but Xerlin also allows you to specify GIFs to be associated with each XML tag.

The way you customise Xerlin is to create a plugin jar file and place it in the directory where Xerlin can find it. When the user selects File/New they are presented with a list of plugin editors (one for each DTD type).

This cookbook develops a DTD plugin called exampleeditor. If all you wish to do is use the default tag editor but with your own GIFs then ignore the first two steps.

  1. Download the Xerlin source. src-root/ shown below is just a synonym for where the Xerlin code has been expanded. Under the merlot/ directory create a plugins/ directory (note there already is a plugin/ directory). Below plugins/ create exampleeditor/

    +- src-root/
       |
       +- org/
          |
          +- merlotxml/
             |
             +- merlot/
               |
               +- plugins/
                  |
                  +- exampleeditor/
                     |
                     +- ExampleEditor.java
    

  2. From the src-root/ run the command
    \jdk1.2\bin\javac -extdirs "d:\program files\merlot\merlot-1.0\lib" \
         org\merlotxml\merlot\plugins\exampleeditor\ExampleEditor.java 
    
  3. Create a jar-staging/ directory according to the tree below. Then copy the ExampleEditor.class into the classes/ directory and create the exampleeditor.dtd and plugin.xml files.

    +- jar-staging
       |
       +- classes/
       |  |
       |  +- org/
       |     |
       |     +- merlotxml/
       |        |
       |        +- merlot/
       |           |
       |           +- plugins/
       |              |
       |              +- exampleeditor/
       |                 |
       |                 +- ExampleEditor.class
       |
       +- dtd/
       |  |
       |  +- exampleeditor.dtd
       |
       +- icons/
       |  |
       |  +- large.gif
       |     small.gif
       |
       +- plugin.xml
    

  4. To create the jar file run the following command from jar-staging/

    \jdk1.2\bin\jar cvf exampleeditor.jar *

  5. Copy the exampleeditor.jar to the plugins/ directory in the runtime (installed) Xerlin directory
  6. Select New from the File menu, the exampleeditor DTD info should appear in the list of available DTDs. Whenever you create an Ingredient tag, the ExampleEditor.class is invoked (which just prints to System.out)

Code

ExampleEditor.java

package org.merlotxml.merlot.plugins.exampleeditor;

import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.beans.PropertyVetoException;
import org.merlotxml.merlot.*;
import org.merlotxml.util.xml.*;


public class ExampleEditor implements MerlotDOMEditor 
{
    /**
     * Returns a set of menu items for any special actions for 
     * this particular editor
     * that it wants in the popup menu. Standard stuff like cut, copy, paste
     * is taken care of by other objects. If nothing needs added,
     * can return null.
     * 
     * @param node the node for which to get the menu items
     */
    public  JMenuItem[] getMenuItems(MerlotDOMNode node)
    {
	return null;
    }
    
    /**
     * returns a panel for editing this type of component.
     */
    public JPanel getEditPanel(MerlotDOMNode node) 
    {
      System.out.println("Custom edit panel");
      // this function must create an *EditPanel, so just use the vanilla one
	return new GenericDOMEditPanel(node);
    }
    
    /**
     * called by the editor when the user has chosen to save their
     * changes in a panel. 
     * @param p the panel that was retreived with getEditPanel(node);
     *
     */
    public void savePanel(JPanel p)
	throws PropertyVetoException
    {
	if (p instanceof GenericDOMEditPanel) {
	    (( GenericDOMEditPanel)p).save();
	}
    }
    
	
    /**
     * Tells the edit panel it's gaining focus, so it can put the cursor in the first
     * field. XXX this should probably be handled by event listening instead
     */
    public void grabFocus(JPanel p)
    {
    }
	
    /**
     * Returns true if the component editor wants a particular node hidden
     * from the user. If the editor wants to filter 
     * what the user sees in their display, it should look at the
     * given node, otherwise it should return false. This is usefull
     * particularly if the editor handles its children. It can hide
     * the children nodes from the user's view.
     */
    public boolean suppressNode(MerlotDOMNode node) 
    {
	return false;
    }
    
    /**
     * Old deprecated way to allows the plugin to hide certain items 
     * on the add-> menu. For example, the plugin for the 
     * accessibility permissions might not
     * want the user to be able to directly add an "access" element, so
     * it can request that that be suppressed.
     */
    public boolean suppressAddType(DTDElement el)
    {
	return false;
    } 

    /**
     * New encoraged way to
     * allow the plugin to hide certain items on the add-> menu. For
     * example, the plugin for the accessibility permissions might not
     * want the user to be able to directly add an "access" element, so
     * it can request that that be suppressed.
     */
    public boolean suppressAddType(GrammarComplexType el)
    {
        return false;
    }
  
}

exampleeditor.dtd

Note that as the ExampleEditor tag has a #REQUIRED attribute this causes Xerlin to print a warning on System.err (?) when this DTD is loaded.

<?xml encoding="US-ASCII"?>

<!ELEMENT ExampleEditor (Ingredients?,Steps?)*>
<!ATTLIST ExampleEditor
  name CDATA #REQUIRED
  description CDATA #IMPLIED
  url CDATA #IMPLIED
  type (soup|main|pudding) "pudding"
>

<!ELEMENT Ingredients (Ingredient)*>
<!ATTLIST Ingredients
  name CDATA #IMPLIED
>

<!ELEMENT Ingredient EMPTY>
<!ATTLIST Ingredient
  name CDATA #IMPLIED
  amount CDATA #IMPLIED
>

<!ELEMENT Steps (Step)*>
<!ATTLIST Steps
  name CDATA #IMPLIED
>

<!ELEMENT Step EMPTY>
<!ATTLIST Step
  name CDATA #IMPLIED
  instruction CDATA #IMPLIED
>

plugin.xml

<?xml version="1.0"?>

<dtd-plugin>
	<name>Example Editor</name>
	<longName>Example Editor (cookbook example)</longName>
	<version>1.0</version>
	<author>Robert Parker</author>
	<url>http://www.cookbook.com</url>
	<dtd>
		<file>dtd/exampleeditor.dtd</file>
		<doctype>ExampleEditor</doctype>
		<publicID>-//cookbook.com//Example Editor 1.0//EN</publicID>
		<systemID>http://www.cookbook.com/dtd/exampleeditor.dtd</systemID>
	</dtd>
      <icon source="icons/large.gif" smallSource="icons/small.gif">
            <element>Ingredients</element>
            <element>Steps</element>
      </icon>
	<editor>
            <element>Ingredient</element>
            <class>org.merlotxml.merlot.plugins.exampleeditor.ExampleEditor</class>
      </editor>
	
</dtd-plugin>