blob: 0be66ff4bc47407740970bab6a2c406588110af6 [file] [log] [blame]
/*******************************************************************************
* 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();
}
}
}