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/27 16:33:31 UTC

[03/11] incubator-taverna-workbench git commit:

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/net/sf/taverna/t2/workbench/views/graph/toolbar/GraphEditToolbarSection.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/net/sf/taverna/t2/workbench/views/graph/toolbar/GraphEditToolbarSection.java b/taverna-graph-view/src/main/java/net/sf/taverna/t2/workbench/views/graph/toolbar/GraphEditToolbarSection.java
deleted file mode 100644
index 7a06acc..0000000
--- a/taverna-graph-view/src/main/java/net/sf/taverna/t2/workbench/views/graph/toolbar/GraphEditToolbarSection.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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 net.sf.taverna.t2.workbench.views.graph.toolbar;
-
-import static org.apache.taverna.ui.menu.DefaultToolBar.DEFAULT_TOOL_BAR;
-
-import java.net.URI;
-
-import org.apache.taverna.ui.menu.AbstractMenuSection;
-
-/**
- * @author Alex Nenadic
- */
-public class GraphEditToolbarSection extends AbstractMenuSection {
-	public static final URI GRAPH_EDIT_TOOLBAR_SECTION = URI
-			.create("http://taverna.sf.net/2008/t2workbench/menu#graphEditToolbarSection");
-
-	public GraphEditToolbarSection() {
-		super(DEFAULT_TOOL_BAR, 30, GRAPH_EDIT_TOOLBAR_SECTION);
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/net/sf/taverna/t2/workbench/views/graph/toolbar/RenameWFInputOutputProcessorToolbarAction.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/net/sf/taverna/t2/workbench/views/graph/toolbar/RenameWFInputOutputProcessorToolbarAction.java b/taverna-graph-view/src/main/java/net/sf/taverna/t2/workbench/views/graph/toolbar/RenameWFInputOutputProcessorToolbarAction.java
deleted file mode 100644
index 4a55db8..0000000
--- a/taverna-graph-view/src/main/java/net/sf/taverna/t2/workbench/views/graph/toolbar/RenameWFInputOutputProcessorToolbarAction.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * 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 net.sf.taverna.t2.workbench.views.graph.toolbar;
-
-import static net.sf.taverna.t2.workbench.views.graph.toolbar.GraphEditToolbarSection.GRAPH_EDIT_TOOLBAR_SECTION;
-
-import java.net.URI;
-
-import javax.swing.Action;
-
-import org.apache.taverna.ui.menu.AbstractMenuAction;
-import org.apache.taverna.workbench.edits.EditManager;
-import org.apache.taverna.workbench.selection.SelectionManager;
-import net.sf.taverna.t2.workbench.views.graph.actions.RenameWFInputOutputProcessorAction;
-
-/**
- * @author Alex Nenadic
- */
-public class RenameWFInputOutputProcessorToolbarAction extends
-		AbstractMenuAction {
-	private static final URI RENAME_WF_INPUT_OUTPUT_PROCESSOR_URI = URI
-			.create("http://taverna.sf.net/2008/t2workbench/menu#graphToolbarRenameWFInputOutputProcessor");
-
-	private EditManager editManager;
-	private SelectionManager selectionManager;
-
-	public RenameWFInputOutputProcessorToolbarAction() {
-		super(GRAPH_EDIT_TOOLBAR_SECTION, 30,
-				RENAME_WF_INPUT_OUTPUT_PROCESSOR_URI);
-	}
-
-	@Override
-	protected Action createAction() {
-		return new RenameWFInputOutputProcessorAction(editManager,
-				selectionManager);
-	}
-
-	public void setEditManager(EditManager editManager) {
-		this.editManager = editManager;
-	}
-
-	public void setSelectionManager(SelectionManager selectionManager) {
-		this.selectionManager = selectionManager;
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/AutoScrollInteractor.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/AutoScrollInteractor.java b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/AutoScrollInteractor.java
new file mode 100644
index 0000000..50237ea
--- /dev/null
+++ b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/AutoScrollInteractor.java
@@ -0,0 +1,200 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.views.graph;
+
+import static java.awt.event.InputEvent.BUTTON1_DOWN_MASK;
+import static java.awt.event.InputEvent.BUTTON1_MASK;
+import static java.awt.event.MouseEvent.BUTTON1;
+import static java.awt.event.MouseEvent.MOUSE_DRAGGED;
+import static java.awt.event.MouseEvent.MOUSE_PRESSED;
+import static java.lang.System.currentTimeMillis;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.awt.geom.AffineTransform;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.apache.batik.swing.JSVGCanvas;
+import org.apache.batik.swing.gvt.InteractorAdapter;
+import org.apache.batik.swing.gvt.JGVTComponent;
+
+/**
+ * An interactor that scrolls the canvas view if the mouse is dragged to the
+ * edge of the canvas.
+ * 
+ * @author David Withers
+ */
+public class AutoScrollInteractor extends InteractorAdapter {
+	/**
+	 * Defines the border around the canvas in which the auto scroll will become
+	 * active.
+	 */
+	private static final int BORDER = 25;
+	/**
+	 * The interval, in milliseconds, between scroll events.
+	 */
+	private static final long SCROLL_INTERVAL = 100;
+
+	private JSVGCanvas svgCanvas;
+	private Dimension canvasSize;
+	private int scrollX;
+	private int scrollY;
+	private int mouseX;
+	private int mouseY;
+
+	/**
+	 * Component used to identify mouse events generated by this class
+	 */
+	private Component eventIdentifier = new Component() {
+		private static final long serialVersionUID = -295542754718804222L;
+	};
+
+	private static Timer timer = new Timer("GraphAutoScrollTimer", true);
+
+	private TimerTask task;
+
+	/**
+	 * Whether the interactor has finished.
+	 */
+	protected boolean finished = true;
+
+	public AutoScrollInteractor(JSVGCanvas svgCanvas) {
+		this.svgCanvas = svgCanvas;
+	}
+
+	@Override
+	public boolean startInteraction(InputEvent ie) {
+		int mods = ie.getModifiers();
+		if (ie.getID() == MOUSE_PRESSED && (mods & BUTTON1_MASK) != 0) {
+			AffineTransform transform = svgCanvas.getRenderingTransform();
+			// check if we're zoomed in
+			if (transform.getScaleX() > 1d || transform.getScaleY() > 1d) {
+				canvasSize = svgCanvas.getSize();
+				return true;
+			}
+		}
+		return false;
+	}
+
+	@Override
+	public boolean endInteraction() {
+		return finished;
+	}
+
+	@Override
+	public void mousePressed(final MouseEvent e) {
+		if (startInteraction(e)) {
+			finished = false;
+			task = new TimerTask() {
+				@Override
+				public void run() {
+					scrollTimerCallback(e);
+				}
+			};
+			timer.schedule(task, 0, SCROLL_INTERVAL);
+		}
+	}
+
+	/**
+	 * Dispatches a mouse drag event that updates the mouse location by the
+	 * amount that the canvas has been scrolled.
+	 * 
+	 * @param dragX
+	 * @param dragY
+	 */
+	private void dispatchDragEvent(double dragX, double dragY) {
+		int x = (int) (mouseX + dragX);
+		int y = (int) (mouseY + dragY);
+		MouseEvent mouseDragEvent = new MouseEvent(eventIdentifier,
+				MOUSE_DRAGGED, currentTimeMillis(), BUTTON1_DOWN_MASK, x, y, 1,
+				false, BUTTON1);
+		svgCanvas.dispatchEvent(mouseDragEvent);
+	}
+
+	@Override
+	public void mouseReleased(MouseEvent e) {
+		if (!finished) {
+			finished = true;
+			scrollX = 0;
+			scrollY = 0;
+			if (task != null)
+				task.cancel();
+		}
+	}
+
+	@Override
+	public void mouseDragged(MouseEvent e) {
+		// ignore events generated by this class
+		if (!finished && e.getSource() != eventIdentifier) {
+			mouseX = e.getX();
+			mouseY = e.getY();
+			int minX = BORDER;
+			int maxX = canvasSize.width - BORDER;
+			int minY = BORDER;
+			int maxY = canvasSize.height - BORDER;
+
+			scrollX = (mouseX < minX) ? (minX - mouseX)
+					: (mouseX > maxX) ? (maxX - mouseX) : 0;
+			scrollY = (mouseY < minY) ? (minY - mouseY)
+					: (mouseY > maxY) ? (maxY - mouseY) : 0;
+		}
+	}
+
+	private void scrollTimerCallback(MouseEvent e) {
+		double x = scrollX;
+		double y = scrollY;
+		if (x == 0 && y == 0)
+			return;
+
+		JGVTComponent c = (JGVTComponent) e.getSource();
+		AffineTransform rt = (AffineTransform) c.getRenderingTransform()
+				.clone();
+		double currentTranslateX = rt.getTranslateX();
+		double currentTranslateY = rt.getTranslateY();
+		// the tranlation that will show the east edge
+		double maxTranslateX = -((canvasSize.width * rt.getScaleX()) - canvasSize.width);
+		// the translation that will show the south
+		double maxTranslateY = -((canvasSize.height * rt.getScaleY()) - canvasSize.height);
+
+		if (x > 0 && currentTranslateX + x > 0)
+			// scroll left && not at west edge
+			x = -currentTranslateX;
+		else if (x < 0 && currentTranslateX + x < maxTranslateX)
+			// scroll right && not at east edge
+			x = maxTranslateX - currentTranslateX;
+
+		if (y > 0 && currentTranslateY + y > 0)
+			// scroll up && not at north edge
+			y = -currentTranslateY;
+		else if (y < 0 && currentTranslateY + y < maxTranslateY)
+			// scroll down && not at south edge
+			y = maxTranslateY - currentTranslateY;
+
+		if (x != 0d || y != 0d) {
+			AffineTransform at = AffineTransform.getTranslateInstance(x, y);
+			rt.preConcatenate(at);
+			c.setRenderingTransform(rt);
+			dispatchDragEvent(x, y);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/GraphViewComponent.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/GraphViewComponent.java b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/GraphViewComponent.java
new file mode 100644
index 0000000..4ec1a28
--- /dev/null
+++ b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/GraphViewComponent.java
@@ -0,0 +1,547 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.views.graph;
+
+import static java.awt.BorderLayout.CENTER;
+import static java.awt.BorderLayout.NORTH;
+import static javax.swing.Action.SHORT_DESCRIPTION;
+import static javax.swing.Action.SMALL_ICON;
+import static javax.swing.BoxLayout.PAGE_AXIS;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.allportIcon;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.blobIcon;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.expandNestedIcon;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.horizontalIcon;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.noportIcon;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.refreshIcon;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.verticalIcon;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.zoomInIcon;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.zoomOutIcon;
+import static org.apache.taverna.workbench.views.graph.config.GraphViewConfiguration.ALIGNMENT;
+import static org.apache.taverna.workbench.views.graph.config.GraphViewConfiguration.ANIMATION_ENABLED;
+import static org.apache.taverna.workbench.views.graph.config.GraphViewConfiguration.ANIMATION_SPEED;
+import static org.apache.taverna.workbench.views.graph.config.GraphViewConfiguration.PORT_STYLE;
+import static org.apache.batik.swing.svg.AbstractJSVGComponent.ALWAYS_DYNAMIC;
+
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.JToggleButton;
+import javax.swing.JToolBar;
+import javax.swing.Timer;
+import javax.swing.border.EmptyBorder;
+
+import org.apache.taverna.lang.observer.Observable;
+import org.apache.taverna.lang.observer.SwingAwareObserver;
+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.edits.EditManager.AbstractDataflowEditEvent;
+import org.apache.taverna.workbench.edits.EditManager.EditManagerEvent;
+import org.apache.taverna.workbench.file.FileManager;
+import org.apache.taverna.workbench.file.events.ClosedDataflowEvent;
+import org.apache.taverna.workbench.file.events.FileManagerEvent;
+import org.apache.taverna.workbench.models.graph.Graph.Alignment;
+import org.apache.taverna.workbench.models.graph.GraphController;
+import org.apache.taverna.workbench.models.graph.GraphController.PortStyle;
+import org.apache.taverna.workbench.models.graph.svg.SVGGraphController;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.selection.events.SelectionManagerEvent;
+import org.apache.taverna.workbench.selection.events.WorkflowBundleSelectionEvent;
+import org.apache.taverna.workbench.selection.events.WorkflowSelectionEvent;
+import org.apache.taverna.workbench.ui.dndhandler.ServiceTransferHandler;
+import org.apache.taverna.workbench.ui.zaria.UIComponentSPI;
+import org.apache.taverna.workbench.views.graph.config.GraphViewConfiguration;
+import org.apache.taverna.workbench.views.graph.menu.ResetDiagramAction;
+import org.apache.taverna.workbench.views.graph.menu.ZoomInAction;
+import org.apache.taverna.workbench.views.graph.menu.ZoomOutAction;
+
+import org.apache.batik.swing.JSVGCanvas;
+import org.apache.batik.swing.JSVGScrollPane;
+import org.apache.batik.swing.gvt.GVTTreeRendererAdapter;
+import org.apache.batik.swing.gvt.GVTTreeRendererEvent;
+import org.apache.log4j.Logger;
+
+import org.apache.taverna.commons.services.ServiceRegistry;
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.scufl2.api.core.Workflow;
+
+/**
+ * @author David Withers
+ * @author Alex Nenadic
+ * @author Tom Oinn
+ */
+public class GraphViewComponent extends JPanel implements UIComponentSPI {
+	private static final long serialVersionUID = 7404937056378331528L;
+	private static final Logger logger = Logger.getLogger(GraphViewComponent.class);
+
+	private Workflow workflow;
+	private SVGGraphController graphController;
+	private JPanel diagramPanel;
+
+	private Map<WorkflowBundle, Set<Workflow>> workflowsMap = new IdentityHashMap<>();
+
+	private Map<Workflow, SVGGraphController> graphControllerMap = new IdentityHashMap<>();
+	private Map<Workflow, JPanel> diagramPanelMap = new IdentityHashMap<>();
+	private Map<Workflow, Action[]> diagramActionsMap = new IdentityHashMap<>();
+
+	private Timer timer;
+
+	private CardLayout cardLayout;
+
+	private final ColourManager colourManager;
+	private final EditManager editManager;
+	private final MenuManager menuManager;
+	private final GraphViewConfiguration graphViewConfiguration;
+	private final WorkbenchConfiguration workbenchConfiguration;
+	private final SelectionManager selectionManager;
+	private final ServiceRegistry serviceRegistry;
+
+	public GraphViewComponent(ColourManager colourManager,
+			EditManager editManager, FileManager fileManager,
+			MenuManager menuManager,
+			GraphViewConfiguration graphViewConfiguration,
+			WorkbenchConfiguration workbenchConfiguration,
+			SelectionManager selectionManager, ServiceRegistry serviceRegistry) {
+		this.colourManager = colourManager;
+		this.editManager = editManager;
+		this.menuManager = menuManager;
+		this.graphViewConfiguration = graphViewConfiguration;
+		this.workbenchConfiguration = workbenchConfiguration;
+		this.selectionManager = selectionManager;
+		this.serviceRegistry = serviceRegistry;
+
+		cardLayout = new CardLayout();
+		setLayout(cardLayout);
+
+		ActionListener taskPerformer = new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				if (graphController != null)
+					graphController.redraw();
+				timer.stop();
+			}
+		};
+		timer = new Timer(100, taskPerformer);
+
+		addComponentListener(new ComponentAdapter() {
+			@Override
+			public void componentResized(ComponentEvent e) {
+				if (timer.isRunning())
+					timer.restart();
+				else
+					timer.start();
+			}
+		});
+
+		editManager.addObserver(new EditManagerObserver());
+		selectionManager.addObserver(new SelectionManagerObserver());
+		fileManager.addObserver(new FileManagerObserver());
+	}
+
+	@Override
+	protected void finalize() throws Throwable {
+		if (timer != null)
+			timer.stop();
+	}
+
+	@Override
+	public String getName() {
+		return "Graph View Component";
+	}
+
+	@Override
+	public ImageIcon getIcon() {
+		return null;
+	}
+
+	@Override
+	public void onDisplay() {
+	}
+
+	@Override
+	public void onDispose() {
+		if (timer != null)
+			timer.stop();
+	}
+
+	private JPanel createDiagramPanel(Workflow workflow) {
+		final JPanel diagramPanel = new JPanel(new BorderLayout());
+
+		// get the default diagram settings
+		Alignment alignment = Alignment.valueOf(graphViewConfiguration
+				.getProperty(ALIGNMENT));
+		PortStyle portStyle = PortStyle.valueOf(graphViewConfiguration
+				.getProperty(PORT_STYLE));
+		boolean animationEnabled = Boolean.parseBoolean(graphViewConfiguration
+				.getProperty(ANIMATION_ENABLED));
+		int animationSpeed = Integer.parseInt(graphViewConfiguration
+				.getProperty(ANIMATION_SPEED));
+
+		// create an SVG canvas
+		final JSVGCanvas svgCanvas = new JSVGCanvas(null, true, false);
+		svgCanvas.setEnableZoomInteractor(false);
+		svgCanvas.setEnableRotateInteractor(false);
+		svgCanvas.setDocumentState(ALWAYS_DYNAMIC);
+		svgCanvas.setTransferHandler(new ServiceTransferHandler(editManager,
+				menuManager, selectionManager, serviceRegistry));
+
+		AutoScrollInteractor asi = new AutoScrollInteractor(svgCanvas);
+		svgCanvas.addMouseListener(asi);
+		svgCanvas.addMouseMotionListener(asi);
+
+		final JSVGScrollPane svgScrollPane = new MySvgScrollPane(svgCanvas);
+
+		GVTTreeRendererAdapter gvtTreeRendererAdapter = new GVTTreeRendererAdapter() {
+			@Override
+			public void gvtRenderingCompleted(GVTTreeRendererEvent e) {
+				logger.info("Rendered svg");
+				svgScrollPane.reset();
+				diagramPanel.revalidate();
+			}
+		};
+		svgCanvas.addGVTTreeRendererListener(gvtTreeRendererAdapter);
+
+		// create a graph controller
+		SVGGraphController svgGraphController = new SVGGraphController(
+				workflow, selectionManager.getSelectedProfile(), false,
+				svgCanvas, alignment, portStyle, editManager, menuManager,
+				colourManager, workbenchConfiguration);
+		svgGraphController.setDataflowSelectionModel(selectionManager
+				.getDataflowSelectionModel(workflow.getParent()));
+		svgGraphController.setAnimationSpeed(animationEnabled ? animationSpeed
+				: 0);
+
+		graphControllerMap.put(workflow, svgGraphController);
+
+		// Toolbar with actions related to graph
+		JToolBar graphActionsToolbar = graphActionsToolbar(workflow,
+				svgGraphController, svgCanvas, alignment, portStyle);
+		graphActionsToolbar.setAlignmentX(LEFT_ALIGNMENT);
+		graphActionsToolbar.setFloatable(false);
+
+		// Panel to hold the toolbars
+		JPanel toolbarPanel = new JPanel();
+		toolbarPanel.setLayout(new BoxLayout(toolbarPanel, PAGE_AXIS));
+		toolbarPanel.add(graphActionsToolbar);
+
+		diagramPanel.add(toolbarPanel, NORTH);
+		diagramPanel.add(svgScrollPane, CENTER);
+
+		// JTextField workflowHierarchy = new JTextField(workflow.getName());
+		// diagramPanel.add(workflowHierarchy, BorderLayout.SOUTH);
+
+		return diagramPanel;
+	}
+
+	@SuppressWarnings("serial")
+	private JToolBar graphActionsToolbar(Workflow workflow,
+			final SVGGraphController graphController, JSVGCanvas svgCanvas,
+			Alignment alignment, PortStyle portStyle) {
+		JToolBar toolBar = new JToolBar();
+
+		JButton resetDiagramButton = new JButton();
+		resetDiagramButton.setBorder(new EmptyBorder(0, 2, 0, 2));
+		JButton zoomInButton = new JButton();
+		zoomInButton.setBorder(new EmptyBorder(0, 2, 0, 2));
+		JButton zoomOutButton = new JButton();
+		zoomOutButton.setBorder(new EmptyBorder(0, 2, 0, 2));
+
+		Action resetDiagramAction = svgCanvas.new ResetTransformAction();
+		ResetDiagramAction.setDesignAction(resetDiagramAction);
+		resetDiagramAction.putValue(SHORT_DESCRIPTION, "Reset Diagram");
+		resetDiagramAction.putValue(SMALL_ICON, refreshIcon);
+		resetDiagramButton.setAction(resetDiagramAction);
+
+		Action zoomInAction = svgCanvas.new ZoomAction(1.2);
+		ZoomInAction.setDesignAction(zoomInAction);
+		zoomInAction.putValue(SHORT_DESCRIPTION, "Zoom In");
+		zoomInAction.putValue(SMALL_ICON, zoomInIcon);
+		zoomInButton.setAction(zoomInAction);
+
+		Action zoomOutAction = svgCanvas.new ZoomAction(1 / 1.2);
+		ZoomOutAction.setDesignAction(zoomOutAction);
+		zoomOutAction.putValue(SHORT_DESCRIPTION, "Zoom Out");
+		zoomOutAction.putValue(SMALL_ICON, zoomOutIcon);
+		zoomOutButton.setAction(zoomOutAction);
+
+		diagramActionsMap.put(workflow, new Action[] { resetDiagramAction,
+				zoomInAction, zoomOutAction });
+
+		toolBar.add(resetDiagramButton);
+		toolBar.add(zoomInButton);
+		toolBar.add(zoomOutButton);
+
+		toolBar.addSeparator();
+
+		ButtonGroup nodeTypeGroup = new ButtonGroup();
+
+		JToggleButton noPorts = new JToggleButton();
+		JToggleButton allPorts = new JToggleButton();
+		JToggleButton blobs = new JToggleButton();
+		nodeTypeGroup.add(noPorts);
+		nodeTypeGroup.add(allPorts);
+		nodeTypeGroup.add(blobs);
+
+		if (portStyle.equals(PortStyle.NONE))
+			noPorts.setSelected(true);
+		else if (portStyle.equals(PortStyle.ALL))
+			allPorts.setSelected(true);
+		else
+			blobs.setSelected(true);
+
+		noPorts.setAction(new AbstractAction() {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				graphController.setPortStyle(PortStyle.NONE);
+				graphController.redraw();
+			}
+		});
+		noPorts.getAction().putValue(SHORT_DESCRIPTION,
+				"Display no service ports");
+		noPorts.getAction().putValue(SMALL_ICON, noportIcon);
+		noPorts.setFocusPainted(false);
+
+		allPorts.setAction(new AbstractAction() {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				graphController.setPortStyle(PortStyle.ALL);
+				graphController.redraw();
+			}
+		});
+		allPorts.getAction().putValue(SHORT_DESCRIPTION,
+				"Display all service ports");
+		allPorts.getAction().putValue(SMALL_ICON, allportIcon);
+		allPorts.setFocusPainted(false);
+
+		blobs.setAction(new AbstractAction() {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				graphController.setPortStyle(PortStyle.BLOB);
+				graphController.redraw();
+			}
+		});
+		blobs.getAction().putValue(SHORT_DESCRIPTION,
+				"Display services as circles");
+		blobs.getAction().putValue(SMALL_ICON, blobIcon);
+		blobs.setFocusPainted(false);
+
+		toolBar.add(noPorts);
+		toolBar.add(allPorts);
+		toolBar.add(blobs);
+
+		toolBar.addSeparator();
+
+		ButtonGroup alignmentGroup = new ButtonGroup();
+
+		JToggleButton vertical = new JToggleButton();
+		JToggleButton horizontal = new JToggleButton();
+		alignmentGroup.add(vertical);
+		alignmentGroup.add(horizontal);
+
+		if (alignment.equals(Alignment.VERTICAL)) {
+			vertical.setSelected(true);
+		} else {
+			horizontal.setSelected(true);
+		}
+
+		vertical.setAction(new AbstractAction() {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				graphController.setAlignment(Alignment.VERTICAL);
+				graphController.redraw();
+			}
+		});
+		vertical.getAction().putValue(SHORT_DESCRIPTION,
+				"Align services vertically");
+		vertical.getAction().putValue(SMALL_ICON, verticalIcon);
+		vertical.setFocusPainted(false);
+
+		horizontal.setAction(new AbstractAction() {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				graphController.setAlignment(Alignment.HORIZONTAL);
+				graphController.redraw();
+			}
+
+		});
+		horizontal.getAction().putValue(SHORT_DESCRIPTION,
+				"Align services horizontally");
+		horizontal.getAction().putValue(SMALL_ICON, horizontalIcon);
+		horizontal.setFocusPainted(false);
+
+		toolBar.add(vertical);
+		toolBar.add(horizontal);
+
+		toolBar.addSeparator();
+
+		JToggleButton expandNested = new JToggleButton();
+		expandNested.setSelected(true);
+
+		expandNested.setAction(new AbstractAction() {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				graphController.setExpandNestedDataflows(!graphController
+						.expandNestedDataflows());
+				graphController.redraw();
+			}
+		});
+		expandNested.getAction().putValue(SHORT_DESCRIPTION,
+				"Expand Nested Workflows");
+		expandNested.getAction().putValue(SMALL_ICON, expandNestedIcon);
+		expandNested.setFocusPainted(false);
+		toolBar.add(expandNested);
+
+		return toolBar;
+	}
+
+	/**
+	 * Sets the Workflow to display in the graph view.
+	 *
+	 * @param workflow
+	 */
+	private void setWorkflow(Workflow workflow) {
+		this.workflow = workflow;
+		if (!diagramPanelMap.containsKey(workflow))
+			addWorkflow(workflow);
+		graphController = graphControllerMap.get(workflow);
+		diagramPanel = diagramPanelMap.get(workflow);
+		Action[] actions = diagramActionsMap.get(workflow);
+		if (actions != null && actions.length == 3) {
+			ResetDiagramAction.setDesignAction(actions[0]);
+			ZoomInAction.setDesignAction(actions[1]);
+			ZoomOutAction.setDesignAction(actions[2]);
+		}
+		cardLayout.show(this, String.valueOf(diagramPanel.hashCode()));
+		graphController.redraw();
+	}
+
+	private void addWorkflow(Workflow workflow) {
+		JPanel newDiagramPanel = createDiagramPanel(workflow);
+		add(newDiagramPanel, String.valueOf(newDiagramPanel.hashCode()));
+		diagramPanelMap.put(workflow, newDiagramPanel);
+		if (!workflowsMap.containsKey(workflow.getParent()))
+			workflowsMap.put(workflow.getParent(), new HashSet<Workflow>());
+		workflowsMap.get(workflow.getParent()).add(workflow);
+	}
+
+	private void removeWorkflow(Workflow workflow) {
+		JPanel panel = diagramPanelMap.remove(workflow);
+		if (panel != null)
+			remove(panel);
+		SVGGraphController removedController = graphControllerMap.remove(workflow);
+		if (removedController != null)
+			removedController.shutdown();
+		diagramActionsMap.remove(workflow);
+		Set<Workflow> workflows = workflowsMap.get(workflow.getParent());
+		if (workflows != null)
+			workflows.remove(workflow);
+	}
+
+	public GraphController getGraphController(Workflow workflow) {
+		return graphControllerMap.get(workflow);
+	}
+
+	private class EditManagerObserver extends
+			SwingAwareObserver<EditManagerEvent> {
+		@Override
+		public void notifySwing(Observable<EditManagerEvent> sender,
+				EditManagerEvent message) {
+			if (!(message instanceof AbstractDataflowEditEvent))
+				return;
+			AbstractDataflowEditEvent dataflowEditEvent = (AbstractDataflowEditEvent) message;
+			if (dataflowEditEvent.getDataFlow() != workflow.getParent())
+				return;
+			
+			boolean animationEnabled = Boolean
+					.parseBoolean(graphViewConfiguration
+							.getProperty(ANIMATION_ENABLED));
+			int animationSpeed = (animationEnabled ? Integer
+					.parseInt(graphViewConfiguration
+							.getProperty(ANIMATION_SPEED)) : 0);
+			boolean animationSettingChanged = (animationEnabled != (graphController
+					.getAnimationSpeed() != 0));
+
+			if (graphController.isDotMissing() || animationSettingChanged) {
+				removeWorkflow(workflow);
+				setWorkflow(workflow);
+			} else {
+				if (animationSpeed != graphController.getAnimationSpeed())
+					graphController.setAnimationSpeed(animationSpeed);
+				graphController.redraw();
+			}
+		}
+	}
+
+	private class FileManagerObserver extends SwingAwareObserver<FileManagerEvent> {
+		@Override
+		public void notifySwing(Observable<FileManagerEvent> sender, final FileManagerEvent message) {
+			if (!(message instanceof ClosedDataflowEvent))
+				return;
+			ClosedDataflowEvent closedDataflowEvent = (ClosedDataflowEvent) message;
+
+			WorkflowBundle workflowBundle = closedDataflowEvent.getDataflow();
+			if (workflowsMap.containsKey(workflowBundle))
+				for (Workflow workflow : workflowsMap.remove(workflowBundle))
+					removeWorkflow(workflow);
+		}
+	}
+
+	private class SelectionManagerObserver extends
+			SwingAwareObserver<SelectionManagerEvent> {
+		@Override
+		public void notifySwing(Observable<SelectionManagerEvent> sender,
+				SelectionManagerEvent message) {
+			if (message instanceof WorkflowSelectionEvent)
+				setWorkflow(selectionManager.getSelectedWorkflow());
+			else if (message instanceof WorkflowBundleSelectionEvent)
+				setWorkflow(selectionManager.getSelectedWorkflow());
+		}
+	}
+
+	private class MySvgScrollPane extends JSVGScrollPane {
+		private static final long serialVersionUID = -1539947450704269879L;
+
+		public MySvgScrollPane(JSVGCanvas canvas) {
+			super(canvas);
+		}
+
+		@Override
+		public void reset() {
+			super.resizeScrollBars();
+			super.reset();
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/GraphViewComponentFactory.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/GraphViewComponentFactory.java b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/GraphViewComponentFactory.java
new file mode 100644
index 0000000..3b0cff4
--- /dev/null
+++ b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/GraphViewComponentFactory.java
@@ -0,0 +1,99 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.views.graph;
+
+import javax.swing.ImageIcon;
+
+import org.apache.taverna.commons.services.ServiceRegistry;
+
+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.file.FileManager;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.ui.zaria.UIComponentFactorySPI;
+import org.apache.taverna.workbench.ui.zaria.UIComponentSPI;
+import org.apache.taverna.workbench.views.graph.config.GraphViewConfiguration;
+
+/**
+ * @author David Withers
+ */
+public class GraphViewComponentFactory implements UIComponentFactorySPI {
+	private EditManager editManager;
+	private FileManager fileManager;
+	private MenuManager menuManager;
+	private SelectionManager selectionManager;
+	private ColourManager colourManager;
+	private WorkbenchConfiguration workbenchConfiguration;
+	private GraphViewConfiguration graphViewConfiguration;
+	private ServiceRegistry serviceRegistry;
+
+	@Override
+	public UIComponentSPI getComponent() {
+		return new GraphViewComponent(colourManager, editManager, fileManager,
+				menuManager, graphViewConfiguration, workbenchConfiguration,
+				selectionManager, serviceRegistry);
+	}
+
+	@Override
+	public ImageIcon getIcon() {
+		return null;
+	}
+
+	@Override
+	public String getName() {
+		return "Graph View";
+	}
+
+	public void setEditManager(EditManager editManager) {
+		this.editManager = editManager;
+	}
+
+	public void setFileManager(FileManager fileManager) {
+		this.fileManager = fileManager;
+	}
+
+	public void setMenuManager(MenuManager menuManager) {
+		this.menuManager = menuManager;
+	}
+
+	public void setSelectionManager(SelectionManager selectionManager) {
+		this.selectionManager = selectionManager;
+	}
+
+	public void setColourManager(ColourManager colourManager) {
+		this.colourManager = colourManager;
+	}
+
+	public void setWorkbenchConfiguration(
+			WorkbenchConfiguration workbenchConfiguration) {
+		this.workbenchConfiguration = workbenchConfiguration;
+	}
+
+	public void setGraphViewConfiguration(
+			GraphViewConfiguration graphViewConfiguration) {
+		this.graphViewConfiguration = graphViewConfiguration;
+	}
+
+	public void setServiceRegistry(ServiceRegistry serviceRegistry) {
+		this.serviceRegistry = serviceRegistry;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/AddWFInputAction.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/AddWFInputAction.java b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/AddWFInputAction.java
new file mode 100644
index 0000000..b702393
--- /dev/null
+++ b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/AddWFInputAction.java
@@ -0,0 +1,68 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.views.graph.actions;
+
+import static java.awt.event.InputEvent.ALT_DOWN_MASK;
+import static java.awt.event.InputEvent.SHIFT_DOWN_MASK;
+import static java.awt.event.KeyEvent.VK_I;
+import static javax.swing.KeyStroke.getKeyStroke;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.inputIcon;
+
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+
+import org.apache.taverna.ui.menu.DesignOnlyAction;
+import org.apache.taverna.workbench.design.actions.AddDataflowInputAction;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.scufl2.api.core.Workflow;
+
+/**
+ * An action that adds a workflow input.
+ * 
+ * @author Alex Nenadic
+ * @author Alan R Williams
+ */
+@SuppressWarnings("serial")
+public class AddWFInputAction extends AbstractAction implements
+		DesignOnlyAction {
+	private final EditManager editManager;
+	private final SelectionManager selectionManager;
+
+	public AddWFInputAction(EditManager editManager,
+			SelectionManager selectionManager) {
+		super();
+		this.editManager = editManager;
+		this.selectionManager = selectionManager;
+		putValue(SMALL_ICON, inputIcon);
+		putValue(NAME, "Workflow input port");
+		putValue(SHORT_DESCRIPTION, "Workflow input port");
+		putValue(ACCELERATOR_KEY,
+				getKeyStroke(VK_I, SHIFT_DOWN_MASK | ALT_DOWN_MASK));
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent e) {
+		Workflow workflow = selectionManager.getSelectedWorkflow();
+		new AddDataflowInputAction(workflow, null, editManager,
+				selectionManager).actionPerformed(e);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/AddWFOutputAction.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/AddWFOutputAction.java b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/AddWFOutputAction.java
new file mode 100644
index 0000000..8f8eaeb
--- /dev/null
+++ b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/AddWFOutputAction.java
@@ -0,0 +1,68 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.views.graph.actions;
+
+import static java.awt.event.InputEvent.ALT_DOWN_MASK;
+import static java.awt.event.InputEvent.SHIFT_DOWN_MASK;
+import static java.awt.event.KeyEvent.VK_O;
+import static javax.swing.KeyStroke.getKeyStroke;
+
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+
+import org.apache.taverna.ui.menu.DesignOnlyAction;
+import org.apache.taverna.workbench.design.actions.AddDataflowOutputAction;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.icons.WorkbenchIcons;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.scufl2.api.core.Workflow;
+
+/**
+ * An action that adds a workflow output.
+ * 
+ * @author Alex Nenadic
+ * @author Alan R Williams
+ */
+@SuppressWarnings("serial")
+public class AddWFOutputAction extends AbstractAction implements
+		DesignOnlyAction {
+	private final EditManager editManager;
+	private final SelectionManager selectionManager;
+
+	public AddWFOutputAction(EditManager editManager,
+			SelectionManager selectionManager) {
+		super();
+		this.editManager = editManager;
+		this.selectionManager = selectionManager;
+		putValue(SMALL_ICON, WorkbenchIcons.outputIcon);
+		putValue(NAME, "Workflow output port");
+		putValue(SHORT_DESCRIPTION, "Workflow output port");
+		putValue(ACCELERATOR_KEY,
+				getKeyStroke(VK_O, SHIFT_DOWN_MASK | ALT_DOWN_MASK));
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent e) {
+		Workflow workflow = selectionManager.getSelectedWorkflow();
+		new AddDataflowOutputAction(workflow, null, editManager,
+				selectionManager).actionPerformed(e);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/DeleteGraphComponentAction.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/DeleteGraphComponentAction.java b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/DeleteGraphComponentAction.java
new file mode 100644
index 0000000..a25b4bc
--- /dev/null
+++ b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/DeleteGraphComponentAction.java
@@ -0,0 +1,179 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.views.graph.actions;
+
+import static java.awt.event.KeyEvent.VK_DELETE;
+import static javax.swing.KeyStroke.getKeyStroke;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.deleteIcon;
+
+import java.awt.event.ActionEvent;
+import java.util.Set;
+
+import javax.swing.AbstractAction;
+
+import org.apache.taverna.lang.observer.Observable;
+import org.apache.taverna.lang.observer.Observer;
+import org.apache.taverna.lang.observer.SwingAwareObserver;
+import org.apache.taverna.ui.menu.DesignOnlyAction;
+import org.apache.taverna.workbench.design.actions.RemoveConditionAction;
+import org.apache.taverna.workbench.design.actions.RemoveDataflowInputPortAction;
+import org.apache.taverna.workbench.design.actions.RemoveDataflowOutputPortAction;
+import org.apache.taverna.workbench.design.actions.RemoveDatalinkAction;
+import org.apache.taverna.workbench.design.actions.RemoveProcessorAction;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.selection.DataflowSelectionModel;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.selection.events.DataflowSelectionMessage;
+import org.apache.taverna.workbench.selection.events.SelectionManagerEvent;
+import org.apache.taverna.workbench.selection.events.WorkflowBundleSelectionEvent;
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.scufl2.api.core.ControlLink;
+import org.apache.taverna.scufl2.api.core.DataLink;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
+import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
+
+/**
+ * An action that deletes the selected graph component.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class DeleteGraphComponentAction extends AbstractAction implements DesignOnlyAction {
+	/** Current workflow's selection model event observer.*/
+	private Observer<DataflowSelectionMessage> workflowSelectionObserver = new DataflowSelectionObserver();
+
+	private final EditManager editManager;
+	private final SelectionManager selectionManager;
+
+	public DeleteGraphComponentAction(EditManager editManager, final SelectionManager selectionManager) {
+		super();
+		this.editManager = editManager;
+		this.selectionManager = selectionManager;
+		putValue(SMALL_ICON, deleteIcon);
+		putValue(NAME, "Delete");
+		putValue(SHORT_DESCRIPTION, "Delete selected component");
+		putValue(ACCELERATOR_KEY, getKeyStroke(VK_DELETE, 0));
+		setEnabled(false);
+
+		selectionManager.addObserver(new SelectionManagerObserver());
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent e) {
+		WorkflowBundle workflowBundle = selectionManager
+				.getSelectedWorkflowBundle();
+		DataflowSelectionModel dataFlowSelectionModel = selectionManager
+				.getDataflowSelectionModel(workflowBundle);
+		// Get all selected components
+		Set<Object> selectedWFComponents = dataFlowSelectionModel.getSelection();
+		for (Object selectedWFComponent : selectedWFComponents)
+			if (selectedWFComponent instanceof Processor) {
+				Processor processor = (Processor) selectedWFComponent;
+				new RemoveProcessorAction(processor.getParent(), processor,
+						null, editManager, selectionManager).actionPerformed(e);
+			} else if (selectedWFComponent instanceof DataLink) {
+				DataLink dataLink = (DataLink) selectedWFComponent;
+				new RemoveDatalinkAction(dataLink.getParent(), dataLink, null,
+						editManager, selectionManager).actionPerformed(e);
+			} else if (selectedWFComponent instanceof InputWorkflowPort) {
+				InputWorkflowPort port = (InputWorkflowPort) selectedWFComponent;
+				new RemoveDataflowInputPortAction(port.getParent(), port, null,
+						editManager, selectionManager).actionPerformed(e);
+			} else if (selectedWFComponent instanceof OutputWorkflowPort) {
+				OutputWorkflowPort port = (OutputWorkflowPort) selectedWFComponent;
+				new RemoveDataflowOutputPortAction(port.getParent(), port,
+						null, editManager, selectionManager).actionPerformed(e);
+			} else if (selectedWFComponent instanceof ControlLink) {
+				ControlLink controlLink = (ControlLink) selectedWFComponent;
+				new RemoveConditionAction(controlLink.getParent(), controlLink,
+						null, editManager, selectionManager).actionPerformed(e);
+			}
+	}
+
+	/**
+	 * Check if action should be enabled or disabled and update its status.
+	 */
+	public void updateStatus(WorkflowBundle selectionWorkflowBundle) {
+		if (selectionWorkflowBundle != null) {
+			DataflowSelectionModel selectionModel = selectionManager
+					.getDataflowSelectionModel(selectionWorkflowBundle);
+			Set<Object> selection = selectionModel.getSelection();
+			if (!selection.isEmpty()) {
+				// Take the first selected item - we only support single selections anyway
+				Object selected = selection.toArray()[0];
+				if ((selected instanceof Processor)
+						|| (selected instanceof InputWorkflowPort)
+						|| (selected instanceof OutputWorkflowPort)
+						|| (selected instanceof DataLink)
+						|| (selected instanceof ControlLink)) {
+					setEnabled(true);
+					return;
+				}
+			}
+		}
+		setEnabled(false);
+	}
+
+	/**
+	 * Observes events on workflow Selection Manager, i.e. when a workflow node
+	 * is selected in the graph view, and enables/disables this action
+	 * accordingly.
+	 */
+	private final class DataflowSelectionObserver extends
+			SwingAwareObserver<DataflowSelectionMessage> {
+		@Override
+		public void notifySwing(Observable<DataflowSelectionMessage> sender,
+				DataflowSelectionMessage message) {
+			updateStatus(selectionManager.getSelectedWorkflowBundle());
+		}
+	}
+
+	private final class SelectionManagerObserver extends
+			SwingAwareObserver<SelectionManagerEvent> {
+		@Override
+		public void notifySwing(Observable<SelectionManagerEvent> sender,
+				SelectionManagerEvent message) {
+			if (!(message instanceof WorkflowBundleSelectionEvent))
+				return;
+			WorkflowBundleSelectionEvent workflowBundleSelectionEvent = (WorkflowBundleSelectionEvent) message;
+			WorkflowBundle oldFlow = workflowBundleSelectionEvent
+					.getPreviouslySelectedWorkflowBundle();
+			WorkflowBundle newFlow = workflowBundleSelectionEvent
+					.getSelectedWorkflowBundle();
+
+			/*
+			 * Remove the workflow selection model listener from the previous
+			 * (if any) and add to the new workflow (if any)
+			 */
+			if (oldFlow != null)
+				selectionManager.getDataflowSelectionModel(oldFlow)
+						.removeObserver(workflowSelectionObserver);
+
+			// Update the buttons status as current dataflow has changed
+			updateStatus(newFlow);
+
+			if (newFlow != null)
+				selectionManager.getDataflowSelectionModel(newFlow)
+						.addObserver(workflowSelectionObserver);
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/RenameWFInputOutputProcessorAction.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/RenameWFInputOutputProcessorAction.java b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/RenameWFInputOutputProcessorAction.java
new file mode 100644
index 0000000..5c01a0b
--- /dev/null
+++ b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/actions/RenameWFInputOutputProcessorAction.java
@@ -0,0 +1,183 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.views.graph.actions;
+
+import static java.awt.event.KeyEvent.VK_F2;
+import static javax.swing.JOptionPane.WARNING_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static javax.swing.KeyStroke.getKeyStroke;
+
+import java.awt.event.ActionEvent;
+import java.util.Set;
+
+import javax.swing.AbstractAction;
+
+import org.apache.taverna.lang.observer.Observable;
+import org.apache.taverna.lang.observer.Observer;
+import org.apache.taverna.lang.observer.SwingAwareObserver;
+import org.apache.taverna.ui.menu.DesignOnlyAction;
+import org.apache.taverna.workbench.design.actions.EditDataflowInputPortAction;
+import org.apache.taverna.workbench.design.actions.EditDataflowOutputPortAction;
+import org.apache.taverna.workbench.design.actions.RenameProcessorAction;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.icons.WorkbenchIcons;
+import org.apache.taverna.workbench.selection.DataflowSelectionModel;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.selection.events.DataflowSelectionMessage;
+import org.apache.taverna.workbench.selection.events.SelectionManagerEvent;
+import org.apache.taverna.workbench.selection.events.WorkflowBundleSelectionEvent;
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
+import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
+
+/**
+ * An action that allows user to rename workflow input, output or
+ * processor, in case one of these is currently selected in the Graph View.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class RenameWFInputOutputProcessorAction extends AbstractAction implements DesignOnlyAction {
+	/** Current workflow's selection model event observer.*/
+	private Observer<DataflowSelectionMessage> workflowSelectionObserver = new DataflowSelectionObserver();
+
+	private final EditManager editManager;
+	private final SelectionManager selectionManager;
+
+	public RenameWFInputOutputProcessorAction(EditManager editManager,
+			final SelectionManager selectionManager) {
+		super();
+		this.editManager = editManager;
+		this.selectionManager = selectionManager;
+		putValue(SMALL_ICON, WorkbenchIcons.renameIcon);
+		putValue(NAME, "Rename");
+		putValue(SHORT_DESCRIPTION, "Rename inputs, outputs or services");
+		putValue(ACCELERATOR_KEY, getKeyStroke(VK_F2, 0));
+		setEnabled(false);
+
+		selectionManager.addObserver(new SelectionManagerObserver());
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent e) {
+		WorkflowBundle workflowBundle = selectionManager
+				.getSelectedWorkflowBundle();
+		DataflowSelectionModel dataFlowSelectionModel = selectionManager
+				.getDataflowSelectionModel(workflowBundle);
+		// Get selected port
+		Set<Object> selectedWFComponents = dataFlowSelectionModel
+				.getSelection();
+		if (selectedWFComponents.size() > 1) {
+			showMessageDialog(
+					null,
+					"Only one workflow component should be selected for this action.",
+					"Warning", WARNING_MESSAGE);
+		} else {
+			Object selectedWFComponent = selectedWFComponents.toArray()[0];
+			if (selectedWFComponent instanceof InputWorkflowPort) {
+				InputWorkflowPort port = (InputWorkflowPort) selectedWFComponent;
+				new EditDataflowInputPortAction(port.getParent(), port, null,
+						editManager, selectionManager).actionPerformed(e);
+			} else if (selectedWFComponent instanceof OutputWorkflowPort) {
+				OutputWorkflowPort port = (OutputWorkflowPort) selectedWFComponent;
+				new EditDataflowOutputPortAction(port.getParent(), port, null,
+						editManager, selectionManager).actionPerformed(e);
+			} else if (selectedWFComponent instanceof Processor) {
+				Processor processor = (Processor) selectedWFComponent;
+				new RenameProcessorAction(processor.getParent(), processor,
+						null, editManager, selectionManager).actionPerformed(e);
+			} else { // should not happen as the button will be disabled otherwise, but ...
+				showMessageDialog(
+						null,
+						"This action does not apply for the selected component.",
+						"Warning", WARNING_MESSAGE);
+			}
+		}
+	}
+
+	/**
+	 * Check if action should be enabled or disabled and update its status.
+	 */
+	public void updateStatus() {
+		WorkflowBundle workflowBundle = selectionManager
+				.getSelectedWorkflowBundle();
+		DataflowSelectionModel selectionModel = selectionManager
+				.getDataflowSelectionModel(workflowBundle);
+
+		// List of all selected objects in the graph view
+		Set<Object> selection = selectionModel.getSelection();
+
+		if (!selection.isEmpty()) {
+			// Take the first selected item - we only support single selections anyway
+			Object selected = selection.toArray()[0];
+			if ((selected instanceof Processor)
+					|| (selected instanceof InputWorkflowPort)
+					|| (selected instanceof OutputWorkflowPort)) {
+				setEnabled(true);
+				return;
+			}
+		}
+		setEnabled(false);
+	}
+
+	/**
+	 * Observes events on workflow Selection Manager, i.e. when a workflow node
+	 * is selected in the graph view, and enables/disables this action
+	 * accordingly.
+	 */
+	private final class DataflowSelectionObserver extends
+			SwingAwareObserver<DataflowSelectionMessage> {
+		@Override
+		public void notifySwing(Observable<DataflowSelectionMessage> sender,
+				DataflowSelectionMessage message) {
+			updateStatus();
+		}
+	}
+
+	private final class SelectionManagerObserver extends
+			SwingAwareObserver<SelectionManagerEvent> {
+		@Override
+		public void notifySwing(Observable<SelectionManagerEvent> sender,
+				SelectionManagerEvent message) {
+			if (!(message instanceof WorkflowBundleSelectionEvent))
+				return;
+			WorkflowBundleSelectionEvent workflowBundleSelectionEvent = (WorkflowBundleSelectionEvent) message;
+			WorkflowBundle oldFlow = workflowBundleSelectionEvent
+					.getPreviouslySelectedWorkflowBundle();
+			WorkflowBundle newFlow = workflowBundleSelectionEvent
+					.getSelectedWorkflowBundle();
+			// Update the buttons status as current dataflow has changed
+			updateStatus();
+
+			/*
+			 * Remove the workflow selection model listener from the previous
+			 * (if any) and add to the new workflow (if any)
+			 */
+			if (oldFlow != null)
+				selectionManager.getDataflowSelectionModel(oldFlow)
+						.removeObserver(workflowSelectionObserver);
+
+			if (newFlow != null)
+				selectionManager.getDataflowSelectionModel(newFlow)
+						.addObserver(workflowSelectionObserver);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/config/GraphViewConfiguration.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/config/GraphViewConfiguration.java b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/config/GraphViewConfiguration.java
new file mode 100644
index 0000000..1b03c58
--- /dev/null
+++ b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/config/GraphViewConfiguration.java
@@ -0,0 +1,79 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.views.graph.config;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import uk.org.taverna.configuration.AbstractConfigurable;
+import uk.org.taverna.configuration.ConfigurationManager;
+
+import org.apache.taverna.workbench.models.graph.Graph.Alignment;
+import org.apache.taverna.workbench.models.graph.GraphController.PortStyle;
+
+/**
+ * Configuration for the GraphViewComponent.
+ * 
+ * @author David Withers
+ */
+public class GraphViewConfiguration extends AbstractConfigurable {
+	public static final String PORT_STYLE = "portStyle";
+	public static final String ALIGNMENT = "alignment";
+	public static final String ANIMATION_ENABLED = "animationEnabled";
+	public static final String ANIMATION_SPEED = "animationSpeed";
+
+	private Map<String, String> defaultPropertyMap;
+
+	public GraphViewConfiguration(ConfigurationManager configurationManager) {
+		super(configurationManager);
+	}
+
+	@Override
+	public String getCategory() {
+		return "general";
+	}
+
+	@Override
+	public Map<String, String> getDefaultPropertyMap() {
+		if (defaultPropertyMap == null) {
+			defaultPropertyMap = new HashMap<>();
+			defaultPropertyMap.put(PORT_STYLE, PortStyle.NONE.toString());
+			defaultPropertyMap.put(ALIGNMENT, Alignment.VERTICAL.toString());
+			defaultPropertyMap.put(ANIMATION_ENABLED, "false");
+			defaultPropertyMap.put(ANIMATION_SPEED, "800");
+		}
+		return defaultPropertyMap;
+	}
+
+	@Override
+	public String getDisplayName() {
+		return "Diagram";
+	}
+
+	@Override
+	public String getFilePrefix() {
+		return "Diagram";
+	}
+
+	@Override
+	public String getUUID() {
+		return "3686BA31-449F-4147-A8AC-0C3F63AFC68F";
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/config/GraphViewConfigurationPanel.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/config/GraphViewConfigurationPanel.java b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/config/GraphViewConfigurationPanel.java
new file mode 100644
index 0000000..3e24645
--- /dev/null
+++ b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/config/GraphViewConfigurationPanel.java
@@ -0,0 +1,359 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.views.graph.config;
+
+import static java.awt.GridBagConstraints.HORIZONTAL;
+import static java.awt.GridBagConstraints.NORTHWEST;
+import static java.awt.GridBagConstraints.RELATIVE;
+import static java.awt.GridBagConstraints.REMAINDER;
+import static java.awt.GridBagConstraints.WEST;
+import static javax.swing.SwingConstants.LEFT;
+import static org.apache.taverna.workbench.helper.Helper.showHelp;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.allportIcon;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.blobIcon;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.horizontalIcon;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.noportIcon;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.verticalIcon;
+import static org.apache.taverna.workbench.views.graph.config.GraphViewConfiguration.ALIGNMENT;
+import static org.apache.taverna.workbench.views.graph.config.GraphViewConfiguration.ANIMATION_ENABLED;
+import static org.apache.taverna.workbench.views.graph.config.GraphViewConfiguration.ANIMATION_SPEED;
+import static org.apache.taverna.workbench.views.graph.config.GraphViewConfiguration.PORT_STYLE;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.Hashtable;
+
+import javax.swing.AbstractAction;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JSlider;
+import javax.swing.JTextArea;
+import javax.swing.border.EmptyBorder;
+
+import org.apache.taverna.workbench.models.graph.Graph.Alignment;
+import org.apache.taverna.workbench.models.graph.GraphController.PortStyle;
+
+/**
+ * UI for GraphViewConfiguration.
+ * 
+ * @author David Withers
+ */
+public class GraphViewConfigurationPanel extends JPanel {
+	private static final long serialVersionUID = 3779779432230124131L;
+	private static final int ANIMATION_SPEED_MIN = 100;
+	private static final int ANIMATION_SPEED_MAX = 3100;
+
+	private GraphViewConfiguration configuration;
+	private JRadioButton noPorts;
+	private JRadioButton allPorts;
+	private JRadioButton blobs;
+	private JRadioButton vertical;
+	private JRadioButton horizontal;
+	private JCheckBox animation;
+	private JLabel animationSpeedLabel;
+	private JSlider animationSpeedSlider;
+
+	public GraphViewConfigurationPanel(GraphViewConfiguration configuration) {
+		this.configuration = configuration;
+		GridBagLayout gridbag = new GridBagLayout();
+		GridBagConstraints c = new GridBagConstraints();
+		setLayout(gridbag);
+
+		// Title describing what kind of settings we are configuring here
+		JTextArea descriptionText = new JTextArea(
+				"Default settings for the workflow diagram");
+		descriptionText.setLineWrap(true);
+		descriptionText.setWrapStyleWord(true);
+		descriptionText.setEditable(false);
+		descriptionText.setFocusable(false);
+		descriptionText.setBorder(new EmptyBorder(10, 10, 10, 10));
+
+		JLabel defaultLayoutLabel = new JLabel("Service display");
+
+		noPorts = new JRadioButton();
+		allPorts = new JRadioButton();
+		blobs = new JRadioButton();
+
+		JLabel noPortsLabel = new JLabel("Name only", noportIcon, LEFT);
+		JLabel allPortsLabel = new JLabel("Name and ports", allportIcon, LEFT);
+		JLabel blobsLabel = new JLabel("No text", blobIcon, LEFT);
+
+		ButtonGroup buttonGroup = new ButtonGroup();
+		buttonGroup.add(noPorts);
+		buttonGroup.add(allPorts);
+		buttonGroup.add(blobs);
+
+		JLabel defaultAlignmentLabel = new JLabel("Diagram alignment");
+
+		vertical = new JRadioButton();
+		horizontal = new JRadioButton();
+
+		JLabel verticalLabel = new JLabel("Vertical", verticalIcon, LEFT);
+		JLabel horizontalLabel = new JLabel("Horizontal", horizontalIcon, LEFT);
+
+		ButtonGroup alignmentButtonGroup = new ButtonGroup();
+		alignmentButtonGroup.add(horizontal);
+		alignmentButtonGroup.add(vertical);
+
+		animation = new JCheckBox("Enable animation");
+
+		animationSpeedLabel = new JLabel("Animation speed");
+
+		animationSpeedSlider = new JSlider(ANIMATION_SPEED_MIN,
+				ANIMATION_SPEED_MAX);
+		animationSpeedSlider.setMajorTickSpacing(500);
+		animationSpeedSlider.setMinorTickSpacing(100);
+		animationSpeedSlider.setPaintTicks(true);
+		animationSpeedSlider.setPaintLabels(true);
+		animationSpeedSlider.setInverted(true);
+		animationSpeedSlider.setSnapToTicks(true);
+
+		Hashtable<Integer, JLabel> labelTable = new Hashtable<>();
+		labelTable.put(new Integer(ANIMATION_SPEED_MIN), new JLabel("Fast"));
+		labelTable.put(new Integer(
+				((ANIMATION_SPEED_MAX - ANIMATION_SPEED_MIN) / 2)
+						+ ANIMATION_SPEED_MIN), new JLabel("Medium"));
+		labelTable.put(new Integer(ANIMATION_SPEED_MAX), new JLabel("Slow"));
+		animationSpeedSlider.setLabelTable(labelTable);
+
+		animation.addItemListener(new ItemListener() {
+			@Override
+			public void itemStateChanged(ItemEvent e) {
+				boolean animationEnabled = animation.isSelected();
+				animationSpeedLabel.setEnabled(animationEnabled);
+				animationSpeedSlider.setEnabled(animationEnabled);
+			}
+		});
+
+		// Set current configuration values
+		setFields(configuration);
+
+		c.anchor = WEST;
+		c.gridx = 0;
+		c.gridwidth = REMAINDER;
+		c.weightx = 1d;
+		c.weighty = 0d;
+		c.fill = HORIZONTAL;
+
+		add(descriptionText, c);
+
+		c.insets = new Insets(10, 0, 10, 0);
+		add(defaultLayoutLabel, c);
+
+		c.insets = new Insets(0, 20, 0, 0);
+		c.gridwidth = 1;
+		c.weightx = 0d;
+		add(noPorts, c);
+		c.insets = new Insets(0, 5, 0, 0);
+		c.gridx = RELATIVE;
+		add(noPortsLabel, c);
+
+		c.insets = new Insets(0, 10, 0, 0);
+		add(allPorts, c);
+		c.insets = new Insets(0, 5, 0, 0);
+		add(allPortsLabel, c);
+
+		c.insets = new Insets(0, 10, 0, 0);
+		add(blobs, c);
+		c.insets = new Insets(0, 5, 0, 0);
+		c.gridwidth = REMAINDER;
+		c.weightx = 1d;
+		add(blobsLabel, c);
+
+		// alignment
+		c.insets = new Insets(20, 0, 10, 0);
+		c.gridx = 0;
+		add(defaultAlignmentLabel, c);
+
+		c.insets = new Insets(0, 20, 0, 0);
+		c.gridx = 0;
+		c.gridwidth = 1;
+		c.weightx = 0d;
+		add(vertical, c);
+		c.insets = new Insets(0, 5, 0, 0);
+		c.gridx = RELATIVE;
+		add(verticalLabel, c);
+
+		c.insets = new Insets(0, 10, 0, 0);
+		add(horizontal, c);
+		c.insets = new Insets(0, 5, 0, 0);
+		c.gridwidth = REMAINDER;
+		c.weightx = 1d;
+		add(horizontalLabel, c);
+
+		// animation
+		c.gridx = 0;
+		c.gridwidth = REMAINDER;
+		c.insets = new Insets(20, 0, 10, 0);
+		add(animation, c);
+
+		c.insets = new Insets(0, 20, 0, 0);
+		add(animationSpeedLabel, c);
+
+		c.insets = new Insets(0, 20, 10, 30);
+		c.anchor = NORTHWEST;
+		c.weighty = 0d;
+		add(animationSpeedSlider, c);
+
+		// Buttons
+		c.gridx = 0;
+		c.insets = new Insets(0, 20, 10, 30);
+		c.anchor = NORTHWEST;
+		c.weighty = 1d;
+		add(createButtonPanel(), c);
+	}
+
+	/**
+	 * Create the panel with the buttons.
+	 */
+	@SuppressWarnings("serial")
+	private JPanel createButtonPanel() {
+		final JPanel panel = new JPanel();
+
+		/**
+		 * The helpButton shows help about the current component
+		 */
+		JButton helpButton = new JButton(new AbstractAction("Help") {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				showHelp(panel);
+			}
+		});
+		panel.add(helpButton);
+
+		/**
+		 * The resetButton changes the property values shown to those
+		 * corresponding to the configuration currently applied.
+		 */
+		JButton resetButton = new JButton(new AbstractAction("Reset") {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				setFields(configuration);
+			}
+		});
+		panel.add(resetButton);
+
+		/**
+		 * The applyButton applies the shown field values to the
+		 * {@link HttpProxyConfiguration} and saves them for future.
+		 */
+		JButton applyButton = new JButton(new AbstractAction("Apply") {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				applySettings();
+				setFields(configuration);
+			}
+		});
+		panel.add(applyButton);
+
+		return panel;
+	}
+
+	/**
+	 * Save the currently set field values to the {@link GraphViewConfiguration}
+	 * . Also apply those values to the currently running Taverna.
+	 */
+	private void applySettings() {
+		// Service display
+		if (noPorts.isSelected()) {
+			configuration.setProperty(PORT_STYLE, PortStyle.NONE.toString());
+		} else if (allPorts.isSelected()) {
+			configuration.setProperty(PORT_STYLE, PortStyle.ALL.toString());
+		} else if (blobs.isSelected()) {
+			configuration.setProperty(PORT_STYLE, PortStyle.BLOB.toString());
+		}
+
+		// Diagram alignment
+		if (vertical.isSelected()) {
+			configuration.setProperty(ALIGNMENT, Alignment.VERTICAL.toString());
+		} else if (horizontal.isSelected()) {
+			configuration.setProperty(ALIGNMENT,
+					Alignment.HORIZONTAL.toString());
+		}
+
+		// Animation and its speed
+		if (animation.isSelected()) {
+			configuration.setProperty(ANIMATION_ENABLED, String.valueOf(true));
+		} else {
+			configuration.setProperty(ANIMATION_ENABLED, String.valueOf(false));
+		}
+		int speed = animationSpeedSlider.getValue();
+		configuration.setProperty(ANIMATION_SPEED, String.valueOf(speed));
+	}
+
+	/**
+	 * Set the shown configuration field values to those currently in use (i.e.
+	 * last saved configuration).
+	 */
+	private void setFields(GraphViewConfiguration configurable) {
+		PortStyle portStyle = PortStyle.valueOf(configurable
+				.getProperty(PORT_STYLE));
+		if (portStyle.equals(PortStyle.NONE)) {
+			noPorts.setSelected(true);
+		} else if (portStyle.equals(PortStyle.ALL)) {
+			allPorts.setSelected(true);
+		} else {
+			blobs.setSelected(true);
+		}
+
+		Alignment alignment = Alignment.valueOf(configurable
+				.getProperty(ALIGNMENT));
+		if (alignment.equals(Alignment.VERTICAL)) {
+			vertical.setSelected(true);
+		} else {
+			horizontal.setSelected(true);
+		}
+
+		boolean animationEnabled = Boolean.parseBoolean(configurable
+				.getProperty(ANIMATION_ENABLED));
+		animation.setSelected(animationEnabled);
+
+		Integer animationSpeed = Integer.valueOf(configurable
+				.getProperty(ANIMATION_SPEED));
+		if (animationSpeed > ANIMATION_SPEED_MAX) {
+			animationSpeed = ANIMATION_SPEED_MAX;
+		} else if (animationSpeed < ANIMATION_SPEED_MIN) {
+			animationSpeed = ANIMATION_SPEED_MIN;
+		}
+		animationSpeedSlider.setValue(animationSpeed);
+		animationSpeedSlider.setEnabled(animationEnabled);
+
+		animationSpeedLabel.setEnabled(animationEnabled);
+	}
+
+	// for testing only
+	public static void main(String[] args) {
+		JDialog dialog = new JDialog();
+		dialog.add(new GraphViewConfigurationPanel(null));
+		dialog.setModal(true);
+		dialog.setSize(500, 400);
+		dialog.setVisible(true);
+		System.exit(0);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/config/GraphViewConfigurationUIFactory.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/config/GraphViewConfigurationUIFactory.java b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/config/GraphViewConfigurationUIFactory.java
new file mode 100644
index 0000000..770b79c
--- /dev/null
+++ b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/config/GraphViewConfigurationUIFactory.java
@@ -0,0 +1,54 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.views.graph.config;
+
+import javax.swing.JPanel;
+
+import uk.org.taverna.configuration.Configurable;
+import uk.org.taverna.configuration.ConfigurationUIFactory;
+
+/**
+ * ConfigurationFactory for the GraphViewConfiguration.
+ * 
+ * @author David Withers
+ */
+public class GraphViewConfigurationUIFactory implements ConfigurationUIFactory {
+	private GraphViewConfiguration graphViewConfiguration;
+
+	@Override
+	public boolean canHandle(String uuid) {
+		return uuid.equals(getConfigurable().getUUID());
+	}
+
+	@Override
+	public JPanel getConfigurationPanel() {
+		return new GraphViewConfigurationPanel(graphViewConfiguration);
+	}
+
+	@Override
+	public Configurable getConfigurable() {
+		return graphViewConfiguration;
+	}
+
+	public void setGraphViewConfiguration(
+			GraphViewConfiguration graphViewConfiguration) {
+		this.graphViewConfiguration = graphViewConfiguration;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/AddWFInputMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/AddWFInputMenuAction.java b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/AddWFInputMenuAction.java
new file mode 100644
index 0000000..cad5986
--- /dev/null
+++ b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/AddWFInputMenuAction.java
@@ -0,0 +1,59 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.views.graph.menu;
+
+import static org.apache.taverna.workbench.views.graph.menu.InsertMenu.INSERT;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import org.apache.taverna.ui.menu.AbstractMenuAction;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.views.graph.actions.AddWFInputAction;
+
+/**
+ * @author Alex Nenadic
+ */
+public class AddWFInputMenuAction extends AbstractMenuAction {
+	private static final URI ADD_WF_INPUT_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#graphMenuAddWFInput");
+
+	private EditManager editManager;
+	private SelectionManager selectionManager;
+
+	public AddWFInputMenuAction() {
+		super(INSERT, 10, ADD_WF_INPUT_URI);
+	}
+
+	@Override
+	protected Action createAction() {
+		return new AddWFInputAction(editManager, selectionManager);
+	}
+
+	public void setEditManager(EditManager editManager) {
+		this.editManager = editManager;
+	}
+
+	public void setSelectionManager(SelectionManager selectionManager) {
+		this.selectionManager = selectionManager;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/AddWFOutputMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/AddWFOutputMenuAction.java b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/AddWFOutputMenuAction.java
new file mode 100644
index 0000000..1aeb495
--- /dev/null
+++ b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/AddWFOutputMenuAction.java
@@ -0,0 +1,59 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.views.graph.menu;
+
+import static org.apache.taverna.workbench.views.graph.menu.InsertMenu.INSERT;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import org.apache.taverna.ui.menu.AbstractMenuAction;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.views.graph.actions.AddWFOutputAction;
+
+/**
+ * @author Alex Nenadic
+ */
+public class AddWFOutputMenuAction extends AbstractMenuAction {
+	private static final URI ADD_WF_OUTPUT_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#graphMenuAddWFOutput");
+
+	private EditManager editManager;
+	private SelectionManager selectionManager;
+
+	public AddWFOutputMenuAction() {
+		super(INSERT, 20, ADD_WF_OUTPUT_URI);
+	}
+
+	@Override
+	protected Action createAction() {
+		return new AddWFOutputAction(editManager, selectionManager);
+	}
+
+	public void setEditManager(EditManager editManager) {
+		this.editManager = editManager;
+	}
+
+	public void setSelectionManager(SelectionManager selectionManager) {
+		this.selectionManager = selectionManager;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/DeleteGraphComponentMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/DeleteGraphComponentMenuAction.java b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/DeleteGraphComponentMenuAction.java
new file mode 100644
index 0000000..243350e
--- /dev/null
+++ b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/DeleteGraphComponentMenuAction.java
@@ -0,0 +1,60 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.views.graph.menu;
+
+import static org.apache.taverna.workbench.views.graph.menu.GraphDeleteMenuSection.GRAPH_DELETE_MENU_SECTION;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import org.apache.taverna.ui.menu.AbstractMenuAction;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.views.graph.actions.DeleteGraphComponentAction;
+
+/**
+ * @author Alex Nenadic
+ * @author Alan R Williams
+ */
+public class DeleteGraphComponentMenuAction extends AbstractMenuAction {
+	private static final URI DELETE_GRAPH_COMPONENT_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#graphMenuDeleteGraphComponent");
+
+	private EditManager editManager;
+	private SelectionManager selectionManager;
+
+	public DeleteGraphComponentMenuAction() {
+		super(GRAPH_DELETE_MENU_SECTION, 10, DELETE_GRAPH_COMPONENT_URI);
+	}
+
+	@Override
+	protected Action createAction() {
+		return new DeleteGraphComponentAction(editManager, selectionManager);
+	}
+
+	public void setEditManager(EditManager editManager) {
+		this.editManager = editManager;
+	}
+
+	public void setSelectionManager(SelectionManager selectionManager) {
+		this.selectionManager = selectionManager;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/bf8a7ea2/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/DiagramMenu.java
----------------------------------------------------------------------
diff --git a/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/DiagramMenu.java b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/DiagramMenu.java
new file mode 100644
index 0000000..0b1497b
--- /dev/null
+++ b/taverna-graph-view/src/main/java/org/apache/taverna/workbench/views/graph/menu/DiagramMenu.java
@@ -0,0 +1,43 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.views.graph.menu;
+
+import static java.awt.event.KeyEvent.VK_V;
+import static javax.swing.Action.MNEMONIC_KEY;
+import static org.apache.taverna.ui.menu.DefaultMenuBar.DEFAULT_MENU_BAR;
+
+import java.net.URI;
+
+import org.apache.taverna.ui.menu.AbstractMenu;
+
+public class DiagramMenu extends AbstractMenu {
+	public static final URI DIAGRAM = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#diagram");
+
+	public DiagramMenu() {
+		super(DEFAULT_MENU_BAR, 65, DIAGRAM, "View");
+	}
+
+	public static DummyAction makeAction() {
+		DummyAction action = new DummyAction("View");
+		action.putValue(MNEMONIC_KEY, VK_V);
+		return action;
+	}
+}