You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2015/03/20 15:22:34 UTC

[20/51] [abbrv] [partial] incubator-taverna-workbench git commit: taverna-workbench-* -> taverna-*

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-menu-items/src/main/resources/META-INF/spring/menu-items-context.xml
----------------------------------------------------------------------
diff --git a/taverna-menu-items/src/main/resources/META-INF/spring/menu-items-context.xml b/taverna-menu-items/src/main/resources/META-INF/spring/menu-items-context.xml
new file mode 100644
index 0000000..6208a72
--- /dev/null
+++ b/taverna-menu-items/src/main/resources/META-INF/spring/menu-items-context.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<bean id="ActivityInputPortSection" class="net.sf.taverna.t2.ui.menu.items.activityport.ActivityInputPortSection" />
+	<bean id="ActivityOutputPortSection" class="net.sf.taverna.t2.ui.menu.items.activityport.ActivityOutputPortSection" />
+	<bean id="ConditionMenuActions" class="net.sf.taverna.t2.ui.menu.items.processor.ConditionMenuActions">
+			<property name="editManager" ref="editManager" />
+			<property name="selectionManager" ref="selectionManager" />
+			<property name="activityIconManager" ref="activityIconManager" />
+	</bean>
+	<bean id="AnnotatedConfigureMenuAction" class="net.sf.taverna.t2.ui.menu.items.annotated.AnnotatedConfigureMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="selectionManager" ref="selectionManager" />
+			<property name="annotationBeans" ref="annotationBeans" />
+	</bean>
+	<bean id="ConditionSection" class="net.sf.taverna.t2.ui.menu.items.controllink.ConditionSection" />
+	<bean id="ConfigureRunningContextualMenuSection" class="net.sf.taverna.t2.ui.menu.items.contextualviews.ConfigureRunningContextualMenuSection" />
+	<bean id="ConfigureSection" class="net.sf.taverna.t2.ui.menu.items.contextualviews.ConfigureSection" />
+	<bean id="ConnectDataflowInputPortMenuActions" class="net.sf.taverna.t2.ui.menu.items.ports.ConnectDataflowInputPortMenuActions">
+			<property name="editManager" ref="editManager" />
+			<property name="menuManager" ref="menuManager" />
+			<property name="workbenchConfiguration" ref="workbenchConfiguration" />
+			<property name="activityIconManager" ref="activityIconManager" />
+			<property name="colourManager" ref="colourManager" />
+	</bean>
+	<bean id="ConnectDataflowOutputPortMenuActions" class="net.sf.taverna.t2.ui.menu.items.ports.ConnectDataflowOutputPortMenuActions">
+			<property name="editManager" ref="editManager" />
+			<property name="menuManager" ref="menuManager" />
+			<property name="workbenchConfiguration" ref="workbenchConfiguration" />
+			<property name="activityIconManager" ref="activityIconManager" />
+			<property name="colourManager" ref="colourManager" />
+	</bean>
+	<bean id="ConnectInputPortMenuActions" class="net.sf.taverna.t2.ui.menu.items.activityport.ConnectInputPortMenuActions">
+			<property name="editManager" ref="editManager" />
+			<property name="menuManager" ref="menuManager" />
+			<property name="workbenchConfiguration" ref="workbenchConfiguration" />
+			<property name="activityIconManager" ref="activityIconManager" />
+			<property name="colourManager" ref="colourManager" />
+	</bean>
+	<bean id="ConnectOutputPortMenuActions" class="net.sf.taverna.t2.ui.menu.items.activityport.ConnectOutputPortMenuActions">
+			<property name="editManager" ref="editManager" />
+			<property name="menuManager" ref="menuManager" />
+			<property name="workbenchConfiguration" ref="workbenchConfiguration" />
+			<property name="activityIconManager" ref="activityIconManager" />
+			<property name="colourManager" ref="colourManager" />
+	</bean>
+	<bean id="CreateInputMenuAction" class="net.sf.taverna.t2.ui.menu.items.workflow.CreateInputMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="selectionManager" ref="selectionManager" />
+	</bean>
+	<bean id="CreateOutputMenuAction" class="net.sf.taverna.t2.ui.menu.items.workflow.CreateOutputMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="selectionManager" ref="selectionManager" />
+	</bean>
+	<bean id="EditDataflowInputPortMenuAction" class="net.sf.taverna.t2.ui.menu.items.ports.EditDataflowInputPortMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="selectionManager" ref="selectionManager" />
+	</bean>
+	<bean id="EditDataflowOutputPortMenuAction" class="net.sf.taverna.t2.ui.menu.items.ports.EditDataflowOutputPortMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="selectionManager" ref="selectionManager" />
+	</bean>
+	<bean id="EditSection" class="net.sf.taverna.t2.ui.menu.items.contextualviews.EditSection" />
+	<bean id="InsertSection" class="net.sf.taverna.t2.ui.menu.items.contextualviews.InsertSection" />
+	<bean id="LinkSection" class="net.sf.taverna.t2.ui.menu.items.datalink.LinkSection" />
+	<bean id="PasteMenuAction" class="net.sf.taverna.t2.ui.menu.items.contextualviews.PasteMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="menuManager" ref="menuManager" />
+			<property name="selectionManager" ref="selectionManager" />
+			<property name="serviceRegistry" ref="serviceRegistry" />
+	</bean>
+	<bean id="ProcessorSection" class="net.sf.taverna.t2.ui.menu.items.processor.ProcessorSection" />
+	<bean id="RemoveConditionMenuAction" class="net.sf.taverna.t2.ui.menu.items.controllink.RemoveConditionMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="selectionManager" ref="selectionManager" />
+	</bean>
+	<bean id="RemoveDataflowInputPortMenuAction" class="net.sf.taverna.t2.ui.menu.items.ports.RemoveDataflowInputPortMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="selectionManager" ref="selectionManager" />
+	</bean>
+	<bean id="RemoveDataflowOutputPortMenuAction" class="net.sf.taverna.t2.ui.menu.items.ports.RemoveDataflowOutputPortMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="selectionManager" ref="selectionManager" />
+	</bean>
+	<bean id="RemoveLinkMenuAction" class="net.sf.taverna.t2.ui.menu.items.datalink.RemoveLinkMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="selectionManager" ref="selectionManager" />
+	</bean>
+	<bean id="RemoveProcessorMenuAction" class="net.sf.taverna.t2.ui.menu.items.processor.RemoveProcessorMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="selectionManager" ref="selectionManager" />
+	</bean>
+	<bean id="RenameProcessorMenuAction" class="net.sf.taverna.t2.ui.menu.items.processor.RenameProcessorMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="selectionManager" ref="selectionManager" />
+	</bean>
+	<bean id="SetConstantInputPortValueMenuAction" class="net.sf.taverna.t2.ui.menu.items.activityport.SetConstantInputPortValueMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="selectionManager" ref="selectionManager" />
+			<property name="serviceRegistry" ref="serviceRegistry" />
+	</bean>
+	<bean id="ShowConfigureMenuAction" class="net.sf.taverna.t2.ui.menu.items.contextualviews.ShowConfigureMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="menuManager" ref="menuManager" />
+			<property name="selectionManager" ref="selectionManager" />
+	</bean>
+	<bean id="ShowDetailsContextualMenuAction" class="net.sf.taverna.t2.ui.menu.items.contextualviews.ShowDetailsContextualMenuAction">
+			<property name="workbench" ref="workbench" />
+	</bean>
+	<bean id="ShowDetailsMenuAction" class="net.sf.taverna.t2.ui.menu.items.contextualviews.ShowDetailsMenuAction">
+			<property name="workbench" ref="workbench" />
+	</bean>
+	<bean id="ShowReportsContextualMenuAction" class="net.sf.taverna.t2.ui.menu.items.contextualviews.ShowReportsContextualMenuAction">
+			<property name="selectionManager" ref="selectionManager" />
+			<property name="reportManager" ref="reportManager" />
+			<property name="workbench" ref="workbench" />
+	</bean>
+	<bean id="WorkflowInputPortSection" class="net.sf.taverna.t2.ui.menu.items.ports.WorkflowInputPortSection" />
+	<bean id="WorkflowOutputPortSection" class="net.sf.taverna.t2.ui.menu.items.ports.WorkflowOutputPortSection" />
+	<bean id="WorkflowServiceTemplatesSection" class="net.sf.taverna.t2.ui.menu.items.workflow.WorkflowServiceTemplatesSection" />
+
+</beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-monitor-view/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-monitor-view/pom.xml b/taverna-monitor-view/pom.xml
new file mode 100644
index 0000000..962367f
--- /dev/null
+++ b/taverna-monitor-view/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.taverna.workbench</groupId>
+		<artifactId>taverna-workbench</artifactId>
+		<version>3.1.0-incubating-SNAPSHOT</version>
+	</parent>
+	<artifactId>monitor-view</artifactId>
+	<packaging>bundle</packaging>
+	<name>Monitor View</name>
+	<dependencies>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>workbench-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>graph-model</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+ 		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>results-view</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>graph-view</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.lang</groupId>
+			<artifactId>ui</artifactId>
+			<version>${t2.lang.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.taverna.engine</groupId>
+			<artifactId>taverna-report-api</artifactId>
+			<version>${platform.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.taverna.engine</groupId>
+			<artifactId>taverna-run-api</artifactId>
+			<version>${platform.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>commons-beanutils</groupId>
+			<artifactId>commons-beanutils</artifactId>
+			<version>${commons.beanutils.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/MonitorViewComponent.java
----------------------------------------------------------------------
diff --git a/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/MonitorViewComponent.java b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/MonitorViewComponent.java
new file mode 100644
index 0000000..7ebd21f
--- /dev/null
+++ b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/MonitorViewComponent.java
@@ -0,0 +1,168 @@
+
+/*******************************************************************************
+ * 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.monitor;
+
+import static java.awt.BorderLayout.CENTER;
+import static java.awt.BorderLayout.SOUTH;
+import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED;
+import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED;
+import static org.apache.batik.ext.swing.GridBagConstants.EAST;
+import static org.apache.batik.ext.swing.GridBagConstants.NONE;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+
+import net.sf.taverna.t2.workbench.ui.Updatable;
+import net.sf.taverna.t2.workbench.views.monitor.graph.MonitorGraphComponent;
+import net.sf.taverna.t2.workbench.views.monitor.progressreport.TableMonitorComponent;
+
+/**
+ * Component that shows the progress of a workflow run, either through a graph or
+ * a table shown in separate tabs. For previous runs, it pulls processor and workflow
+ * statuses from provenance.
+ *
+ * Graph and table are interactive, where clicking on them triggers displaying of
+ * workflow results or intermediate results in a separate component.
+ *
+ * It also contains buttons to pause/resume and stop a workflow run.
+ *
+ */
+@SuppressWarnings({"serial","unused"})
+public class MonitorViewComponent extends JPanel implements Updatable {
+	private MonitorGraphComponent monitorGraph;
+	private TableMonitorComponent tableMonitorComponent;
+
+	private JTabbedPane tabbedPane;
+	private JPanel buttonsPanel;
+
+	public MonitorViewComponent() {
+		super(new BorderLayout());
+		tabbedPane = new JTabbedPane();
+		buttonsPanel = new JPanel(new GridBagLayout());
+
+//		buttonsPanel.add(new JLabel("Workflow status"));
+//
+//		buttonsPanel.add(new JButton("Pause"));
+//		buttonsPanel.add(new JButton("Cancel"));
+//		buttonsPanel.add(new JButton("Show results"));
+
+		add(tabbedPane, CENTER);
+		add(buttonsPanel, SOUTH);
+	}
+
+	public void setMonitorGraph(MonitorGraphComponent monitorGraph) {
+		this.monitorGraph = monitorGraph;
+		tabbedPane.add("Graph", monitorGraph);
+	}
+
+	public void setTableMonitorComponent(TableMonitorComponent tableMonitorComponent) {
+		this.tableMonitorComponent = tableMonitorComponent;
+
+		JScrollPane scrollPane = new JScrollPane(tableMonitorComponent,
+				VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
+
+		tabbedPane.add("Progress report", scrollPane);
+	}
+
+	public void addWorkflowRunStatusLabel(JLabel statusLabel){
+		GridBagConstraints gbc = new GridBagConstraints();
+
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+
+		gbc.fill = NONE;
+		buttonsPanel.add(statusLabel, gbc);
+	}
+
+	public void addWorkflowPauseButton(JButton workflowRunPauseButton) {
+		GridBagConstraints gbc = new GridBagConstraints();
+
+		gbc.gridx = 1;
+		gbc.gridy = 0;
+
+		gbc.fill = NONE;
+		gbc.weightx = 0.0;
+		buttonsPanel.add(workflowRunPauseButton, gbc);
+	}
+
+	public void addWorkflowCancelButton(JButton workflowRunCancelButton) {
+		GridBagConstraints gbc = new GridBagConstraints();
+
+		gbc.gridx = 2;
+		gbc.gridy = 0;
+
+		gbc.fill = NONE;
+		gbc.weightx = 0.0;
+		buttonsPanel.add(workflowRunCancelButton, gbc);
+	}
+
+	public void addReloadWorkflowButton(JButton reloadWorkflowButton) {
+		GridBagConstraints gbc = new GridBagConstraints();
+
+		gbc.gridx = 3;
+		gbc.gridy = 0;
+
+		gbc.fill = NONE;
+		gbc.weightx = 1.0;
+		gbc.anchor = EAST;
+		buttonsPanel.add(reloadWorkflowButton, gbc);
+	}
+
+	public void addIntermediateValuesButton(JButton intermediateValuesButton) {
+		GridBagConstraints gbc = new GridBagConstraints();
+
+		gbc.gridx = 4;
+		gbc.gridy = 0;
+
+		gbc.fill = NONE;
+		gbc.weightx = 1.0;
+		gbc.anchor = EAST;
+		buttonsPanel.add(intermediateValuesButton, gbc);
+	}
+
+	public void addWorkflowResultsButton(JButton workflowResultsButton) {
+		GridBagConstraints gbc = new GridBagConstraints();
+
+		gbc.gridx = 5;
+		gbc.gridy = 0;
+
+		gbc.fill = NONE;
+		gbc.weightx = 0.0;
+		gbc.anchor = EAST;
+		buttonsPanel.add(workflowResultsButton, gbc);
+	}
+
+	@Override
+	public void update() {
+		Component selectedComponent = tabbedPane.getSelectedComponent();
+		if (selectedComponent instanceof Updatable)
+			((Updatable) selectedComponent).update();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/graph/GraphMonitor.java
----------------------------------------------------------------------
diff --git a/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/graph/GraphMonitor.java b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/graph/GraphMonitor.java
new file mode 100644
index 0000000..ecaff3e
--- /dev/null
+++ b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/graph/GraphMonitor.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * 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.monitor.graph;
+
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.closeIcon;
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.tickIcon;
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.workingIcon;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+
+import net.sf.taverna.t2.workbench.models.graph.GraphController;
+import net.sf.taverna.t2.workbench.ui.Updatable;
+import uk.org.taverna.platform.report.ActivityReport;
+import uk.org.taverna.platform.report.ProcessorReport;
+import uk.org.taverna.platform.report.State;
+import uk.org.taverna.platform.report.WorkflowReport;
+
+/**
+ * An implementation of the Updatable interface that updates a Graph.
+ * 
+ * @author David Withers
+ */
+public class GraphMonitor implements Updatable {
+	private static final String STATUS_RUNNING = "Running";
+	private static final String STATUS_FINISHED = "Finished";
+	private static final String STATUS_CANCELLED = "Cancelled";
+
+	/**
+	 * Workflow run status label - we can only tell of workflow is running or is
+	 * finished from inside this monitor. If workfow run is stopped or paused -
+	 * this will be updated form the run-ui.
+	 */
+	private JLabel workflowRunStatusLabel;
+	/**
+	 * Similarly to {@link #workflowRunStatusLabel} - we disable the pause anc
+	 * cancel buttons when workflow runs is finished
+	 */
+	private JButton workflowRunPauseButton;
+	private JButton workflowRunCancelButton;
+	private GraphController graphController;
+	private Set<GraphMonitorNode> processors = new HashSet<>();
+	private final WorkflowReport workflowReport;
+
+	public GraphMonitor(GraphController graphController,
+			WorkflowReport workflowReport) {
+		this.graphController = graphController;
+		this.workflowReport = workflowReport;
+		createMonitorNodes(workflowReport.getSubject().getName(),
+				workflowReport);
+		redraw();
+	}
+
+	private void createMonitorNodes(String id, WorkflowReport workflowReport) {
+		for (ProcessorReport processorReport : workflowReport
+				.getProcessorReports()) {
+			String processorId = id + processorReport.getSubject().getName();
+			processors.add(new GraphMonitorNode(processorId, processorReport,
+					graphController));
+			for (ActivityReport activityReport : processorReport
+					.getActivityReports()) {
+				WorkflowReport nestedWorkflowReport = activityReport
+						.getNestedWorkflowReport();
+				if (nestedWorkflowReport != null)
+					createMonitorNodes(processorId, nestedWorkflowReport);
+			}
+		}
+	}
+
+	public void redraw() {
+		for (GraphMonitorNode node : processors)
+			node.redraw();
+	}
+
+	@Override
+	public void update() {
+		for (GraphMonitorNode node : processors)
+			node.update();
+		// updateState();
+	}
+
+	@SuppressWarnings("unused")
+	private void updateState() {
+		State state = workflowReport.getState();
+		switch (state) {
+		case COMPLETED:
+		case FAILED:
+			workflowRunStatusLabel.setText(STATUS_FINISHED);
+			workflowRunStatusLabel.setIcon(tickIcon);
+			workflowRunPauseButton.setEnabled(false);
+			workflowRunCancelButton.setEnabled(false);
+			break;
+		case CANCELLED:
+			workflowRunStatusLabel.setText(STATUS_CANCELLED);
+			workflowRunStatusLabel.setIcon(closeIcon);
+			workflowRunPauseButton.setEnabled(false);
+			workflowRunCancelButton.setEnabled(false);
+			break;
+		case RUNNING:
+			workflowRunStatusLabel.setText(STATUS_RUNNING);
+			workflowRunStatusLabel.setIcon(workingIcon);
+		default:
+			break;
+		}
+	}
+
+	// Set the status label that will be updated from this monitor
+	public void setWorkflowRunStatusLabel(JLabel workflowRunStatusLabel) {
+		this.workflowRunStatusLabel = workflowRunStatusLabel;
+	}
+
+	public void setWorkflowRunPauseButton(JButton workflowRunPauseButton) {
+		this.workflowRunPauseButton = workflowRunPauseButton;
+	}
+
+	public void setWorkflowRunCancelButton(JButton workflowRunCancelButton) {
+		this.workflowRunCancelButton = workflowRunCancelButton;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/graph/GraphMonitorNode.java
----------------------------------------------------------------------
diff --git a/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/graph/GraphMonitorNode.java b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/graph/GraphMonitorNode.java
new file mode 100644
index 0000000..8e5c441
--- /dev/null
+++ b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/graph/GraphMonitorNode.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * 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.monitor.graph;
+
+import static java.lang.Math.max;
+import net.sf.taverna.t2.workbench.models.graph.GraphController;
+import uk.org.taverna.platform.report.ProcessorReport;
+
+/**
+ * A <code>MonitorNode</code> that updates a <code>Graph</code> when
+ * <code>ProcessorReport</code> property changes.
+ * 
+ * @author David Withers
+ */
+public class GraphMonitorNode {
+	private ProcessorReport processorReport;
+	private GraphController graphController;
+	private String processorId;
+	private int queueSize = 0;
+	private int sentJobs = 0;
+	private int completedJobs = 0;
+	private int errors = 0;
+
+	public GraphMonitorNode(String id, ProcessorReport processorReport,
+			GraphController graphController) {
+		this.processorReport = processorReport;
+		this.graphController = graphController;
+		processorId = id;
+	}
+
+	/**
+	 * Updates the <code>Graph</code> when changes to properties are detected.
+	 */
+	public void update() {
+		synchronized (graphController) {
+			boolean queueSizeChanged = false;
+			boolean sentJobsChanged = false;
+			boolean completedJobsChanged = false;
+			boolean errorsChanged = false;
+
+			int newQueueSize = processorReport.getJobsQueued();
+			newQueueSize = newQueueSize == -1 ? 0 : newQueueSize;
+			if (queueSize != newQueueSize) {
+				queueSize = newQueueSize;
+				queueSizeChanged = true;
+			}
+
+			int newSentJobs = processorReport.getJobsStarted();
+			if (sentJobs != newSentJobs) {
+				sentJobs = newSentJobs;
+				sentJobsChanged = true;
+			}
+
+			int newCompletedJobs = processorReport.getJobsCompleted();
+			if (completedJobs != newCompletedJobs) {
+				completedJobs = newCompletedJobs;
+				completedJobsChanged = true;
+			}
+
+			int newErrors = processorReport.getJobsCompletedWithErrors();
+			if (errors != newErrors) {
+				errors = newErrors;
+				errorsChanged = true;
+			}
+
+			if (queueSizeChanged || sentJobsChanged || completedJobsChanged
+					|| errorsChanged) {
+				if (completedJobsChanged)
+					graphController.setIteration(processorId, completedJobs);
+				if (completedJobs > 0)
+					graphController.setNodeCompleted(processorId,
+							(completedJobs / (float) (sentJobs + queueSize)));
+				if (sentJobsChanged) {
+					// graphController.setEdgeActive(processorId, true);
+				}
+				if (errorsChanged && errors > 0)
+					graphController.setErrors(processorId, errors);
+			}
+		}
+	}
+
+	public void redraw() {
+		synchronized (graphController) {
+			queueSize = max(processorReport.getJobsQueued(), 0);
+			sentJobs = processorReport.getJobsStarted();
+			completedJobs = processorReport.getJobsCompleted();
+			errors = processorReport.getJobsCompletedWithErrors();
+
+			graphController.setIteration(processorId, completedJobs);
+			if (completedJobs > 0)
+				graphController.setNodeCompleted(processorId,
+						(completedJobs / (float) (sentJobs + queueSize)));
+			if (errors > 0)
+				graphController.setErrors(processorId, errors);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/graph/MonitorGraphComponent.java
----------------------------------------------------------------------
diff --git a/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/graph/MonitorGraphComponent.java b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/graph/MonitorGraphComponent.java
new file mode 100644
index 0000000..0be66ff
--- /dev/null
+++ b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/graph/MonitorGraphComponent.java
@@ -0,0 +1,378 @@
+/*******************************************************************************
+ * 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.monitor.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 net.sf.taverna.t2.workbench.icons.WorkbenchIcons.refreshIcon;
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.zoomInIcon;
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.zoomOutIcon;
+import static org.apache.batik.swing.svg.AbstractJSVGComponent.ALWAYS_DYNAMIC;
+
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.swing.Action;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JToolBar;
+import javax.swing.Timer;
+import javax.swing.border.EmptyBorder;
+
+import net.sf.taverna.t2.workbench.configuration.colour.ColourManager;
+import net.sf.taverna.t2.workbench.configuration.workbench.WorkbenchConfiguration;
+import net.sf.taverna.t2.workbench.models.graph.GraphElement;
+import net.sf.taverna.t2.workbench.models.graph.GraphEventManager;
+import net.sf.taverna.t2.workbench.models.graph.svg.SVGGraphController;
+import net.sf.taverna.t2.workbench.selection.DataflowSelectionModel;
+import net.sf.taverna.t2.workbench.selection.SelectionManager;
+import net.sf.taverna.t2.workbench.ui.Updatable;
+import net.sf.taverna.t2.workbench.views.graph.AutoScrollInteractor;
+import net.sf.taverna.t2.workbench.views.graph.menu.ResetDiagramAction;
+import net.sf.taverna.t2.workbench.views.graph.menu.ZoomInAction;
+import net.sf.taverna.t2.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 uk.org.taverna.platform.run.api.InvalidRunIdException;
+import uk.org.taverna.platform.run.api.RunService;
+import uk.org.taverna.scufl2.api.core.Processor;
+import uk.org.taverna.scufl2.api.core.Workflow;
+import uk.org.taverna.scufl2.api.port.WorkflowPort;
+import uk.org.taverna.scufl2.api.profiles.Profile;
+
+/**
+ * Use to display the graph for fresh workflow runs and allow the user to click
+ * on processors to see the intermediate results for processors pulled from
+ * provenance.
+ */
+@SuppressWarnings("serial")
+public class MonitorGraphComponent extends JPanel implements Updatable {
+	private static Logger logger = Logger.getLogger(MonitorGraphComponent.class);
+
+	private SVGGraphController graphController;
+	private JPanel diagramPanel;
+	private GraphMonitor graphMonitor;
+
+	private Map<String, SVGGraphController> graphControllerMap = new HashMap<>();
+	private Map<String, GraphMonitor> graphMonitorMap = new HashMap<>();
+	private Map<String, JPanel> diagramPanelMap = new HashMap<>();
+	private Map<String, Action[]> diagramActionsMap = new HashMap<>();
+
+	@SuppressWarnings("unused")
+	private Timer timer;
+	private CardLayout cardLayout;
+	@SuppressWarnings("unused")
+	private JLabel statusLabel;
+
+	private final RunService runService;
+	private final ColourManager colourManager;
+	private final WorkbenchConfiguration workbenchConfiguration;
+	private final SelectionManager selectionManager;
+
+	public MonitorGraphComponent(RunService runService, ColourManager colourManager,
+			WorkbenchConfiguration workbenchConfiguration, SelectionManager selectionManager) {
+		this.runService = runService;
+		this.colourManager = colourManager;
+		this.workbenchConfiguration = workbenchConfiguration;
+		this.selectionManager = selectionManager;
+
+		cardLayout = new CardLayout();
+		setLayout(cardLayout);
+
+//		ActionListener taskPerformer = new ActionListener() {
+//			public void actionPerformed(ActionEvent evt) {
+//				if (graphController != null) {
+//					graphController.redraw();
+//					graphMonitor.redraw();
+//				}
+//				timer.stop();
+//			}
+//		};
+//		timer = new Timer(100, taskPerformer);
+//
+//		addComponentListener(new ComponentAdapter() {
+//			public void componentResized(ComponentEvent e) {
+//				if (timer.isRunning()) {
+//					timer.restart();
+//				} else {
+//					timer.start();
+//				}
+//			}
+//		});
+
+	}
+
+	@Override
+	protected void finalize() throws Throwable {
+		if (graphController != null)
+			graphController.shutdown();
+	}
+
+	@Override
+	public void update() {
+		if (graphMonitor != null)
+			graphMonitor.update();
+	}
+
+	private JPanel createDiagramPanel(String workflowRun) {
+		final JPanel diagramPanel = new JPanel(new BorderLayout());
+
+		try {
+			Workflow workflow = runService.getWorkflow(workflowRun);
+			Profile profile = runService.getProfile(workflowRun);
+
+			// get the default diagram settings
+			// Alignment alignment = Alignment.valueOf(graphViewConfiguration
+			// .getProperty(GraphViewConfiguration.ALIGNMENT));
+			// PortStyle portStyle = PortStyle.valueOf(graphViewConfiguration
+			// .getProperty(GraphViewConfiguration.PORT_STYLE));
+
+			// create an SVG canvas
+			final JSVGCanvas svgCanvas = new JSVGCanvas(null, true, false);
+			svgCanvas.setEnableZoomInteractor(false);
+			svgCanvas.setEnableRotateInteractor(false);
+			svgCanvas.setDocumentState(ALWAYS_DYNAMIC);
+
+			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, profile, true, svgCanvas, null, null,
+					colourManager, workbenchConfiguration);
+			DataflowSelectionModel selectionModel = selectionManager
+					.getWorkflowRunSelectionModel(workflowRun);
+			svgGraphController.setDataflowSelectionModel(selectionModel);
+			svgGraphController
+					.setGraphEventManager(new MonitorGraphEventManager(
+							selectionModel));
+
+			graphControllerMap.put(workflowRun, svgGraphController);
+
+			// Toolbar with actions related to graph
+			JToolBar graphActionsToolbar = graphActionsToolbar(workflowRun, svgCanvas);
+			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);
+		} catch (InvalidRunIdException e) {
+			diagramPanel.add(new JLabel("Workflow run ID invalid", JLabel.CENTER),
+					CENTER);
+		}
+		return diagramPanel;
+	}
+
+	protected JToolBar graphActionsToolbar(String workflowRun, JSVGCanvas svgCanvas) {
+		JToolBar toolBar = new JToolBar();
+		toolBar.setAlignmentX(LEFT_ALIGNMENT);
+		toolBar.setFloatable(false);
+
+		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.setResultsAction(resetDiagramAction);
+		resetDiagramAction.putValue(SHORT_DESCRIPTION, "Reset Diagram");
+		resetDiagramAction.putValue(SMALL_ICON, refreshIcon);
+		resetDiagramButton.setAction(resetDiagramAction);
+
+		Action zoomInAction = svgCanvas.new ZoomAction(1.2);
+		ZoomInAction.setResultsAction(zoomInAction);
+		zoomInAction.putValue(SHORT_DESCRIPTION, "Zoom In");
+		zoomInAction.putValue(SMALL_ICON, zoomInIcon);
+		zoomInButton.setAction(zoomInAction);
+
+		Action zoomOutAction = svgCanvas.new ZoomAction(1 / 1.2);
+		ZoomOutAction.setResultsAction(zoomOutAction);
+		zoomOutAction.putValue(SHORT_DESCRIPTION, "Zoom Out");
+		zoomOutAction.putValue(SMALL_ICON, zoomOutIcon);
+		zoomOutButton.setAction(zoomOutAction);
+
+		// diagramActionsMap.put(workflowRun, new Action[] { resetDiagramAction, zoomInAction,
+		// zoomOutAction });
+
+		toolBar.add(resetDiagramButton);
+		toolBar.add(zoomInButton);
+		toolBar.add(zoomOutButton);
+
+		return toolBar;
+	}
+
+	// public void setStatus(Status status) {
+	// switch (status) {
+	// case RUNNING :
+	// statusLabel.setText("Workflow running");
+	// statusLabel.setIcon(WorkbenchIcons.workingIcon);
+	// if (workflow != null){ // should not be null really, workflow should be set before this
+	// method is called
+	// workflow.setIsRunning(true);
+	// }
+	// break;
+	// case FINISHED :
+	// statusLabel.setText("Workflow finished");
+	// statusLabel.setIcon(WorkbenchIcons.tickIcon);
+	// if (workflow != null){// should not be null really, workflow should be set before this method
+	// is called
+	// workflow.setIsRunning(false);
+	// }
+	// break;
+	// }
+	// }
+
+	public void setWorkflowRun(String workflowRun) throws InvalidRunIdException {
+		if (workflowRun != null) {
+			if (!diagramPanelMap.containsKey(workflowRun))
+				addWorkflowRun(workflowRun);
+			graphController = graphControllerMap.get(workflowRun);
+			diagramPanel = diagramPanelMap.get(workflowRun);
+			graphMonitor = graphMonitorMap.get(workflowRun);
+			Action[] actions = diagramActionsMap.get(workflowRun);
+			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();
+		}
+	}
+
+	public void addWorkflowRun(String workflowRun) throws InvalidRunIdException {
+		JPanel newDiagramPanel = createDiagramPanel(workflowRun);
+		add(newDiagramPanel, String.valueOf(newDiagramPanel.hashCode()));
+		diagramPanelMap.put(workflowRun, newDiagramPanel);
+		graphMonitorMap.put(workflowRun,
+				new GraphMonitor(graphControllerMap.get(workflowRun),
+						runService.getWorkflowReport(workflowRun)));
+	}
+
+	public void removeWorkflowRun(String workflowRun) {
+		JPanel removedDiagramPanel = diagramPanelMap.remove(workflowRun);
+		if (removedDiagramPanel != null)
+			remove(removedDiagramPanel);
+		SVGGraphController removedController = graphControllerMap
+				.remove(workflowRun);
+		if (removedController != null)
+			removedController.shutdown();
+		graphMonitorMap.remove(workflowRun);
+		diagramActionsMap.remove(workflowRun);
+	}
+
+	private class MonitorGraphEventManager implements GraphEventManager {
+		private final DataflowSelectionModel selectionModel;
+
+		public MonitorGraphEventManager(DataflowSelectionModel selectionModel) {
+			this.selectionModel = selectionModel;
+		}
+
+		@Override
+		public void mouseClicked(final GraphElement graphElement, short button,
+				boolean altKey, boolean ctrlKey, boolean metaKey, int x, int y,
+				int screenX, int screenY) {
+			Object workflowObject = graphElement.getWorkflowBean();
+			if (workflowObject instanceof Processor
+					|| workflowObject instanceof WorkflowPort)
+				selectionModel.addSelection(workflowObject);
+		}
+
+		@Override
+		public void mouseDown(GraphElement graphElement, short button,
+				boolean altKey, boolean ctrlKey, boolean metaKey, int x, int y,
+				int screenX, int screenY) {
+		}
+
+		@Override
+		public void mouseMoved(GraphElement graphElement, short button,
+				boolean altKey, boolean ctrlKey, boolean metaKey, int x, int y,
+				int screenX, int screenY) {
+		}
+
+		@Override
+		public void mouseUp(GraphElement graphElement, short button,
+				boolean altKey, boolean ctrlKey, boolean metaKey, int x, int y,
+				int screenX, int screenY) {
+		}
+
+		@Override
+		public void mouseOut(GraphElement graphElement, short button,
+				boolean altKey, boolean ctrlKey, boolean metaKey, int x, int y,
+				int screenX, int screenY) {
+		}
+
+		@Override
+		public void mouseOver(GraphElement graphElement, short button,
+				boolean altKey, boolean ctrlKey, boolean metaKey, int x, int y,
+				int screenX, int screenY) {
+		}
+	}
+
+	private class MySvgScrollPane extends JSVGScrollPane {
+		private static final long serialVersionUID = 6890422410714378543L;
+
+		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/52fd79dd/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/TableMonitorComponent.java
----------------------------------------------------------------------
diff --git a/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/TableMonitorComponent.java b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/TableMonitorComponent.java
new file mode 100644
index 0000000..bb82421
--- /dev/null
+++ b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/TableMonitorComponent.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (C) 2013 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.monitor.progressreport;
+
+import java.awt.CardLayout;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
+import net.sf.taverna.t2.workbench.selection.SelectionManager;
+import net.sf.taverna.t2.workbench.ui.Updatable;
+import uk.org.taverna.platform.report.WorkflowReport;
+import uk.org.taverna.platform.run.api.InvalidRunIdException;
+import uk.org.taverna.platform.run.api.RunService;
+
+/**
+ * @author David Withers
+ */
+@SuppressWarnings("serial")
+public class TableMonitorComponent extends JPanel implements Updatable {
+	private Map<String, WorkflowRunProgressTreeTable> tableMap = new HashMap<>();
+	private Map<String, WorkflowRunProgressTreeTableModel> tableModelMap = new HashMap<>();
+	private WorkflowRunProgressTreeTable table;
+	private WorkflowRunProgressTreeTableModel tableModel;
+	private CardLayout cardLayout;
+
+	private final RunService runService;
+	private final SelectionManager selectionManager;
+	private final ActivityIconManager activityIconManager;
+
+	public TableMonitorComponent(RunService runService,
+			SelectionManager selectionManager,
+			ActivityIconManager activityIconManager) {
+		this.runService = runService;
+		this.selectionManager = selectionManager;
+		this.activityIconManager = activityIconManager;
+
+		cardLayout = new CardLayout();
+		setLayout(cardLayout);
+	}
+
+	public void setWorkflowRun(String workflowRun) throws InvalidRunIdException {
+		if (workflowRun != null) {
+			if (!tableMap.containsKey(workflowRun))
+				addWorkflowRun(workflowRun);
+			table = tableMap.get(workflowRun);
+			tableModel = tableModelMap.get(workflowRun);
+			cardLayout.show(this, String.valueOf(table.hashCode()));
+		}
+	}
+
+	public void addWorkflowRun(String workflowRun) throws InvalidRunIdException {
+		WorkflowReport workflowReport = runService
+				.getWorkflowReport(workflowRun);
+		WorkflowRunProgressTreeTableModel newTableModel = new WorkflowRunProgressTreeTableModel(
+				workflowReport);
+		WorkflowRunProgressTreeTable newTable = new WorkflowRunProgressTreeTable(
+				newTableModel, activityIconManager,
+				selectionManager.getWorkflowRunSelectionModel(workflowRun));
+
+		add(new JScrollPane(newTable), String.valueOf(newTable.hashCode()));
+		tableMap.put(workflowRun, newTable);
+		tableModelMap.put(workflowRun, newTableModel);
+	}
+
+	public void removeWorkflowRun(String workflowRun) {
+		WorkflowRunProgressTreeTable removedTable = tableMap
+				.remove(workflowRun);
+		if (removedTable != null)
+			remove(removedTable);
+		tableModelMap.remove(workflowRun);
+	}
+
+	@Override
+	public void update() {
+		if (tableModel != null)
+			tableModel.update();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/WorkflowRunProgressTreeCellRenderer.java
----------------------------------------------------------------------
diff --git a/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/WorkflowRunProgressTreeCellRenderer.java b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/WorkflowRunProgressTreeCellRenderer.java
new file mode 100644
index 0000000..4c4d6ad
--- /dev/null
+++ b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/WorkflowRunProgressTreeCellRenderer.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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.monitor.progressreport;
+
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.workflowExplorerIcon;
+
+import java.awt.Component;
+import java.util.Set;
+
+import javax.swing.Icon;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
+import uk.org.taverna.platform.report.ActivityReport;
+import uk.org.taverna.platform.report.ProcessorReport;
+import uk.org.taverna.platform.report.WorkflowReport;
+
+/**
+ * Cell renderer for Workflow Explorer tree.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class WorkflowRunProgressTreeCellRenderer extends DefaultTreeCellRenderer {
+	private ActivityIconManager activityIconManager;
+
+	public WorkflowRunProgressTreeCellRenderer(ActivityIconManager activityIconManager) {
+		this.activityIconManager = activityIconManager;
+	}
+
+	@Override
+	public Component getTreeCellRendererComponent(JTree tree, Object value,
+			boolean sel, boolean expanded, boolean leaf, int row,
+			boolean hasFocus) {
+		Component result = super.getTreeCellRendererComponent(tree, value, sel,
+				expanded, leaf, row, hasFocus);
+
+		Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
+
+		WorkflowRunProgressTreeCellRenderer renderer = (WorkflowRunProgressTreeCellRenderer) result;
+
+		if (userObject instanceof WorkflowReport) // the root node
+			renderWorkflowReport(renderer, (WorkflowReport) userObject);
+		else if (userObject instanceof ProcessorReport)
+			renderProcessorReport(renderer, (ProcessorReport) userObject);
+
+		return result;
+	}
+
+	private void renderWorkflowReport(
+			WorkflowRunProgressTreeCellRenderer renderer,
+			WorkflowReport workflowReport) {
+		renderer.setIcon(workflowExplorerIcon);
+		renderer.setText(workflowReport.getSubject().getName());
+	}
+
+	private void renderProcessorReport(WorkflowRunProgressTreeCellRenderer renderer,
+			ProcessorReport processorReport) {
+		/*
+		 * Get the activity associated with the processor - currently only
+		 * one gets displayed
+		 */
+		Set<ActivityReport> activityReports = processorReport
+				.getActivityReports();
+		String text = processorReport.getSubject().getName();
+		if (!activityReports.isEmpty()) {
+			ActivityReport activityReport = activityReports.iterator()
+					.next();
+			Icon icon = activityIconManager.iconForActivity(activityReport
+					.getSubject());
+			if (icon != null)
+				renderer.setIcon(icon);
+		}
+		renderer.setText(text);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/WorkflowRunProgressTreeTable.java
----------------------------------------------------------------------
diff --git a/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/WorkflowRunProgressTreeTable.java b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/WorkflowRunProgressTreeTable.java
new file mode 100644
index 0000000..f1f031c
--- /dev/null
+++ b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/WorkflowRunProgressTreeTable.java
@@ -0,0 +1,112 @@
+package net.sf.taverna.t2.workbench.views.monitor.progressreport;
+
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+
+import net.sf.taverna.t2.lang.observer.Observable;
+import net.sf.taverna.t2.lang.observer.SwingAwareObserver;
+import net.sf.taverna.t2.lang.ui.treetable.JTreeTable;
+import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
+import net.sf.taverna.t2.workbench.selection.DataflowSelectionModel;
+import net.sf.taverna.t2.workbench.selection.events.DataflowSelectionMessage;
+import uk.org.taverna.platform.report.StatusReport;
+import uk.org.taverna.scufl2.api.core.Processor;
+import uk.org.taverna.scufl2.api.core.Workflow;
+import uk.org.taverna.scufl2.api.port.WorkflowPort;
+
+@SuppressWarnings("serial")
+public class WorkflowRunProgressTreeTable extends JTreeTable {
+	private final WorkflowRunProgressTreeTableModel treeTableModel;
+	private final DataflowSelectionModel selectionModel;
+	private final DataflowSelectionObserver dataflowSelectionObserver;
+
+	public WorkflowRunProgressTreeTable(
+			WorkflowRunProgressTreeTableModel treeTableModel,
+			ActivityIconManager activityIconManager,
+			DataflowSelectionModel selectionModel) {
+		super(treeTableModel);
+
+		this.treeTableModel = treeTableModel;
+		this.selectionModel = selectionModel;
+
+		this.tree.setCellRenderer(new WorkflowRunProgressTreeCellRenderer(
+				activityIconManager));
+		this.tree.setEditable(false);
+		this.tree.setExpandsSelectedPaths(true);
+		this.tree.setDragEnabled(false);
+		this.tree.setScrollsOnExpand(false);
+
+		getTableHeader().setReorderingAllowed(false);
+		getSelectionModel().setSelectionMode(
+				ListSelectionModel.SINGLE_SELECTION);
+		getSelectionModel().addListSelectionListener(
+				new TableSelectionListener());
+
+		dataflowSelectionObserver = new DataflowSelectionObserver();
+		selectionModel.addObserver(dataflowSelectionObserver);
+	}
+
+	@Override
+	protected void finalize() throws Throwable {
+		selectionModel.removeObserver(dataflowSelectionObserver);
+	}
+
+	/**
+	 * Return object in the tree part of this JTreeTable that corresponds to
+	 * this row. It will either be a workflow (tree root) or a processor.
+	 */
+	public Object getTreeObjectForRow(int row) {
+		TreePath path = tree.getPathForRow(row);
+		if (path == null)
+			return null;
+		return ((DefaultMutableTreeNode) path.getLastPathComponent())
+				.getUserObject();
+	}
+
+	public void setSelectedRowForObject(Object workflowObject) {
+		// Find the row for the object in the tree
+		DefaultMutableTreeNode node = treeTableModel.getNodeForObject(workflowObject);
+		if (node != null) {
+			TreeNode[] path = node.getPath();
+			tree.scrollPathToVisible(new TreePath(path));
+			int row = tree.getRowForPath(new TreePath(path));
+			if (row >= 0)
+				// Set selected row on the table
+				setRowSelectionInterval(row, row);
+		}
+	}
+
+	private class DataflowSelectionObserver extends SwingAwareObserver<DataflowSelectionMessage> {
+		@Override
+		public void notifySwing(Observable<DataflowSelectionMessage> sender,
+				DataflowSelectionMessage message) {
+			for (Object selection : selectionModel.getSelection()) {
+				if (selection instanceof Processor
+						|| selection instanceof Workflow)
+					setSelectedRowForObject(selection);
+				else if (selection instanceof WorkflowPort)
+					setSelectedRowForObject(((WorkflowPort) selection)
+							.getParent());
+			}
+		}
+	}
+
+	private class TableSelectionListener implements ListSelectionListener {
+		@Override
+		public void valueChanged(ListSelectionEvent e) {
+			if (e.getValueIsAdjusting())
+				return;
+			int selectedRow = getSelectedRow();
+			if (selectedRow < 0)
+				return;
+			Object selection = getTreeObjectForRow(selectedRow);
+			if (selection instanceof StatusReport)
+				selectionModel.addSelection(((StatusReport<?, ?>) selection)
+						.getSubject());
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/WorkflowRunProgressTreeTableModel.java
----------------------------------------------------------------------
diff --git a/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/WorkflowRunProgressTreeTableModel.java b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/WorkflowRunProgressTreeTableModel.java
new file mode 100644
index 0000000..1e2e6e9
--- /dev/null
+++ b/taverna-monitor-view/src/main/java/net/sf/taverna/t2/workbench/views/monitor/progressreport/WorkflowRunProgressTreeTableModel.java
@@ -0,0 +1,279 @@
+/*******************************************************************************
+ * 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.monitor.progressreport;
+
+import static java.util.Collections.nCopies;
+import static net.sf.taverna.t2.workbench.views.monitor.progressreport.WorkflowRunProgressTreeTableModel.Column.values;
+import static net.sf.taverna.t2.workbench.views.results.processor.ProcessorResultsComponent.formatMilliseconds;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+
+import net.sf.taverna.t2.lang.ui.treetable.AbstractTreeTableModel;
+import net.sf.taverna.t2.lang.ui.treetable.TreeTableModel;
+import uk.org.taverna.platform.report.ActivityReport;
+import uk.org.taverna.platform.report.Invocation;
+import uk.org.taverna.platform.report.ProcessorReport;
+import uk.org.taverna.platform.report.State;
+import uk.org.taverna.platform.report.StatusReport;
+import uk.org.taverna.platform.report.WorkflowReport;
+
+/**
+ * A TreeTableModel used to display the progress of a workfow run. The workflow
+ * and its processors (some of which may be nested) are represented as a tree,
+ * where their properties, such as status, start and finish times, number of
+ * iterations, etc. are represented as table columns.
+ * 
+ * @author Alex Nenadic
+ * @author Stian Soiland-Reyes
+ * @author David Withers
+ */
+public class WorkflowRunProgressTreeTableModel extends AbstractTreeTableModel {
+	public static final String NAME = "Name";
+	public static final String STATUS = "Status";
+	public static final String AVERAGE_ITERATION_TIME = "Average time per iteration";
+	public static final String ITERATIONS = "Queued iterations";
+	public static final String ITERATIONS_DONE = "Completed iterations";
+	public static final String ITERATIONS_FAILED = "Iterations with errors";
+
+	public enum Column {
+		NAME("Name", TreeTableModel.class), STATUS("Status"), ITERATIONS_QUEUED(
+				"Queued iterations"), ITERATIONS_DONE("Iterations done"), ITERATIONS_FAILED(
+				"Iterations w/errors"), AVERAGE_ITERATION_TIME(
+				"Average time/iteration"), START_TIME(
+				"First iteration started", Date.class), FINISH_TIME(
+				"Last iteration ended", Date.class);
+
+		private final String label;
+		private final Class<?> columnClass;
+
+		Column(String label) {
+			this(label, String.class);
+		}
+
+		Column(String label, Class<?> columnClass) {
+			this.label = label;
+			this.columnClass = columnClass;
+		}
+
+		public Class<?> getColumnClass() {
+			return columnClass;
+		}
+
+		public String getLabel() {
+			return label;
+		}
+
+		@Override
+		public String toString() {
+			return label;
+		}
+	}
+
+	// Table data (maps workflow element nodes to column data associated with them)
+	private final Map<DefaultMutableTreeNode, List<Object>> data = new HashMap<>();
+	private final Map<Object, DefaultMutableTreeNode> nodeForObject = new HashMap<>();
+	private final DefaultMutableTreeNode rootNode;
+
+	public WorkflowRunProgressTreeTableModel(WorkflowReport workflowReport) {
+		super(new DefaultMutableTreeNode(workflowReport));
+		rootNode = (DefaultMutableTreeNode) this.getRoot();
+		createTree(workflowReport, rootNode);
+	}
+
+	private void createTree(WorkflowReport workflowReport, DefaultMutableTreeNode root) {
+		// If this is the root of the tree rather than a root of the nested sub-tree
+		if (root.equals(rootNode)) {
+			List<Object> columnData = new ArrayList<>(nCopies(values().length,
+					null));
+			setColumnValues(workflowReport, columnData);
+			nodeForObject.put(workflowReport, root);
+			nodeForObject.put(workflowReport.getSubject(), root);
+			data.put(root, columnData);
+		}
+		// One row for each processor
+		for (ProcessorReport processorReport : workflowReport.getProcessorReports()) {
+			List<Object> columnData = new ArrayList<>(nCopies(values().length,
+					null));
+			DefaultMutableTreeNode processorNode = new DefaultMutableTreeNode(
+					processorReport);
+			setColumnValues(processorReport, columnData);
+			nodeForObject.put(processorReport, processorNode);
+			nodeForObject.put(processorReport.getSubject(), processorNode);
+			data.put(processorNode, columnData);
+			root.add(processorNode);
+
+			Set<ActivityReport> activityReports = processorReport.getActivityReports();
+			if (activityReports.size() == 1) {
+				WorkflowReport nestedWorkflowReport = activityReports.iterator().next()
+						.getNestedWorkflowReport();
+				if (nestedWorkflowReport != null)
+					// create sub-tree
+					createTree(nestedWorkflowReport, processorNode);
+			}
+		}
+	}
+
+	public DefaultMutableTreeNode getNodeForObject(Object workflowObject) {
+		return nodeForObject.get(workflowObject);
+	}
+
+	public void setColumnValues(StatusReport<?, ?> report, List<Object> columns) {
+		if (report instanceof WorkflowReport) {
+			WorkflowReport workflowReport = (WorkflowReport) report;
+
+			State state = workflowReport.getState();
+			Date startTime = workflowReport.getStartedDate();
+			Date finishTime = workflowReport.getCompletedDate();
+
+			columns.set(Column.NAME.ordinal(), workflowReport.getSubject().getName());
+			columns.set(Column.STATUS.ordinal(), state);
+			columns.set(Column.ITERATIONS_DONE.ordinal(), "-");
+			columns.set(Column.ITERATIONS_FAILED.ordinal(), "-");
+			columns.set(Column.ITERATIONS_QUEUED.ordinal(), "-");
+			columns.set(Column.START_TIME.ordinal(), startTime);
+			columns.set(Column.FINISH_TIME.ordinal(), finishTime);
+			if (startTime != null && finishTime != null)
+				columns.set(Column.AVERAGE_ITERATION_TIME.ordinal(),
+						formatMilliseconds(finishTime.getTime() - finishTime.getTime()));
+			else
+				columns.set(Column.AVERAGE_ITERATION_TIME.ordinal(), "-");
+		} else if (report instanceof ProcessorReport) {
+			ProcessorReport processorReport = (ProcessorReport) report;
+
+			State state = processorReport.getState();
+			SortedSet<Invocation> invocations = processorReport
+					.getInvocations();
+
+			columns.set(Column.NAME.ordinal(), processorReport.getSubject()
+					.getName());
+			columns.set(Column.STATUS.ordinal(), state);
+			columns.set(Column.ITERATIONS_QUEUED.ordinal(),
+					processorReport.getJobsQueued());
+			columns.set(Column.ITERATIONS_DONE.ordinal(),
+					processorReport.getJobsCompleted());
+			columns.set(Column.ITERATIONS_FAILED.ordinal(),
+					processorReport.getJobsCompletedWithErrors());
+
+			if (invocations.isEmpty()) {
+				columns.set(Column.START_TIME.ordinal(), null);
+				columns.set(Column.FINISH_TIME.ordinal(), null);
+				columns.set(Column.AVERAGE_ITERATION_TIME.ordinal(), null); // iteration
+			} else {
+				Date earliestStartTime = invocations.first().getStartedDate();
+				Date latestFinishTime = invocations.first().getCompletedDate();
+				long totalInvocationTime = 0;
+				int finishedInvocations = 0;
+
+				for (Invocation invocation : invocations) {
+					// Get the earliest start time of all invocations
+					Date startTime = invocation.getStartedDate();
+					if (startTime != null) {
+						if (startTime.before(earliestStartTime))
+							earliestStartTime = startTime;
+						// Get the latest finish time of all invocations
+						Date finishTime = invocation.getCompletedDate();
+						if (finishTime != null) {
+							if (finishTime.after(latestFinishTime)) {
+								latestFinishTime = finishTime;
+								totalInvocationTime += finishTime.getTime() - startTime.getTime();
+							}
+							finishedInvocations++;
+						}
+					}
+				}
+
+				columns.set(Column.START_TIME.ordinal(), earliestStartTime);
+				columns.set(Column.FINISH_TIME.ordinal(), latestFinishTime);
+				if (finishedInvocations > 0) {
+					long averageTime = totalInvocationTime / finishedInvocations;
+					columns.set(Column.AVERAGE_ITERATION_TIME.ordinal(),
+							formatMilliseconds(averageTime));
+				} else
+					columns.set(Column.AVERAGE_ITERATION_TIME.ordinal(), "-");
+			}
+		}
+	}
+
+	public void update() {
+		update(rootNode);
+		fireTreeNodesChanged(rootNode, rootNode.getPath(), null, null);
+	}
+
+	private void update(DefaultMutableTreeNode node) {
+		setColumnValues((StatusReport<?, ?>) node.getUserObject(), data.get(node));
+		for (int i = 0; i < node.getChildCount(); i++)
+			update((DefaultMutableTreeNode) node.getChildAt(i));
+	}
+
+	//
+	// The TreeModel interface
+	//
+
+	@Override
+	public int getChildCount(Object node) {
+		return ((TreeNode) node).getChildCount();
+	}
+
+	@Override
+	public Object getChild(Object node, int i) {
+		return ((TreeNode) node).getChildAt(i);
+	}
+
+	//
+	// The TreeTableNode interface.
+	//
+
+	@Override
+	public int getColumnCount() {
+		return values().length;
+	}
+
+	@Override
+	public String getColumnName(int column) {
+		return values()[column].getLabel();
+	}
+
+	@Override
+	public Class<?> getColumnClass(int column) {
+		return values()[column].getColumnClass();
+	}
+
+	public Object getValueAt(Object node, Column column) {
+		return getValueAt(node, column.ordinal());
+	}
+
+	@Override
+	public Object getValueAt(Object node, int column) {
+		List<Object> columnValues = data.get(node);
+		if (columnValues == null)
+			return null;
+		return columnValues.get(column);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-monitor-view/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentFactorySPI
----------------------------------------------------------------------
diff --git a/taverna-monitor-view/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentFactorySPI b/taverna-monitor-view/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentFactorySPI
new file mode 100644
index 0000000..cf13a46
--- /dev/null
+++ b/taverna-monitor-view/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentFactorySPI
@@ -0,0 +1 @@
+net.sf.taverna.t2.workbench.views.monitor.graph.MonitorGraphComponentFactory
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-monitor-view/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentSPI
----------------------------------------------------------------------
diff --git a/taverna-monitor-view/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentSPI b/taverna-monitor-view/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentSPI
new file mode 100644
index 0000000..30f1743
--- /dev/null
+++ b/taverna-monitor-view/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.zaria.UIComponentSPI
@@ -0,0 +1 @@
+net.sf.taverna.t2.workbench.views.monitor.graph.MonitorGraphComponent
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-monitor-view/src/main/resources/META-INF/spring/monitor-view-context-osgi.xml
----------------------------------------------------------------------
diff --git a/taverna-monitor-view/src/main/resources/META-INF/spring/monitor-view-context-osgi.xml b/taverna-monitor-view/src/main/resources/META-INF/spring/monitor-view-context-osgi.xml
new file mode 100644
index 0000000..ab22b97
--- /dev/null
+++ b/taverna-monitor-view/src/main/resources/META-INF/spring/monitor-view-context-osgi.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans:beans xmlns="http://www.springframework.org/schema/osgi" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:beans="http://www.springframework.org/schema/beans"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans.xsd
+                      http://www.springframework.org/schema/osgi
+                      http://www.springframework.org/schema/osgi/spring-osgi.xsd">
+
+</beans:beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-monitor-view/src/main/resources/META-INF/spring/monitor-view-context.xml
----------------------------------------------------------------------
diff --git a/taverna-monitor-view/src/main/resources/META-INF/spring/monitor-view-context.xml b/taverna-monitor-view/src/main/resources/META-INF/spring/monitor-view-context.xml
new file mode 100644
index 0000000..d662d87
--- /dev/null
+++ b/taverna-monitor-view/src/main/resources/META-INF/spring/monitor-view-context.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+</beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-parallelize-ui/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-parallelize-ui/pom.xml b/taverna-parallelize-ui/pom.xml
new file mode 100644
index 0000000..e74c474
--- /dev/null
+++ b/taverna-parallelize-ui/pom.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.taverna.workbench</groupId>
+		<artifactId>taverna-workbench</artifactId>
+		<version>3.1.0-incubating-SNAPSHOT</version>
+	</parent>
+	<artifactId>parallelize-ui</artifactId>
+	<packaging>bundle</packaging>
+	<name>Parallelize layer contextual view</name>
+	<dependencies>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>contextual-views-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>menu-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>edits-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>selection-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-databind</artifactId>
+			<version>${jackson-databind.version}</version>
+		</dependency>
+	</dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-parallelize-ui/src/main/java/net/sf/taverna/t2/workbench/parallelize/ParallelizeConfigurationPanel.java
----------------------------------------------------------------------
diff --git a/taverna-parallelize-ui/src/main/java/net/sf/taverna/t2/workbench/parallelize/ParallelizeConfigurationPanel.java b/taverna-parallelize-ui/src/main/java/net/sf/taverna/t2/workbench/parallelize/ParallelizeConfigurationPanel.java
new file mode 100644
index 0000000..f951da6
--- /dev/null
+++ b/taverna-parallelize-ui/src/main/java/net/sf/taverna/t2/workbench/parallelize/ParallelizeConfigurationPanel.java
@@ -0,0 +1,99 @@
+package net.sf.taverna.t2.workbench.parallelize;
+
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.border.EmptyBorder;
+
+import uk.org.taverna.scufl2.api.configurations.Configuration;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+@SuppressWarnings("serial")
+public class ParallelizeConfigurationPanel extends JPanel {
+
+	private ObjectNode json;
+	private JTextField maxJobsField = new JTextField(10);
+	private final String processorName;
+
+	public ParallelizeConfigurationPanel(Configuration configuration, String processorName) {
+		if (configuration.getJson().has("parallelize")) {
+			json = (ObjectNode) configuration.getJson().get("parallelize").deepCopy();
+		} else {
+			json = configuration.getJsonAsObjectNode().objectNode();
+		}
+		this.processorName = processorName;
+		this.setLayout(new GridBagLayout());
+		this.setBorder(new EmptyBorder(10,10,10,10));
+		populate();
+	}
+
+	public void populate() {
+		this.removeAll();
+		GridBagConstraints gbc = new GridBagConstraints();
+		JLabel jobs = new JLabel("<html><body>Maximum numbers of items to process at the same time</body></html>");
+
+		jobs.setBorder(new EmptyBorder(0,0,0,10));
+		gbc.weightx = 0.8;
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		this.add(jobs, gbc);
+		if (json.has("maximumJobs")) {
+			maxJobsField.setText(json.get("maximumJobs").asText());
+		} else {
+			maxJobsField.setText("1");
+		}
+		gbc.weightx = 0.2;
+		gbc.fill = GridBagConstraints.HORIZONTAL;
+		this.add(maxJobsField, gbc);
+		gbc.weightx = 0.1;
+		this.add(new JPanel(), gbc);
+
+		gbc.gridy=1;
+		gbc.gridx=0;
+		gbc.gridwidth=3;
+		gbc.weightx=0;
+		gbc.anchor = GridBagConstraints.SOUTH;
+		gbc.fill = GridBagConstraints.BOTH;
+		gbc.weighty = 1.0;
+		JLabel explanationLabel = new JLabel("<html><body><small>" +
+					"The service <b>" +  processorName + "</b> will be invoked as soon as the required inputs " +
+				    "for an iteration are available, but no more than the maximum number of items " +
+					"will be invoked at the same time."
+					+ "</small></body></html>");
+		this.add(explanationLabel, gbc);
+
+		this.setPreferredSize(new Dimension(350, 170));
+	}
+
+	public boolean validateConfig() {
+		String errorText = "";
+		int maxJobs = -1;
+		try {
+			maxJobs = Integer.parseInt(maxJobsField.getText());
+			if (maxJobs < 1) {
+				errorText += "The maximum number of items must be a positive integer.\n";
+			}
+		}
+		catch (NumberFormatException e) {
+			errorText += "The maximum number of items must be an integer.\n";
+		}
+
+		if (errorText.length() > 0) {
+			JOptionPane.showMessageDialog(this, errorText, "", JOptionPane.ERROR_MESSAGE);
+			return false;
+		}
+		return true;
+	}
+
+	public JsonNode getJson() {
+		json.put("maximumJobs", maxJobsField.getText());
+		return json;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-parallelize-ui/src/main/java/net/sf/taverna/t2/workbench/parallelize/ParallelizeConfigureAction.java
----------------------------------------------------------------------
diff --git a/taverna-parallelize-ui/src/main/java/net/sf/taverna/t2/workbench/parallelize/ParallelizeConfigureAction.java b/taverna-parallelize-ui/src/main/java/net/sf/taverna/t2/workbench/parallelize/ParallelizeConfigureAction.java
new file mode 100644
index 0000000..6727c59
--- /dev/null
+++ b/taverna-parallelize-ui/src/main/java/net/sf/taverna/t2/workbench/parallelize/ParallelizeConfigureAction.java
@@ -0,0 +1,185 @@
+/**
+ *
+ */
+package net.sf.taverna.t2.workbench.parallelize;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+import net.sf.taverna.t2.workbench.edits.Edit;
+import net.sf.taverna.t2.workbench.edits.EditException;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.helper.HelpEnabledDialog;
+import net.sf.taverna.t2.workbench.selection.SelectionManager;
+import net.sf.taverna.t2.workflow.edits.AddChildEdit;
+import net.sf.taverna.t2.workflow.edits.ChangeJsonEdit;
+
+import org.apache.log4j.Logger;
+
+import uk.org.taverna.scufl2.api.common.Scufl2Tools;
+import uk.org.taverna.scufl2.api.configurations.Configuration;
+import uk.org.taverna.scufl2.api.core.Processor;
+import uk.org.taverna.scufl2.api.profiles.Profile;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * @author alanrw
+ * @author David Withers
+ */
+@SuppressWarnings("serial")
+public class ParallelizeConfigureAction extends AbstractAction {
+
+	private Frame owner;
+	private final Processor processor;
+	private final ParallelizeContextualView parallelizeContextualView;
+
+	private EditManager editManager;
+
+	private static Logger logger = Logger.getLogger(ParallelizeConfigureAction.class);
+
+	private final Scufl2Tools scufl2Tools = new Scufl2Tools();
+	private final SelectionManager selectionManager;
+
+	public ParallelizeConfigureAction(Frame owner,
+			ParallelizeContextualView parallelizeContextualView,
+			Processor processor, EditManager editManager, SelectionManager selectionManager) {
+		super("Configure");
+		this.owner = owner;
+		this.parallelizeContextualView = parallelizeContextualView;
+		this.processor = processor;
+		this.editManager = editManager;
+		this.selectionManager = selectionManager;
+	}
+
+	public void actionPerformed(ActionEvent e) {
+		String processorName = processor.getName();
+		String title = "Parallel jobs for service " + processorName;
+		final JDialog dialog = new HelpEnabledDialog(owner, title, true);
+		Configuration configuration;
+		try {
+			configuration = scufl2Tools.configurationFor(processor, selectionManager.getSelectedProfile());
+		} catch (IndexOutOfBoundsException ex) {
+			configuration = new Configuration();
+		}
+		ParallelizeConfigurationPanel parallelizeConfigurationPanel = new ParallelizeConfigurationPanel(configuration, processorName);
+		dialog.add(parallelizeConfigurationPanel, BorderLayout.CENTER);
+
+		JPanel buttonPanel = new JPanel();
+		buttonPanel.setLayout(new FlowLayout());
+
+		JButton okButton = new JButton(new OKAction(dialog,
+				parallelizeConfigurationPanel));
+		buttonPanel.add(okButton);
+
+		JButton resetButton = new JButton(new ResetAction(
+				parallelizeConfigurationPanel));
+		buttonPanel.add(resetButton);
+
+		JButton cancelButton = new JButton(new CancelAction(dialog));
+		buttonPanel.add(cancelButton);
+
+		dialog.add(buttonPanel, BorderLayout.SOUTH);
+		dialog.pack();
+		dialog.setLocationRelativeTo(null);
+		dialog.setVisible(true);
+	}
+
+	public class ResetAction extends AbstractAction {
+
+		private final ParallelizeConfigurationPanel parallelizeConfigurationPanel;
+
+		public ResetAction(ParallelizeConfigurationPanel parallelizeConfigurationPanel) {
+			super("Reset");
+			this.parallelizeConfigurationPanel = parallelizeConfigurationPanel;
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			parallelizeConfigurationPanel.populate();
+		}
+
+	}
+
+	public class OKAction extends AbstractAction {
+
+		private final ParallelizeConfigurationPanel parallelizeConfigurationPanel;
+		private final JDialog dialog;
+
+		public OKAction(JDialog dialog, ParallelizeConfigurationPanel parallelizeConfigurationPanel) {
+			super("OK");
+			this.dialog = dialog;
+			this.parallelizeConfigurationPanel = parallelizeConfigurationPanel;
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			if (parallelizeConfigurationPanel.validateConfig()) {
+				try {
+					try {
+						Configuration configuration = scufl2Tools.configurationFor(processor, selectionManager.getSelectedProfile());
+						ObjectNode json = configuration.getJsonAsObjectNode().deepCopy();
+						ObjectNode parallelizeNode = null;
+						if (json.has("parallelize")) {
+							parallelizeNode = (ObjectNode) json.get("parallelize");
+						} else {
+							parallelizeNode = json.objectNode();
+							json.put("parallelize", parallelizeNode);
+						}
+						JsonNode newParallelizeNode = parallelizeConfigurationPanel.getJson();
+						Iterator<Entry<String, JsonNode>> fields = newParallelizeNode.fields();
+						while (fields.hasNext()) {
+							Entry<String, JsonNode> entry = fields.next();
+							parallelizeNode.set(entry.getKey(), entry.getValue());
+						}
+						Edit<Configuration> edit = new ChangeJsonEdit(configuration, json);
+						editManager.doDataflowEdit(selectionManager.getSelectedWorkflowBundle(), edit);
+					} catch (IndexOutOfBoundsException ex) {
+						Configuration configuration = new Configuration();
+						configuration.setConfigures(processor);
+						ObjectNode json = configuration.getJsonAsObjectNode();
+						json.put("parallelize", parallelizeConfigurationPanel.getJson());
+						Edit<Profile> edit = new AddChildEdit<Profile>(selectionManager.getSelectedProfile(), configuration);
+						editManager.doDataflowEdit(selectionManager.getSelectedWorkflowBundle(), edit);
+					}
+					dialog.setVisible(false);
+					if (parallelizeContextualView != null) {
+						parallelizeContextualView.refreshView();
+					}
+				} catch (EditException e1) {
+					logger.warn("Could not configure jobs", e1);
+					JOptionPane.showMessageDialog(owner, "Could not configure jobs",
+							"An error occured when configuring jobs: " + e1.getMessage(),
+							JOptionPane.ERROR_MESSAGE);
+				}
+			}
+		}
+
+	}
+
+	public class CancelAction extends AbstractAction {
+
+		private final JDialog dialog;
+
+		public CancelAction(JDialog dialog) {
+			super("Cancel");
+			this.dialog = dialog;
+
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			dialog.setVisible(false);
+		}
+
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-parallelize-ui/src/main/java/net/sf/taverna/t2/workbench/parallelize/ParallelizeConfigureMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-parallelize-ui/src/main/java/net/sf/taverna/t2/workbench/parallelize/ParallelizeConfigureMenuAction.java b/taverna-parallelize-ui/src/main/java/net/sf/taverna/t2/workbench/parallelize/ParallelizeConfigureMenuAction.java
new file mode 100644
index 0000000..194d81e
--- /dev/null
+++ b/taverna-parallelize-ui/src/main/java/net/sf/taverna/t2/workbench/parallelize/ParallelizeConfigureMenuAction.java
@@ -0,0 +1,77 @@
+/**********************************************************************
+ * Copyright (C) 2007-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 net.sf.taverna.t2.workbench.parallelize;
+
+import java.awt.event.ActionEvent;
+import java.net.URI;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+
+import net.sf.taverna.t2.ui.menu.AbstractContextualMenuAction;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.selection.SelectionManager;
+import uk.org.taverna.scufl2.api.core.Processor;
+
+public class ParallelizeConfigureMenuAction extends AbstractContextualMenuAction {
+
+	public static final URI configureRunningSection = URI
+			.create("http://taverna.sf.net/2009/contextMenu/configureRunning");
+
+	private static final URI PARALLELIZE_CONFIGURE_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/parallelizeConfigure");
+
+	public static URI TYPE = URI.create("http://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/Parallelize");
+
+	private EditManager editManager;
+
+	private SelectionManager selectionManager;
+
+	public ParallelizeConfigureMenuAction() {
+		super(configureRunningSection, 10, PARALLELIZE_CONFIGURE_URI);
+	}
+
+	@SuppressWarnings("serial")
+	@Override
+	protected Action createAction() {
+		return new AbstractAction("Parallel jobs...") {
+			public void actionPerformed(ActionEvent e) {
+				Processor processor = (Processor) getContextualSelection().getSelection();
+				ParallelizeConfigureAction parallelizeConfigureAction = new ParallelizeConfigureAction(
+						null, null, processor, editManager, selectionManager);
+				parallelizeConfigureAction.actionPerformed(e);
+			}
+		};
+	}
+
+	public boolean isEnabled() {
+		return super.isEnabled() && (getContextualSelection().getSelection() instanceof Processor);
+	}
+
+	public void setEditManager(EditManager editManager) {
+		this.editManager = editManager;
+	}
+
+	public void setSelectionManager(SelectionManager selectionManager) {
+		this.selectionManager = selectionManager;
+	}
+
+}