You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by re...@apache.org on 2015/03/26 19:52:02 UTC
[13/51] [partial] incubator-taverna-workbench git commit: all
packages are moved to org.apache.taverna.*
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraph.java
----------------------------------------------------------------------
diff --git a/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraph.java b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraph.java
new file mode 100644
index 0000000..1b1df78
--- /dev/null
+++ b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraph.java
@@ -0,0 +1,439 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package org.apache.taverna.workbench.models.graph.svg;
+
+import static org.apache.taverna.workbench.models.graph.svg.SVGGraphSettings.COMPLETED_COLOUR;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.animate;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.calculatePoints;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.createAnimationElement;
+import static org.apache.batik.util.CSSConstants.CSS_BLACK_VALUE;
+import static org.apache.batik.util.CSSConstants.CSS_NONE_VALUE;
+import static org.apache.batik.util.SVGConstants.SVG_ANIMATE_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_ANIMATE_TRANSFORM_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_CLICK_EVENT_TYPE;
+import static org.apache.batik.util.SVGConstants.SVG_END_VALUE;
+import static org.apache.batik.util.SVGConstants.SVG_FILL_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_FONT_FAMILY_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_FONT_SIZE_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_MIDDLE_VALUE;
+import static org.apache.batik.util.SVGConstants.SVG_MOUSEMOVE_EVENT_TYPE;
+import static org.apache.batik.util.SVGConstants.SVG_MOUSEUP_EVENT_TYPE;
+import static org.apache.batik.util.SVGConstants.SVG_NONE_VALUE;
+import static org.apache.batik.util.SVGConstants.SVG_POINTS_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_STROKE_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_STROKE_DASHARRAY_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_TRANSFORM_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.TRANSFORM_TRANSLATE;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Point;
+
+import org.apache.taverna.workbench.models.graph.Graph;
+import org.apache.taverna.workbench.models.graph.GraphEdge;
+import org.apache.taverna.workbench.models.graph.GraphNode;
+import org.apache.taverna.workbench.models.graph.svg.event.SVGMouseClickEventListener;
+import org.apache.taverna.workbench.models.graph.svg.event.SVGMouseMovedEventListener;
+import org.apache.taverna.workbench.models.graph.svg.event.SVGMouseOutEventListener;
+import org.apache.taverna.workbench.models.graph.svg.event.SVGMouseOverEventListener;
+import org.apache.taverna.workbench.models.graph.svg.event.SVGMouseUpEventListener;
+
+import org.apache.batik.dom.svg.SVGOMAnimationElement;
+import org.apache.batik.dom.svg.SVGOMGElement;
+import org.apache.batik.dom.svg.SVGOMPolygonElement;
+import org.apache.batik.dom.svg.SVGOMTextElement;
+import org.w3c.dom.Text;
+import org.w3c.dom.events.EventTarget;
+import org.w3c.dom.svg.SVGElement;
+
+/**
+ * SVG representation of a graph.
+ *
+ * @author David Withers
+ */
+public class SVGGraph extends Graph {
+ private SVGGraphController graphController;
+ private SVGGraphElementDelegate delegate;
+ private SVGMouseClickEventListener mouseClickAction;
+ private SVGMouseMovedEventListener mouseMovedAction;
+ private SVGMouseUpEventListener mouseUpAction;
+ @SuppressWarnings("unused")
+ private SVGMouseOverEventListener mouseOverAction;
+ @SuppressWarnings("unused")
+ private SVGMouseOutEventListener mouseOutAction;
+ private SVGOMGElement mainGroup, labelGroup;
+ private SVGOMPolygonElement polygon, completedPolygon;
+ private SVGOMTextElement label, iteration, error;
+ private Text labelText, iterationText, errorsText;
+ private SVGOMAnimationElement animateShape, animatePosition, animateLabel;
+
+ public SVGGraph(SVGGraphController graphController) {
+ super(graphController);
+ this.graphController = graphController;
+
+ mouseClickAction = new SVGMouseClickEventListener(this);
+ mouseMovedAction = new SVGMouseMovedEventListener(this);
+ mouseUpAction = new SVGMouseUpEventListener(this);
+ mouseOverAction = new SVGMouseOverEventListener(this);
+ mouseOutAction = new SVGMouseOutEventListener(this);
+
+ mainGroup = graphController.createGElem();
+ mainGroup.setAttribute(SVG_FONT_SIZE_ATTRIBUTE, "10");
+ mainGroup.setAttribute(SVG_FONT_FAMILY_ATTRIBUTE, "Helvetica");
+ mainGroup.setAttribute(SVG_STROKE_ATTRIBUTE, CSS_BLACK_VALUE);
+ mainGroup.setAttribute(SVG_STROKE_DASHARRAY_ATTRIBUTE, CSS_NONE_VALUE);
+ mainGroup.setAttribute(SVG_STROKE_WIDTH_ATTRIBUTE, "1");
+ mainGroup.setAttribute(SVG_FILL_ATTRIBUTE, CSS_NONE_VALUE);
+
+ EventTarget t = (EventTarget) mainGroup;
+ t.addEventListener(SVG_CLICK_EVENT_TYPE, mouseClickAction, false);
+ t.addEventListener(SVG_MOUSEMOVE_EVENT_TYPE, mouseMovedAction, false);
+ t.addEventListener(SVG_MOUSEUP_EVENT_TYPE, mouseUpAction, false);
+ // t.addEventListener(SVGConstants.SVG_MOUSEOVER_EVENT_TYPE, mouseOverAction, false);
+ // t.addEventListener(SVGConstants.SVG_MOUSEOUT_EVENT_TYPE, mouseOutAction, false);
+
+ polygon = graphController.createPolygon();
+ mainGroup.appendChild(polygon);
+
+ completedPolygon = graphController.createPolygon();
+ completedPolygon.setAttribute(SVG_POINTS_ATTRIBUTE,
+ calculatePoints(getShape(), 0, 0));
+ completedPolygon.setAttribute(SVG_FILL_ATTRIBUTE, COMPLETED_COLOUR);
+ // completedPolygon.setAttribute(SVGConstants.SVG_FILL_OPACITY_ATTRIBUTE, "0.8");
+ // completedPolygon.setAttribute(SVG_STROKE_ATTRIBUTE, SVG_NONE_VALUE);
+ mainGroup.appendChild(completedPolygon);
+
+ labelText = graphController.createText("");
+ label = graphController.createText(labelText);
+ label.setAttribute(SVG_TEXT_ANCHOR_ATTRIBUTE, SVG_MIDDLE_VALUE);
+ label.setAttribute(SVG_FILL_ATTRIBUTE, CSS_BLACK_VALUE);
+ label.setAttribute(SVG_STROKE_ATTRIBUTE, SVG_NONE_VALUE);
+ labelGroup = graphController.createGElem();
+ labelGroup.appendChild(label);
+ mainGroup.appendChild(labelGroup);
+
+ iterationText = graphController.createText("");
+ iteration = graphController.createText(iterationText);
+ iteration.setAttribute(SVG_TEXT_ANCHOR_ATTRIBUTE, SVG_END_VALUE);
+ iteration.setAttribute(SVG_FONT_SIZE_ATTRIBUTE, "6");
+ iteration.setAttribute(SVG_FONT_FAMILY_ATTRIBUTE, "sans-serif");
+ iteration.setAttribute(SVG_FILL_ATTRIBUTE, CSS_BLACK_VALUE);
+ iteration.setAttribute(SVG_STROKE_ATTRIBUTE, SVG_NONE_VALUE);
+ polygon.appendChild(iteration);
+
+ errorsText = graphController.createText("");
+ error = graphController.createText(errorsText);
+ error.setAttribute(SVG_TEXT_ANCHOR_ATTRIBUTE, SVG_END_VALUE);
+ error.setAttribute(SVG_FONT_SIZE_ATTRIBUTE, "6");
+ error.setAttribute(SVG_FONT_FAMILY_ATTRIBUTE, "sans-serif");
+ error.setAttribute(SVG_FILL_ATTRIBUTE, CSS_BLACK_VALUE);
+ error.setAttribute(SVG_STROKE_ATTRIBUTE, SVG_NONE_VALUE);
+ polygon.appendChild(error);
+
+ animateShape = createAnimationElement(graphController, SVG_ANIMATE_TAG,
+ SVG_POINTS_ATTRIBUTE, null);
+
+ animatePosition = createAnimationElement(graphController,
+ SVG_ANIMATE_TRANSFORM_TAG, SVG_TRANSFORM_ATTRIBUTE,
+ TRANSFORM_TRANSLATE);
+
+ animateLabel = createAnimationElement(graphController,
+ SVG_ANIMATE_TRANSFORM_TAG, SVG_TRANSFORM_ATTRIBUTE,
+ TRANSFORM_TRANSLATE);
+
+ delegate = new SVGGraphElementDelegate(graphController, this, mainGroup);
+ }
+
+ public SVGElement getSVGElement() {
+ return mainGroup;
+ }
+
+ @Override
+ public void addEdge(GraphEdge edge) {
+ if (edge instanceof SVGGraphEdge) {
+ final SVGGraphEdge svgGraphEdge = (SVGGraphEdge) edge;
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ float opacity = svgGraphEdge.getOpacity();
+ svgGraphEdge.setOpacity(0);
+ mainGroup.appendChild(svgGraphEdge.getSVGElement());
+ svgGraphEdge.setOpacity(opacity);
+ }
+ });
+ }
+ super.addEdge(edge);
+ }
+
+ @Override
+ public void addNode(GraphNode node) {
+ super.addNode(node);
+ if (node instanceof SVGGraphNode) {
+ final SVGGraphNode svgGraphNode = (SVGGraphNode) node;
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ float opacity = svgGraphNode.getOpacity();
+ svgGraphNode.setOpacity(0);
+ mainGroup.appendChild(svgGraphNode.getSVGElement());
+ svgGraphNode.setOpacity(opacity);
+ }
+ });
+ }
+ }
+
+ @Override
+ public void addSubgraph(Graph subgraph) {
+ super.addSubgraph(subgraph);
+ if (subgraph instanceof SVGGraph) {
+ final SVGGraph svgGraph = (SVGGraph) subgraph;
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ float opacity = svgGraph.getOpacity();
+ svgGraph.setOpacity(0);
+ mainGroup.appendChild(svgGraph.getSVGElement());
+ svgGraph.setOpacity(opacity);
+ }
+ });
+ }
+ }
+
+ @Override
+ public boolean removeEdge(GraphEdge edge) {
+ if (edge instanceof SVGGraphEdge) {
+ final SVGGraphEdge svgGraphEdge = (SVGGraphEdge) edge;
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ mainGroup.removeChild(svgGraphEdge.getSVGElement());
+ }
+ });
+ }
+ return super.removeEdge(edge);
+ }
+
+ @Override
+ public boolean removeNode(GraphNode node) {
+ if (node instanceof SVGGraphNode) {
+ final SVGGraphNode svgGraphNode = (SVGGraphNode) node;
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ mainGroup.removeChild(svgGraphNode.getSVGElement());
+ }
+ });
+ }
+ return super.removeNode(node);
+ }
+
+ @Override
+ public boolean removeSubgraph(Graph subgraph) {
+ if (subgraph instanceof SVGGraph) {
+ final SVGGraph svgGraph = (SVGGraph) subgraph;
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ mainGroup.removeChild(svgGraph.getSVGElement());
+ }
+ });
+ }
+ return super.removeSubgraph(subgraph);
+ }
+
+ @Override
+ public void setPosition(final Point position) {
+ final Point oldPosition = getPosition();
+ if (position != null && !position.equals(oldPosition)) {
+ super.setPosition(position);
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ if (graphController.isAnimatable())
+ animate(animatePosition, polygon,
+ graphController.getAnimationSpeed(),
+ oldPosition.x + ", " + oldPosition.y,
+ position.x + ", " + position.y);
+ else
+ polygon.setAttribute(SVG_TRANSFORM_ATTRIBUTE,
+ "translate(" + position.x + " " + position.y
+ + ")");
+ }
+ });
+ }
+ }
+
+ @Override
+ public void setSize(final Dimension size) {
+ final Dimension oldSize = getSize();
+ if (size != null && !size.equals(oldSize)) {
+ super.setSize(size);
+ updateShape(oldSize.width, oldSize.height);
+ }
+ }
+
+ @Override
+ public void setShape(Shape shape) {
+ final Dimension oldSize = getSize();
+ final Shape currentShape = getShape();
+ if (shape != null && !shape.equals(currentShape)) {
+ super.setShape(shape);
+ updateShape(oldSize.width, oldSize.height);
+ }
+ }
+
+ @Override
+ public void setLabel(final String label) {
+ super.setLabel(label);
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ labelText.setData(label);
+ }
+ });
+ }
+
+ @Override
+ public void setLabelPosition(final Point labelPosition) {
+ final Point oldLabelPosition = getLabelPosition();
+ if (labelPosition != null && !labelPosition.equals(oldLabelPosition)) {
+ super.setLabelPosition(labelPosition);
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ if (graphController.isAnimatable()
+ && oldLabelPosition != null)
+ animate(animateLabel, labelGroup,
+ graphController.getAnimationSpeed(),
+ oldLabelPosition.x + ", " + oldLabelPosition.y,
+ labelPosition.x + ", " + labelPosition.y);
+ else
+ labelGroup.setAttribute(SVG_TRANSFORM_ATTRIBUTE,
+ "translate(" + labelPosition.x + " "
+ + labelPosition.y + ")");
+ }
+ });
+ }
+ }
+
+ @Override
+ public void setIteration(final int iteration) {
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ if (iteration > 0)
+ iterationText.setData(String.valueOf(iteration));
+ else
+ iterationText.setData("");
+ }
+ });
+ }
+
+ @Override
+ public void setCompleted(final float complete) {
+ super.setCompleted(complete);
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ Dimension size = getSize();
+ Point position = getPosition();
+ completedPolygon.setAttribute(
+ SVG_POINTS_ATTRIBUTE,
+ calculatePoints(getShape(),
+ (int) (size.width * complete), size.height));
+ completedPolygon.setAttribute(SVG_TRANSFORM_ATTRIBUTE,
+ "translate(" + position.x + " " + position.y + ")");
+ }
+ });
+ }
+
+ private void updateShape(final int oldWidth, final int oldHeight) {
+ if (getShape() != null && getWidth() > 0f && getHeight() > 0f) {
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ if (graphController.isAnimatable())
+ animate(animateShape,
+ polygon,
+ graphController.getAnimationSpeed(),
+ calculatePoints(getShape(), oldWidth, oldHeight),
+ calculatePoints(getShape(), getWidth(),
+ getHeight()));
+ else {
+ polygon.setAttribute(
+ SVG_POINTS_ATTRIBUTE,
+ calculatePoints(getShape(), getWidth(),
+ getHeight()));
+ iteration.setAttribute(SVG_TRANSFORM_ATTRIBUTE,
+ "translate(" + (getWidth() - 1.5) + " 5.5)");
+ error.setAttribute(SVG_TRANSFORM_ATTRIBUTE,
+ "translate(" + (getWidth() - 1.5) + " "
+ + (getHeight() - 1) + ")");
+ }
+ }
+ });
+ }
+ }
+
+ @Override
+ public void setSelected(final boolean selected) {
+ delegate.setSelected(selected);
+ super.setSelected(selected);
+ }
+
+ @Override
+ public void setLineStyle(final LineStyle lineStyle) {
+ delegate.setLineStyle(lineStyle);
+ super.setLineStyle(lineStyle);
+ }
+
+ @Override
+ public void setColor(final Color color) {
+ delegate.setColor(color);
+ super.setColor(color);
+ }
+
+ @Override
+ public void setFillColor(final Color fillColor) {
+ delegate.setFillColor(fillColor);
+ super.setFillColor(fillColor);
+ }
+
+ @Override
+ public void setVisible(final boolean visible) {
+ delegate.setVisible(visible);
+ super.setVisible(visible);
+ }
+
+ @Override
+ public void setFiltered(final boolean filtered) {
+ delegate.setFiltered(filtered);
+ super.setFiltered(filtered);
+ }
+
+ @Override
+ public void setOpacity(final float opacity) {
+ delegate.setOpacity(opacity);
+ super.setOpacity(opacity);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphController.java
----------------------------------------------------------------------
diff --git a/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphController.java b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphController.java
new file mode 100644
index 0000000..7eb6453
--- /dev/null
+++ b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphController.java
@@ -0,0 +1,552 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package org.apache.taverna.workbench.models.graph.svg;
+
+import static java.awt.Color.BLACK;
+import static java.awt.Color.GREEN;
+import static java.lang.Float.parseFloat;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.animate;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.calculateAngle;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.createAnimationElement;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.createSVGDocument;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.getDot;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.getHexValue;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.svgNS;
+import static org.apache.batik.util.SVGConstants.SVG_ANIMATE_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_ELLIPSE_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_FILL_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_FONT_FAMILY_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_FONT_SIZE_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_G_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_LINE_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_PATH_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_POINTS_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_POLYGON_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_RECT_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_STYLE_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_TEXT_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_TRANSFORM_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_VIEW_BOX_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_X1_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_X2_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_Y1_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_Y2_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_Y_ATTRIBUTE;
+
+import java.awt.Color;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Timer;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.configuration.colour.ColourManager;
+import org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.models.graph.DotWriter;
+import org.apache.taverna.workbench.models.graph.Graph;
+import org.apache.taverna.workbench.models.graph.Graph.Alignment;
+import org.apache.taverna.workbench.models.graph.GraphController;
+import org.apache.taverna.workbench.models.graph.GraphEdge;
+import org.apache.taverna.workbench.models.graph.GraphElement;
+import org.apache.taverna.workbench.models.graph.GraphNode;
+import org.apache.taverna.workbench.models.graph.dot.GraphLayout;
+
+import org.apache.batik.bridge.UpdateManager;
+import org.apache.batik.dom.svg.SVGOMAnimationElement;
+import org.apache.batik.dom.svg.SVGOMEllipseElement;
+import org.apache.batik.dom.svg.SVGOMGElement;
+import org.apache.batik.dom.svg.SVGOMPathElement;
+import org.apache.batik.dom.svg.SVGOMPolygonElement;
+import org.apache.batik.dom.svg.SVGOMRectElement;
+import org.apache.batik.dom.svg.SVGOMTextElement;
+import org.apache.batik.swing.JSVGCanvas;
+import org.apache.batik.swing.gvt.GVTTreeRendererAdapter;
+import org.apache.batik.swing.gvt.GVTTreeRendererEvent;
+import org.apache.log4j.Logger;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+import org.w3c.dom.svg.SVGDocument;
+import org.w3c.dom.svg.SVGElement;
+import org.w3c.dom.svg.SVGPoint;
+import org.w3c.dom.svg.SVGSVGElement;
+
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.api.profiles.Profile;
+
+public class SVGGraphController extends GraphController {
+ private static final Logger logger = Logger.getLogger(SVGGraphController.class);
+ @SuppressWarnings("unused")
+ private static final Timer timer = new Timer("SVG Graph controller timer", true);
+ private static final String dotErrorMessage = "Cannot draw diagram(s)\n" +
+ "\n" +
+ "Install dot as described\n" +
+ "at http://www.taverna.org.uk\n" +
+ "and specify its location\n" +
+ "in the workbench preferences";
+
+ private Map<String, List<SVGGraphEdge>> datalinkMap = new HashMap<>();
+ private final JSVGCanvas svgCanvas;
+ private SVGDocument svgDocument;
+ private GraphLayout graphLayout = new GraphLayout();
+ private EdgeLine edgeLine;
+ private UpdateManager updateManager;
+ private ExecutorService executor = Executors.newFixedThreadPool(1);
+ private boolean drawingDiagram = false;
+ private int animationSpeed;
+ private Rectangle bounds, oldBounds;
+ private SVGOMAnimationElement animateBounds;
+ private boolean dotMissing = false;
+ private final WorkbenchConfiguration workbenchConfiguration;
+
+ public SVGGraphController(Workflow dataflow, Profile profile,
+ boolean interactive, JSVGCanvas svgCanvas, EditManager editManager,
+ MenuManager menuManager, ColourManager colourManager,
+ WorkbenchConfiguration workbenchConfiguration) {
+ super(dataflow, profile, interactive, svgCanvas, editManager,
+ menuManager, colourManager);
+ this.svgCanvas = svgCanvas;
+ this.workbenchConfiguration = workbenchConfiguration;
+ installUpdateManager();
+ layoutSVGDocument(svgCanvas.getBounds());
+ svgCanvas.setDocument(getSVGDocument());
+ }
+
+ public SVGGraphController(Workflow dataflow, Profile profile,
+ boolean interactive, JSVGCanvas svgCanvas, Alignment alignment,
+ PortStyle portStyle, EditManager editManager,
+ MenuManager menuManager, ColourManager colourManager,
+ WorkbenchConfiguration workbenchConfiguration) {
+ super(dataflow, profile, interactive, svgCanvas, alignment, portStyle,
+ editManager, menuManager, colourManager);
+ this.svgCanvas = svgCanvas;
+ this.workbenchConfiguration = workbenchConfiguration;
+ installUpdateManager();
+ layoutSVGDocument(svgCanvas.getBounds());
+ svgCanvas.setDocument(getSVGDocument());
+ }
+
+ private void installUpdateManager() {
+ svgCanvas.addGVTTreeRendererListener(new GVTTreeRendererAdapter() {
+ @Override
+ public void gvtRenderingCompleted(GVTTreeRendererEvent ev) {
+ setUpdateManager(svgCanvas.getUpdateManager());
+ }
+ });
+ }
+
+ @Override
+ public GraphEdge createGraphEdge() {
+ return new SVGGraphEdge(this);
+ }
+
+ @Override
+ public Graph createGraph() {
+ return new SVGGraph(this);
+ }
+
+ @Override
+ public GraphNode createGraphNode() {
+ return new SVGGraphNode(this);
+ }
+
+ public JSVGCanvas getSVGCanvas() {
+ return svgCanvas;
+ }
+
+ public synchronized SVGDocument getSVGDocument() {
+ if (svgDocument == null)
+ svgDocument = createSVGDocument();
+ return svgDocument;
+ }
+
+ @Override
+ public void redraw() {
+ Graph graph = generateGraph();
+ Rectangle actualBounds = layoutGraph(graph, svgCanvas.getBounds());
+ setBounds(actualBounds);
+ transformGraph(getGraph(), graph);
+ }
+
+ private void layoutSVGDocument(Rectangle bounds) {
+ animateBounds = createAnimationElement(this, SVG_ANIMATE_TAG,
+ SVG_VIEW_BOX_ATTRIBUTE, null);
+ updateManager = null;
+ datalinkMap.clear();
+
+ Graph graph = getGraph();
+ if (graph instanceof SVGGraph) {
+ SVGGraph svgGraph = (SVGGraph) graph;
+ SVGSVGElement svgElement = getSVGDocument().getRootElement();
+ SVGElement graphElement = svgGraph.getSVGElement();
+ svgElement.appendChild(graphElement);
+
+ setBounds(layoutGraph(graph, bounds));
+
+ edgeLine = EdgeLine.createAndAdd(getSVGDocument(), this);
+ }
+ drawingDiagram = true;
+ }
+
+ public Rectangle layoutGraph(Graph graph, Rectangle bounds) {
+ Rectangle actualBounds = null;
+ bounds = new Rectangle(bounds);
+ StringWriter stringWriter = new StringWriter();
+ DotWriter dotWriter = new DotWriter(stringWriter);
+ try {
+ dotWriter.writeGraph(graph);
+ String layout = getDot(stringWriter.toString(), workbenchConfiguration);
+ if (layout.isEmpty())
+ logger.warn("Invalid dot returned");
+ else
+ actualBounds = graphLayout.layoutGraph(this, graph, layout, bounds);
+ } catch (IOException e) {
+ outputMessage(dotErrorMessage);
+ setDotMissing(true);
+ logger.warn("Couldn't generate dot");
+ }
+ return actualBounds;
+ }
+
+ private void setDotMissing(boolean b) {
+ this.dotMissing = b;
+ }
+
+ public boolean isDotMissing() {
+ return dotMissing;
+ }
+
+ public void setBounds(final Rectangle bounds) {
+ oldBounds = this.bounds;
+ this.bounds = bounds;
+ updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ SVGSVGElement svgElement = getSVGDocument().getRootElement();
+ if (isAnimatable() && oldBounds != null) {
+ String from = "0 0 " + oldBounds.width + " "
+ + oldBounds.height;
+ String to = "0 0 " + bounds.width + " " + bounds.height;
+ animate(animateBounds, svgElement, getAnimationSpeed(),
+ from, to);
+ } else if ((svgElement != null) && (bounds != null))
+ svgElement.setAttribute(SVG_VIEW_BOX_ATTRIBUTE,
+ "0 0 " + String.valueOf(bounds.width) + " "
+ + String.valueOf(bounds.height));
+ }
+ });
+ }
+
+ private void outputMessage(final String message) {
+ SVGSVGElement svgElement = getSVGDocument().getRootElement();
+ String[] parts = message.split("\n");
+ int initialPosition = 200;
+ for (int i = 0; i < parts.length; i++) {
+ Text errorsText = createText(parts[i]);
+ SVGOMTextElement error = (SVGOMTextElement) createElement(SVG_TEXT_TAG);
+ error.setAttribute(SVG_Y_ATTRIBUTE,
+ Integer.toString(initialPosition + i * 60));
+ error.setAttribute(SVG_FONT_SIZE_ATTRIBUTE, "20");
+ error.setAttribute(SVG_FONT_FAMILY_ATTRIBUTE, "sans-serif");
+ error.setAttribute(SVG_FILL_ATTRIBUTE, "red");
+ error.appendChild(errorsText);
+ svgElement.appendChild(error);
+ }
+ bounds = new Rectangle(300, parts.length * 60 + 200);
+ svgCanvas.setDocument(getSVGDocument());
+ }
+
+ public void setUpdateManager(UpdateManager updateManager) {
+ this.updateManager = updateManager;
+ drawingDiagram = false;
+ resetSelection();
+ }
+
+ @Override
+ public boolean startEdgeCreation(GraphElement graphElement, Point point) {
+ boolean alreadyStarted = edgeCreationFromSource || edgeCreationFromSink;
+ boolean started = super.startEdgeCreation(graphElement, point);
+ if (!alreadyStarted && started) {
+ if (edgeMoveElement instanceof SVGGraphEdge) {
+ SVGGraphEdge svgGraphEdge = (SVGGraphEdge) edgeMoveElement;
+ SVGPoint sourcePoint = svgGraphEdge.getPathElement()
+ .getPointAtLength(0f);
+ edgeLine.setSourcePoint(new Point((int) sourcePoint.getX(),
+ (int) sourcePoint.getY()));
+ } else
+ edgeLine.setSourcePoint(point);
+ edgeLine.setTargetPoint(point);
+ edgeLine.setColour(Color.BLACK);
+ // edgeLine.setVisible(true);
+ }
+ return started;
+ }
+
+ @Override
+ public boolean moveEdgeCreationTarget(GraphElement graphElement, Point point) {
+ boolean linkValid = super.moveEdgeCreationTarget(graphElement, point);
+ if (edgeMoveElement instanceof SVGGraphEdge)
+ ((SVGGraphEdge) edgeMoveElement).setVisible(false);
+ if (edgeCreationFromSink) {
+ edgeLine.setSourcePoint(point);
+ if (linkValid)
+ edgeLine.setColour(GREEN);
+ else
+ edgeLine.setColour(BLACK);
+ edgeLine.setVisible(true);
+ } else if (edgeCreationFromSource) {
+ edgeLine.setTargetPoint(point);
+ if (linkValid)
+ edgeLine.setColour(GREEN);
+ else
+ edgeLine.setColour(BLACK);
+ edgeLine.setVisible(true);
+ }
+ return linkValid;
+ }
+
+ @Override
+ public boolean stopEdgeCreation(GraphElement graphElement, Point point) {
+ GraphEdge movedEdge = edgeMoveElement;
+ boolean edgeCreated = super.stopEdgeCreation(graphElement, point);
+ if (!edgeCreated && movedEdge instanceof SVGGraphEdge)
+ ((SVGGraphEdge) movedEdge).setVisible(true);
+ edgeLine.setVisible(false);
+ return edgeCreated;
+ }
+
+ @Override
+ public void setEdgeActive(String edgeId, boolean active) {
+ if (datalinkMap.containsKey(edgeId))
+ for (GraphEdge datalink : datalinkMap.get(edgeId))
+ datalink.setActive(active);
+ }
+
+ public Element createElement(String tag) {
+ return getSVGDocument().createElementNS(svgNS, tag);
+ }
+
+ SVGOMGElement createGElem() {
+ return (SVGOMGElement) createElement(SVG_G_TAG);
+ }
+
+ SVGOMPolygonElement createPolygon() {
+ return (SVGOMPolygonElement) createElement(SVG_POLYGON_TAG);
+ }
+
+ SVGOMEllipseElement createEllipse() {
+ return (SVGOMEllipseElement) createElement(SVG_ELLIPSE_TAG);
+ }
+
+ SVGOMPathElement createPath() {
+ return (SVGOMPathElement) createElement(SVG_PATH_TAG);
+ }
+
+ SVGOMRectElement createRect() {
+ return (SVGOMRectElement) createElement(SVG_RECT_TAG);
+ }
+
+ public Text createText(String text) {
+ return getSVGDocument().createTextNode(text);
+ }
+
+ SVGOMTextElement createText(Text text) {
+ SVGOMTextElement elem = (SVGOMTextElement) createElement(SVG_TEXT_TAG);
+ elem.appendChild(text);
+ return elem;
+ }
+
+ public void updateSVGDocument(final Runnable thread) {
+ if (updateManager == null && !drawingDiagram)
+ thread.run();
+ else if (!executor.isShutdown())
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ waitForUpdateManager();
+ try {
+ updateManager.getUpdateRunnableQueue().invokeLater(
+ thread);
+ } catch (IllegalStateException e) {
+ logger.error("Update of SVG failed", e);
+ }
+ }
+
+ private void waitForUpdateManager() {
+ try {
+ while (updateManager == null)
+ Thread.sleep(200);
+ } catch (InterruptedException e) {
+ }
+ }
+ });
+// if (updateManager == null)
+// thread.run();
+// else
+// updateManager.getUpdateRunnableQueue().invokeLater(thread);
+ }
+
+ public boolean isAnimatable() {
+ return animationSpeed > 0 && updateManager != null && !drawingDiagram;
+ }
+
+ /**
+ * Returns the animation speed in milliseconds.
+ *
+ * @return the animation speed in milliseconds
+ */
+ public int getAnimationSpeed() {
+ return animationSpeed;
+ }
+
+ /**
+ * Sets the animation speed in milliseconds. A value of 0 turns off animation.
+ *
+ * @param animationSpeed the animation speed in milliseconds
+ */
+ public void setAnimationSpeed(int animationSpeed) {
+ this.animationSpeed = animationSpeed;
+ }
+
+ @Override
+ public void shutdown() {
+ super.shutdown();
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ getSVGCanvas().stopProcessing();
+ executor.shutdown();
+ }
+ });
+ }
+
+}
+
+class EdgeLine {
+ private static final float arrowLength = 10f;
+ private static final float arrowWidth = 3f;
+
+ private Element line;
+ private Element pointer;
+ private SVGGraphController graphController;
+
+ private EdgeLine(SVGGraphController graphController) {
+ this.graphController = graphController;
+ }
+
+ public static EdgeLine createAndAdd(SVGDocument svgDocument, SVGGraphController graphController) {
+ EdgeLine edgeLine = new EdgeLine(graphController);
+ edgeLine.line = svgDocument.createElementNS(svgNS, SVG_LINE_TAG);
+ edgeLine.line.setAttribute(SVG_STYLE_ATTRIBUTE,
+ "fill:none;stroke:black");
+ edgeLine.line.setAttribute("pointer-events", "none");
+ edgeLine.line.setAttribute("visibility", "hidden");
+ edgeLine.line.setAttribute(SVG_X1_ATTRIBUTE, "0");
+ edgeLine.line.setAttribute(SVG_Y1_ATTRIBUTE, "0");
+ edgeLine.line.setAttribute(SVG_X2_ATTRIBUTE, "0");
+ edgeLine.line.setAttribute(SVG_Y2_ATTRIBUTE, "0");
+
+ edgeLine.pointer = svgDocument.createElementNS(svgNS, SVG_POLYGON_TAG);
+ edgeLine.pointer.setAttribute(SVG_STYLE_ATTRIBUTE,
+ "fill:black;stroke:black");
+ edgeLine.pointer.setAttribute(SVG_POINTS_ATTRIBUTE, "0,0 "
+ + -arrowLength + "," + arrowWidth + " " + -arrowLength + ","
+ + -arrowWidth + " 0,0");
+ edgeLine.pointer.setAttribute("pointer-events", "none");
+ edgeLine.pointer.setAttribute("visibility", "hidden");
+
+ Element svgRoot = svgDocument.getDocumentElement();
+ svgRoot.insertBefore(edgeLine.line, null);
+ svgRoot.insertBefore(edgeLine.pointer, null);
+
+ return edgeLine;
+ }
+
+ public void setSourcePoint(final Point point) {
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ line.setAttribute(SVG_X1_ATTRIBUTE,
+ String.valueOf(point.getX()));
+ line.setAttribute(SVG_Y1_ATTRIBUTE,
+ String.valueOf(point.getY()));
+
+ float x = parseFloat(line.getAttribute(SVG_X2_ATTRIBUTE));
+ float y = parseFloat(line.getAttribute(SVG_Y2_ATTRIBUTE));
+ double angle = calculateAngle(line);
+
+ pointer.setAttribute(SVG_TRANSFORM_ATTRIBUTE, "translate(" + x
+ + " " + y + ") rotate(" + angle + " 0 0) ");
+ }
+ });
+ }
+
+ public void setTargetPoint(final Point point) {
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ line.setAttribute(SVG_X2_ATTRIBUTE,
+ String.valueOf(point.getX()));
+ line.setAttribute(SVG_Y2_ATTRIBUTE,
+ String.valueOf(point.getY()));
+
+ double angle = calculateAngle(line);
+ pointer.setAttribute(SVG_TRANSFORM_ATTRIBUTE, "translate("
+ + point.x + " " + point.y + ") rotate(" + angle
+ + " 0 0) ");
+ }
+ });
+ }
+
+ public void setColour(final Color colour) {
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ String hexColour = getHexValue(colour);
+ line.setAttribute(SVG_STYLE_ATTRIBUTE, "fill:none;stroke:"
+ + hexColour + ";");
+ pointer.setAttribute(SVG_STYLE_ATTRIBUTE, "fill:" + hexColour
+ + ";stroke:" + hexColour + ";");
+ }
+ });
+ }
+
+ public void setVisible(final boolean visible) {
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ if (visible) {
+ line.setAttribute("visibility", "visible");
+ pointer.setAttribute("visibility", "visible");
+ } else {
+ line.setAttribute("visibility", "hidden");
+ pointer.setAttribute("visibility", "hidden");
+ }
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphEdge.java
----------------------------------------------------------------------
diff --git a/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphEdge.java b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphEdge.java
new file mode 100644
index 0000000..736c6e5
--- /dev/null
+++ b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphEdge.java
@@ -0,0 +1,311 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package org.apache.taverna.workbench.models.graph.svg;
+
+import static org.apache.taverna.workbench.models.graph.svg.SVGGraphSettings.SELECTED_COLOUR;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.adjustPathLength;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.animate;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.calculateAngle;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.createAnimationElement;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.getHexValue;
+import static org.apache.batik.util.CSSConstants.CSS_BLACK_VALUE;
+import static org.apache.batik.util.CSSConstants.CSS_DISPLAY_PROPERTY;
+import static org.apache.batik.util.CSSConstants.CSS_INLINE_VALUE;
+import static org.apache.batik.util.CSSConstants.CSS_NONE_VALUE;
+import static org.apache.batik.util.SMILConstants.SMIL_ADDITIVE_ATTRIBUTE;
+import static org.apache.batik.util.SMILConstants.SMIL_SUM_VALUE;
+import static org.apache.batik.util.SVGConstants.SVG_ANIMATE_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_ANIMATE_TRANSFORM_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_CLICK_EVENT_TYPE;
+import static org.apache.batik.util.SVGConstants.SVG_CX_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_CY_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_D_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_FILL_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_MOUSEDOWN_EVENT_TYPE;
+import static org.apache.batik.util.SVGConstants.SVG_NONE_VALUE;
+import static org.apache.batik.util.SVGConstants.SVG_POINTS_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_RX_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_RY_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_STROKE_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_STROKE_DASHARRAY_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_TRANSFORM_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_ZERO_VALUE;
+import static org.apache.batik.util.SVGConstants.TRANSFORM_ROTATE;
+import static org.apache.batik.util.SVGConstants.TRANSFORM_TRANSLATE;
+
+import java.awt.Color;
+import java.awt.Point;
+import java.util.List;
+
+import org.apache.taverna.workbench.models.graph.GraphEdge;
+import org.apache.taverna.workbench.models.graph.svg.event.SVGMouseClickEventListener;
+import org.apache.taverna.workbench.models.graph.svg.event.SVGMouseDownEventListener;
+import org.apache.taverna.workbench.models.graph.svg.event.SVGMouseOutEventListener;
+import org.apache.taverna.workbench.models.graph.svg.event.SVGMouseOverEventListener;
+
+import org.apache.batik.dom.svg.SVGGraphicsElement;
+import org.apache.batik.dom.svg.SVGOMAnimationElement;
+import org.apache.batik.dom.svg.SVGOMEllipseElement;
+import org.apache.batik.dom.svg.SVGOMGElement;
+import org.apache.batik.dom.svg.SVGOMPathElement;
+import org.apache.batik.dom.svg.SVGOMPolygonElement;
+import org.w3c.dom.events.EventTarget;
+import org.w3c.dom.svg.SVGElement;
+
+/**
+ * SVG representation of a graph edge.
+ *
+ * @author David Withers
+ */
+public class SVGGraphEdge extends GraphEdge {
+ private static final String ARROW_LENGTH = "8.5";
+ private static final String ARROW_WIDTH = "3";
+ private static final String ELLIPSE_RADIUS = "3.5";
+
+ private SVGGraphController graphController;
+ private SVGGraphElementDelegate delegate;
+ private SVGMouseClickEventListener mouseClickAction;
+ private SVGMouseDownEventListener mouseDownAction;
+ @SuppressWarnings("unused")
+ private SVGMouseOverEventListener mouseOverAction;
+ @SuppressWarnings("unused")
+ private SVGMouseOutEventListener mouseOutAction;
+ private SVGOMGElement mainGroup;
+ private SVGOMPathElement path, deleteButton;
+ private SVGOMPolygonElement polygon;
+ private SVGOMEllipseElement ellipse;
+ private SVGGraphicsElement arrowHead;
+ private SVGOMAnimationElement animatePath, animatePosition, animateRotation;
+
+ public SVGGraphEdge(SVGGraphController graphController) {
+ super(graphController);
+ this.graphController = graphController;
+
+ mouseClickAction = new SVGMouseClickEventListener(this);
+ mouseDownAction = new SVGMouseDownEventListener(this);
+ mouseOverAction = new SVGMouseOverEventListener(this);
+ mouseOutAction = new SVGMouseOutEventListener(this);
+
+ mainGroup = graphController.createGElem();
+ mainGroup.setAttribute(SVG_STROKE_ATTRIBUTE, CSS_BLACK_VALUE);
+ mainGroup.setAttribute(SVG_STROKE_DASHARRAY_ATTRIBUTE, CSS_NONE_VALUE);
+ mainGroup.setAttribute(SVG_STROKE_WIDTH_ATTRIBUTE, "1");
+
+ path = graphController.createPath();
+ path.setAttribute(SVG_FILL_ATTRIBUTE, SVG_NONE_VALUE);
+ EventTarget t = (EventTarget) path;
+ t.addEventListener(SVG_CLICK_EVENT_TYPE, mouseClickAction, false);
+ // t.addEventListener(SVGConstants.SVG_MOUSEOVER_EVENT_TYPE, mouseOverAction, false);
+ // t.addEventListener(SVGConstants.SVG_MOUSEOUT_EVENT_TYPE, mouseOutAction, false);
+ mainGroup.appendChild(path);
+
+ polygon = graphController.createPolygon();
+ polygon.setAttribute(SVG_POINTS_ATTRIBUTE, ARROW_LENGTH + ", 0"
+ + " 0, -" + ARROW_WIDTH + " 0," + ARROW_WIDTH);
+ t = (EventTarget) polygon;
+ t.addEventListener(SVG_CLICK_EVENT_TYPE, mouseClickAction, false);
+ t.addEventListener(SVG_MOUSEDOWN_EVENT_TYPE, mouseDownAction, false);
+ // t.addEventListener(SVGConstants.SVG_MOUSEOVER_EVENT_TYPE, mouseOverAction, false);
+ // t.addEventListener(SVGConstants.SVG_MOUSEOUT_EVENT_TYPE, mouseOutAction, false);
+
+ ellipse = graphController.createEllipse();
+ ellipse.setAttribute(SVG_CX_ATTRIBUTE, ELLIPSE_RADIUS);
+ ellipse.setAttribute(SVG_CY_ATTRIBUTE, SVG_ZERO_VALUE);
+ ellipse.setAttribute(SVG_RX_ATTRIBUTE, ELLIPSE_RADIUS);
+ ellipse.setAttribute(SVG_RY_ATTRIBUTE, ELLIPSE_RADIUS);
+
+ arrowHead = polygon;
+ mainGroup.appendChild(arrowHead);
+
+ deleteButton = graphController.createPath();
+ deleteButton.setAttribute(SVG_STROKE_ATTRIBUTE, "red");
+ deleteButton.setAttribute(SVG_STROKE_WIDTH_ATTRIBUTE, "2");
+ deleteButton.setAttribute(SVG_D_ATTRIBUTE,
+ "M-3.5,-7L3.5,0M-3.5,0L3.5,-7");
+ deleteButton.setAttribute(CSS_DISPLAY_PROPERTY, CSS_NONE_VALUE);
+ mainGroup.appendChild(deleteButton);
+
+ animatePath = createAnimationElement(graphController, SVG_ANIMATE_TAG,
+ SVG_D_ATTRIBUTE, null);
+
+ animatePosition = createAnimationElement(graphController,
+ SVG_ANIMATE_TRANSFORM_TAG, SVG_TRANSFORM_ATTRIBUTE,
+ TRANSFORM_TRANSLATE);
+
+ animateRotation = createAnimationElement(graphController,
+ SVG_ANIMATE_TRANSFORM_TAG, SVG_TRANSFORM_ATTRIBUTE,
+ TRANSFORM_ROTATE);
+ animateRotation.setAttribute(SMIL_ADDITIVE_ATTRIBUTE, SMIL_SUM_VALUE);
+
+ delegate = new SVGGraphElementDelegate(graphController, this, mainGroup);
+ }
+
+ public SVGElement getSVGElement() {
+ return mainGroup;
+ }
+
+ /**
+ * Returns the path.
+ *
+ * @return the path
+ */
+ public SVGOMPathElement getPathElement() {
+ return path;
+ }
+
+ @Override
+ public void setSelected(boolean selected) {
+ super.setSelected(selected);
+ final String color = selected ? SELECTED_COLOUR
+ : getHexValue(getColor());
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ mainGroup.setAttribute(SVG_STROKE_ATTRIBUTE, color);
+ mainGroup.setAttribute(SVG_FILL_ATTRIBUTE, color);
+ }
+ });
+ }
+
+ @Override
+ public void setActive(final boolean active) {
+ super.setActive(active);
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ if (active) {
+ path.setAttribute(SVG_STROKE_WIDTH_ATTRIBUTE, "2");
+ deleteButton.setAttribute(CSS_DISPLAY_PROPERTY,
+ CSS_INLINE_VALUE);
+ } else {
+ path.setAttribute(SVG_STROKE_WIDTH_ATTRIBUTE, "1");
+ deleteButton.setAttribute(CSS_DISPLAY_PROPERTY,
+ CSS_NONE_VALUE);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void setArrowHeadStyle(final ArrowStyle arrowHeadStyle) {
+ super.setArrowHeadStyle(arrowHeadStyle);
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ if (ArrowStyle.NONE.equals(arrowHeadStyle))
+ mainGroup.removeChild(arrowHead);
+ else if (ArrowStyle.NORMAL.equals(arrowHeadStyle)) {
+ mainGroup.removeChild(arrowHead);
+ arrowHead = polygon;
+ mainGroup.appendChild(arrowHead);
+ } else if (ArrowStyle.DOT.equals(arrowHeadStyle)) {
+ mainGroup.removeChild(arrowHead);
+ arrowHead = ellipse;
+ mainGroup.appendChild(arrowHead);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void setPath(final List<Point> pointList) {
+ if (pointList == null)
+ return;
+
+ final List<Point> oldPointList = getPath();
+ super.setPath(pointList);
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ Point lastPoint = pointList.get(pointList.size() - 1);
+ double angle = calculateAngle(pointList);
+ if (graphController.isAnimatable() && oldPointList != null) {
+ adjustPathLength(oldPointList, pointList.size());
+ Point oldLastPoint = oldPointList.get(oldPointList.size() - 1);
+ double oldAngle = calculateAngle(oldPointList);
+ animate(animatePath, path,
+ graphController.getAnimationSpeed(),
+ SVGUtil.getPath(oldPointList),
+ SVGUtil.getPath(pointList));
+
+ animate(animatePosition, polygon,
+ graphController.getAnimationSpeed(), oldLastPoint.x
+ + ", " + oldLastPoint.y, lastPoint.x + ", "
+ + lastPoint.y);
+
+ animate(animateRotation, polygon,
+ graphController.getAnimationSpeed(), oldAngle
+ + " 0 0", angle + " 0 0");
+
+ ellipse.setAttribute(SVG_TRANSFORM_ATTRIBUTE, "translate("
+ + lastPoint.x + " " + lastPoint.y + ") rotate("
+ + angle + " 0 0) ");
+ deleteButton.setAttribute(SVG_TRANSFORM_ATTRIBUTE,
+ "translate(" + lastPoint.x + " " + lastPoint.y
+ + ")");
+ } else {
+ path.setAttribute(SVG_D_ATTRIBUTE,
+ SVGUtil.getPath(pointList));
+ polygon.setAttribute(SVG_TRANSFORM_ATTRIBUTE, "translate("
+ + lastPoint.x + " " + lastPoint.y + ") rotate("
+ + angle + " 0 0) ");
+ ellipse.setAttribute(SVG_TRANSFORM_ATTRIBUTE, "translate("
+ + lastPoint.x + " " + lastPoint.y + ") rotate("
+ + angle + " 0 0) ");
+ deleteButton.setAttribute(SVG_TRANSFORM_ATTRIBUTE,
+ "translate(" + lastPoint.x + " " + lastPoint.y
+ + ")");
+ }
+ }
+ });
+ }
+
+ @Override
+ public void setColor(final Color color) {
+ delegate.setColor(color);
+ super.setColor(color);
+ }
+
+ @Override
+ public void setFillColor(final Color fillColor) {
+ delegate.setFillColor(fillColor);
+ super.setFillColor(fillColor);
+ }
+
+ @Override
+ public void setVisible(final boolean visible) {
+ delegate.setVisible(visible);
+ super.setVisible(visible);
+ }
+
+ @Override
+ public void setFiltered(final boolean filtered) {
+ delegate.setFiltered(filtered);
+ super.setFiltered(filtered);
+ }
+
+ @Override
+ public void setOpacity(final float opacity) {
+ delegate.setOpacity(opacity);
+ super.setOpacity(opacity);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphElementDelegate.java
----------------------------------------------------------------------
diff --git a/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphElementDelegate.java b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphElementDelegate.java
new file mode 100644
index 0000000..aaea6d1
--- /dev/null
+++ b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphElementDelegate.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (C) 2009 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package org.apache.taverna.workbench.models.graph.svg;
+
+import static org.apache.taverna.workbench.models.graph.GraphElement.LineStyle.NONE;
+import static org.apache.taverna.workbench.models.graph.svg.SVGGraphSettings.SELECTED_COLOUR;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.animate;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.createAnimationElement;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.getHexValue;
+import static org.apache.batik.util.CSSConstants.CSS_DISPLAY_PROPERTY;
+import static org.apache.batik.util.CSSConstants.CSS_INLINE_VALUE;
+import static org.apache.batik.util.CSSConstants.CSS_NONE_VALUE;
+import static org.apache.batik.util.CSSConstants.CSS_OPACITY_PROPERTY;
+import static org.apache.batik.util.CSSConstants.CSS_POINTER_EVENTS_PROPERTY;
+import static org.apache.batik.util.CSSConstants.CSS_VISIBLEPAINTED_VALUE;
+import static org.apache.batik.util.SVGConstants.SVG_ANIMATE_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_FILL_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_NONE_VALUE;
+import static org.apache.batik.util.SVGConstants.SVG_STROKE_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_STROKE_DASHARRAY_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE;
+
+import java.awt.Color;
+
+import org.apache.taverna.workbench.models.graph.GraphElement;
+import org.apache.taverna.workbench.models.graph.GraphElement.LineStyle;
+
+import org.apache.batik.dom.svg.SVGOMAnimationElement;
+import org.apache.batik.dom.svg.SVGOMElement;
+
+/**
+ * Delegate for GraphElements. Logically a superclass of SVGGraph, SVGGraphNode
+ * and SVGGraphEdge (if java had multiple inheritance).
+ *
+ * @author David Withers
+ */
+public class SVGGraphElementDelegate {
+ private SVGGraphController graphController;
+ private GraphElement graphElement;
+ private SVGOMElement mainGroup;
+ private SVGOMAnimationElement animateOpacity;
+
+ public SVGGraphElementDelegate(SVGGraphController graphController,
+ GraphElement graphElement, SVGOMElement mainGroup) {
+ this.graphController = graphController;
+ this.graphElement = graphElement;
+ this.mainGroup = mainGroup;
+
+ animateOpacity = createAnimationElement(graphController,
+ SVG_ANIMATE_TAG, CSS_OPACITY_PROPERTY, null);
+ }
+
+ public void setSelected(final boolean selected) {
+ boolean currentSelected = graphElement.isSelected();
+ if (currentSelected != selected
+ && !LineStyle.NONE.equals(graphElement.getLineStyle()))
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ mainGroup.setAttribute(SVG_STROKE_ATTRIBUTE,
+ selected ? SELECTED_COLOUR
+ : getHexValue(graphElement.getColor()));
+ mainGroup.setAttribute(SVG_STROKE_WIDTH_ATTRIBUTE,
+ selected ? "2" : "1");
+ }
+ });
+ }
+
+ public void setLineStyle(final LineStyle lineStyle) {
+ LineStyle currentLineStyle = graphElement.getLineStyle();
+ if (!currentLineStyle.equals(lineStyle))
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ String stroke = SVG_NONE_VALUE, dash = SVG_NONE_VALUE;
+ switch (lineStyle) {
+ case DOTTED:
+ stroke = getHexValue(graphElement.getColor());
+ dash = "1,5";
+ break;
+ case SOLID:
+ stroke = getHexValue(graphElement.getColor());
+ default:
+ break;
+ }
+ mainGroup.setAttribute(SVG_STROKE_ATTRIBUTE, stroke);
+ mainGroup
+ .setAttribute(SVG_STROKE_DASHARRAY_ATTRIBUTE, dash);
+ }
+ });
+ }
+
+ public void setColor(final Color color) {
+ Color currentColor = graphElement.getColor();
+ if (currentColor != color && NONE != graphElement.getLineStyle())
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ mainGroup.setAttribute(SVG_STROKE_ATTRIBUTE,
+ getHexValue(color));
+ }
+ });
+ }
+
+ public void setFillColor(final Color fillColor) {
+ Color currentFillColor = graphElement.getFillColor();
+ if (currentFillColor != fillColor)
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ mainGroup.setAttribute(SVG_FILL_ATTRIBUTE,
+ getHexValue(fillColor));
+ }
+ });
+ }
+
+ public void setVisible(final boolean visible) {
+ boolean currentVisible = graphElement.isVisible();
+ if (currentVisible != visible)
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ mainGroup.setAttribute(CSS_DISPLAY_PROPERTY,
+ visible ? CSS_INLINE_VALUE : CSS_NONE_VALUE);
+ }
+ });
+ }
+
+ public void setOpacity(final float opacity) {
+ final float currentOpacity = graphElement.getOpacity();
+ if (currentOpacity != opacity)
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ if (graphController.isAnimatable())
+ animate(animateOpacity, mainGroup,
+ graphController.getAnimationSpeed(),
+ String.valueOf(currentOpacity),
+ String.valueOf(opacity));
+ else
+ mainGroup.setAttribute(CSS_OPACITY_PROPERTY,
+ String.valueOf(opacity));
+ }
+ });
+ }
+
+ public void setFiltered(final boolean filtered) {
+ boolean currentFiltered = graphElement.isFiltered();
+ if (currentFiltered != filtered)
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ mainGroup.setAttribute(CSS_POINTER_EVENTS_PROPERTY,
+ filtered ? CSS_NONE_VALUE
+ : CSS_VISIBLEPAINTED_VALUE);
+ setOpacity(filtered ? 0.2f : 1f);
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphNode.java
----------------------------------------------------------------------
diff --git a/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphNode.java b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphNode.java
new file mode 100644
index 0000000..49ee0e1
--- /dev/null
+++ b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphNode.java
@@ -0,0 +1,611 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package org.apache.taverna.workbench.models.graph.svg;
+
+import static org.apache.taverna.workbench.models.graph.svg.SVGGraphSettings.COMPLETED_COLOUR;
+import static org.apache.taverna.workbench.models.graph.svg.SVGGraphSettings.ERROR_COLOUR;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.animate;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.calculatePoints;
+import static org.apache.taverna.workbench.models.graph.svg.SVGUtil.createAnimationElement;
+import static org.apache.batik.util.CSSConstants.CSS_ALL_VALUE;
+import static org.apache.batik.util.CSSConstants.CSS_BLACK_VALUE;
+import static org.apache.batik.util.CSSConstants.CSS_DISPLAY_PROPERTY;
+import static org.apache.batik.util.CSSConstants.CSS_HIDDEN_VALUE;
+import static org.apache.batik.util.CSSConstants.CSS_INLINE_VALUE;
+import static org.apache.batik.util.CSSConstants.CSS_NONE_VALUE;
+import static org.apache.batik.util.CSSConstants.CSS_POINTER_EVENTS_PROPERTY;
+import static org.apache.batik.util.CSSConstants.CSS_VISIBILITY_PROPERTY;
+import static org.apache.batik.util.CSSConstants.CSS_VISIBLE_VALUE;
+import static org.apache.batik.util.SVGConstants.SVG_ANIMATE_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_ANIMATE_TRANSFORM_TAG;
+import static org.apache.batik.util.SVGConstants.SVG_CLICK_EVENT_TYPE;
+import static org.apache.batik.util.SVGConstants.SVG_CX_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_CY_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_D_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_END_VALUE;
+import static org.apache.batik.util.SVGConstants.SVG_FILL_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_FILL_OPACITY_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_FONT_FAMILY_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_FONT_SIZE_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_HEIGHT_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_MIDDLE_VALUE;
+import static org.apache.batik.util.SVGConstants.SVG_MOUSEDOWN_EVENT_TYPE;
+import static org.apache.batik.util.SVGConstants.SVG_MOUSEMOVE_EVENT_TYPE;
+import static org.apache.batik.util.SVGConstants.SVG_MOUSEOUT_EVENT_TYPE;
+import static org.apache.batik.util.SVGConstants.SVG_MOUSEOVER_EVENT_TYPE;
+import static org.apache.batik.util.SVGConstants.SVG_NONE_VALUE;
+import static org.apache.batik.util.SVGConstants.SVG_POINTS_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_RX_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_RY_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_STROKE_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_STROKE_DASHARRAY_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_TRANSFORM_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_WIDTH_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_X_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.SVG_Y_ATTRIBUTE;
+import static org.apache.batik.util.SVGConstants.TRANSFORM_TRANSLATE;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Point;
+
+import org.apache.taverna.workbench.models.graph.Graph;
+import org.apache.taverna.workbench.models.graph.GraphNode;
+import org.apache.taverna.workbench.models.graph.svg.event.SVGMouseClickEventListener;
+import org.apache.taverna.workbench.models.graph.svg.event.SVGMouseDownEventListener;
+import org.apache.taverna.workbench.models.graph.svg.event.SVGMouseMovedEventListener;
+import org.apache.taverna.workbench.models.graph.svg.event.SVGMouseOutEventListener;
+import org.apache.taverna.workbench.models.graph.svg.event.SVGMouseOverEventListener;
+
+import org.apache.batik.dom.svg.SVGOMAnimationElement;
+import org.apache.batik.dom.svg.SVGOMEllipseElement;
+import org.apache.batik.dom.svg.SVGOMGElement;
+import org.apache.batik.dom.svg.SVGOMPathElement;
+import org.apache.batik.dom.svg.SVGOMPolygonElement;
+import org.apache.batik.dom.svg.SVGOMRectElement;
+import org.apache.batik.dom.svg.SVGOMTextElement;
+import org.apache.batik.util.CSSConstants;
+import org.apache.batik.util.SVGConstants;
+import org.w3c.dom.Text;
+import org.w3c.dom.events.Event;
+import org.w3c.dom.events.EventListener;
+import org.w3c.dom.events.EventTarget;
+import org.w3c.dom.svg.SVGElement;
+
+/**
+ * SVG representation of a graph node.
+ *
+ * @author David Withers
+ */
+public class SVGGraphNode extends GraphNode {
+ private SVGGraphController graphController;
+ private SVGGraphElementDelegate delegate;
+ private SVGMouseClickEventListener mouseClickAction;
+ private SVGMouseMovedEventListener mouseMovedAction;
+ private SVGMouseDownEventListener mouseDownAction;
+ @SuppressWarnings("unused")
+ private SVGMouseOverEventListener mouseOverAction;
+ @SuppressWarnings("unused")
+ private SVGMouseOutEventListener mouseOutAction;
+ private SVGOMGElement mainGroup, labelGroup, portsGroup;
+ private SVGElement expandedElement, contractedElement;
+ private SVGOMPolygonElement polygon, completedPolygon;
+ private SVGOMEllipseElement ellipse;
+ private SVGOMTextElement label, iteration, error;
+ private Text labelText, iterationText, errorsText;
+ private SVGElement deleteButton;
+ private SVGOMAnimationElement animateShape, animatePosition, animateLabel, animateIteration,
+ animateErrors;
+
+ public SVGGraphNode(SVGGraphController graphController) {
+ super(graphController);
+ this.graphController = graphController;
+ mouseClickAction = new SVGMouseClickEventListener(this);
+ mouseDownAction = new SVGMouseDownEventListener(this);
+ mouseMovedAction = new SVGMouseMovedEventListener(this);
+ mouseOverAction = new SVGMouseOverEventListener(this);
+ mouseOutAction = new SVGMouseOutEventListener(this);
+
+ mainGroup = graphController.createGElem();
+ mainGroup.setAttribute("alignment-baseline", SVG_MIDDLE_VALUE);
+ mainGroup.setAttribute(SVG_STROKE_ATTRIBUTE, CSS_BLACK_VALUE);
+ mainGroup.setAttribute(SVG_STROKE_DASHARRAY_ATTRIBUTE, CSS_NONE_VALUE);
+ mainGroup.setAttribute(SVG_STROKE_WIDTH_ATTRIBUTE, "1");
+ mainGroup.setAttribute(SVG_FILL_ATTRIBUTE, CSS_NONE_VALUE);
+
+ EventTarget t = (EventTarget) mainGroup;
+ t.addEventListener(SVG_CLICK_EVENT_TYPE, mouseClickAction, false);
+ t.addEventListener(SVG_MOUSEMOVE_EVENT_TYPE, mouseMovedAction, false);
+ t.addEventListener(SVG_MOUSEDOWN_EVENT_TYPE, mouseDownAction, false);
+// t.addEventListener(SVGConstants.SVG_MOUSEOVER_EVENT_TYPE, mouseOverAction, false);
+// t.addEventListener(SVGConstants.SVG_MOUSEOUT_EVENT_TYPE, mouseOutAction, false);
+
+ expandedElement = graphController.createGElem();
+ contractedElement = graphController.createGElem();
+
+ portsGroup = graphController.createGElem();
+ portsGroup.setAttribute(CSS_DISPLAY_PROPERTY, CSS_NONE_VALUE);
+ contractedElement.appendChild(portsGroup);
+
+ mainGroup.appendChild(contractedElement);
+
+ polygon = graphController.createPolygon();
+ contractedElement.appendChild(polygon);
+
+ ellipse = graphController.createEllipse();
+ ellipse.setAttribute(CSS_DISPLAY_PROPERTY, CSS_NONE_VALUE);
+ ellipse.setAttribute(SVG_RX_ATTRIBUTE, String.valueOf(2));
+ ellipse.setAttribute(SVG_CX_ATTRIBUTE, String.valueOf(0));
+ ellipse.setAttribute(SVG_RY_ATTRIBUTE, String.valueOf(2));
+ ellipse.setAttribute(SVG_CY_ATTRIBUTE, String.valueOf(0));
+ contractedElement.appendChild(ellipse);
+
+ completedPolygon = graphController.createPolygon();
+ completedPolygon.setAttribute(SVG_POINTS_ATTRIBUTE,
+ calculatePoints(getShape(), 0, 0));
+ completedPolygon.setAttribute(SVG_FILL_ATTRIBUTE, COMPLETED_COLOUR);
+ completedPolygon.setAttribute(SVG_FILL_OPACITY_ATTRIBUTE, "0.8");
+ contractedElement.appendChild(completedPolygon);
+
+ labelText = graphController.createText("");
+ label = graphController.createText(labelText);
+ label.setAttribute(SVG_TEXT_ANCHOR_ATTRIBUTE, SVG_MIDDLE_VALUE);
+ label.setAttribute("baseline-shift", "-35%");
+ label.setAttribute(SVG_FILL_ATTRIBUTE, CSS_BLACK_VALUE);
+ label.setAttribute(SVG_STROKE_ATTRIBUTE, SVGConstants.SVG_NONE_VALUE);
+ labelGroup = graphController.createGElem();
+ labelGroup.appendChild(label);
+ contractedElement.appendChild(labelGroup);
+
+ iterationText = graphController.createText("");
+ iteration = graphController.createText(iterationText);
+ iteration.setAttribute(SVG_TEXT_ANCHOR_ATTRIBUTE, SVG_END_VALUE);
+ iteration.setAttribute(SVG_FONT_SIZE_ATTRIBUTE, "6");
+ iteration.setAttribute(SVG_FONT_FAMILY_ATTRIBUTE, "sans-serif");
+ iteration.setAttribute(SVG_FILL_ATTRIBUTE, CSS_BLACK_VALUE);
+ iteration.setAttribute(SVG_STROKE_ATTRIBUTE, SVG_NONE_VALUE);
+ contractedElement.appendChild(iteration);
+
+ errorsText = graphController.createText("");
+ error = graphController.createText(errorsText);
+ error.setAttribute(SVG_TEXT_ANCHOR_ATTRIBUTE, SVG_END_VALUE);
+ error.setAttribute(SVG_FONT_SIZE_ATTRIBUTE, "6");
+ error.setAttribute(SVG_FONT_FAMILY_ATTRIBUTE, "sans-serif");
+ error.setAttribute(SVG_FILL_ATTRIBUTE, CSSConstants.CSS_BLACK_VALUE);
+ error.setAttribute(SVG_STROKE_ATTRIBUTE, SVG_NONE_VALUE);
+ contractedElement.appendChild(error);
+
+ // deleteButton = createDeleteButton();
+ // g.appendChild(deleteButton);
+
+ animateShape = createAnimationElement(graphController, SVG_ANIMATE_TAG,
+ SVG_POINTS_ATTRIBUTE, null);
+
+ animatePosition = createAnimationElement(graphController,
+ SVG_ANIMATE_TRANSFORM_TAG, SVG_TRANSFORM_ATTRIBUTE,
+ TRANSFORM_TRANSLATE);
+
+ animateLabel = SVGUtil.createAnimationElement(graphController,
+ SVG_ANIMATE_TRANSFORM_TAG, SVG_TRANSFORM_ATTRIBUTE,
+ TRANSFORM_TRANSLATE);
+
+ animateIteration = createAnimationElement(graphController,
+ SVG_ANIMATE_TRANSFORM_TAG, SVG_TRANSFORM_ATTRIBUTE,
+ TRANSFORM_TRANSLATE);
+
+ animateErrors = createAnimationElement(graphController,
+ SVG_ANIMATE_TRANSFORM_TAG, SVG_TRANSFORM_ATTRIBUTE,
+ TRANSFORM_TRANSLATE);
+
+ delegate = new SVGGraphElementDelegate(graphController, this, mainGroup);
+ }
+
+ @SuppressWarnings("unused")
+ private SVGElement createDeleteButton() {
+ final SVGOMGElement button = graphController.createGElem();
+ button.setAttribute(CSS_VISIBILITY_PROPERTY, CSS_HIDDEN_VALUE);
+ button.setAttribute(CSS_POINTER_EVENTS_PROPERTY, CSS_ALL_VALUE);
+
+ SVGOMRectElement rect = graphController.createRect();
+ rect.setAttribute(SVG_X_ATTRIBUTE, "4");
+ rect.setAttribute(SVG_Y_ATTRIBUTE, "4");
+ rect.setAttribute(SVG_WIDTH_ATTRIBUTE, "13");
+ rect.setAttribute(SVG_HEIGHT_ATTRIBUTE, "13");
+ rect.setAttribute(SVG_FILL_ATTRIBUTE, "none");
+ button.appendChild(rect);
+
+ final SVGOMPathElement path = graphController.createPath();
+ path.setAttribute(SVG_STROKE_ATTRIBUTE, "white");
+ path.setAttribute(SVG_STROKE_WIDTH_ATTRIBUTE, "2");
+ path.setAttribute(SVG_D_ATTRIBUTE, "M5,5L12,12M5,12L12,5");
+ button.appendChild(path);
+
+ EventTarget t = (EventTarget) button;
+ t.addEventListener(SVG_MOUSEOVER_EVENT_TYPE, new EventListener() {
+ @Override
+ public void handleEvent(Event evt) {
+ if (isInteractive()) {
+ deleteButton.setAttribute(CSS_VISIBILITY_PROPERTY,
+ CSS_VISIBLE_VALUE);
+ path.setAttribute(SVG_STROKE_ATTRIBUTE, "red");
+ evt.stopPropagation();
+ }
+ }
+ }, false);
+ t.addEventListener(SVG_MOUSEOUT_EVENT_TYPE, new EventListener() {
+ @Override
+ public void handleEvent(Event evt) {
+ if (isInteractive()) {
+ path.setAttribute(SVG_STROKE_ATTRIBUTE, "white");
+ evt.stopPropagation();
+ }
+ }
+ }, false);
+
+ return button;
+ }
+
+ public SVGElement getSVGElement() {
+ return mainGroup;
+ }
+
+ @Override
+ public void setActive(final boolean active) {
+ super.setActive(active);
+ if (isInteractive())
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ if (active) {
+ deleteButton.setAttribute(CSS_VISIBILITY_PROPERTY,
+ CSS_VISIBLE_VALUE);
+ // deleteButton.setAttribute(CSSConstants.CSS_DISPLAY_PROPERTY,
+ // CSSConstants.CSS_INLINE_VALUE);
+ } else {
+ deleteButton.setAttribute(CSS_VISIBILITY_PROPERTY,
+ CSS_HIDDEN_VALUE);
+ // button.setAttribute(CSSConstants.CSS_DISPLAY_PROPERTY,
+ // CSSConstants.CSS_NONE_VALUE);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void setGraph(Graph graph) {
+ super.setGraph(graph);
+ if (graph instanceof SVGGraph) {
+ SVGGraph svgGraph = (SVGGraph) graph;
+ final SVGElement graphElement = svgGraph.getSVGElement();
+ if (isExpanded())
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ mainGroup.replaceChild(expandedElement, graphElement);
+ }
+ });
+ expandedElement = graphElement;
+ }
+ }
+
+ @Override
+ public void setExpanded(final boolean expanded) {
+ if (isExpanded() != expanded)
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ if (expanded)
+ mainGroup.replaceChild(expandedElement, contractedElement);
+ else
+ mainGroup.replaceChild(contractedElement, expandedElement);
+ }
+ });
+ super.setExpanded(expanded);
+ }
+
+ @Override
+ public void addSourceNode(final GraphNode sourceNode) {
+ super.addSourceNode(sourceNode);
+ if (sourceNode instanceof SVGGraphNode)
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ SVGGraphNode svgGraphNode = (SVGGraphNode) sourceNode;
+ portsGroup.appendChild(svgGraphNode.getSVGElement());
+ }
+ });
+ }
+
+ @Override
+ public boolean removeSourceNode(final GraphNode sourceNode) {
+ if (sourceNode instanceof SVGGraphNode)
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ SVGGraphNode svgGraphNode = (SVGGraphNode) sourceNode;
+ portsGroup.removeChild(svgGraphNode.getSVGElement());
+ }
+ });
+ return super.removeSourceNode(sourceNode);
+ }
+
+ @Override
+ public void addSinkNode(final GraphNode sinkNode) {
+ super.addSinkNode(sinkNode);
+ if (sinkNode instanceof SVGGraphNode)
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ SVGGraphNode svgGraphNode = (SVGGraphNode) sinkNode;
+ portsGroup.appendChild(svgGraphNode.getSVGElement());
+ }
+ });
+ }
+
+ @Override
+ public boolean removeSinkNode(final GraphNode sinkNode) {
+ if (sinkNode instanceof SVGGraphNode)
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ SVGGraphNode svgGraphNode = (SVGGraphNode) sinkNode;
+ portsGroup.removeChild(svgGraphNode.getSVGElement());
+ }
+ });
+ return super.removeSinkNode(sinkNode);
+ }
+
+ @Override
+ public void setPosition(final Point position) {
+ final Point oldPosition = getPosition();
+ if (position != null && !position.equals(oldPosition)) {
+ super.setPosition(position);
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ if (graphController.isAnimatable())
+ animate(animatePosition, mainGroup,
+ graphController.getAnimationSpeed(),
+ oldPosition.x + ", " + oldPosition.y,
+ position.x + ", " + position.y);
+ else
+ mainGroup.setAttribute(SVG_TRANSFORM_ATTRIBUTE,
+ "translate(" + position.x + " " + position.y
+ + ")");
+ }
+ });
+ }
+ }
+
+ @Override
+ public void setSize(final Dimension size) {
+ final Dimension oldSize = getSize();
+ if (size != null && !size.equals(oldSize)) {
+ super.setSize(size);
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ adjustSize(size, oldSize);
+ }
+ });
+ }
+ }
+
+ /** core of implementation of {@link #setSize(Dimension)} */
+ private void adjustSize(Dimension size, Dimension oldSize) {
+ int oldWidth = oldSize.width;
+ int oldHeight = oldSize.height;
+ if (graphController.isAnimatable()) {
+ if (Shape.CIRCLE.equals(getShape())) {
+ ellipse.setAttribute(SVG_RX_ATTRIBUTE,
+ String.valueOf(size.width / 2f));
+ ellipse.setAttribute(SVG_CX_ATTRIBUTE,
+ String.valueOf(size.width / 2f));
+ ellipse.setAttribute(SVG_RY_ATTRIBUTE,
+ String.valueOf(size.height / 2f));
+ ellipse.setAttribute(SVG_CY_ATTRIBUTE,
+ String.valueOf(size.height / 2f));
+ } else
+ animate(animateShape, polygon,
+ graphController.getAnimationSpeed(),
+ calculatePoints(getShape(), oldWidth, oldHeight),
+ calculatePoints(getShape(), getWidth(), getHeight()));
+
+ if (getLabel() != null && !getLabel().isEmpty())
+ animate(animateLabel, labelGroup,
+ graphController.getAnimationSpeed(), (oldWidth / 2f)
+ + ", " + (oldHeight / 2f), (getWidth() / 2f)
+ + ", " + (getHeight() / 2f));
+ else
+ labelGroup.setAttribute(SVG_TRANSFORM_ATTRIBUTE,
+ "translate(" + getWidth() / 2f + " " + getHeight() / 2f + ")");
+
+ if (getIteration() > 0)
+ animate(animateIteration, iteration,
+ graphController.getAnimationSpeed(), (oldWidth - 1.5)
+ + ", 5.5", (getWidth() - 1.5) + ", 5.5");
+ else
+ iteration.setAttribute(SVG_TRANSFORM_ATTRIBUTE, "translate("
+ + (getWidth() - 1.5) + " 5.5)");
+
+ if (getErrors() > 0)
+ animate(animateErrors, error,
+ graphController.getAnimationSpeed(), (oldWidth - 1.5)
+ + ", " + (oldHeight - 1), (getWidth() - 1.5)
+ + ", " + (getHeight() - 1));
+ else
+ error.setAttribute(SVG_TRANSFORM_ATTRIBUTE, "translate("
+ + (getWidth() - 1.5) + " " + (getHeight() - 1) + ")");
+ } else {
+ if (Shape.CIRCLE.equals(getShape())) {
+ ellipse.setAttribute(SVG_RX_ATTRIBUTE,
+ String.valueOf(size.width / 2f));
+ ellipse.setAttribute(SVG_CX_ATTRIBUTE,
+ String.valueOf(size.width / 2f));
+ ellipse.setAttribute(SVG_RY_ATTRIBUTE,
+ String.valueOf(size.height / 2f));
+ ellipse.setAttribute(SVG_CY_ATTRIBUTE,
+ String.valueOf(size.height / 2f));
+ } else
+ polygon.setAttribute(SVG_POINTS_ATTRIBUTE,
+ calculatePoints(getShape(), getWidth(), getHeight()));
+
+ labelGroup.setAttribute(SVG_TRANSFORM_ATTRIBUTE, "translate("
+ + getWidth() / 2f + " " + getHeight() / 2f + ")");
+ iteration.setAttribute(SVG_TRANSFORM_ATTRIBUTE, "translate("
+ + (getWidth() - 1.5) + " 5.5)");
+ error.setAttribute(SVG_TRANSFORM_ATTRIBUTE, "translate("
+ + (getWidth() - 1.5) + " " + (getHeight() - 1) + ")");
+ }
+ }
+
+ @Override
+ public void setShape(final Shape shape) {
+ final Shape currentShape = getShape();
+ if (shape != null && !shape.equals(currentShape)) {
+ super.setShape(shape);
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ if (Shape.CIRCLE.equals(shape)) {
+ ellipse.setAttribute(CSS_DISPLAY_PROPERTY,
+ CSS_INLINE_VALUE);
+ polygon.setAttribute(CSS_DISPLAY_PROPERTY,
+ CSS_NONE_VALUE);
+ } else if (Shape.CIRCLE.equals(currentShape)) {
+ ellipse.setAttribute(CSS_DISPLAY_PROPERTY,
+ CSS_NONE_VALUE);
+ polygon.setAttribute(CSS_DISPLAY_PROPERTY,
+ CSS_INLINE_VALUE);
+ }
+ if (Shape.RECORD.equals(shape))
+ portsGroup.setAttribute(CSS_DISPLAY_PROPERTY,
+ CSS_INLINE_VALUE);
+ else if (Shape.RECORD.equals(currentShape))
+ portsGroup.setAttribute(CSS_DISPLAY_PROPERTY,
+ CSS_NONE_VALUE);
+ }
+ });
+ }
+ }
+
+ @Override
+ public void setLabel(final String label) {
+ super.setLabel(label);
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ labelText.setData(label);
+ }
+ });
+ }
+
+ @Override
+ public void setIteration(final int iteration) {
+ super.setIteration(iteration);
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ if (iteration > 0)
+ iterationText.setData(String.valueOf(iteration));
+ else
+ iterationText.setData("");
+ }
+ });
+ }
+
+ @Override
+ public void setErrors(final int errors) {
+ super.setErrors(errors);
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ if (errors > 0) {
+ errorsText.setData(String.valueOf(errors));
+ completedPolygon.setAttribute(SVG_FILL_ATTRIBUTE,
+ ERROR_COLOUR);
+ } else {
+ errorsText.setData("");
+ completedPolygon.setAttribute(SVG_FILL_ATTRIBUTE,
+ COMPLETED_COLOUR);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void setCompleted(final float complete) {
+ super.setCompleted(complete);
+ graphController.updateSVGDocument(new Runnable() {
+ @Override
+ public void run() {
+ completedPolygon.setAttribute(
+ SVG_POINTS_ATTRIBUTE,
+ calculatePoints(getShape(),
+ (int) (getWidth() * complete), getHeight()));
+ }
+ });
+ }
+
+ @Override
+ public void setSelected(final boolean selected) {
+ delegate.setSelected(selected);
+ super.setSelected(selected);
+ }
+
+ @Override
+ public void setLineStyle(final LineStyle lineStyle) {
+ delegate.setLineStyle(lineStyle);
+ super.setLineStyle(lineStyle);
+ }
+
+ @Override
+ public void setColor(final Color color) {
+ delegate.setColor(color);
+ super.setColor(color);
+ }
+
+ @Override
+ public void setFillColor(final Color fillColor) {
+ delegate.setFillColor(fillColor);
+ super.setFillColor(fillColor);
+ }
+
+ @Override
+ public void setVisible(final boolean visible) {
+ delegate.setVisible(visible);
+ super.setVisible(visible);
+ }
+
+ @Override
+ public void setFiltered(final boolean filtered) {
+ delegate.setFiltered(filtered);
+ super.setFiltered(filtered);
+ }
+
+ @Override
+ public void setOpacity(final float opacity) {
+ delegate.setOpacity(opacity);
+ super.setOpacity(opacity);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphSettings.java
----------------------------------------------------------------------
diff --git a/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphSettings.java b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphSettings.java
new file mode 100644
index 0000000..2e9e228
--- /dev/null
+++ b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGGraphSettings.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package org.apache.taverna.workbench.models.graph.svg;
+
+public interface SVGGraphSettings {
+ String COMPLETED_COLOUR = "grey";
+ String ERROR_COLOUR = "#dd3131";
+ String SELECTED_COLOUR = "#4377d3";
+ String NORMAL_COLOUR = "black";
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGMonitorShape.java
----------------------------------------------------------------------
diff --git a/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGMonitorShape.java b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGMonitorShape.java
new file mode 100644
index 0000000..7944fc1
--- /dev/null
+++ b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGMonitorShape.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package org.apache.taverna.workbench.models.graph.svg;
+
+import org.apache.batik.dom.svg.SVGOMPolygonElement;
+
+public interface SVGMonitorShape extends SVGShape {
+ /**
+ * Returns the polygon used to display the completed value.
+ *
+ * @return the polygon used to display the completed value
+ */
+ SVGOMPolygonElement getCompletedPolygon();
+
+ /**
+ * Sets the polygon used to display the completed value.
+ *
+ * @param polygon
+ * the new polygon used to display the completed value
+ */
+ void setCompletedPolygon(SVGOMPolygonElement polygon);
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGShape.java
----------------------------------------------------------------------
diff --git a/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGShape.java b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGShape.java
new file mode 100644
index 0000000..2bf4bf9
--- /dev/null
+++ b/taverna-graph-model/src/main/java/org/apache/taverna/workbench/models/graph/svg/SVGShape.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package org.apache.taverna.workbench.models.graph.svg;
+
+public interface SVGShape {
+ public void setIteration(final int iteration);
+
+ // public void setErrors(final int errors);
+
+ // public void setCompleted(final float complete);
+}