http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/activities/dataflow/views/DataflowActivityViewFactory.java ---------------------------------------------------------------------- diff --git a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/activities/dataflow/views/DataflowActivityViewFactory.java b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/activities/dataflow/views/DataflowActivityViewFactory.java new file mode 100644 index 0000000..e4a6ba0 --- /dev/null +++ b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/activities/dataflow/views/DataflowActivityViewFactory.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (C) 2007 The University of Manchester + * + * Modifications to the initial code base are copyright of their + * respective authors, or their employers as appropriate. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + ******************************************************************************/ +package org.apache.taverna.activities.dataflow.views; + +import java.util.Arrays; +import java.util.List; + +import org.apache.taverna.activities.dataflow.servicedescriptions.DataflowTemplateService; +import org.apache.taverna.servicedescriptions.ServiceDescriptionRegistry; +import org.apache.taverna.ui.menu.MenuManager; +import org.apache.taverna.workbench.activityicons.ActivityIconManager; +import org.apache.taverna.workbench.configuration.colour.ColourManager; +import org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration; +import org.apache.taverna.workbench.edits.EditManager; +import org.apache.taverna.workbench.file.FileManager; +import org.apache.taverna.workbench.selection.SelectionManager; +import org.apache.taverna.workbench.ui.views.contextualviews.ContextualView; +import org.apache.taverna.workbench.ui.views.contextualviews.activity.ContextualViewFactory; +import org.apache.taverna.scufl2.api.activity.Activity; + +public class DataflowActivityViewFactory implements ContextualViewFactory<Activity> { + + private EditManager editManager; + private FileManager fileManager; + private MenuManager menuManager; + private ColourManager colourManager; + private ActivityIconManager activityIconManager; + private WorkbenchConfiguration workbenchConfiguration; + private ServiceDescriptionRegistry serviceDescriptionRegistry; + private SelectionManager selectionManager; + + public boolean canHandle(Object object) { + return object instanceof Activity + && ((Activity) object).getType().equals(DataflowTemplateService.ACTIVITY_TYPE); + } + + public List<ContextualView> getViews(Activity activity) { + return Arrays.asList(new ContextualView[] { new DataflowActivityContextualView(activity, + editManager, fileManager, menuManager, activityIconManager, colourManager, + serviceDescriptionRegistry, workbenchConfiguration, selectionManager) }); + } + + public void setEditManager(EditManager editManager) { + this.editManager = editManager; + } + + public void setFileManager(FileManager fileManager) { + this.fileManager = fileManager; + } + + public void setMenuManager(MenuManager menuManager) { + this.menuManager = menuManager; + } + + public void setActivityIconManager(ActivityIconManager activityIconManager) { + this.activityIconManager = activityIconManager; + } + + public void setColourManager(ColourManager colourManager) { + this.colourManager = colourManager; + } + + public void setServiceDescriptionRegistry(ServiceDescriptionRegistry serviceDescriptionRegistry) { + this.serviceDescriptionRegistry = serviceDescriptionRegistry; + } + + public void setWorkbenchConfiguration(WorkbenchConfiguration workbenchConfiguration) { + this.workbenchConfiguration = workbenchConfiguration; + } + + public void setSelectionManager(SelectionManager selectionManager) { + this.selectionManager = selectionManager; + } + +}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/DataflowMerger.java ---------------------------------------------------------------------- diff --git a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/DataflowMerger.java b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/DataflowMerger.java new file mode 100644 index 0000000..b1a839a --- /dev/null +++ b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/DataflowMerger.java @@ -0,0 +1,124 @@ +package org.apache.taverna.workbench.file.importworkflow; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.taverna.workbench.edits.CompoundEdit; +import org.apache.taverna.workbench.edits.Edit; +import org.apache.taverna.workflow.edits.AddChildEdit; +import org.apache.taverna.workflow.edits.AddDataLinkEdit; +import org.apache.taverna.workflow.edits.AddProcessorEdit; +import org.apache.taverna.workflow.edits.AddWorkflowInputPortEdit; +import org.apache.taverna.workflow.edits.AddWorkflowOutputPortEdit; +import org.apache.taverna.scufl2.api.common.AbstractCloneable; +import org.apache.taverna.scufl2.api.container.WorkflowBundle; +import org.apache.taverna.scufl2.api.core.ControlLink; +import org.apache.taverna.scufl2.api.core.DataLink; +import org.apache.taverna.scufl2.api.core.Processor; +import org.apache.taverna.scufl2.api.core.Workflow; +import org.apache.taverna.scufl2.api.port.InputWorkflowPort; +import org.apache.taverna.scufl2.api.port.OutputWorkflowPort; + +/** + * A tool that allows merging of two workflow. + * <p> + * The merge is performed as a series of edit, inserting a copy of the source + * workflow into the destination workflow. + * + * @author Stian Soiland-Reyes + * @author David Withers + */ +public class DataflowMerger { + + /** + * Make a copy of a workflow. + * + * @param source + * workflow to copy + * @return A copy of the workflow. + */ + public static Workflow copyWorkflow(Workflow source) { + WorkflowBundle workflowBundle = AbstractCloneable.cloneWorkflowBean(source.getParent()); + return workflowBundle.getWorkflows().getByName(source.getName()); + } + + private final Workflow destinationWorkflow; + + /** + * Construct a {@link DataflowMerger} for the given destination workflow. + * + * @param destinationWorkflow + * Workflow to be merged into + */ + public DataflowMerger(Workflow destinationWorkflow) { + this.destinationWorkflow = destinationWorkflow; + } + + /** + * Make an {@link Edit} that when performed merges the given source dataflow + * into the destination dataflow. + * <p> + * Internally a copy is made of the source dataflow, to avoid modifying the + * links and processors. + * + * @param sourceDataflow + * Dataflow to merge from + * @return An edit that can perform and undo the insertion of the components + * from the source dataflow. + * @throws MergeException + * If the merge cannot be performed. + */ + public CompoundEdit getMergeEdit(Workflow sourceDataflow) + throws MergeException { + return getMergeEdit(sourceDataflow, ""); + } + + /** + * Make an {@link Edit} that when performed merges the given source dataflow + * into the destination dataflow. + * <p> + * Internally a copy is made of the source dataflow, to avoid modifying the + * links and processors. + * + * @param sourceWorkflow + * Dataflow to merge from + * @param prefix + * A prefix which will be inserted in front of the names for the + * merged workflow components. + * @return An edit that can perform and undo the insertion of the components + * from the source dataflow. + * @throws MergeException + * If the merge cannot be performed. + */ + public CompoundEdit getMergeEdit(Workflow sourceWorkflow, String prefix) + throws MergeException { + List<Edit<?>> compoundEdit = new ArrayList<>(); + + Workflow workflow = copyWorkflow(sourceWorkflow); + + for (InputWorkflowPort input : workflow.getInputPorts()) { + destinationWorkflow.getInputPorts().addWithUniqueName(input); + destinationWorkflow.getInputPorts().remove(input); + compoundEdit.add(new AddWorkflowInputPortEdit(destinationWorkflow, input)); + } + for (OutputWorkflowPort output : workflow.getOutputPorts()) { + destinationWorkflow.getOutputPorts().addWithUniqueName(output); + destinationWorkflow.getOutputPorts().remove(output); + compoundEdit.add(new AddWorkflowOutputPortEdit(destinationWorkflow, output)); + } + for (Processor processor : workflow.getProcessors()) { + processor.setName(prefix + processor.getName()); + compoundEdit.add(new AddProcessorEdit(destinationWorkflow, processor)); + } + for (DataLink dataLink : workflow.getDataLinks()) { + compoundEdit.add(new AddDataLinkEdit(destinationWorkflow, dataLink)); + } + for (ControlLink controlLink : workflow.getControlLinks()) { + compoundEdit.add(new AddChildEdit<Workflow>(destinationWorkflow, controlLink)); + } + + return new CompoundEdit(compoundEdit); + + } + +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/MergeException.java ---------------------------------------------------------------------- diff --git a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/MergeException.java b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/MergeException.java new file mode 100644 index 0000000..889ebde --- /dev/null +++ b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/MergeException.java @@ -0,0 +1,22 @@ +package org.apache.taverna.workbench.file.importworkflow; + +public class MergeException extends Exception { + private static final long serialVersionUID = 6018700359518335402L; + + public MergeException() { + super(); + } + + public MergeException(String message, Throwable cause) { + super(message, cause); + } + + public MergeException(String message) { + super(message); + } + + public MergeException(Throwable cause) { + super(cause); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/AddNestedWorkflowAction.java ---------------------------------------------------------------------- diff --git a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/AddNestedWorkflowAction.java b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/AddNestedWorkflowAction.java new file mode 100644 index 0000000..1286c71 --- /dev/null +++ b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/AddNestedWorkflowAction.java @@ -0,0 +1,59 @@ +package org.apache.taverna.workbench.file.importworkflow.actions; + +import java.awt.Component; +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; + +import org.apache.taverna.activities.dataflow.servicedescriptions.DataflowActivityIcon; +import org.apache.taverna.ui.menu.MenuManager; +import org.apache.taverna.workbench.configuration.colour.ColourManager; +import org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration; +import org.apache.taverna.workbench.edits.EditManager; +import org.apache.taverna.workbench.file.FileManager; +import org.apache.taverna.workbench.file.importworkflow.gui.ImportWorkflowWizard; +import org.apache.taverna.workbench.selection.SelectionManager; +import org.apache.taverna.workbench.ui.Utils; + +/** + * An action for adding a nested workflow. + * + * @author Stian Soiland-Reyes + * + */ +public class AddNestedWorkflowAction extends AbstractAction { + private static final long serialVersionUID = -2242979457902699028L; + private final EditManager editManager; + private final FileManager fileManager; + private final MenuManager menuManager; + private final ColourManager colourManager; + private final WorkbenchConfiguration workbenchConfiguration; + private final SelectionManager selectionManager; + + public AddNestedWorkflowAction(EditManager editManager, FileManager fileManager, + MenuManager menuManager, ColourManager colourManager, + WorkbenchConfiguration workbenchConfiguration, SelectionManager selectionManager) { + super("Add nested workflow", DataflowActivityIcon.getDataflowIcon()); + this.editManager = editManager; + this.fileManager = fileManager; + this.menuManager = menuManager; + this.colourManager = colourManager; + this.workbenchConfiguration = workbenchConfiguration; + this.selectionManager = selectionManager; + } + + public void actionPerformed(ActionEvent e) { + final Component parentComponent; + if (e.getSource() instanceof Component) { + parentComponent = (Component) e.getSource(); + } else { + parentComponent = null; + } + ImportWorkflowWizard wizard = new ImportWorkflowWizard( + Utils.getParentFrame(parentComponent), editManager, fileManager, menuManager, + colourManager, workbenchConfiguration, selectionManager); + wizard.setMergeEnabled(false); + wizard.setVisible(true); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ImportWorkflowAction.java ---------------------------------------------------------------------- diff --git a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ImportWorkflowAction.java b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ImportWorkflowAction.java new file mode 100644 index 0000000..81774b3 --- /dev/null +++ b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ImportWorkflowAction.java @@ -0,0 +1,59 @@ +package org.apache.taverna.workbench.file.importworkflow.actions; + +import java.awt.Component; +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; + +import org.apache.taverna.activities.dataflow.servicedescriptions.DataflowActivityIcon; +import org.apache.taverna.ui.menu.MenuManager; +import org.apache.taverna.workbench.configuration.colour.ColourManager; +import org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration; +import org.apache.taverna.workbench.edits.EditManager; +import org.apache.taverna.workbench.file.FileManager; +import org.apache.taverna.workbench.file.importworkflow.gui.ImportWorkflowWizard; +import org.apache.taverna.workbench.selection.SelectionManager; +import org.apache.taverna.workbench.ui.Utils; + +/** + * A general version of {@link AddNestedWorkflowAction} and {@link MergeWorkflowAction} that allows + * the user to choose which action to perform. + * + * @author Stian Soiland-Reyes + * + */ +public class ImportWorkflowAction extends AbstractAction { + private static final long serialVersionUID = -2242979457902699028L; + private final EditManager editManager; + private final FileManager fileManager; + private final MenuManager menuManager; + private final ColourManager colourManager; + private final WorkbenchConfiguration workbenchConfiguration; + private final SelectionManager selectionManager; + + public ImportWorkflowAction(EditManager editManager, FileManager fileManager, + MenuManager menuManager, ColourManager colourManager, + WorkbenchConfiguration workbenchConfiguration, SelectionManager selectionManager) { + super("Import workflow", DataflowActivityIcon.getDataflowIcon()); + this.editManager = editManager; + this.fileManager = fileManager; + this.menuManager = menuManager; + this.colourManager = colourManager; + this.workbenchConfiguration = workbenchConfiguration; + this.selectionManager = selectionManager; + } + + public void actionPerformed(ActionEvent e) { + final Component parentComponent; + if (e.getSource() instanceof Component) { + parentComponent = (Component) e.getSource(); + } else { + parentComponent = null; + } + ImportWorkflowWizard wizard = new ImportWorkflowWizard( + Utils.getParentFrame(parentComponent), editManager, fileManager, menuManager, + colourManager, workbenchConfiguration, selectionManager); + wizard.setVisible(true); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/MergeWorkflowAction.java ---------------------------------------------------------------------- diff --git a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/MergeWorkflowAction.java b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/MergeWorkflowAction.java new file mode 100644 index 0000000..136490b --- /dev/null +++ b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/MergeWorkflowAction.java @@ -0,0 +1,58 @@ +package org.apache.taverna.workbench.file.importworkflow.actions; + +import java.awt.Component; +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; + +import org.apache.taverna.ui.menu.MenuManager; +import org.apache.taverna.workbench.configuration.colour.ColourManager; +import org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration; +import org.apache.taverna.workbench.edits.EditManager; +import org.apache.taverna.workbench.file.FileManager; +import org.apache.taverna.workbench.file.importworkflow.gui.ImportWorkflowWizard; +import org.apache.taverna.workbench.selection.SelectionManager; +import org.apache.taverna.workbench.ui.Utils; + +/** + * An action for merging two workflows + * + * @author Stian Soiland-Reyes + * + */ +public class MergeWorkflowAction extends AbstractAction { + private static final long serialVersionUID = -2242979457902699028L; + private final EditManager editManager; + private final FileManager fileManager; + private final MenuManager menuManager; + private final ColourManager colourManager; + private final WorkbenchConfiguration workbenchConfiguration; + private final SelectionManager selectionManager; + + public MergeWorkflowAction(EditManager editManager, FileManager fileManager, + MenuManager menuManager, ColourManager colourManager, + WorkbenchConfiguration workbenchConfiguration, SelectionManager selectionManager) { + super("Merge workflow"); + this.editManager = editManager; + this.fileManager = fileManager; + this.menuManager = menuManager; + this.colourManager = colourManager; + this.workbenchConfiguration = workbenchConfiguration; + this.selectionManager = selectionManager; + } + + public void actionPerformed(ActionEvent e) { + final Component parentComponent; + if (e.getSource() instanceof Component) { + parentComponent = (Component) e.getSource(); + } else { + parentComponent = null; + } + ImportWorkflowWizard wizard = new ImportWorkflowWizard( + Utils.getParentFrame(parentComponent), editManager, fileManager, menuManager, + colourManager, workbenchConfiguration, selectionManager); + wizard.setNestedEnabled(false); + wizard.setVisible(true); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/OpenSourceWorkflowAction.java ---------------------------------------------------------------------- diff --git a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/OpenSourceWorkflowAction.java b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/OpenSourceWorkflowAction.java new file mode 100644 index 0000000..d3a110b --- /dev/null +++ b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/OpenSourceWorkflowAction.java @@ -0,0 +1,139 @@ +/******************************************************************************* + * 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 org.apache.taverna.workbench.file.importworkflow.actions; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.prefs.Preferences; + +import javax.swing.AbstractAction; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.filechooser.FileFilter; + +import org.apache.taverna.workbench.file.FileManager; +import org.apache.taverna.workbench.icons.WorkbenchIcons; + +import org.apache.log4j.Logger; + +/** + * @author David Withers + */ +@SuppressWarnings("serial") +public abstract class OpenSourceWorkflowAction extends AbstractAction { + + private static Logger logger = Logger.getLogger(OpenSourceWorkflowAction.class); + + private static final String OPEN_WORKFLOW = "Open workflow..."; + + protected FileManager fileManager; + + public OpenSourceWorkflowAction(FileManager fileManager) { + super(OPEN_WORKFLOW, WorkbenchIcons.openIcon); + this.fileManager = fileManager; + } + + public void actionPerformed(ActionEvent e) { + final Component parentComponent; + if (e.getSource() instanceof Component) { + parentComponent = (Component) e.getSource(); + } else { + parentComponent = null; + } + openWorkflows(parentComponent); + } + + public abstract void openWorkflows(Component parentComponent, File[] files); + + /** + * Pop up an Open-dialogue to select one or more workflow files to open. + * + * @param parentComponent + * The UI parent component to use for pop up dialogues + * @param openCallback + * An {@link OpenCallback} to be called during the file opening. + * The callback will be invoked for each file that has been + * opened, as file opening happens in a separate thread that + * might execute after the return of this method. + * @return <code>false</code> if no files were selected or the dialogue was + * cancelled, or <code>true</code> if the process of opening one or + * more files has been started. + */ + public boolean openWorkflows(final Component parentComponent) { + JFileChooser fileChooser = new JFileChooser(); + Preferences prefs = Preferences.userNodeForPackage(getClass()); + String curDir = prefs.get("currentDir", System.getProperty("user.home")); + fileChooser.setDialogTitle(OPEN_WORKFLOW); + + fileChooser.resetChoosableFileFilters(); + fileChooser.setAcceptAllFileFilterUsed(false); + List<FileFilter> fileFilters = fileManager.getOpenFileFilters(); + if (fileFilters.isEmpty()) { + logger.warn("No file types found for opening workflow"); + JOptionPane + .showMessageDialog(parentComponent, + "No file types found for opening workflow.", "Error", + JOptionPane.ERROR_MESSAGE); + return false; + } + for (FileFilter fileFilter : fileFilters) { + fileChooser.addChoosableFileFilter(fileFilter); + } + + fileChooser.setFileFilter(fileFilters.get(0)); + + fileChooser.setCurrentDirectory(new File(curDir)); + fileChooser.setMultiSelectionEnabled(true); + + int returnVal = fileChooser.showOpenDialog(parentComponent); + if (returnVal == JFileChooser.APPROVE_OPTION) { + prefs.put("currentDir", fileChooser.getCurrentDirectory().toString()); + final File[] selectedFiles = fileChooser.getSelectedFiles(); + if (selectedFiles.length == 0) { + logger.warn("No files selected"); + return false; + } + new FileOpenerThread(parentComponent, selectedFiles).start(); + return true; + } + return false; + } + + private final class FileOpenerThread extends Thread { + private final File[] files; + private final Component parentComponent; + + private FileOpenerThread(Component parentComponent, File[] selectedFiles) { + super("Opening workflows(s) " + Arrays.asList(selectedFiles)); + this.parentComponent = parentComponent; + this.files = selectedFiles; + } + + @Override + public void run() { + openWorkflows(parentComponent, files); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ReplaceNestedWorkflowAction.java ---------------------------------------------------------------------- diff --git a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ReplaceNestedWorkflowAction.java b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ReplaceNestedWorkflowAction.java new file mode 100644 index 0000000..7209ce7 --- /dev/null +++ b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/actions/ReplaceNestedWorkflowAction.java @@ -0,0 +1,84 @@ +package org.apache.taverna.workbench.file.importworkflow.actions; + +import java.awt.Component; +import java.awt.event.ActionEvent; + +import org.apache.taverna.servicedescriptions.ServiceDescriptionRegistry; +import org.apache.taverna.ui.menu.MenuManager; +import org.apache.taverna.workbench.activityicons.ActivityIconManager; +import org.apache.taverna.workbench.configuration.colour.ColourManager; +import org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration; +import org.apache.taverna.workbench.edits.Edit; +import org.apache.taverna.workbench.edits.EditManager; +import org.apache.taverna.workbench.file.FileManager; +import org.apache.taverna.workbench.file.importworkflow.gui.ImportWorkflowWizard; +import org.apache.taverna.workbench.selection.SelectionManager; +import org.apache.taverna.workbench.ui.Utils; +import org.apache.taverna.workbench.ui.actions.activity.ActivityConfigurationAction; +import org.apache.taverna.workflow.edits.ConfigureEdit; +import org.apache.taverna.scufl2.api.activity.Activity; +import org.apache.taverna.scufl2.api.configurations.Configuration; +import org.apache.taverna.scufl2.api.core.Workflow; + +public class ReplaceNestedWorkflowAction extends ActivityConfigurationAction { + private static final long serialVersionUID = 1L; + + private final EditManager editManager; + private final FileManager fileManager; + private final MenuManager menuManager; + + private final ColourManager colourManager; + + private final WorkbenchConfiguration workbenchConfiguration; + + private final SelectionManager selectionManager; + + public ReplaceNestedWorkflowAction(Activity activity, EditManager editManager, + FileManager fileManager, MenuManager menuManager, + ActivityIconManager activityIconManager, ColourManager colourManager, + ServiceDescriptionRegistry serviceDescriptionRegistry, + WorkbenchConfiguration workbenchConfiguration, SelectionManager selectionManager) { + super(activity, activityIconManager, serviceDescriptionRegistry); + this.editManager = editManager; + this.fileManager = fileManager; + this.menuManager = menuManager; + this.colourManager = colourManager; + this.workbenchConfiguration = workbenchConfiguration; + this.selectionManager = selectionManager; + putValue(NAME, "Replace nested workflow"); + } + + public void actionPerformed(ActionEvent e) { + final Component parentComponent; + if (e.getSource() instanceof Component) { + parentComponent = (Component) e.getSource(); + } else { + parentComponent = null; + } + ImportWorkflowWizard wizard = new ImportWorkflowWizard( + Utils.getParentFrame(parentComponent), editManager, fileManager, menuManager, + colourManager, workbenchConfiguration, selectionManager) { + private static final long serialVersionUID = 1L; + +// @Override +// protected Edit<?> makeInsertNestedWorkflowEdit(Workflow nestedFlow, String name) { +// Configuration configuration = new Configuration(); +// configuration.setType(null); +// // TODO use service registry +// return new ConfigureEdit<Activity>(getActivity(), null, configuration); +// } + +// @Override +// protected Activity getInsertedActivity() { +// return getActivity(); +// } + }; + + wizard.setMergeEnabled(false); +// wizard.setCustomDestinationDataflow(fileManager.getCurrentDataflow(), +// "Existing nested workflow"); +// wizard.setDestinationEnabled(false); + wizard.setVisible(true); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/gui/ImportWorkflowWizard.java ---------------------------------------------------------------------- diff --git a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/gui/ImportWorkflowWizard.java b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/gui/ImportWorkflowWizard.java new file mode 100644 index 0000000..6bf4cab --- /dev/null +++ b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/gui/ImportWorkflowWizard.java @@ -0,0 +1,1272 @@ +package org.apache.taverna.workbench.file.importworkflow.gui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.swing.AbstractAction; +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.ButtonModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; +import javax.swing.ProgressMonitor; +import javax.swing.SwingUtilities; + +import org.apache.taverna.activities.dataflow.servicedescriptions.DataflowTemplateService; +import org.apache.taverna.ui.menu.MenuManager; +import org.apache.taverna.workbench.MainWindow; +import org.apache.taverna.workbench.configuration.colour.ColourManager; +import org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration; +import org.apache.taverna.workbench.edits.CompoundEdit; +import org.apache.taverna.workbench.edits.Edit; +import org.apache.taverna.workbench.edits.EditException; +import org.apache.taverna.workbench.edits.EditManager; +import org.apache.taverna.workbench.file.DataflowInfo; +import org.apache.taverna.workbench.file.FileManager; +import org.apache.taverna.workbench.file.exceptions.OpenException; +import org.apache.taverna.workbench.file.importworkflow.DataflowMerger; +import org.apache.taverna.workbench.file.importworkflow.MergeException; +import org.apache.taverna.workbench.file.importworkflow.actions.OpenSourceWorkflowAction; +import org.apache.taverna.workbench.helper.HelpEnabledDialog; +import net.sf.taverna.t2.workbench.models.graph.svg.SVGGraphController; +import org.apache.taverna.workbench.selection.SelectionManager; +import org.apache.taverna.workflow.edits.AddChildEdit; +import org.apache.taverna.workflow.edits.AddProcessorEdit; + +import org.apache.batik.swing.JSVGCanvas; +import org.apache.log4j.Logger; + +import org.apache.taverna.scufl2.api.activity.Activity; +import org.apache.taverna.scufl2.api.common.Scufl2Tools; +import org.apache.taverna.scufl2.api.configurations.Configuration; +import org.apache.taverna.scufl2.api.container.WorkflowBundle; +import org.apache.taverna.scufl2.api.core.Processor; +import org.apache.taverna.scufl2.api.core.Workflow; +import org.apache.taverna.scufl2.api.iterationstrategy.CrossProduct; +import org.apache.taverna.scufl2.api.port.InputActivityPort; +import org.apache.taverna.scufl2.api.port.InputProcessorPort; +import org.apache.taverna.scufl2.api.port.InputWorkflowPort; +import org.apache.taverna.scufl2.api.port.OutputActivityPort; +import org.apache.taverna.scufl2.api.port.OutputProcessorPort; +import org.apache.taverna.scufl2.api.port.OutputWorkflowPort; +import org.apache.taverna.scufl2.api.profiles.ProcessorBinding; +import org.apache.taverna.scufl2.api.profiles.ProcessorInputPortBinding; +import org.apache.taverna.scufl2.api.profiles.ProcessorOutputPortBinding; +import org.apache.taverna.scufl2.api.profiles.Profile; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +@SuppressWarnings("serial") +public class ImportWorkflowWizard extends HelpEnabledDialog { + + private static Logger logger = Logger.getLogger(ImportWorkflowWizard.class); + + private Scufl2Tools scufl2Tools = new Scufl2Tools(); + + protected BrowseFileOnClick browseFileOnClick = new BrowseFileOnClick(); + protected JButton buttonBrowse; + protected JComboBox chooseDataflow; + protected DataflowOpenerThread dataflowOpenerThread; + + private WorkflowBundle destinationWorkflowBundle; + private Workflow destinationWorkflow; + private Profile destinationProfile; + private Workflow sourceWorkflow; + + protected JTextField fieldFile; + + protected JTextField fieldUrl; + protected boolean mergeEnabled = true; + protected boolean nestedEnabled = true; + protected JSVGCanvas previewSource = new JSVGCanvas(null, false, false); + protected JSVGCanvas previewDestination = new JSVGCanvas(null, false, false); + protected JTextField prefixField; + protected JRadioButton radioFile; + protected JRadioButton radioNew; + protected JRadioButton radioOpened; + protected JRadioButton radioUrl; + protected ButtonGroup sourceSelection; + protected ActionListener updateChosenListener = new UpdateChosenListener(); + protected Thread updatePreviewsThread; + protected Component sourceSelectionPanel; + protected JLabel prefixLabel; + protected JLabel prefixHelp; +// protected JPanel destinationSelectionPanel; +// protected ButtonGroup destinationSelection; +// protected JRadioButton radioNewDestination; +// protected JRadioButton radioOpenDestination; +// protected JComboBox destinationAlreadyOpen; + protected JPanel introductionPanel; + protected ButtonGroup actionSelection; + protected JRadioButton actionNested; + protected JRadioButton actionMerge; + protected JRadioButton radioCustomSource; + protected JRadioButton radioCustomDestination; + + private final EditManager editManager; + private final FileManager fileManager; + private final MenuManager menuManager; + private final ColourManager colourManager; + private final WorkbenchConfiguration workbenchConfiguration; + private final SelectionManager selectionManager; + + private WorkflowBundle customSourceDataFlow = null; +// private Workflow customDestinationDataflow = null; + private String customSourceName = ""; +// private String customDestinationName = ""; + + private boolean sourceEnabled = true; +// private boolean destinationEnabled = true; + private Activity insertedActivity; + + public ImportWorkflowWizard(Frame parentFrame, EditManager editManager, + FileManager fileManager, MenuManager menuManager, ColourManager colourManager, + WorkbenchConfiguration workbenchConfiguration, SelectionManager selectionManager) { + super(parentFrame, "Import workflow", true, null); + this.selectionManager = selectionManager; + destinationWorkflow = selectionManager.getSelectedWorkflow(); + destinationProfile = selectionManager.getSelectedProfile(); + destinationWorkflowBundle = selectionManager.getSelectedWorkflowBundle(); + + this.editManager = editManager; + this.fileManager = fileManager; + this.menuManager = menuManager; + this.colourManager = colourManager; + this.workbenchConfiguration = workbenchConfiguration; + + setSize(600, 600); + add(makeContentPane(), BorderLayout.CENTER); + // Add some space + add(new JPanel(), BorderLayout.WEST); + add(new JPanel(), BorderLayout.NORTH); + add(new JPanel(), BorderLayout.SOUTH); + add(new JPanel(), BorderLayout.EAST); + findChosenDataflow(this, true); + updateAll(); + } + + public void setMergeEnabled(boolean importEnabled) { + this.mergeEnabled = importEnabled; + updateAll(); + } + + public void setNestedEnabled(boolean nestedEnabled) { + this.nestedEnabled = nestedEnabled; + updateAll(); + } + + /** + * Silly workaround to avoid "Cannot call invokeAndWait from the event dispatcher thread" + * exception. + * + * @param runnable + */ + public static void invokeAndWait(Runnable runnable) { + if (SwingUtilities.isEventDispatchThread()) { + runnable.run(); + return; + } + try { + SwingUtilities.invokeAndWait(runnable); + } catch (InterruptedException ex) { + // logger.warn("Runnable " + runnable + " was interrupted " + runnable, ex); + } catch (InvocationTargetException e) { + logger.warn("Can't invoke " + runnable, e); + } + } + + protected Component makeWorkflowImage() { + JPanel workflowImages = new JPanel(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridy = 0; + gbc.fill = GridBagConstraints.BOTH; + gbc.weighty = 0.1; + + gbc.weightx = 0.1; + workflowImages.add(new JPanel(), gbc);// filler + + gbc.weightx = 0.0; + previewSource.setBackground(workflowImages.getBackground()); + workflowImages.add(previewSource, gbc); + + JLabel arrow = new JLabel("\u2192"); + arrow.setFont(arrow.getFont().deriveFont(48f)); + workflowImages.add(arrow, gbc); + + previewDestination.setBackground(workflowImages.getBackground()); + workflowImages.add(previewDestination, gbc); + + gbc.weightx = 0.1; + workflowImages.add(new JPanel(), gbc); + gbc.weightx = 0.0; + + return workflowImages; + } + + protected void updateAll() { + updatePreviews(); // will go in separate thread anyway, do it first + updateHeader(); + updateSourceSection(); +// updateDestinationSection(); + updateFooter(); + } + +// protected void updateDestinationSection() { +// +// radioNewDestination.setVisible(false); +// +// radioCustomDestination.setText(customDestinationName); +// radioCustomDestination.setVisible(customDestinationDataflow != null); +// +// // radioNewDestination.setVisible(nestedEnabled); +// // radioNewDestination.setEnabled(actionNested.isSelected()); +// +// destinationSelectionPanel.setVisible(destinationEnabled); +// +// } + + protected synchronized void updatePreviews() { + if (updatePreviewsThread != null && updatePreviewsThread.isAlive()) { + updatePreviewsThread.interrupt(); + } + updatePreviewsThread = new UpdatePreviewsThread(); + updatePreviewsThread.start(); + } + + protected void updateDestinationPreview() { + updateWorkflowGraphic(previewDestination, destinationWorkflow, destinationProfile); + } + + protected void updateSourcePreview() { + Profile sourceProfile = null; + if (sourceWorkflow != null) { + sourceProfile = sourceWorkflow.getParent().getMainProfile(); + } + updateWorkflowGraphic(previewSource, sourceWorkflow, sourceProfile); + } + + protected void updateFooter() { + prefixField.setVisible(mergeEnabled); + prefixLabel.setVisible(mergeEnabled); + prefixHelp.setVisible(mergeEnabled); + + prefixField.setEnabled(actionMerge.isSelected()); + prefixLabel.setEnabled(actionMerge.isSelected()); + prefixHelp.setEnabled(actionMerge.isSelected()); + if (actionMerge.isSelected()) { + prefixHelp.setForeground(prefixLabel.getForeground()); + } else { + // Work around + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4303706 + // and assume gray is the 'disabled' colour in our Look n Feel + prefixHelp.setForeground(Color.gray); + } + + } + + protected void updateHeader() { + makeIntroductionPanel(); + } + + protected void updateSourceSection() { + radioCustomSource.setText(customSourceName); + radioCustomSource.setVisible(customSourceDataFlow != null); + + radioNew.setVisible(nestedEnabled); + radioNew.setEnabled(actionNested.isSelected()); + + if (actionNested.isSelected() && sourceSelection.getSelection() == null) { + // Preselect the new workflow + radioNew.setSelected(true); + } + + sourceSelectionPanel.setVisible(sourceEnabled); + } + + /** + * Create a PNG image of the workflow and place inside an ImageIcon + * + * @param dataflow + * @return + * @throws InvocationTargetException + * @throws InterruptedException + */ + protected void updateWorkflowGraphic(final JSVGCanvas svgCanvas, final Workflow workflow, final Profile profile) { + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + // Set it to blank while reloading + svgCanvas.setSVGDocument(null); + if (workflow != null) { + SVGGraphController currentWfGraphController = new SVGGraphController( + workflow, profile, false, svgCanvas, + editManager, menuManager, colourManager, workbenchConfiguration); + } + } + }); + } catch (InterruptedException e) { + // logger.error(e); + } catch (InvocationTargetException e) { + // logger.error(e); + } + } + + /** + * Open the selected source and destination workflows. If background is true, this method will + * return immediately while a {@link DataflowOpenerThread} performs the updates. If a + * DataflowOpenerThread is already running, it will be interrupted and stopped. + * + * @param parentComponent + * The parent component for showing dialogues + * @param background + * If true, will run in separate thread. + * @return <code>false</code> if running in the background, or if a dialogue was shown and the + * operation is aborted by the user, or <code>true</code> if not running in the + * background and the method completed without user interruption. + */ + protected synchronized boolean findChosenDataflow(Component parentComponent, boolean background) { + if (dataflowOpenerThread != null && dataflowOpenerThread.isAlive()) { + if (background) { + // We've changed our mind + dataflowOpenerThread.interrupt(); + } else { + // We'll let it finish, we don't need to do it again + try { + dataflowOpenerThread.join(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + return !dataflowOpenerThread.shownWarning; + } + } + dataflowOpenerThread = new DataflowOpenerThread(parentComponent, background); + + if (background) { + dataflowOpenerThread.start(); + return false; + } else { + dataflowOpenerThread.run(); + return !dataflowOpenerThread.shownWarning; + } + + } + + protected Container makeContentPane() { + JPanel panel = new JPanel(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + + gbc.ipadx = 5; + gbc.ipady = 5; + + gbc.gridx = 0; + gbc.weightx = 0.1; + gbc.fill = GridBagConstraints.BOTH; + + introductionPanel = makeIntroductionPanel(); + panel.add(introductionPanel, gbc); + + sourceSelectionPanel = makeSourceSelectionPanel(); + panel.add(sourceSelectionPanel, gbc); + +// destinationSelectionPanel = makeDestinationSelectionPanel(); +// panel.add(destinationSelectionPanel, gbc); + + gbc.weighty = 0.1; + panel.add(makeImportStylePanel(), gbc); + + return panel; + } + + protected JPanel makeIntroductionPanel() { + if (introductionPanel == null) { + introductionPanel = new JPanel(new GridBagLayout()); + } else { + introductionPanel.removeAll(); + } + boolean bothEnabled = mergeEnabled && nestedEnabled; + if (bothEnabled) { + introductionPanel.setBorder(BorderFactory.createTitledBorder("Import method")); + } else { + introductionPanel.setBorder(BorderFactory.createEmptyBorder()); + } + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + // gbc.gridy = 0; + gbc.weightx = 0.1; + gbc.fill = GridBagConstraints.BOTH; + gbc.anchor = GridBagConstraints.FIRST_LINE_START; + + StringBuilder nestedHelp = new StringBuilder(); + nestedHelp.append("<html><small>"); + nestedHelp.append("Add a <strong>nested workflow</strong> "); + nestedHelp.append("into the "); + nestedHelp.append("destination workflow as a single service. "); + nestedHelp.append("The nested workflow "); + nestedHelp.append("can be <em>edited separately</em>, but is shown "); + nestedHelp.append("expanded in the diagram of the parent "); + nestedHelp.append("workflow. In the parent workflow you can "); + nestedHelp.append("connect to the input and output ports of the nested "); + nestedHelp.append("workflow. "); + nestedHelp.append("</small></html>"); + + StringBuilder mergeHelp = new StringBuilder(); + mergeHelp.append("<html><small>"); + mergeHelp.append("<strong>Merge</strong> a workflow "); + mergeHelp.append("by copying all services, ports and links "); + mergeHelp.append("directly into the destination workflow. This can be "); + mergeHelp.append("useful for merging smaller workflow fragments. For "); + mergeHelp.append("inclusion of larger workflows you might find using "); + mergeHelp.append("<em>nested workflows</em> more beneficial."); + mergeHelp.append("</small></html>"); + + actionSelection = new ButtonGroup(); + actionNested = new JRadioButton(nestedHelp.toString()); + ActionListener updateListener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + updateSourceSection(); +// updateDestinationSection(); + updateFooter(); + } + }; + actionNested.addActionListener(updateListener); + actionSelection.add(actionNested); + + actionMerge = new JRadioButton(mergeHelp.toString()); + actionMerge.addActionListener(updateListener); + actionSelection.add(actionMerge); + + if (bothEnabled) { + introductionPanel.add(actionNested, gbc); + introductionPanel.add(actionMerge, gbc); + actionNested.setSelected(true); + } else if (nestedEnabled) { + introductionPanel.add(new JLabel(nestedHelp.toString()), gbc); + actionNested.setSelected(true); + } else if (mergeEnabled) { + introductionPanel.add(new JLabel(mergeHelp.toString()), gbc); + actionMerge.setSelected(true); + } + return introductionPanel; + } + +// protected JPanel makeDestinationSelectionPanel() { +// JPanel j = new JPanel(new GridBagLayout()); +// j.setBorder(BorderFactory.createTitledBorder("Workflow destination")); +// +// GridBagConstraints gbc = new GridBagConstraints(); +// gbc.gridx = 0; +// gbc.gridy = 0; +// gbc.fill = GridBagConstraints.BOTH; +// +// destinationSelection = new ButtonGroup(); +// radioNewDestination = new JRadioButton("New workflow"); +// gbc.gridy = 0; +// j.add(radioNewDestination, gbc); +// destinationSelection.add(radioNewDestination); +// radioNewDestination.addActionListener(updateChosenListener); +// +// radioOpenDestination = new JRadioButton("Already opened workflow"); +// gbc.gridy = 2; +// j.add(radioOpenDestination, gbc); +// destinationSelection.add(radioOpenDestination); +// radioOpenDestination.addActionListener(updateChosenListener); +// gbc.weightx = 0.1; +// gbc.gridx = 1; +// destinationAlreadyOpen = makeSelectOpenWorkflowComboBox(true); +// j.add(destinationAlreadyOpen, gbc); +// +// radioCustomDestination = new JRadioButton(customDestinationName); +// radioCustomDestination.setVisible(customDestinationName != null); +// gbc.gridx = 0; +// gbc.gridy = 3; +// gbc.gridwidth = 2; +// j.add(radioCustomDestination, gbc); +// destinationSelection.add(radioCustomDestination); +// radioCustomDestination.addActionListener(updateChosenListener); +// gbc.gridwidth = 1; +// +// radioOpenDestination.setSelected(true); +// return j; +// } + + protected Component makeImportStylePanel() { + JPanel j = new JPanel(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.fill = GridBagConstraints.BOTH; + + j.setBorder(BorderFactory.createTitledBorder("Import")); + + prefixLabel = new JLabel("Prefix"); + j.add(prefixLabel, gbc); + gbc.weightx = 0.1; + gbc.gridx = 1; + + prefixField = new JTextField(10); + prefixLabel.setLabelFor(prefixField); + j.add(prefixField, gbc); + + gbc.gridx = 0; + gbc.gridy = 1; + gbc.gridwidth = 2; + + prefixHelp = new JLabel( + "<html><small>Optional prefix to be prepended to the name of the " + + "inserted services and workflow ports. Even if no prefix is given, duplicate names will be " + + "resolved by adding numbers, for instance <code>my_service_2</code> if <code>my_service</code> already " + + "existed." + "</small></html>"); + prefixHelp.setLabelFor(prefixField); + j.add(prefixHelp, gbc); + + gbc.gridy = 2; + gbc.weightx = 0.1; + gbc.weighty = 0.1; + + j.add(makeWorkflowImage(), gbc); + + gbc.gridy = 3; + gbc.weighty = 0.0; + j.add(new JPanel(), gbc); + + gbc.gridy = 4; + gbc.fill = GridBagConstraints.NONE; + JButton comp = new JButton(new ImportWorkflowAction()); + j.add(comp, gbc); + return j; + + } + + protected Component makeSelectFile() { + JPanel j = new JPanel(new GridBagLayout()); + j.setBorder(BorderFactory.createEtchedBorder()); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.fill = GridBagConstraints.BOTH; + gbc.weightx = 0.1; + + fieldFile = new JTextField(20); + fieldFile.setEditable(false); + fieldFile.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + radioFile.setSelected(true); + } + + @Override + public void focusLost(FocusEvent e) { + findChosenDataflow(e.getComponent(), true); + } + }); + j.add(fieldFile, gbc); + radioFile.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + browseFileOnClick.checkEmptyFile(); + } + } + }); + + gbc.gridx = 1; + gbc.weightx = 0.0; + gbc.fill = GridBagConstraints.NONE; + buttonBrowse = new JButton(new OpenSourceWorkflowAction(fileManager) { + @Override + public void openWorkflows(Component parentComponent, File[] files) { + if (files.length == 0) { + radioFile.setSelected(false); + fieldFile.setText(""); + radioFile.requestFocus(); + return; + } + fieldFile.setText(files[0].getPath()); + if (!radioFile.isSelected()) { + radioFile.setSelected(true); + } + findChosenDataflow(parentComponent, true); + } + }); + buttonBrowse.setText("Browse"); + j.add(buttonBrowse, gbc); + + // This just duplicates things - we already have actions on + // the radioFile and fieldFile that will handle the events + // radioFile.addActionListener(browseFileOnClick); + // fieldFile.addActionListener(browseFileOnClick); + return j; + } + + protected JComboBox makeSelectOpenWorkflowComboBox(boolean selectCurrent) { + List<DataflowSelection> openDataflows = new ArrayList<DataflowSelection>(); + DataflowSelection current = null; + for (WorkflowBundle df : fileManager.getOpenDataflows()) { + String name = df.getMainWorkflow().getName(); + boolean isCurrent = df.equals(fileManager.getCurrentDataflow()); + if (isCurrent) { + // Wrapping as HTML causes weird drop-down box under MAC, so + // we just use normal text + // name = "<html><body>" + name + // + " <i>(current)</i></body></html>"; + name = name + " (current)"; + } + DataflowSelection selection = new DataflowSelection(df, name); + openDataflows.add(selection); + if (isCurrent) { + current = selection; + } + } + JComboBox chooseDataflow = new JComboBox(openDataflows.toArray()); + if (selectCurrent) { + chooseDataflow.setSelectedItem(current); + } + chooseDataflow.addActionListener(updateChosenListener); + return chooseDataflow; + + } + + protected Component makeSourceSelectionPanel() { + JPanel j = new JPanel(new GridBagLayout()); + j.setBorder(BorderFactory.createTitledBorder("Workflow source")); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.fill = GridBagConstraints.BOTH; + + sourceSelection = new ButtonGroup(); + radioNew = new JRadioButton("New workflow"); + gbc.gridy = 0; + j.add(radioNew, gbc); + sourceSelection.add(radioNew); + + radioNew.addActionListener(updateChosenListener); + + radioFile = new JRadioButton("Import from file"); + gbc.gridy = 1; + j.add(radioFile, gbc); + sourceSelection.add(radioFile); + radioFile.addActionListener(updateChosenListener); + + radioUrl = new JRadioButton("Import from URL"); + gbc.gridy = 2; + j.add(radioUrl, gbc); + sourceSelection.add(radioUrl); + radioUrl.addActionListener(updateChosenListener); + + radioOpened = new JRadioButton("Already opened workflow"); + gbc.gridy = 3; + j.add(radioOpened, gbc); + sourceSelection.add(radioOpened); + radioOpened.addActionListener(updateChosenListener); + + radioCustomSource = new JRadioButton(customSourceName); + radioCustomSource.setVisible(customSourceDataFlow != null); + gbc.gridy = 4; + gbc.gridwidth = 2; + j.add(radioCustomSource, gbc); + sourceSelection.add(radioCustomSource); + radioCustomSource.addActionListener(updateChosenListener); + gbc.gridwidth = 1; + + gbc.gridx = 1; + gbc.gridy = 1; + gbc.weightx = 0.1; + j.add(makeSelectFile(), gbc); + + gbc.gridy = 2; + fieldUrl = new JTextField(20); + j.add(fieldUrl, gbc); + fieldUrl.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + radioUrl.setSelected(true); + } + + @Override + public void focusLost(FocusEvent e) { + findChosenDataflow(e.getComponent(), true); + } + }); + + gbc.gridy = 3; + chooseDataflow = makeSelectOpenWorkflowComboBox(false); + chooseDataflow.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + radioOpened.setSelected(true); + } + }); + j.add(chooseDataflow, gbc); + + return j; + } + + protected Edit<?> makeInsertNestedWorkflowEdit(Workflow nestedFlow) { + Processor processor = new Processor(); + processor.setName("nestedWorkflow"); + + CrossProduct crossProduct = new CrossProduct(); + crossProduct.setParent(processor.getIterationStrategyStack()); + + Activity activity = new Activity(); + activity.setType(DataflowTemplateService.ACTIVITY_TYPE); + Configuration configuration = new Configuration(); + configuration.setType(DataflowTemplateService.ACTIVITY_TYPE.resolve("#Config")); + destinationWorkflowBundle.getWorkflows().addWithUniqueName(nestedFlow); + ((ObjectNode) configuration.getJson()).put("nestedWorkflow", nestedFlow.getName()); + destinationWorkflowBundle.getWorkflows().remove(nestedFlow); + configuration.setConfigures(activity); + + ProcessorBinding processorBinding = new ProcessorBinding(); + processorBinding.setBoundProcessor(processor); + processorBinding.setBoundActivity(activity); + + for (InputWorkflowPort workflowPort : nestedFlow.getInputPorts()) { + InputActivityPort activityPort = new InputActivityPort(activity, workflowPort.getName()); + activityPort.setDepth(workflowPort.getDepth()); + // create processor port + InputProcessorPort processorPort = new InputProcessorPort(processor, activityPort.getName()); + processorPort.setDepth(activityPort.getDepth()); + // add a new port binding + new ProcessorInputPortBinding(processorBinding, processorPort, activityPort); + } + for (OutputWorkflowPort workflowPort : nestedFlow.getOutputPorts()) { + OutputActivityPort activityPort = new OutputActivityPort(activity, workflowPort.getName()); + // TODO calculate output depth + activityPort.setDepth(0); + activityPort.setGranularDepth(0); + // create processor port + OutputProcessorPort processorPort = new OutputProcessorPort(processor, activityPort.getName()); + processorPort.setDepth(activityPort.getDepth()); + processorPort.setGranularDepth(activityPort.getGranularDepth()); + // add a new port binding + new ProcessorOutputPortBinding(processorBinding, activityPort, processorPort); + } + + List<Edit<?>> editList = new ArrayList<Edit<?>>(); + editList.add(new AddChildEdit<Profile>(destinationProfile, activity)); + editList.add(new AddChildEdit<Profile>(destinationProfile, configuration)); + editList.add(new AddChildEdit<Profile>(destinationProfile, processorBinding)); + editList.add(new AddProcessorEdit(destinationWorkflow, processor)); + + editList.add(makeInsertWorkflowEdit(nestedFlow, nestedFlow.getParent().getMainProfile())); + + return new CompoundEdit(editList); + } + + protected Edit<?> makeInsertWorkflowEdit(Workflow nestedFlow, Profile profile) { + return makeInsertWorkflowEdit(nestedFlow, profile, new HashSet<>()); + } + + protected Edit<?> makeInsertWorkflowEdit(Workflow nestedFlow, Profile profile, Set<Object> seen) { + List<Edit<?>> editList = new ArrayList<Edit<?>>(); + // add the nested workflow to the workflow bundle + editList.add(new AddChildEdit<WorkflowBundle>(destinationWorkflowBundle, nestedFlow)); + seen.add(nestedFlow); + for (Processor processor : nestedFlow.getProcessors()) { + // add processor bindings to the profile + List<ProcessorBinding> processorBindings = scufl2Tools.processorBindingsForProcessor(processor, profile); + for (ProcessorBinding processorBinding : processorBindings) { + editList.add(new AddChildEdit<Profile>(destinationProfile, processorBinding)); + // add activity to the profile + Activity activity = processorBinding.getBoundActivity(); + if (!seen.contains(activity)) { + editList.add(new AddChildEdit<Profile>(destinationProfile, activity)); + // add activity configurations to the profile + for (Configuration configuration : scufl2Tools.configurationsFor(activity, profile)) { + editList.add(new AddChildEdit<Profile>(destinationProfile, configuration)); + } + seen.add(activity); + } + } + // add processor configurations to the profile + List<Configuration> configurations = scufl2Tools.configurationsFor(processor, profile); + for (Configuration configuration : configurations) { + editList.add(new AddChildEdit<Profile>(destinationProfile, configuration)); + } + + for (Workflow workflow : scufl2Tools.nestedWorkflowsForProcessor(processor, profile)) { + if (!seen.contains(workflow)) { + // recursively add nested workflows + editList.add(makeInsertWorkflowEdit(workflow, profile, seen)); + } + } + } + return new CompoundEdit(editList); + } + +// protected Activity getInsertedActivity() { +// return insertedActivity; +// } + + protected class ImportWorkflowAction extends AbstractAction implements Runnable { + private static final String VALID_NAME_REGEX = "[\\p{L}\\p{Digit}_.]+"; + private Component parentComponent; + private ProgressMonitor progressMonitor; + + protected ImportWorkflowAction() { + super("Import workflow"); + } + + public void actionPerformed(ActionEvent e) { + /* + * if (e.getSource() instanceof Component) { parentComponent = (Component) + * e.getSource(); } else { parentComponent = null; } + */ + parentComponent = MainWindow.getMainWindow(); + Thread t = new Thread(this, "Import workflow"); + progressMonitor = new ProgressMonitor(parentComponent, "Importing workflow", "", 0, 100); + progressMonitor.setMillisToDecideToPopup(200); + progressMonitor.setProgress(5); + t.start(); + setVisible(false); + } + + protected void nested() { + if (progressMonitor.isCanceled()) { + return; + } + progressMonitor.setProgress(15); + selectionManager.setSelectedWorkflowBundle(destinationWorkflowBundle); + if (progressMonitor.isCanceled()) { + return; + } + + progressMonitor.setNote("Copying source workflow"); + Workflow nestedFlow; + try { + nestedFlow = DataflowMerger.copyWorkflow(sourceWorkflow); + } catch (Exception ex) { + logger.warn("Could not copy nested workflow", ex); + progressMonitor.setProgress(100); + JOptionPane.showMessageDialog(parentComponent, + "An error occured while copying workflow:\n" + ex.getLocalizedMessage(), + "Could not copy nested workflow", JOptionPane.WARNING_MESSAGE); + return; + } + if (progressMonitor.isCanceled()) { + return; + } + + progressMonitor.setNote("Creating nested workflow"); + progressMonitor.setProgress(45); + + Edit<?> edit = makeInsertNestedWorkflowEdit(nestedFlow); + if (progressMonitor.isCanceled()) { + return; + } + + progressMonitor.setNote("Inserting nested workflow"); + progressMonitor.setProgress(65); + + try { + editManager.doDataflowEdit(destinationWorkflowBundle, edit); + } catch (EditException e) { + progressMonitor.setProgress(100); + logger.warn("Could not import nested workflow", e); + JOptionPane.showMessageDialog(parentComponent, + "An error occured while importing workflow:\n" + e.getLocalizedMessage(), + "Could not import workflows", JOptionPane.WARNING_MESSAGE); + return; + } + + if (radioNew.isSelected()) { + progressMonitor.setNote("Opening new nested workflow for editing"); + progressMonitor.setProgress(90); + selectionManager.setSelectedWorkflow(nestedFlow); + } + progressMonitor.setProgress(100); + } + + protected void merge() { + progressMonitor.setProgress(10); + DataflowMerger merger = new DataflowMerger(destinationWorkflow); + progressMonitor.setProgress(25); + progressMonitor.setNote("Planning workflow merging"); + + String prefix = prefixField.getText(); + if (!prefix.equals("")) { + if (!prefix.matches("[_.]$")) { + prefix = prefix + "_"; + } + if (!prefix.matches(VALID_NAME_REGEX)) { + progressMonitor.setProgress(100); + final String wrongPrefix = prefix; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(parentComponent, "The merge prefix '" + + wrongPrefix + "' is not valid. Try " + + "using only letters, numbers, " + "underscore and dot.", + "Invalid merge prefix", JOptionPane.ERROR_MESSAGE); + prefixField.requestFocus(); + ImportWorkflowWizard.this.setVisible(true); + } + }); + return; + } + } + + CompoundEdit mergeEdit; + try { + mergeEdit = merger.getMergeEdit(ImportWorkflowWizard.this.sourceWorkflow, prefix); + } catch (MergeException e1) { + progressMonitor.setProgress(100); + logger.warn("Could not merge workflow", e1); + JOptionPane.showMessageDialog(parentComponent, + "An error occured while merging workflows:\n" + e1.getLocalizedMessage(), + "Could not merge workflows", JOptionPane.WARNING_MESSAGE); + return; + } + + progressMonitor.setProgress(55); + selectionManager.setSelectedWorkflowBundle(destinationWorkflowBundle); + + progressMonitor.setNote("Merging workflows"); + progressMonitor.setProgress(75); + + if (progressMonitor.isCanceled()) { + return; + } + + try { + editManager.doDataflowEdit(destinationWorkflowBundle, mergeEdit); + } catch (EditException e1) { + progressMonitor.setProgress(100); + JOptionPane.showMessageDialog(parentComponent, + "An error occured while merging workflows:\n" + e1.getLocalizedMessage(), + "Could not merge workflows", JOptionPane.WARNING_MESSAGE); + return; + } + progressMonitor.setProgress(100); + + } + + public void run() { + boolean completed = findChosenDataflow(parentComponent, false); + if (!completed) { + return; + } + if (actionMerge.isSelected()) { + merge(); + } else if (actionNested.isSelected()) { + nested(); + } + } + } + + protected class UpdatePreviewsThread extends Thread { + protected UpdatePreviewsThread() { + super("Updating destination previews"); + } + + public void run() { + if (Thread.interrupted()) { + return; + } + updateSourcePreview(); + + if (Thread.interrupted()) { + return; + } + updateDestinationPreview(); + } + } + + protected class BrowseFileOnClick implements ActionListener { + public void actionPerformed(ActionEvent e) { + checkEmptyFile(); + } + + public void checkEmptyFile() { + if (radioFile.isSelected() && fieldFile.getText().equals("")) { + // On first label click pop up Browse dialogue. + buttonBrowse.doClick(); + } + } + } + + protected class DataflowOpenerThread extends Thread { + private final boolean background; + private final Component parentComponent; + private boolean shouldStop = false; + private boolean shownWarning = false; + + protected DataflowOpenerThread(Component parentComponent, boolean background) { + super("Inspecting selected workflow"); + this.parentComponent = parentComponent; + this.background = background; + } + + @Override + public void interrupt() { + this.shouldStop = true; + super.interrupt(); + } + + public void run() { + updateSource(); +// updateDestination(); + } + +// public void updateDestination() { +// ButtonModel selection = destinationSelection.getSelection(); +// Workflow chosenDataflow = null; +// if (selection == null) { +// chosenDataflow = null; +// } else if (selection.equals(radioNewDestination.getModel())) { +// chosenDataflow = new Workflow(); +// } else if (selection.equals(radioOpenDestination.getModel())) { +// DataflowSelection chosen = (DataflowSelection) destinationAlreadyOpen +// .getSelectedItem(); +// chosenDataflow = chosen.getDataflow(); +// } else if (selection.equals(radioCustomDestination.getModel())) { +// chosenDataflow = customDestinationDataflow; +// } else { +// logger.error("Unknown selection " + selection); +// } +// +// if (chosenDataflow == null) { +// if (!background && !shownWarning) { +// shownWarning = true; +// SwingUtilities.invokeLater(new Runnable() { +// public void run() { +// JOptionPane.showMessageDialog(parentComponent, +// "You need to choose a destination workflow", +// "No destination workflow chosen", JOptionPane.ERROR_MESSAGE); +// setVisible(true); +// } +// }); +// return; +// } +// } +// if (checkInterrupted()) { +// return; +// } +// if (chosenDataflow != ImportWorkflowWizard.this.destinationDataflow) { +// updateWorkflowGraphic(previewDestination, chosenDataflow); +// if (checkInterrupted()) { +// return; +// } +// ImportWorkflowWizard.this.destinationDataflow = chosenDataflow; +// } +// +// } + + public void updateSource() { + ButtonModel selection = sourceSelection.getSelection(); + Workflow chosenDataflow = null; + if (selection == null) { + chosenDataflow = null; + } else if (selection.equals(radioNew.getModel())) { + WorkflowBundle workflowBundle = new WorkflowBundle(); + workflowBundle.setMainWorkflow(new Workflow()); + workflowBundle.getMainWorkflow().setName(fileManager.getDefaultWorkflowName()); + workflowBundle.setMainProfile(new Profile()); + scufl2Tools.setParents(workflowBundle); + chosenDataflow = workflowBundle.getMainWorkflow(); + } else if (selection.equals(radioFile.getModel())) { + final String filePath = fieldFile.getText(); + try { + DataflowInfo opened = fileManager + .openDataflowSilently(null, new File(filePath)); + if (checkInterrupted()) { + return; + } + chosenDataflow = opened.getDataflow().getMainWorkflow(); + } catch (final OpenException e1) { + if (!background && !shownWarning) { + shownWarning = true; + logger.warn("Could not open workflow for merging: " + filePath, e1); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + radioFile.requestFocus(); + JOptionPane.showMessageDialog(parentComponent, + "An error occured while trying to open " + filePath + "\n" + + e1.getMessage(), "Could not open workflow", + JOptionPane.WARNING_MESSAGE); + setVisible(true); + } + }); + } + } + } else if (selection.equals(radioUrl.getModel())) { + final String url = fieldUrl.getText(); + try { + DataflowInfo opened = fileManager.openDataflowSilently(null, new URL(url)); + if (checkInterrupted()) { + return; + } + chosenDataflow = opened.getDataflow().getMainWorkflow(); + } catch (final OpenException e1) { + if (!background && !shownWarning) { + logger.warn("Could not open source workflow: " + url, e1); + shownWarning = true; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + fieldUrl.requestFocus(); + JOptionPane.showMessageDialog( + parentComponent, + "An error occured while trying to open " + url + "\n" + + e1.getMessage(), "Could not open workflow", + JOptionPane.WARNING_MESSAGE); + setVisible(true); + } + }); + + } + if (checkInterrupted()) { + return; + } + } catch (final MalformedURLException e1) { + if (!background && !shownWarning) { + logger.warn("Invalid workflow URL: " + url, e1); + shownWarning = true; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + fieldUrl.requestFocus(); + JOptionPane.showMessageDialog( + parentComponent, + "The workflow location " + url + " is invalid\n" + + e1.getLocalizedMessage(), "Invalid URL", + JOptionPane.ERROR_MESSAGE); + setVisible(true); + } + }); + } + if (checkInterrupted()) { + return; + } + } + } else if (selection.equals(radioOpened.getModel())) { + DataflowSelection chosen = (DataflowSelection) chooseDataflow.getSelectedItem(); + chosenDataflow = chosen.getDataflow().getMainWorkflow(); + } else if (selection.equals(radioCustomSource.getModel())) { + chosenDataflow = customSourceDataFlow.getMainWorkflow(); + } else { + logger.error("Unknown selection " + selection); + } + if (checkInterrupted()) { + return; + } + if (chosenDataflow != ImportWorkflowWizard.this.sourceWorkflow) { + Profile chosenProfile = null; + if (chosenDataflow != null) { + chosenProfile = chosenDataflow.getParent().getMainProfile(); + } + updateWorkflowGraphic(previewSource, chosenDataflow, chosenProfile); + if (checkInterrupted()) { + return; + } + ImportWorkflowWizard.this.sourceWorkflow = chosenDataflow; + } + if (chosenDataflow == null) { + if (!background && !shownWarning) { + shownWarning = true; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(parentComponent, + "You need to choose a workflow for merging", + "No workflow chosen", JOptionPane.ERROR_MESSAGE); + setVisible(true); + } + }); + } + } + } + + private boolean checkInterrupted() { + if (Thread.interrupted() || this.shouldStop) { + // ImportWorkflowWizard.this.chosenDataflow = null; + return true; + } + return false; + } + } + + public static class DataflowSelection { + private final WorkflowBundle dataflow; + private final String name; + + public DataflowSelection(WorkflowBundle dataflow, String name) { + this.dataflow = dataflow; + this.name = name; + } + + public WorkflowBundle getDataflow() { + return dataflow; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } + + } + + protected class UpdateChosenListener implements ActionListener { + public void actionPerformed(ActionEvent e) { + Component parentComponent; + if (e.getSource() instanceof Component) { + parentComponent = (Component) e.getSource(); + } else { + parentComponent = null; + } + findChosenDataflow(parentComponent, true); + + } + } + + public void setCustomSourceDataflow(WorkflowBundle sourceDataflow, String label) { + this.customSourceDataFlow = sourceDataflow; + this.customSourceName = label; + updateSourceSection(); + radioCustomSource.doClick(); + } + +// public void setCustomDestinationDataflow(Workflow destinationDataflow, String label) { +// this.customDestinationDataflow = destinationDataflow; +// this.customDestinationName = label; +// updateDestinationSection(); +// radioCustomDestination.doClick(); +// } + +// public void setDestinationEnabled(boolean destinationEnabled) { +// this.destinationEnabled = destinationEnabled; +// updateDestinationSection(); +// } + + public void setSourceEnabled(boolean sourceEnabled) { + this.sourceEnabled = sourceEnabled; + updateSourceSection(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/AddNestedWorkflowMenuAction.java ---------------------------------------------------------------------- diff --git a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/AddNestedWorkflowMenuAction.java b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/AddNestedWorkflowMenuAction.java new file mode 100644 index 0000000..759d24a --- /dev/null +++ b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/AddNestedWorkflowMenuAction.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * 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 org.apache.taverna.workbench.file.importworkflow.menu; + +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.net.URI; + +import javax.swing.Action; +import javax.swing.KeyStroke; + +import org.apache.taverna.ui.menu.AbstractMenuAction; +import org.apache.taverna.ui.menu.MenuManager; +import org.apache.taverna.workbench.configuration.colour.ColourManager; +import org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration; +import org.apache.taverna.workbench.edits.EditManager; +import org.apache.taverna.workbench.file.FileManager; +import org.apache.taverna.workbench.file.importworkflow.actions.AddNestedWorkflowAction; +import org.apache.taverna.workbench.selection.SelectionManager; +import net.sf.taverna.t2.workbench.views.graph.menu.InsertMenu; + +/** + * An action to add a nested workflow activity + a wrapping processor to the + * workflow. + * + * @author Alex Nenadic + * @author Stian Soiland-Reyes + * + */ +public class AddNestedWorkflowMenuAction extends AbstractMenuAction { + + private static final String ADD_NESTED_WORKFLOW = "Nested workflow"; + + private static final URI ADD_NESTED_WORKFLOW_URI = URI + .create("http://taverna.sf.net/2008/t2workbench/menu#graphMenuAddNestedWorkflow"); + + private EditManager editManager; + private FileManager fileManager; + private MenuManager menuManager; + private ColourManager colourManager; + private WorkbenchConfiguration workbenchConfiguration; + private SelectionManager selectionManager; + + public AddNestedWorkflowMenuAction() { + super(InsertMenu.INSERT, 400, ADD_NESTED_WORKFLOW_URI); + } + + @Override + protected Action createAction() { + AddNestedWorkflowAction a = new AddNestedWorkflowAction(editManager, fileManager, + menuManager, colourManager, workbenchConfiguration, selectionManager); + // Override name to avoid "Add " + a.putValue(Action.NAME, ADD_NESTED_WORKFLOW); + a.putValue(Action.SHORT_DESCRIPTION, ADD_NESTED_WORKFLOW); + a.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke( + KeyEvent.VK_N, InputEvent.SHIFT_DOWN_MASK + | InputEvent.ALT_DOWN_MASK)); + return a; + + } + + public void setEditManager(EditManager editManager) { + this.editManager = editManager; + } + + public void setFileManager(FileManager fileManager) { + this.fileManager = fileManager; + } + + public void setMenuManager(MenuManager menuManager) { + this.menuManager = menuManager; + } + + public void setColourManager(ColourManager colourManager) { + this.colourManager = colourManager; + } + + public void setWorkbenchConfiguration(WorkbenchConfiguration workbenchConfiguration) { + this.workbenchConfiguration = workbenchConfiguration; + } + + public void setSelectionManager(SelectionManager selectionManager) { + this.selectionManager = selectionManager; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/ImportWorkflowMenuAction.java ---------------------------------------------------------------------- diff --git a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/ImportWorkflowMenuAction.java b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/ImportWorkflowMenuAction.java new file mode 100644 index 0000000..48870ca --- /dev/null +++ b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/ImportWorkflowMenuAction.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * 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 org.apache.taverna.workbench.file.importworkflow.menu; + +import java.net.URI; + +import javax.swing.Action; + +import org.apache.taverna.ui.menu.AbstractContextualMenuAction; +import org.apache.taverna.ui.menu.MenuManager; +import org.apache.taverna.workbench.configuration.colour.ColourManager; +import org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration; +import org.apache.taverna.workbench.edits.EditManager; +import org.apache.taverna.workbench.file.FileManager; +import org.apache.taverna.workbench.file.importworkflow.actions.ImportWorkflowAction; +import org.apache.taverna.workbench.selection.SelectionManager; +import org.apache.taverna.scufl2.api.core.Workflow; + +/** + * An action to import nested/merged workflows. + * + * @author Alex Nenadic + * @author Stian Soiland-Reyes + * + */ +public class ImportWorkflowMenuAction extends AbstractContextualMenuAction { + + private static final URI insertSection = URI + .create("http://taverna.sf.net/2009/contextMenu/insert"); + + private EditManager editManager; + private FileManager fileManager; + private MenuManager menuManager; + private ColourManager colourManager; + private WorkbenchConfiguration workbenchConfiguration; + private SelectionManager selectionManager; + + public ImportWorkflowMenuAction() { + super(insertSection, 400); + } + + @Override + public boolean isEnabled() { + return super.isEnabled() && getContextualSelection().getSelection() instanceof Workflow; + } + + @Override + protected Action createAction() { + ImportWorkflowAction myAction = new ImportWorkflowAction(editManager, fileManager, + menuManager, colourManager, workbenchConfiguration, selectionManager); + // Just "Workflow" as we go under the "Insert" menu + myAction.putValue(Action.NAME, "Nested workflow"); + return myAction; + } + + public void setEditManager(EditManager editManager) { + this.editManager = editManager; + } + + public void setFileManager(FileManager fileManager) { + this.fileManager = fileManager; + } + + public void setMenuManager(MenuManager menuManager) { + this.menuManager = menuManager; + } + + public void setColourManager(ColourManager colourManager) { + this.colourManager = colourManager; + } + + public void setWorkbenchConfiguration(WorkbenchConfiguration workbenchConfiguration) { + this.workbenchConfiguration = workbenchConfiguration; + } + + public void setSelectionManager(SelectionManager selectionManager) { + this.selectionManager = selectionManager; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/MergeWorkflowMenuAction.java ---------------------------------------------------------------------- diff --git a/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/MergeWorkflowMenuAction.java b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/MergeWorkflowMenuAction.java new file mode 100644 index 0000000..05cf1f5 --- /dev/null +++ b/taverna-dataflow-activity-ui/src/main/java/org/apache/taverna/workbench/file/importworkflow/menu/MergeWorkflowMenuAction.java @@ -0,0 +1,65 @@ +package org.apache.taverna.workbench.file.importworkflow.menu; + +import java.net.URI; + +import javax.swing.Action; + +import org.apache.taverna.ui.menu.AbstractMenuAction; +import org.apache.taverna.ui.menu.MenuManager; +import org.apache.taverna.workbench.configuration.colour.ColourManager; +import org.apache.taverna.workbench.configuration.workbench.WorkbenchConfiguration; +import org.apache.taverna.workbench.edits.EditManager; +import org.apache.taverna.workbench.file.FileManager; +import org.apache.taverna.workbench.file.importworkflow.actions.MergeWorkflowAction; +import org.apache.taverna.workbench.selection.SelectionManager; + +public class MergeWorkflowMenuAction extends AbstractMenuAction { + + public static final URI INSERT_URI = URI + .create("http://taverna.sf.net/2008/t2workbench/menu#insert"); + + public static final URI IMPORT_URI = URI + .create("http://taverna.sf.net/2008/t2workbench/menu#insert"); + + private EditManager editManager; + private FileManager fileManager; + private MenuManager menuManager; + private ColourManager colourManager; + private WorkbenchConfiguration workbenchConfiguration; + private SelectionManager selectionManager; + + public MergeWorkflowMenuAction() { + super(INSERT_URI, 2000, IMPORT_URI); + } + + @Override + protected Action createAction() { + return new MergeWorkflowAction(editManager, fileManager, menuManager, colourManager, + workbenchConfiguration, selectionManager); + } + + public void setEditManager(EditManager editManager) { + this.editManager = editManager; + } + + public void setFileManager(FileManager fileManager) { + this.fileManager = fileManager; + } + + public void setMenuManager(MenuManager menuManager) { + this.menuManager = menuManager; + } + + public void setColourManager(ColourManager colourManager) { + this.colourManager = colourManager; + } + + public void setWorkbenchConfiguration(WorkbenchConfiguration workbenchConfiguration) { + this.workbenchConfiguration = workbenchConfiguration; + } + + public void setSelectionManager(SelectionManager selectionManager) { + this.selectionManager = selectionManager; + } + +}