http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ListConfigurationComponent.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ListConfigurationComponent.java b/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ListConfigurationComponent.java deleted file mode 100644 index c0e3aab..0000000 --- a/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ListConfigurationComponent.java +++ /dev/null @@ -1,119 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2012 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.views.contextualviews.activity; - -import static java.awt.BorderLayout.CENTER; -import static java.awt.BorderLayout.EAST; -import static java.awt.BorderLayout.SOUTH; -import static java.awt.FlowLayout.RIGHT; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.FlowLayout; -import java.awt.event.ActionEvent; -import java.util.List; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.JScrollPane; - -/** - * @author David Withers - */ -@SuppressWarnings("serial") -public abstract class ListConfigurationComponent<T> extends JPanel { - private static final String REMOVE = "Remove"; - private static final String ADD = "Add"; - - private String name; - private List<T> items; - private JPanel listPanel; - - public ListConfigurationComponent(String name, List<T> items) { - this.name = name; - setLayout(new BorderLayout()); - - listPanel = new JPanel(new ListLayout()); - JPanel buttonPanel = new JPanel(new FlowLayout(RIGHT)); - buttonPanel.add(new JButton(createAddAction())); - - add(new JScrollPane(listPanel), CENTER); - add(buttonPanel, SOUTH); - - setItems(items); - } - - protected void setItems(List<T> items) { - this.items = items; - listPanel.removeAll(); - for (T item : items) - addItemComponent(item); - } - - protected void addItem(T item) { - items.add(item); - addItemComponent(item); - } - - protected void addItemComponent(T item) { - JComponent itemPanel = new JPanel(new BorderLayout()); - itemPanel.add(createItemComponent(item), CENTER); - itemPanel.add(new JButton(createRemoveAction(item)), EAST); - listPanel.add(itemPanel); - listPanel.revalidate(); - listPanel.repaint(); - } - - protected void removeItem(T item) { - int index = items.indexOf(item); - if (index >= 0) { - items.remove(index); - listPanel.remove(index); - listPanel.revalidate(); - listPanel.repaint(); - } - } - - private Action createRemoveAction(final T item) { - return new AbstractAction(REMOVE) { - @Override - public void actionPerformed(ActionEvent e) { - removeItem(item); - } - }; - } - - private Action createAddAction() { - return new AbstractAction(ADD + " " + name) { - @Override - public void actionPerformed(ActionEvent e) { - addItem(createDefaultItem()); - } - }; - } - - protected abstract Component createItemComponent(T item); - - protected abstract T createDefaultItem(); -}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ListLayout.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ListLayout.java b/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ListLayout.java deleted file mode 100644 index 0ce35b5..0000000 --- a/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ListLayout.java +++ /dev/null @@ -1,92 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2012 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.views.contextualviews.activity; - -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Insets; -import java.awt.LayoutManager; - -/** - * Lays out components vertically using their preferred height and the available - * width. - * - * @author David Withers - */ -public class ListLayout implements LayoutManager { - private static final int DEFAULT_GAP = 5; - private final int gap; - - public ListLayout() { - this(DEFAULT_GAP); - } - - public ListLayout(int gap) { - this.gap = gap; - } - - @Override - public void removeLayoutComponent(Component comp) { - } - - @Override - public void addLayoutComponent(String name, Component comp) { - } - - @Override - public void layoutContainer(Container parent) { - Insets insets = parent.getInsets(); - int x = insets.left; - int y = insets.top; - int width = parent.getWidth() - insets.left - insets.right; - Component[] components = parent.getComponents(); - for (int i = 0; i < components.length; i++) { - components[i].setLocation(x, y); - components[i].setSize(width, - components[i].getPreferredSize().height); - y = y + gap + components[i].getHeight(); - } - } - - @Override - public Dimension minimumLayoutSize(Container parent) { - Insets insets = parent.getInsets(); - int minimumWidth = 0; - int minimumHeight = 0; - Component[] components = parent.getComponents(); - for (int i = 0; i < components.length; i++) { - Dimension size = components[i].getPreferredSize(); - if (size.width > minimumWidth) - minimumWidth = size.width; - minimumHeight = minimumHeight + size.height + gap; - } - minimumWidth = minimumWidth + insets.left + insets.right; - minimumHeight = minimumHeight + insets.top + insets.bottom; - - return new Dimension(minimumWidth, minimumHeight); - } - - @Override - public Dimension preferredLayoutSize(Container parent) { - return minimumLayoutSize(parent); - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/MultiPageActivityConfigurationPanel.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/MultiPageActivityConfigurationPanel.java b/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/MultiPageActivityConfigurationPanel.java deleted file mode 100644 index c6862ff..0000000 --- a/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/MultiPageActivityConfigurationPanel.java +++ /dev/null @@ -1,65 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2012 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.views.contextualviews.activity; - -import static java.awt.BorderLayout.CENTER; - -import java.awt.BorderLayout; -import java.awt.Component; - -import javax.swing.JTabbedPane; - -import org.apache.taverna.scufl2.api.activity.Activity; - -/** - * Component for configuring activities that have multiple configuration pages. - * - * @author David Withers - */ -@SuppressWarnings("serial") -public abstract class MultiPageActivityConfigurationPanel extends - ActivityConfigurationPanel { - private JTabbedPane tabbedPane; - - /** - * Constructs a new <code>MultiPageActivityConfigurationPanel</code>. - * - * @param activity - */ - public MultiPageActivityConfigurationPanel(Activity activity) { - super(activity); - setLayout(new BorderLayout()); - tabbedPane = new JTabbedPane(); - add(tabbedPane, CENTER); - } - - public void addPage(String name, Component component) { - tabbedPane.addTab(name, component); - } - - public void removePage(String name) { - tabbedPane.removeTabAt(tabbedPane.indexOfTab(name)); - } - - public void removeAllPages() { - tabbedPane.removeAll(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ScriptConfigurationComponent.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ScriptConfigurationComponent.java b/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ScriptConfigurationComponent.java deleted file mode 100644 index 8cb7652..0000000 --- a/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ScriptConfigurationComponent.java +++ /dev/null @@ -1,150 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2012 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.views.contextualviews.activity; - -import static java.awt.BorderLayout.CENTER; -import static java.awt.BorderLayout.SOUTH; -import static java.awt.Color.WHITE; -import static java.awt.Font.PLAIN; -import static javax.swing.JOptionPane.INFORMATION_MESSAGE; -import static javax.swing.JOptionPane.YES_NO_OPTION; -import static javax.swing.JOptionPane.YES_OPTION; -import static javax.swing.JOptionPane.showConfirmDialog; -import static javax.swing.JOptionPane.showMessageDialog; -import static net.sf.taverna.t2.lang.ui.FileTools.readStringFromFile; -import static net.sf.taverna.t2.lang.ui.FileTools.saveStringToFile; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Set; - -import javax.swing.JButton; -import javax.swing.JPanel; -import javax.swing.JTextPane; - -import net.sf.taverna.t2.lang.ui.KeywordDocument; -import net.sf.taverna.t2.lang.ui.LineEnabledTextPanel; -import net.sf.taverna.t2.lang.ui.LinePainter; -import net.sf.taverna.t2.lang.ui.NoWrapEditorKit; - -/** - * Component for configuring activities that have scripts. - * - * @author David Withers - */ -@SuppressWarnings("serial") -public class ScriptConfigurationComponent extends JPanel { - private JTextPane scriptTextArea; - - public ScriptConfigurationComponent(String script, Set<String> keywords, - Set<String> ports, final String scriptType, - final String fileExtension) { - this(script, keywords, ports, scriptType, fileExtension, ""); - } - - public ScriptConfigurationComponent(String script, Set<String> keywords, - Set<String> ports, final String scriptType, - final String fileExtension, final String resetScript) { - super(new BorderLayout()); - scriptTextArea = new JTextPane(); - new LinePainter(scriptTextArea, WHITE); - - final KeywordDocument doc = new KeywordDocument(keywords, ports); - - // NOTE: Due to T2-1145 - always set editor kit BEFORE setDocument - scriptTextArea.setEditorKit(new NoWrapEditorKit()); - scriptTextArea.setFont(new Font("Monospaced", PLAIN, 14)); - scriptTextArea.setDocument(doc); - scriptTextArea.setText(script); - scriptTextArea.setCaretPosition(0); - scriptTextArea.setPreferredSize(new Dimension(200, 100)); - - add(new LineEnabledTextPanel(scriptTextArea), CENTER); - - final JButton checkScriptButton = new JButton("Check script"); - checkScriptButton.setToolTipText("Check the " + scriptType + " script"); - checkScriptButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent ex) { - showMessageDialog(ScriptConfigurationComponent.this, scriptType - + " script check not implemented", scriptType - + " script check", INFORMATION_MESSAGE); - } - }); - - JButton loadScriptButton = new JButton("Load script"); - loadScriptButton.setToolTipText("Load a " + scriptType - + " script from a file"); - loadScriptButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - String newScript = readStringFromFile( - ScriptConfigurationComponent.this, "Load " + scriptType - + " script", fileExtension); - if (newScript != null) { - scriptTextArea.setText(newScript); - scriptTextArea.setCaretPosition(0); - } - } - }); - - JButton saveRScriptButton = new JButton("Save script"); - saveRScriptButton.setToolTipText("Save the " + scriptType - + " script to a file"); - saveRScriptButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - saveStringToFile(ScriptConfigurationComponent.this, "Save " - + scriptType + " script", fileExtension, - scriptTextArea.getText()); - } - }); - - JButton clearScriptButton = new JButton("Clear script"); - clearScriptButton.setToolTipText("Clear current script from the edit area"); - clearScriptButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (showConfirmDialog(ScriptConfigurationComponent.this, - "Do you really want to clear the script?", - "Clearing the script", YES_NO_OPTION) == YES_OPTION) - scriptTextArea.setText(resetScript); - } - }); - - JPanel buttonPanel = new JPanel(); - buttonPanel.setLayout(new FlowLayout()); - buttonPanel.add(checkScriptButton); - buttonPanel.add(loadScriptButton); - buttonPanel.add(saveRScriptButton); - buttonPanel.add(clearScriptButton); - - add(buttonPanel, SOUTH); - } - - public String getScript() { - return scriptTextArea.getText(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ValidatingTextField.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ValidatingTextField.java b/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ValidatingTextField.java deleted file mode 100644 index cf1ff96..0000000 --- a/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ValidatingTextField.java +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2012 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.views.contextualviews.activity; - -import javax.swing.JTextField; - -/** - * Adds a "<tt>valid</tt>" property to a JTextField. - * - * @author David Withers - */ -@SuppressWarnings("serial") -public class ValidatingTextField extends JTextField { - private boolean valid = true; - - public ValidatingTextField() { - } - - public ValidatingTextField(String text) { - super(text); - } - - @Override - public boolean isValid() { - return valid; - } - - public void setValid(boolean valid) { - if (this.valid != valid) { - boolean old = this.valid; - this.valid = valid; - firePropertyChange("valid", old, valid); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ValidatingTextGroup.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ValidatingTextGroup.java b/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ValidatingTextGroup.java deleted file mode 100644 index 7597f7c..0000000 --- a/taverna-contextual-views-api/src/main/java/net/sf/taverna/t2/workbench/ui/views/contextualviews/activity/ValidatingTextGroup.java +++ /dev/null @@ -1,119 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2012 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.views.contextualviews.activity; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; - -/** - * - * - * @author David Withers - */ -public class ValidatingTextGroup { - private Map<ValidatingTextField, DocumentListener> textComponents; - - public ValidatingTextGroup() { - textComponents = new HashMap<>(); - } - - public void addValidTextComponent(ValidatingTextField textComponent) { - setUniqueText(textComponent); - DocumentListener documentListener = new ValidatorDocumentListener(); - textComponent.getDocument().addDocumentListener(documentListener); - textComponents.put(textComponent, documentListener); - } - - public void addTextComponent(ValidatingTextField textComponent) { - DocumentListener documentListener = new ValidatorDocumentListener(); - textComponent.getDocument().addDocumentListener(documentListener); - textComponents.put(textComponent, documentListener); - validate(); - } - - public void removeTextComponent(ValidatingTextField textComponent) { - textComponent.getDocument().removeDocumentListener( - textComponents.remove(textComponent)); - validate(); - } - - private void setUniqueText(ValidatingTextField textComponent) { - String text = textComponent.getText(); - if (textExists(text)) { - // Remove any existing number suffix - String nameTemplate = text.replaceAll("_\\d+$", "_"); - long i = 1; - do { - text = nameTemplate + i++; - } while (textExists(text)); - - textComponent.setText(text); - } - } - - private void validate() { - Map<String, ValidatingTextField> textValues = new HashMap<>(); - Set<ValidatingTextField> maybeValid = new HashSet<>(); - for (ValidatingTextField textComponent : textComponents.keySet()) { - ValidatingTextField duplicate = textValues.get(textComponent - .getText()); - if (duplicate != null) { - duplicate.setValid(false); - maybeValid.remove(duplicate); - textComponent.setValid(false); - } else { - textValues.put(textComponent.getText(), textComponent); - maybeValid.add(textComponent); - } - } - for (ValidatingTextField textComponent : maybeValid) - textComponent.setValid(true); - } - - private boolean textExists(String text) { - for (ValidatingTextField currentTextComponent : textComponents.keySet()) - if (text.equals(currentTextComponent.getText())) - return true; - return false; - } - - class ValidatorDocumentListener implements DocumentListener { - @Override - public void insertUpdate(DocumentEvent e) { - validate(); - } - - @Override - public void removeUpdate(DocumentEvent e) { - validate(); - } - - @Override - public void changedUpdate(DocumentEvent e) { - validate(); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/actions/activity/ActivityConfigurationAction.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/actions/activity/ActivityConfigurationAction.java b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/actions/activity/ActivityConfigurationAction.java new file mode 100644 index 0000000..23fae78 --- /dev/null +++ b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/actions/activity/ActivityConfigurationAction.java @@ -0,0 +1,166 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.actions.activity; + +import java.util.List; +import java.util.WeakHashMap; + +import javax.swing.AbstractAction; +import javax.swing.JDialog; + +import org.apache.taverna.lang.observer.Observable; +import org.apache.taverna.lang.observer.Observer; +import org.apache.taverna.servicedescriptions.ServiceDescription; +import org.apache.taverna.servicedescriptions.ServiceDescriptionRegistry; +import org.apache.taverna.workbench.activityicons.ActivityIconManager; +import org.apache.taverna.workbench.file.FileManager; +import org.apache.taverna.workbench.file.events.ClosingDataflowEvent; +import org.apache.taverna.workbench.file.events.FileManagerEvent; +import org.apache.taverna.workbench.ui.views.contextualviews.activity.ActivityConfigurationDialog; +import org.apache.taverna.scufl2.api.activity.Activity; +import org.apache.taverna.scufl2.api.common.Scufl2Tools; +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.profiles.ProcessorBinding; +import org.apache.taverna.scufl2.api.profiles.Profile; + +@SuppressWarnings("serial") +public abstract class ActivityConfigurationAction extends AbstractAction { + private static WeakHashMap<Activity, ActivityConfigurationDialog> configurationDialogs = new WeakHashMap<>(); + private static DataflowCloseListener listener; + + protected Activity activity; + private final ServiceDescriptionRegistry serviceDescriptionRegistry; + + public ActivityConfigurationAction(Activity activity, + ActivityIconManager activityIconManager, + ServiceDescriptionRegistry serviceDescriptionRegistry) { + this.activity = activity; + this.serviceDescriptionRegistry = serviceDescriptionRegistry; + putValue(SMALL_ICON, + activityIconManager.iconForActivity(activity.getType())); + } + + protected Activity getActivity() { + return activity; + } + + protected ServiceDescription getServiceDescription() { + return serviceDescriptionRegistry.getServiceDescription(activity + .getType()); + } + + protected static void setDialog(Activity activity, + ActivityConfigurationDialog dialog, FileManager fileManager) { + if (listener == null) { + listener = new DataflowCloseListener(); + /* + * Ensure that the DataflowCloseListener is the first notified + * listener. Otherwise you cannot save the configurations. + */ + List<Observer<FileManagerEvent>> existingListeners = fileManager + .getObservers(); + fileManager.addObserver(listener); + for (Observer<FileManagerEvent> observer : existingListeners) + if (!observer.equals(listener)) { + fileManager.removeObserver(observer); + fileManager.addObserver(observer); + } + } + if (configurationDialogs.containsKey(activity)) { + ActivityConfigurationDialog currentDialog = configurationDialogs + .get(activity); + if (!currentDialog.equals(dialog) && currentDialog.isVisible()) + currentDialog.setVisible(false); + } + configurationDialogs.put(activity, dialog); + dialog.setVisible(true); + } + + public static void clearDialog(Activity activity) { + if (configurationDialogs.containsKey(activity)) { + ActivityConfigurationDialog currentDialog = configurationDialogs + .get(activity); + if (currentDialog.isVisible()) + currentDialog.setVisible(false); + configurationDialogs.remove(activity); + currentDialog.dispose(); + } + } + + protected static void clearDialog(JDialog dialog) { + if (configurationDialogs.containsValue(dialog)) { + if (dialog.isVisible()) + dialog.setVisible(false); + for (Activity activity : configurationDialogs.keySet()) + if (configurationDialogs.get(activity).equals(dialog)) + configurationDialogs.remove(activity); + dialog.dispose(); + } + } + + public static boolean closeDialog(Activity activity) { + boolean closeIt = true; + if (configurationDialogs.containsKey(activity)) { + ActivityConfigurationDialog currentDialog = configurationDialogs + .get(activity); + if (currentDialog.isVisible()) + closeIt = currentDialog.closeDialog(); + if (closeIt) + configurationDialogs.remove(activity); + } + return closeIt; + } + + public static ActivityConfigurationDialog getDialog(Activity activity) { + return configurationDialogs.get(activity); + } + + private static class DataflowCloseListener implements + Observer<FileManagerEvent> { + private Scufl2Tools scufl2Tools = new Scufl2Tools(); + + @Override + public void notify(Observable<FileManagerEvent> sender, + FileManagerEvent message) throws Exception { + if (message instanceof ClosingDataflowEvent) { + ClosingDataflowEvent closingDataflowEvent = (ClosingDataflowEvent) message; + if (closingDataflowEvent.isAbortClose()) + return; + closingDataflow(closingDataflowEvent, + ((ClosingDataflowEvent) message).getDataflow()); + } + } + + private void closingDataflow(ClosingDataflowEvent event, + WorkflowBundle bundle) { + Profile profile = bundle.getMainProfile(); + for (Workflow workflow : bundle.getWorkflows()) + for (Processor p : workflow.getProcessors()) { + ProcessorBinding processorBinding = scufl2Tools + .processorBindingForProcessor(p, profile); + Activity activity = processorBinding.getBoundActivity(); + if (!closeDialog(activity)) + event.setAbortClose(true); + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/actions/activity/ActivityContextualView.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/actions/activity/ActivityContextualView.java b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/actions/activity/ActivityContextualView.java new file mode 100644 index 0000000..58323d6 --- /dev/null +++ b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/actions/activity/ActivityContextualView.java @@ -0,0 +1,68 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.actions.activity; + +import org.apache.taverna.workbench.ui.views.contextualviews.ContextualView; +import org.apache.taverna.scufl2.api.activity.Activity; +import org.apache.taverna.scufl2.api.common.Scufl2Tools; +import org.apache.taverna.scufl2.api.configurations.Configuration; + +/** + * A contextual view specific to an Activity. Concrete subclasses must + * initialise the view by calling {@link #initView()}. + * <p> + * The implementation provides a view based upon the properties set in the + * Configuration + * + * @author Stuart Owen + * @author Ian Dunlop + * + * @see Activity + * @see ContextualView + */ +@SuppressWarnings("serial") +public abstract class ActivityContextualView extends ContextualView { + private Activity activity; + private Scufl2Tools scufl2Tools = new Scufl2Tools(); + + /** + * Constructs an instance of the view. + * <p> + * The constructor parameter for the implementation of this class should + * define the specific Activity type itself. + * + * @param activity + */ + protected ActivityContextualView(Activity activity) { + super(); + this.activity = activity; + } + + public Activity getActivity() { + return activity; + } + + public Configuration getConfigBean() { + return scufl2Tools.configurationFor(activity, activity.getParent()); + } + + @Override + public abstract void refreshView(); +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/actions/activity/HTMLBasedActivityContextualView.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/actions/activity/HTMLBasedActivityContextualView.java b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/actions/activity/HTMLBasedActivityContextualView.java new file mode 100644 index 0000000..1d649cf --- /dev/null +++ b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/actions/activity/HTMLBasedActivityContextualView.java @@ -0,0 +1,80 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.actions.activity; + +import static org.apache.taverna.lang.ui.HtmlUtils.buildTableOpeningTag; +import static org.apache.taverna.lang.ui.HtmlUtils.createEditorPane; +import static org.apache.taverna.lang.ui.HtmlUtils.getHtmlHead; +import static org.apache.taverna.lang.ui.HtmlUtils.panelForHtml; + +import javax.swing.JComponent; +import javax.swing.JEditorPane; + +import org.apache.taverna.workbench.configuration.colour.ColourManager; +import org.apache.taverna.scufl2.api.activity.Activity; + +@SuppressWarnings("serial") +public abstract class HTMLBasedActivityContextualView extends ActivityContextualView { + private static final String BEANSHELL_URI = "http://ns.taverna.org.uk/2010/activity/beanshell"; + private static final String LOCALWORKER_URI = "http://ns.taverna.org.uk/2010/activity/localworker"; + private JEditorPane editorPane; + private final ColourManager colourManager; + + public HTMLBasedActivityContextualView(Activity activity, ColourManager colourManager) { + super(activity); + this.colourManager = colourManager; + initView(); + } + + @Override + public JComponent getMainFrame() { + editorPane = createEditorPane(buildHtml()); + return panelForHtml(editorPane); + } + + private String buildHtml() { + StringBuilder html = new StringBuilder(getHtmlHead(getBackgroundColour())); + html.append(buildTableOpeningTag()); + html.append("<tr><th colspan=\"2\">").append(getViewTitle()).append("</th></tr>"); + html.append(getRawTableRowsHtml()).append("</table>"); + html.append("</body></html>"); + return html.toString(); + } + + protected abstract String getRawTableRowsHtml(); + + public String getBackgroundColour() { + String activityType = getActivity().getType().toString(); + if (LOCALWORKER_URI.equals(activityType)) + if (getConfigBean().getJson().get("isAltered").booleanValue()) + return (String) colourManager.getProperty(BEANSHELL_URI); + String colour = (String) colourManager.getProperty(activityType); + return colour == null ? "#ffffff" : colour; + } + + /** + * Update the html view with the latest information in the configuration + * bean + */ + @Override + public void refreshView() { + editorPane.setText(buildHtml()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/AddLayerFactorySPI.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/AddLayerFactorySPI.java b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/AddLayerFactorySPI.java new file mode 100644 index 0000000..91aad6c --- /dev/null +++ b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/AddLayerFactorySPI.java @@ -0,0 +1,42 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.views.contextualviews; + +import java.net.URI; + +import javax.swing.Action; + +import org.apache.taverna.scufl2.api.core.Processor; + +/** + * SPI for adding dispatch stack layers to a processor, such as + * {@link org.apache.taverna.workflowmodel.processor.dispatch.layers.Loop}. + * <p> + * Buttons or similar will be added in the processor contextual view. + * + * @author Stian Soiland-Reyes + */ +public interface AddLayerFactorySPI { + boolean canAddLayerFor(Processor proc); + + Action getAddLayerActionFor(Processor proc); + + boolean canCreateLayerClass(URI dispatchLayerType); +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/ContextualView.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/ContextualView.java b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/ContextualView.java new file mode 100644 index 0000000..394f2a9 --- /dev/null +++ b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/ContextualView.java @@ -0,0 +1,108 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.views.contextualviews; + +import static java.awt.BorderLayout.CENTER; + +import java.awt.BorderLayout; +import java.awt.Frame; + +import javax.swing.Action; +import javax.swing.JComponent; +import javax.swing.JPanel; + +/** + * An abstract class defining the base container to hold a contextual view over + * Dataflow element. + * <p> + * The specific implementation of this class to support a given dataflow element + * needs to implement the {@link #getMainFrame()} and {@link #getViewTitle()}. + * <p> + * If a view is associated with an action handler to configure this component, + * then the {@link #getConfigureAction(Frame) getConfigureAction} handler must + * be over-ridden. If this returns null then the configure button is left + * disabled and it is not possible to configure the element. + * + * @author Stuart Owen + * @author Ian Dunlop + * @author Alan R Williams + */ +@SuppressWarnings("serial") +public abstract class ContextualView extends JPanel { + /** + * When implemented, this method should define the main frame that is placed + * in this container, and provides a static view of the Dataflow element. + * + * @return a JComponent that represents the dataflow element. + */ + public abstract JComponent getMainFrame(); + + /** + * @return a String providing a title for the view + */ + public abstract String getViewTitle(); + + /** + * Allows the item to be configured, but returning an action handler that + * will be invoked when selecting to configure. By default this is provided + * by a button. + * <p> + * If there is no ability to configure the given item, then this should + * return null. + * + * @param owner + * the owning dialog to be used when displaying dialogues for + * configuration options + * @return an action that allows the element being viewed to be configured. + */ + public Action getConfigureAction(Frame owner) { + return null; + } + + /** + * This <i>must</i> be called by any sub-classes after they have initialised + * their own view since it gets their main panel and adds it to the main + * contextual view. If you don't do this you will get a very empty frame + * popping up! + */ + public void initView() { + setLayout(new BorderLayout()); + add(getMainFrame(), CENTER); + setName(getViewTitle()); + } + + public abstract void refreshView(); + + public abstract int getPreferredPosition(); + + public static String getTextFromDepth(String kind, Integer depth) { + String labelText = "The last prediction said the " + kind; + if (depth == null) { + labelText += " would not transmit a value"; + } else if (depth == -1) { + labelText += " was invalid/unpredicted"; + } else if (depth == 0) { + labelText += " would carry a single value"; + } else { + labelText += " would carry a list of depth " + depth; + } + return labelText; + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ActivityConfigurationDialog.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ActivityConfigurationDialog.java b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ActivityConfigurationDialog.java new file mode 100644 index 0000000..372bba5 --- /dev/null +++ b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ActivityConfigurationDialog.java @@ -0,0 +1,493 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.views.contextualviews.activity; + +import static java.awt.BorderLayout.SOUTH; +import static java.awt.Cursor.DEFAULT_CURSOR; +import static java.awt.Cursor.WAIT_CURSOR; +import static java.awt.Cursor.getPredefinedCursor; +import static java.lang.Math.max; +import static javax.swing.JOptionPane.CANCEL_OPTION; +import static javax.swing.JOptionPane.NO_OPTION; +import static javax.swing.JOptionPane.YES_NO_CANCEL_OPTION; +import static javax.swing.JOptionPane.YES_NO_OPTION; +import static javax.swing.JOptionPane.YES_OPTION; +import static javax.swing.JOptionPane.showConfirmDialog; +import static org.apache.taverna.workbench.MainWindow.getMainWindow; +import static org.apache.taverna.workbench.helper.Helper.showHelp; +import static org.apache.taverna.workbench.ui.actions.activity.ActivityConfigurationAction.clearDialog; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.swing.AbstractAction; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.border.EmptyBorder; + +import org.apache.taverna.lang.observer.Observable; +import org.apache.taverna.lang.observer.Observer; +import org.apache.taverna.lang.ui.DeselectingButton; +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.edits.EditManager.DataFlowRedoEvent; +import org.apache.taverna.workbench.edits.EditManager.DataFlowUndoEvent; +import org.apache.taverna.workbench.edits.EditManager.EditManagerEvent; +import org.apache.taverna.workbench.helper.HelpEnabledDialog; +import org.apache.taverna.workflow.edits.AddChildEdit; +import org.apache.taverna.workflow.edits.AddProcessorInputPortEdit; +import org.apache.taverna.workflow.edits.AddProcessorOutputPortEdit; +import org.apache.taverna.workflow.edits.ChangeDepthEdit; +import org.apache.taverna.workflow.edits.ChangeGranularDepthEdit; +import org.apache.taverna.workflow.edits.ChangeJsonEdit; +import org.apache.taverna.workflow.edits.RemoveChildEdit; +import org.apache.taverna.workflow.edits.RemoveProcessorInputPortEdit; +import org.apache.taverna.workflow.edits.RemoveProcessorOutputPortEdit; +import org.apache.taverna.workflow.edits.RenameEdit; + +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.port.ActivityPort; +import org.apache.taverna.scufl2.api.port.InputActivityPort; +import org.apache.taverna.scufl2.api.port.InputProcessorPort; +import org.apache.taverna.scufl2.api.port.OutputActivityPort; +import org.apache.taverna.scufl2.api.port.OutputProcessorPort; +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 ActivityConfigurationDialog extends HelpEnabledDialog { + private enum PortType { + INPUT, OUTPUT + } + + protected static Logger logger = Logger.getLogger(ActivityConfigurationDialog.class); + private static final Scufl2Tools scufl2Tools = new Scufl2Tools(); + + private final EditManager editManager; + + private Activity activity; + private ActivityConfigurationPanel panel; + protected WorkflowBundle owningWorkflowBundle; + protected Processor owningProcessor; + private Observer<EditManagerEvent> observer; + Dimension minimalSize = null; + Dimension buttonPanelSize = null; + JPanel buttonPanel; + protected JButton applyButton; + + public ActivityConfigurationDialog(Activity a, ActivityConfigurationPanel p, + EditManager editManager) { + super(getMainWindow(), "Configuring " + a.getClass().getSimpleName(), + false, null); + this.activity = a; + this.panel = p; + this.editManager = editManager; + + owningWorkflowBundle = activity.getParent().getParent(); + owningProcessor = findProcessor(a); + + setTitle(getRelativeName(owningWorkflowBundle, activity)); + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + setLayout(new BorderLayout()); + + add(panel, BorderLayout.CENTER); + + buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + buttonPanel.setBorder(new EmptyBorder(5, 20, 5, 5)); + + JButton helpButton = new DeselectingButton("Help", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + showHelp(panel); + } + }); + buttonPanel.add(helpButton); + + applyButton = new DeselectingButton("Apply", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + /* + * For the moment it always does an apply as what should be + * happening is that the apply button only becomes available + * when the configuration has changed. However, many + * configuration panels are not set up to detected changes + */ + // if (panel.isConfigurationChanged()) { + if (checkPanelValues()) + applyConfiguration(); + // } else { + // logger.info("Ignoring apply"); + // } + } + }); + buttonPanel.add(applyButton); + + JButton closeButton = new DeselectingButton("Close", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + closeDialog(); + } + }); + buttonPanel.add(closeButton); + + add(buttonPanel, SOUTH); + + this.addWindowListener(new WindowAdapter() { + @Override + public void windowOpened(WindowEvent e) { + requestFocusInWindow(); + panel.whenOpened(); + } + + @Override + public void windowClosing(WindowEvent e) { + closeDialog(); + } + }); + pack(); + minimalSize = getSize(); + setLocationRelativeTo(null); + setResizable(true); + addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + int newWidth = max(getWidth(), minimalSize.width); + int newHeight = max(getHeight(), minimalSize.height); + setSize(new Dimension(newWidth, newHeight)); + } + }); + + observer = new Observer<EditManagerEvent>() { + @Override + public void notify(Observable<EditManagerEvent> sender, EditManagerEvent message) + throws Exception { + logger.info("sender is a " + sender.getClass().getCanonicalName()); + logger.info("message is a " + message.getClass().getCanonicalName()); + Edit<?> edit = message.getEdit(); + logger.info(edit.getClass().getCanonicalName()); + considerEdit(message, edit); + } + }; + editManager.addObserver(observer); + } + + private boolean checkPanelValues() { + boolean result = false; + try { + setCursor(getPredefinedCursor(WAIT_CURSOR)); + result = panel.checkValues(); + } finally { + setCursor(getPredefinedCursor(DEFAULT_CURSOR)); + } + return result; + } + + private void considerEdit(EditManagerEvent message, Edit<?> edit) { + // boolean result = false; + if (edit instanceof CompoundEdit) { + for (Edit<?> subEdit : ((CompoundEdit) edit).getChildEdits()) + considerEdit(message, subEdit); + return; + } + + Object subject = edit.getSubject(); + if (subject == owningProcessor) { + // panel.reevaluate(); + setTitle(getRelativeName(owningWorkflowBundle, activity)); + } else if (subject == owningWorkflowBundle) { + for (Workflow workflow : owningWorkflowBundle.getWorkflows()) + if (!workflow.getProcessors().contains(owningProcessor)) + clearDialog(activity); + } else if (subject == activity) { + if (message instanceof DataFlowUndoEvent) { + logger.info("undo of activity edit found"); + panel.refreshConfiguration(); + } else if (message instanceof DataFlowRedoEvent) { + logger.info("redo of activity edit found"); + panel.refreshConfiguration(); + } + } + } + + protected void configureActivity(ObjectNode json, List<ActivityPortConfiguration> inputPorts, + List<ActivityPortConfiguration> outputPorts) { + configureActivity(owningWorkflowBundle, activity, json, inputPorts, outputPorts); + } + + public void configureActivity(WorkflowBundle workflowBundle, Activity activity, + ObjectNode json, List<ActivityPortConfiguration> inputPorts, + List<ActivityPortConfiguration> outputPorts) { + try { + List<Edit<?>> editList = new ArrayList<Edit<?>>(); + Profile profile = activity.getParent(); + List<ProcessorBinding> processorBindings = scufl2Tools + .processorBindingsToActivity(activity); + Configuration configuration = scufl2Tools.configurationFor(activity, profile); + editList.add(new ChangeJsonEdit(configuration, json)); + + configurePorts(activity, editList, processorBindings, inputPorts, PortType.INPUT); + configurePorts(activity, editList, processorBindings, outputPorts, PortType.OUTPUT); + editManager.doDataflowEdit(workflowBundle, new CompoundEdit(editList)); + } catch (IllegalStateException | EditException e) { + logger.error(e); + } + } + + private void configurePorts(Activity activity, List<Edit<?>> editList, + List<ProcessorBinding> processorBindings, + List<ActivityPortConfiguration> portDefinitions, PortType portType) { + Set<ActivityPort> ports = new HashSet<>(); + for (ActivityPort activityPort : portType == PortType.INPUT ? activity + .getInputPorts() : activity.getOutputPorts()) + ports.add(activityPort); + for (ActivityPortConfiguration portDefinition : portDefinitions) { + String portName = portDefinition.getName(); + int portDepth = portDefinition.getDepth(); + int granularPortDepth = portDefinition.getGranularDepth(); + ActivityPort activityPort = portDefinition.getActivityPort(); + if (activityPort == null) { + // no activity port so add a new one + if (portType == PortType.INPUT) + createInputPort(activity, editList, processorBindings, portDefinition); + else + createOutputPort(activity, editList, processorBindings, portDefinition); + } else { + ports.remove(activityPort); + // check if port has changed + for (ProcessorBinding processorBinding : processorBindings) + if (portType == PortType.INPUT) + for (ProcessorInputPortBinding portBinding : processorBinding + .getInputPortBindings()) { + if (!portBinding.getBoundActivityPort().equals( + activityPort)) + continue; + InputProcessorPort processorPort = portBinding + .getBoundProcessorPort(); + if (!activityPort.getName().equals(portName)) + // port name changed + if (processorPort.getName().equals(activityPort.getName())) + // default mapping so change processor port + editList.add(new RenameEdit<>(processorPort, portName)); + if (!processorPort.getDepth().equals(portDepth)) + // port depth changed + editList.add(new ChangeDepthEdit<>( + processorPort, portDepth)); + } + else + for (ProcessorOutputPortBinding portBinding : processorBinding + .getOutputPortBindings()) { + if (!portBinding.getBoundActivityPort().equals( + activityPort)) + continue; + OutputProcessorPort processorPort = portBinding + .getBoundProcessorPort(); + if (!activityPort.getName().equals(portName)) + // port name changed + if (processorPort.getName().equals( + activityPort.getName())) + // default mapping so change processor port + editList.add(new RenameEdit<>( + processorPort, portName)); + if (!processorPort.getDepth().equals(portDepth)) + // port depth changed + editList.add(new ChangeDepthEdit<>( + processorPort, portDepth)); + if (!processorPort.getGranularDepth().equals( + granularPortDepth)) + // port granular depth changed + editList.add(new ChangeGranularDepthEdit<>( + processorPort, granularPortDepth)); + } + if (!activityPort.getName().equals(portName)) + // port name changed + editList.add(new RenameEdit<>(activityPort, portName)); + if (!activityPort.getDepth().equals(portDepth)) + // port depth changed + editList.add(new ChangeDepthEdit<>(activityPort, portDepth)); + if (activityPort instanceof OutputActivityPort) { + OutputActivityPort outputActivityPort = (OutputActivityPort) activityPort; + Integer granularDepth = outputActivityPort + .getGranularDepth(); + if (granularDepth == null + || !granularDepth.equals(granularPortDepth)) + // granular port depth changed + editList.add(new ChangeGranularDepthEdit<>( + outputActivityPort, granularPortDepth)); + } + } + } + + // remove any unconfigured ports + for (ActivityPort activityPort : ports) { + // remove processor ports and bindings + for (ProcessorBinding processorBinding : processorBindings) + if (portType.equals(PortType.INPUT)) + for (ProcessorInputPortBinding portBinding : processorBinding + .getInputPortBindings()) { + if (portBinding.getBoundActivityPort().equals(activityPort)) { + editList.add(new RemoveProcessorInputPortEdit(processorBinding + .getBoundProcessor(), portBinding.getBoundProcessorPort())); + editList.add(new RemoveChildEdit<>(processorBinding, + portBinding)); + } + } + else + for (ProcessorOutputPortBinding portBinding : processorBinding + .getOutputPortBindings()) + if (portBinding.getBoundActivityPort().equals(activityPort)) { + editList.add(new RemoveProcessorOutputPortEdit(processorBinding + .getBoundProcessor(), portBinding.getBoundProcessorPort())); + editList.add(new RemoveChildEdit<>(processorBinding, + portBinding)); + } + // remove activity port + editList.add(new RemoveChildEdit<Activity>(activity, activityPort)); + } + } + + private void createInputPort(Activity activity, List<Edit<?>> editList, + List<ProcessorBinding> processorBindings, + ActivityPortConfiguration portDefinition) { + InputActivityPort actPort = new InputActivityPort(null, + portDefinition.getName()); + actPort.setDepth(portDefinition.getDepth()); + // add port to activity + editList.add(new AddChildEdit<>(activity, actPort)); + for (ProcessorBinding processorBinding : processorBindings) { + Processor processor = processorBinding.getBoundProcessor(); + // add a new processor port + InputProcessorPort procPort = new InputProcessorPort(); + procPort.setName(portDefinition.getName()); + procPort.setDepth(portDefinition.getDepth()); + editList.add(new AddProcessorInputPortEdit(processor, procPort)); + // add a new port binding + ProcessorInputPortBinding binding = new ProcessorInputPortBinding(); + binding.setBoundProcessorPort(procPort); + binding.setBoundActivityPort(actPort); + editList.add(new AddChildEdit<>(processorBinding, binding)); + } + } + + private void createOutputPort(Activity activity, List<Edit<?>> editList, + List<ProcessorBinding> processorBindings, + ActivityPortConfiguration portDefinition) { + OutputActivityPort actPort = new OutputActivityPort(null, + portDefinition.getName()); + actPort.setDepth(portDefinition.getDepth()); + actPort.setGranularDepth(portDefinition.getGranularDepth()); + // add port to activity + editList.add(new AddChildEdit<Activity>(activity, actPort)); + for (ProcessorBinding processorBinding : processorBindings) { + Processor processor = processorBinding.getBoundProcessor(); + // add a new processor port + OutputProcessorPort procPort = new OutputProcessorPort(); + procPort.setName(portDefinition.getName()); + procPort.setDepth(portDefinition.getDepth()); + procPort.setGranularDepth(portDefinition.getGranularDepth()); + editList.add(new AddProcessorOutputPortEdit(processor, procPort)); + // add a new port binding + ProcessorOutputPortBinding binding = new ProcessorOutputPortBinding(); + binding.setBoundProcessorPort(procPort); + binding.setBoundActivityPort(actPort); + editList.add(new AddChildEdit<>(processorBinding, binding)); + } + } + + protected static Processor findProcessor(Activity activity) { + for (ProcessorBinding processorBinding : scufl2Tools + .processorBindingsToActivity(activity)) + return processorBinding.getBoundProcessor(); + return null; + } + + public static String getRelativeName(WorkflowBundle workflowBundle, Activity activity) { + StringBuilder relativeName = new StringBuilder(""); + if (workflowBundle != null) { + Workflow workflow = workflowBundle.getMainWorkflow(); + if (workflow != null) { + relativeName.append(workflow.getName()); + relativeName.append(":"); + } + } + Processor processor = findProcessor(activity); + if (processor != null) + relativeName.append(processor.getName()); + return relativeName.toString(); + } + + public boolean closeDialog() { + if (panel.isConfigurationChanged()) { + String relativeName = getRelativeName(owningWorkflowBundle, activity); + if (checkPanelValues()) { + int answer = showConfirmDialog(this, + "Do you want to save the configuration of " + relativeName + "?", + relativeName, YES_NO_CANCEL_OPTION); + if (answer == YES_OPTION) { + applyConfiguration(); + } else if (answer == CANCEL_OPTION) { + return false; + } + } else if (showConfirmDialog( + this, + "New configuration could not be saved. Do you still want to close?", + relativeName, YES_NO_OPTION) == NO_OPTION) + return false; + } + panel.whenClosed(); + clearDialog(activity); + return true; + } + + private void applyConfiguration() { + panel.noteConfiguration(); + configureActivity(panel.getJson(), panel.getInputPorts(), + panel.getOutputPorts()); + panel.refreshConfiguration(); + } + + @Override + public void dispose() { + super.dispose(); + editManager.removeObserver(observer); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ActivityConfigurationPanel.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ActivityConfigurationPanel.java b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ActivityConfigurationPanel.java new file mode 100644 index 0000000..b0a6fa9 --- /dev/null +++ b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ActivityConfigurationPanel.java @@ -0,0 +1,230 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.views.contextualviews.activity; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.swing.JPanel; + +import org.apache.log4j.Logger; + +import org.apache.taverna.commons.services.ActivityTypeNotFoundException; +import org.apache.taverna.commons.services.InvalidConfigurationException; +import org.apache.taverna.commons.services.ServiceRegistry; +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.port.ActivityPort; +import org.apache.taverna.scufl2.api.port.InputActivityPort; +import org.apache.taverna.scufl2.api.port.OutputActivityPort; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * @author alanrw + */ +@SuppressWarnings("serial") +public abstract class ActivityConfigurationPanel extends JPanel { + private static final Logger logger = Logger.getLogger(ActivityConfigurationPanel.class); + private final static Scufl2Tools scufl2Tools = new Scufl2Tools(); + + // protected final URITools uriTools = new URITools(); + private final Activity activity; + private final Configuration configuration; + private final List<ActivityPortConfiguration> inputPorts; + private final List<ActivityPortConfiguration> outputPorts; + protected ObjectNode json; + + public ActivityConfigurationPanel(Activity activity) { + this(activity, scufl2Tools.configurationFor(activity, + activity.getParent())); + } + + public ActivityConfigurationPanel(Activity activity, + Configuration configuration) { + this.activity = activity; + this.configuration = configuration; + inputPorts = new ArrayList<>(); + outputPorts = new ArrayList<>(); + } + + /** + * Initializes the configuration panel. This method is also used to discard + * any changes and reset the panel to its initial state. Subclasses should + * implement this method to set up the panel and must call + * <tt>super.initialise()</tt> first. + */ + protected void initialise() { + json = configuration.getJson().deepCopy(); + inputPorts.clear(); + for (InputActivityPort activityPort : activity.getInputPorts()) + inputPorts.add(new ActivityPortConfiguration(activityPort)); + outputPorts.clear(); + for (OutputActivityPort activityPort : activity.getOutputPorts()) + outputPorts.add(new ActivityPortConfiguration(activityPort)); + } + + public abstract boolean checkValues(); + + public abstract void noteConfiguration(); + + public boolean isConfigurationChanged() { + noteConfiguration(); + if (portsChanged(inputPorts, activity.getInputPorts().size())) + return true; + if (portsChanged(outputPorts, activity.getOutputPorts().size())) + return true; + return !json.equals(configuration.getJson()); + } + + public Configuration getConfiguration() { + return configuration; + } + + public ObjectNode getJson() { + return json; + } + + protected void setJson(ObjectNode json) { + this.json = json; + } + + public void refreshConfiguration() { + initialise(); + } + + public void whenOpened() { + } + + public void whenClosed() { + } + + /** + * Convenience method for getting simple String property values. + * + * @param name + * the property name + * @return the property value + */ + protected String getProperty(String name) { + JsonNode jsonNode = json.get(name); + if (jsonNode == null) + return null; + return json.get(name).asText(); + } + + /** + * Convenience method for setting simple String property values. + * + * @param name + * the property name + * @param value + * the property value + */ + protected void setProperty(String name, String value) { + json.put(name, value); + } + + public List<ActivityPortConfiguration> getInputPorts() { + return inputPorts; + } + + public List<ActivityPortConfiguration> getOutputPorts() { + return outputPorts; + } + + protected void configureInputPorts(ServiceRegistry serviceRegistry) { + try { + Map<String, InputActivityPort> newInputPorts = new HashMap<>(); + for (InputActivityPort port : serviceRegistry + .getActivityInputPorts(getActivity().getType(), getJson())) + newInputPorts.put(port.getName(), port); + List<ActivityPortConfiguration> inputPorts = getInputPorts(); + for (ActivityPortConfiguration portConfig : new ArrayList<>( + inputPorts)) + if (newInputPorts.containsKey(portConfig.getName())) { + InputActivityPort port = newInputPorts.remove(portConfig + .getName()); + portConfig.setDepth(port.getDepth()); + } else + inputPorts.remove(portConfig); + for (InputActivityPort newPort : newInputPorts.values()) + inputPorts.add(new ActivityPortConfiguration(newPort.getName(), + newPort.getDepth())); + } catch (InvalidConfigurationException | ActivityTypeNotFoundException e) { + logger.warn("Error configuring input ports", e); + } + } + + protected void configureOutputPorts(ServiceRegistry serviceRegistry) { + try { + Map<String, OutputActivityPort> newOutputPorts = new HashMap<>(); + for (OutputActivityPort port : serviceRegistry + .getActivityOutputPorts(getActivity().getType(), getJson())) + newOutputPorts.put(port.getName(), port); + List<ActivityPortConfiguration> outputPorts = getOutputPorts(); + for (ActivityPortConfiguration portConfig : new ArrayList<>( + outputPorts)) + if (newOutputPorts.containsKey(portConfig.getName())) { + OutputActivityPort port = newOutputPorts.remove(portConfig + .getName()); + portConfig.setDepth(port.getDepth()); + portConfig.setGranularDepth(port.getGranularDepth()); + } else + outputPorts.remove(portConfig); + for (OutputActivityPort newPort : newOutputPorts.values()) + outputPorts.add(new ActivityPortConfiguration( + newPort.getName(), newPort.getDepth())); + } catch (InvalidConfigurationException | ActivityTypeNotFoundException e) { + logger.warn("Error configuring output ports", e); + } + } + + private boolean portsChanged(List<ActivityPortConfiguration> portDefinitions, int ports) { + int checkedPorts = 0; + for (ActivityPortConfiguration portDefinition : portDefinitions) { + String portName = portDefinition.getName(); + int portDepth = portDefinition.getDepth(); + ActivityPort activityPort = portDefinition.getActivityPort(); + if (activityPort == null) + // new port added + return true; + if (!activityPort.getName().equals(portName)) + // port name changed + return true; + if (!activityPort.getDepth().equals(portDepth)) + // port depth changed + return true; + checkedPorts++; + } + if (checkedPorts < ports) + // ports deleted + return true; + return false; + } + + public Activity getActivity() { + return activity; + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ActivityPortConfiguration.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ActivityPortConfiguration.java b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ActivityPortConfiguration.java new file mode 100644 index 0000000..f3ea920 --- /dev/null +++ b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ActivityPortConfiguration.java @@ -0,0 +1,83 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.views.contextualviews.activity; + +import org.apache.taverna.scufl2.api.port.ActivityPort; + +/** + * + * + * @author David Withers + */ +public class ActivityPortConfiguration { + + private ActivityPort activityPort; + + private String name; + + private int depth; + + private int granularDepth; + + public ActivityPortConfiguration(ActivityPort activityPort) { + this.activityPort = activityPort; + name = activityPort.getName(); + depth = activityPort.getDepth(); + } + + public ActivityPortConfiguration(String name, int depth) { + this(name, depth, depth); + } + + public ActivityPortConfiguration(String name, int depth, int granularDepth) { + this.name = name; + this.depth = depth; + this.granularDepth = granularDepth; + } + + public ActivityPort getActivityPort() { + return activityPort; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getDepth() { + return depth; + } + + public void setDepth(int depth) { + this.depth = depth; + } + + public int getGranularDepth() { + return granularDepth; + } + + public void setGranularDepth(int granularDepth) { + this.granularDepth = granularDepth; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ContextualViewFactory.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ContextualViewFactory.java b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ContextualViewFactory.java new file mode 100644 index 0000000..926268f --- /dev/null +++ b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ContextualViewFactory.java @@ -0,0 +1,62 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.views.contextualviews.activity; + +import java.util.List; + +import org.apache.taverna.workbench.ui.views.contextualviews.ContextualView; + +/** + * Defines a factory class that when associated with a selected object creates a + * {@link ContextualView} for that selection. + * <p> + * This factory acts as an SPI to find {@link ContextualView}s for a given + * Activity and other workflow components. + * </p> + * + * @author Stuart Owen + * @author Ian Dunlop + * @author Stian Soiland-Reyes + * + * + * @param <SelectionType> + * - the selection type this factory is associated with + * + * @see ContextualView + * @see ContextualViewFactoryRegistry + */ +public interface ContextualViewFactory<SelectionType> { + /** + * @param selection + * - the object for which ContextualViews needs to be generated + * @return instance of {@link ContextualView} + */ + public List<ContextualView> getViews(SelectionType selection); + + /** + * Used by the SPI system to find the correct factory that can handle the + * given object type. + * + * @param selection + * @return true if this factory relates to the given selection type + * @see ContextualViewFactoryRegistry + */ + public boolean canHandle(Object selection); +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ContextualViewFactoryRegistry.java ---------------------------------------------------------------------- diff --git a/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ContextualViewFactoryRegistry.java b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ContextualViewFactoryRegistry.java new file mode 100644 index 0000000..735302d --- /dev/null +++ b/taverna-contextual-views-api/src/main/java/org/apache/taverna/workbench/ui/views/contextualviews/activity/ContextualViewFactoryRegistry.java @@ -0,0 +1,42 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.views.contextualviews.activity; + +import java.util.List; + +/** + * A registry for discovering ActivityViewFactories for a given object, + * like an {@link org.apache.taverna.workflowmodel.processor.activity.Activity}. + * + * @author David Withers + */ +public interface ContextualViewFactoryRegistry { + /** + * Discover and return the ContextualViewFactory associated to the provided + * object. This is accomplished by returning the discovered + * {@link ContextualViewFactory#canHandle(Object)} that returns true for + * that Object. + * + * @param object + * @return + * @see ContextualViewFactory#canHandle(Object) + */ + public <T> List<ContextualViewFactory<? super T>> getViewFactoriesForObject(T object); +}