Writing a Tool Plugin

Preliminaries

A tool is a mechanism to edit a graph. All currently available tools can be selected via buttons which are located on the vertical tool bar called mode which is located at the left side of a view window.
This document explains how a new tool can be realized using the plugin mechanism of Gravisto. For the following example(s) it is necessary to have Graffiti_Core and Graffiti_Editor in your classpath.

Getting Started

Like for every plugin it is assumed that you provide a valid plugin description file first. This description file must also declare its dependency to Gravisto's Default Edit Mode plugin, because the mode to which this tool should be added must be loaded first by the plugin manager:

<plugin>

    ...

    <deps>
        <plugindesc>
            <name>Default Edit Mode</name>
            <main>org.graffiti.plugins.modes.defaultEditMode.DefaultEditModePlugin</main>
            <version>1.0.0</version>
            <available></available>
        </plugindesc>
    </deps>
</plugin>
      

The next step is creating a new plugin adapter, e.g. TestToolPlugin. For a tool plugin which is member of the package de.chris.plugins.tools.test it looks similar to the following:

package de.chris.plugins.tools.test;

import org.graffiti.core.ImageBundle;
import org.graffiti.plugin.EditorPluginAdapter;
import org.graffiti.plugin.gui.GraffitiComponent;
import org.graffiti.plugin.tool.Tool;

public class ToolsTestPlugin
    extends EditorPluginAdapter
{
    private ImageBundle iBundle = ImageBundle.getInstance();

    public ToolsTestPlugin()
    {
        this.tools = new Tool[1];
        this.tools[0] = new TestTool();
        
        this.guiComponents = new GraffitiComponent[1];
        this.guiComponents[0] = new TestToolButton(tools[0]);
    }
}
      

Because a single tool plugin can contain more than tools, the inherited member array tools can be filled with an arbitrary number of tool objects. For this ever tool must implement the interface org.graffiti.plugin.tool.Tool interface.
Additionally, the above example adds a new button which is used for activating TestTool. See HOWTO: Writing a GUI Plugin for details on that topic.

Writing a Tool

The following is the code of an example tool which gives the node on which the users clicks a random color:

package de.chris.plugins.tools.test;

import java.awt.Component;
import java.awt.event.MouseEvent;

import javax.swing.SwingUtilities;

import org.graffiti.graph.GraphElement;
import org.graffiti.graph.Node;

import org.graffiti.plugin.tool.AbstractTool;
import org.graffiti.plugin.view.GraphElementComponent;

import org.graffiti.session.Session;

public class TestTool
    extends AbstractTool
{
    public void mousePressed(MouseEvent e)
    {
        if(!SwingUtilities.isLeftMouseButton(e))
        {
            return;
        }

        System.out.println("left clicked");

        Component clickedComp = ((Component) e.getSource()).getComponentAt(e.getPoint());

        if(clickedComp instanceof GraphElementComponent)
        {
            System.out.println("clicked on a graph element");

            GraphElement ge = ((GraphElementComponent) clickedComp).getGraphElement();

            if(ge instanceof Node)
            {
                Node n = (Node) ge;
                System.out.println("clicked on a node");
                n.setInteger("graphics.fillcolor.red",
                    (int) Math.round(Math.random() * 255));
                n.setInteger("graphics.fillcolor.green",
                    (int) Math.round(Math.random() * 255));
                n.setInteger("graphics.fillcolor.blue",
                    (int) Math.round(Math.random() * 255));
            }
        }
    }

    public void sessionDataChanged(Session s)
    {
    }
}
      

The class TextTool is derived from org.graffiti.plugin.tool.AbstractTool which is an implementation of org.graffiti.plugin.tool.Tool. If you are planing to add undo functionality to your tool, you should take AbstractUndoableTool instead.
TextTool is automatically a mouse listener and overwrites mousePressed to be notified when the user has pressed a mouse button. After assuring this was a left click and the component under the mouse cursor was a node it colors this node. The method sessionDataChanged needs to be overwritten because every tool is automatically SessionListener which demands this. For our purposes we need not to do here anything.

Adding a Tool Button

Now we need some gui component for activating our tool. The default for every tool should be a toggle button on the vertical mode bar. Therefore we use the following code which is added to GuiComponentsTestPlugin::guiComponents[0]:

package de.chris.plugins.tools.test;

import javax.swing.ImageIcon;

import org.graffiti.plugin.gui.ToolButton;
import org.graffiti.plugin.tool.Tool;

public class TestToolButton
    extends ToolButton
{
    public TestToolButton(Tool tool)
    {
        super(tool, "org.graffiti.plugins.modes.defaultEditMode",
            new ImageIcon(TestToolButton.class.getResource("smiley.gif")));
    }
}
      

In the constructor the super constructor in ToolButton is called which adds this toggle button to the mode bar with the given ID (here to default mode bar with the ID "org.graffiti.plugins.modes.defaultEditMode"). The called constructor of ToolButton further needs the tool object which should be activated and a icon for the button.