Step by step

To build a new modeler as the sample modeler, first download the Java Abstract Modeler. After you download it, create a new project in your favorite IDE and import/use abstractModeler.jar in this project.

Basicaly, all you need is to create your classes to represent both your specific business object and its visual representation, the visual item. More specifically, the abstract modeler need you to provide:

  • Your business objects
  • Your items (visual representation of your business objects)
  • The new item factories (to link business objects and items)
  • The palette creation tool for your specific objects
  • The update panels to be used by the generic UpdateTool
  • The PaletteToolProvider that defines the tools to display in the palette
  • The controller that use a PaletteToolProvider and holds the link between the above
  • The applet that displays your modeler

The new business object

In the SampleModeler, we added a single business object definition:

package org.ericmignot.modeler.sample.data;

import org.ericmignot.modeler.helpers.data.DefaultBusinessObject;

public class SimpleBusinessObject extends DefaultBusinessObject
{
    public static final String FIELD_NAME = "Name";
    
    private String name;

    public SimpleBusinessObject()
    {
        this.setName(null);        
    }
    
    public String getName() 
    {
        return name;
    }

    public void setName(String name) 
    {
        this.name = name;
        this.fireUpdated();
    }
    
    /**
     * Manages Name field name
     * @param fieldName
     * @param fieldValue
     * @return true if the field was set, false otherwise
     */
    public boolean setFieldValue(String fieldName, String fieldValue)
    {
        if (FIELD_NAME.equalsIgnoreCase(fieldName))
        {
            this.setName(fieldValue);
            return true;
        }
        return super.setFieldValue(fieldName, fieldValue);
    }
    public String getFieldValue(String fieldName)
    {
        if (FIELD_NAME.equalsIgnoreCase(fieldName))
        {
            return this.getName();
        }
        return super.getFieldValue(fieldName);
    }
    
    protected String getParamsXML()
    {
        String toReturn = super.getParamsXML() ;
        if (this.getName() != null)
        {
            toReturn +=
            "<Param Name='Name' Value='" + this.getName() + "' /> ;
        }
        return toReturn;
    }
}

The new items

In the SampleModeler, we added a single item definition:

package org.ericmignot.modeler.sample.gui.workarea;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;

import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;

import org.ericmignot.modeler.data.BusinessObject;
import org.ericmignot.modeler.gui.palette.UpdatePanel;
import org.ericmignot.modeler.helpers.gui.workarea.DefaultItem;
import org.ericmignot.modeler.sample.data.SimpleBusinessObject;
import org.ericmignot.modeler.sample.gui.palette.SimpleUpdatePanel;

public class SimpleItem extends DefaultItem
{
    private JLabel nameLabel;
    private static int NOMINAL_FONT_SIZE = 12;

    public SimpleItem()
    {
        this.setLayout(new BorderLayout());
        this.nameLabel = new JLabel();
        this.nameLabel.setOpaque(true);
        this.nameLabel.setHorizontalTextPosition(SwingConstants.CENTER);
        this.add(this.nameLabel, BorderLayout.CENTER);
        this.setBorder(new LineBorder(Color.black));
    }
    
    public JLabel getNameLabel()
    {
        return this.nameLabel;
    }
    
    
    public void zoomChanged()
    {
        int fontSize = (int) (NOMINAL_FONT_SIZE * this.getWorkArea().getZoomFactor());
        Font font = new Font("Arial", Font.PLAIN, fontSize);
        this.nameLabel.setFont(font);
    }
    
    public void businessObjectUpdatedImpl(BusinessObject businessObject)
    {
        this.nameLabel.setText(((SimpleBusinessObject) businessObject).getName());
    }
    
    public UpdatePanel createUpdatePanel() 
    {
        return new SimpleUpdatePanel();
    }

}

The item factory

In the SampleModeler, only one factory is needed:

package org.ericmignot.modeler.sample.gui.workarea;

import org.ericmignot.modeler.data.BusinessObject;
import org.ericmignot.modeler.gui.workarea.Item;
import org.ericmignot.modeler.gui.workarea.ItemFactory;
import org.ericmignot.modeler.gui.workarea.WorkArea;

public class SimpleItemFactory implements ItemFactory
{

    /**
     * 
     * @param businessObject assumed to be a SimpleBusinessObject
     * @return an instance of SimpleItem
     */
    public Item[] createModelerItems(BusinessObject businessObject, WorkArea workArea)
    {
        Item[] toReturn = new Item[1];
        toReturn[0] = new SimpleItem();
        toReturn[0].setBusinessObject(businessObject);
        return toReturn;
    }
}

The palette creation tool

In the SampleModeler, the creation tool for the SimpleItem:

package org.ericmignot.modeler.sample.gui.palette;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;

import javax.swing.Icon;
import javax.swing.JToggleButton;

import org.ericmignot.modeler.data.BusinessObject;
import org.ericmignot.modeler.data.Model;
import org.ericmignot.modeler.gui.StaticValues;
import org.ericmignot.modeler.gui.palette.AbstractCreationTool;
import org.ericmignot.modeler.sample.data.SimpleBusinessObject;
import org.ericmignot.modeler.util.graphic.FixedSquaredSizePanel;
import org.ericmignot.modeler.util.graphic.GraphicHelper;

public class SimpleItemCreationTool extends AbstractCreationTool 
{
    private static long NEW_ID = -1;
    
    private JToggleButton button;
    private int x;
    private int y;
    private Dimension halfSize;

    public SimpleItemCreationTool()
    {
        this.button = new JToggleButton(
                "New", 
                new NewSimpleItemIcon());
        this.setHalfSize(new Dimension(50, 25));
    }
    
    public Dimension getHalfSize() 
    {
        return halfSize;
    }

    public void setHalfSize(Dimension size) 
    {
        this.halfSize = size;
    }
    public void setHalfSize(int x, int y) 
    {
        this.halfSize = new Dimension(x, y);
    }

    public JToggleButton getButton() 
    {
        return this.button;
    }
    
    public void workAreaReleased(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public BusinessObject buildBusinessObject()
    {
        SimpleBusinessObject bo = new SimpleBusinessObject();
        bo.setCenter(new Point(this.x, this.y));
        bo.setHalfSize(this.getHalfSize());        
        // computing new negative id
        Model model = this.getController().getModel();
        while (model.getBusinessObjectById(bo.getClass().getName(), NEW_ID) != null)
        {
            NEW_ID --;
        }
        bo.setId(NEW_ID);
        bo.setName("New " + NEW_ID);
        return bo;
    }

    private class NewSimpleItemIcon implements Icon 
    {
        private FixedSquaredSizePanel panel;
        private int size;
        
        public NewSimpleItemIcon()
        {
            this.size = 20;
            this.panel = new FixedSquaredSizePanel(
                    GraphicHelper.buildColor(StaticValues.getInstance().get("Design.WorkArea.BackgroundColor", "236, 233, 216")), 
                    Color.black, 
                    14);
            this.panel.setSize(this.size, this.size);
        }
        
        public int getIconWidth()
        {
            return this.size;
        }
        
        public int getIconHeight()
        {
            return this.size;
        }
        
        public void paintIcon(Component c, Graphics g, int x, int y)
        {
            g.translate(x, y);
            this.panel.paintComponent(g);
            g.translate(-x, -y);
        }


    }

}

The update panel

In the SampleModeler, we need only one UpdatePanel to update the SimpleItem fields :

package org.ericmignot.modeler.sample.gui.palette;

import java.awt.BorderLayout;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import org.ericmignot.modeler.gui.palette.UpdatePanel;
import org.ericmignot.modeler.sample.data.SimpleBusinessObject;

public class SimpleUpdatePanel extends UpdatePanel
{
    private JTextField nameField;
    
    private SimpleBusinessObject getSimpleBusinessObject()
    {
        return (SimpleBusinessObject) this.getBusinessObject();
    }

    protected JPanel getSpecificPanel() 
    {        
        JLabel nameLabel = new JLabel("Name : ");
        nameField = new JTextField(this.getSimpleBusinessObject().getName(), 20);
        
        JPanel toReturn = new JPanel(new BorderLayout());
        toReturn.add(nameLabel, BorderLayout.WEST);
        toReturn.add(nameField, BorderLayout.CENTER);
        
        return toReturn;
    }
    
    public JTextField getNameField()
    {
        return this.nameField;
    }

    protected Map getNewValues() 
    {
        Map toReturn = new HashMap();
        toReturn.put (SimpleBusinessObject.FIELD_NAME, this.nameField.getText());
        return toReturn;
    }

}

The PaletteToolProvider

In the SampleModeler, we both use our new tool to create SimpleBusinessObjects and the default tools provided by the AbstractModeler

package org.ericmignot.modeler.sample.gui.palette;

import org.ericmignot.modeler.gui.palette.DeleteTool;
import org.ericmignot.modeler.gui.palette.LinkCreationTool;
import org.ericmignot.modeler.gui.palette.MoveTool;
import org.ericmignot.modeler.gui.palette.PaletteTool;
import org.ericmignot.modeler.gui.palette.PaletteToolProvider;
import org.ericmignot.modeler.gui.palette.SimplePointCreationTool;
import org.ericmignot.modeler.gui.palette.UpdateTool;

public class SamplePaletteToolProvider implements PaletteToolProvider 
{

    public PaletteTool[] getPaletteTools()
    {
        PaletteTool[] toReturn = new PaletteTool[]
        {
                new MoveTool(),
                new SimpleItemCreationTool(),
                new LinkCreationTool(),
                new SimplePointCreationTool(),
                new DeleteTool(),
                new UpdateTool()
        };

        return toReturn;
    }
}

The controller

In the SampleModeler, we use our specific factory for SimpleItem and the generic factories provided by the AbstractModeler to create the links and the points in the link line

package org.ericmignot.modeler.sample.gui;

import org.ericmignot.modeler.data.Link;
import org.ericmignot.modeler.data.SimplePoint;
import org.ericmignot.modeler.gui.Controller;
import org.ericmignot.modeler.gui.workarea.LinkItemFactory;
import org.ericmignot.modeler.gui.workarea.PointItemFactory;
import org.ericmignot.modeler.sample.data.SimpleBusinessObject;
import org.ericmignot.modeler.sample.gui.palette.SamplePaletteToolProvider;
import org.ericmignot.modeler.sample.gui.workarea.SimpleItemFactory;

public class SampleController extends Controller 
{

    public SampleController()
    {
        this.setItemFactory(SimpleBusinessObject.class, new SimpleItemFactory());
        this.setItemFactory(SimplePoint.class, new PointItemFactory());
        this.setItemFactory(Link.class, new LinkItemFactory());        
        
        this.setPaletteToolProvider(new SamplePaletteToolProvider());
    }

}

The applet

<APPLET 
        archive="sampleModeler.jar, abstractModeler.jar" 
        id="myApplet" 
        code="org.ericmignot.modeler.sample.gui.SampleApplet.class" 
        codebase="." 
        width="700" height="400" 
        MAYSCRIPT
        >
</Applet>