blob: a212a69dbc4b7524b38ab138f599e20cdbe8f652 [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.ui.workflowexplorer;
import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.controlLinkIcon;
import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.datalinkIcon;
import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.folderClosedIcon;
import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.folderOpenIcon;
import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.inputIcon;
import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.inputPortIcon;
import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.outputIcon;
import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.outputPortIcon;
import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.workflowExplorerIcon;
import java.awt.Component;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import net.sf.taverna.t2.lang.ui.icons.Icons;
//import net.sf.taverna.t2.visit.VisitReport.Status;
import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
import net.sf.taverna.t2.workbench.report.ReportManager;
import org.apache.commons.beanutils.BeanUtils;
import uk.org.taverna.scufl2.api.activity.Activity;
import uk.org.taverna.scufl2.api.common.Scufl2Tools;
import uk.org.taverna.scufl2.api.core.BlockingControlLink;
import uk.org.taverna.scufl2.api.core.DataLink;
import uk.org.taverna.scufl2.api.core.Processor;
import uk.org.taverna.scufl2.api.core.Workflow;
import uk.org.taverna.scufl2.api.port.InputProcessorPort;
import uk.org.taverna.scufl2.api.port.InputWorkflowPort;
import uk.org.taverna.scufl2.api.port.OutputProcessorPort;
import uk.org.taverna.scufl2.api.port.OutputWorkflowPort;
import uk.org.taverna.scufl2.api.port.Port;
import uk.org.taverna.scufl2.api.port.ProcessorPort;
import uk.org.taverna.scufl2.api.port.ReceiverPort;
import uk.org.taverna.scufl2.api.port.SenderPort;
import uk.org.taverna.scufl2.api.profiles.ProcessorBinding;
/**
* Cell renderer for Workflow Explorer tree.
*
* @author Alex Nenadic
* @author David Withers
*/
public class WorkflowExplorerTreeCellRenderer extends DefaultTreeCellRenderer {
// FIXME This enum is just a workaround
enum Status {
OK, WARNING, SEVERE
}
private static final long serialVersionUID = -1326663036193567147L;
private static final String RUNS_AFTER = " runs after ";
private final ActivityIconManager activityIconManager;
@SuppressWarnings("unused")
private Workflow workflow = null;
@SuppressWarnings("unused")
private final ReportManager reportManager;
private Scufl2Tools scufl2Tools = new Scufl2Tools();
public WorkflowExplorerTreeCellRenderer(Workflow workflow, ReportManager reportManager,
ActivityIconManager activityIconManager) {
super();
this.workflow = workflow;
this.reportManager = reportManager;
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();
// TODO rewrite report manager to use scufl2 validation
// Status status = reportManager.getStatus(workflow, userObject);
Status status = Status.OK;
WorkflowExplorerTreeCellRenderer renderer = (WorkflowExplorerTreeCellRenderer) result;
if (userObject instanceof Workflow) { // the root node
if (!hasGrandChildren((DefaultMutableTreeNode) value))
renderer.setIcon(workflowExplorerIcon);
else
renderer.setIcon(chooseIcon(workflowExplorerIcon, status));
renderer.setText(((Workflow) userObject).getName());
} else if (userObject instanceof InputWorkflowPort) {
renderer.setIcon(chooseIcon(inputIcon, status));
renderer.setText(((InputWorkflowPort) userObject).getName());
} else if (userObject instanceof OutputWorkflowPort) {
renderer.setIcon(chooseIcon(outputIcon, status));
renderer.setText(((OutputWorkflowPort) userObject).getName());
} else if (userObject instanceof Processor) {
Processor p = (Processor) userObject;
/*
* Get the activity associated with the processor - currently only
* the first one in the list gets displayed
*/
List<ProcessorBinding> processorbindings = scufl2Tools
.processorBindingsForProcessor(p, p.getParent().getParent()
.getMainProfile());
String text = p.getName();
if (!processorbindings.isEmpty()) {
Activity activity = processorbindings.get(0).getBoundActivity();
Icon basicIcon = activityIconManager.iconForActivity(activity);
renderer.setIcon(chooseIcon(basicIcon, status));
try {
String extraDescription = BeanUtils.getProperty(activity,
"extraDescription");
text += " - " + extraDescription;
} catch (IllegalAccessException | InvocationTargetException
| NoSuchMethodException e) {
// no problem
}
}
renderer.setText(text);
}
// Processor's child input port
else if (userObject instanceof InputProcessorPort) {
renderer.setIcon(chooseIcon(inputPortIcon, status));
renderer.setText(((InputProcessorPort) userObject).getName());
}
// Processor's child output port
else if (userObject instanceof OutputProcessorPort) {
renderer.setIcon(chooseIcon(outputPortIcon, status));
renderer.setText(((OutputProcessorPort) userObject).getName());
} else if (userObject instanceof DataLink) {
renderer.setIcon(chooseIcon(datalinkIcon, status));
SenderPort source = ((DataLink) userObject).getReceivesFrom();
String sourceName = findName(source);
ReceiverPort sink = ((DataLink) userObject).getSendsTo();
String sinkName = findName(sink);
renderer.setText(sourceName + " -> " + sinkName);
} else if (userObject instanceof BlockingControlLink) {
renderer.setIcon(chooseIcon(controlLinkIcon, status));
String htmlText = "<html><head></head><body>"
+ ((BlockingControlLink) userObject).getBlock().getName()
+ " "
+ RUNS_AFTER
+ " "
+ ((BlockingControlLink) userObject).getUntilFinished()
.getName() + "</body></html>";
renderer.setText(htmlText);
} else {
/*
* It one of the main container nodes (inputs, outputs, processors,
* datalinks) or a nested workflow node
*/
if (expanded)
renderer.setIcon(folderOpenIcon);
else
renderer.setIcon(folderClosedIcon);
}
return result;
}
private static Icon chooseIcon(final Icon basicIcon, Status status) {
if (status == null)
return basicIcon;
if (status == Status.OK)
return basicIcon;
else if (status == Status.WARNING)
return Icons.warningIcon;
else if (status == Status.SEVERE)
return Icons.severeIcon;
return basicIcon;
}
private static boolean hasGrandChildren(DefaultMutableTreeNode node) {
int childCount = node.getChildCount();
for (int i = 0; i < childCount; i++)
if (node.getChildAt(i).getChildCount() > 0)
return true;
return false;
}
private String findName(Port port) {
if (port instanceof ProcessorPort) {
String sourceProcessorName = ((ProcessorPort) port).getParent()
.getName();
return sourceProcessorName + ":" + port.getName();
}
return port.getName();
}
}