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

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

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/config/ServiceDescriptionConfigUIFactory.java
----------------------------------------------------------------------
diff --git a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/config/ServiceDescriptionConfigUIFactory.java b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/config/ServiceDescriptionConfigUIFactory.java
new file mode 100644
index 0000000..8746b54
--- /dev/null
+++ b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/config/ServiceDescriptionConfigUIFactory.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.servicepanel.config;
+
+import javax.swing.JPanel;
+
+import uk.org.taverna.configuration.Configurable;
+import uk.org.taverna.configuration.ConfigurationUIFactory;
+
+import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionRegistry;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionsConfiguration;
+
+public class ServiceDescriptionConfigUIFactory implements ConfigurationUIFactory {
+	private ServiceDescriptionsConfiguration serviceDescriptionsConfiguration;
+	private ServiceDescriptionRegistry serviceDescriptionRegistry;
+
+	@Override
+	public boolean canHandle(String uuid) {
+		return uuid.equals(serviceDescriptionsConfiguration.getUUID());
+	}
+
+	@Override
+	public Configurable getConfigurable() {
+		return serviceDescriptionsConfiguration;
+	}
+
+	@Override
+	public JPanel getConfigurationPanel() {
+		return new ServiceDescriptionConfigPanel(serviceDescriptionsConfiguration, serviceDescriptionRegistry);
+	}
+
+	public void setServiceDescriptionRegistry(ServiceDescriptionRegistry serviceDescriptionRegistry) {
+		this.serviceDescriptionRegistry = serviceDescriptionRegistry;
+	}
+
+	public void setServiceDescriptionsConfiguration(ServiceDescriptionsConfiguration serviceDescriptionsConfiguration) {
+		this.serviceDescriptionsConfiguration = serviceDescriptionsConfiguration;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/menu/AddServiceProviderMenu.java
----------------------------------------------------------------------
diff --git a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/menu/AddServiceProviderMenu.java b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/menu/AddServiceProviderMenu.java
new file mode 100644
index 0000000..f975778
--- /dev/null
+++ b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/menu/AddServiceProviderMenu.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.servicepanel.menu;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.JPopupMenu;
+
+import net.sf.taverna.t2.servicedescriptions.ConfigurableServiceProvider;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescription;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionRegistry;
+import net.sf.taverna.t2.workbench.ui.servicepanel.ServicePanel;
+import net.sf.taverna.t2.workbench.ui.servicepanel.actions.AddServiceProviderAction;
+
+/**
+ * A menu that provides a set up menu actions for adding new service providers
+ * to the Service Panel.
+ * <p>
+ * The Actions are discovered from the {@link ServiceDescriptionProvider}s found
+ * through the SPI.
+ *
+ * @author Stuart Owen
+ * @author Stian Soiland-Reyes
+ * @author Alan R Williams
+ *
+ * @see ServiceDescription
+ * @see ServicePanel
+ * @see ServiceDescriptionRegistry#addServiceDescriptionProvider(ServiceDescriptionProvider)
+ */
+@SuppressWarnings("serial")
+public class AddServiceProviderMenu extends JButton {
+	public static class ServiceProviderComparator implements
+			Comparator<ServiceDescriptionProvider> {
+		@Override
+		public int compare(ServiceDescriptionProvider o1,
+				ServiceDescriptionProvider o2) {
+			return o1.getName().toLowerCase().compareTo(
+					o2.getName().toLowerCase());
+		}
+	}
+
+	private final static String ADD_SERVICE_PROVIDER_MENU_NAME = "Import new services";
+
+	private final ServiceDescriptionRegistry serviceDescriptionRegistry;
+
+	public AddServiceProviderMenu(ServiceDescriptionRegistry serviceDescriptionRegistry) {
+		super();
+		this.serviceDescriptionRegistry = serviceDescriptionRegistry;
+
+		final Component c = createCustomComponent();
+		setAction(new AbstractAction(ADD_SERVICE_PROVIDER_MENU_NAME) {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				((JPopupMenu) c).show(AddServiceProviderMenu.this, 0,
+						AddServiceProviderMenu.this.getHeight());
+			}
+		});
+	}
+
+	private Component createCustomComponent() {
+		JPopupMenu addServiceMenu = new JPopupMenu(
+				ADD_SERVICE_PROVIDER_MENU_NAME);
+		addServiceMenu.setToolTipText("Add a new service provider");
+		boolean isEmpty = true;
+		List<ConfigurableServiceProvider> providers = new ArrayList<>(
+				serviceDescriptionRegistry.getUnconfiguredServiceProviders());
+		Collections.sort(providers,  new ServiceProviderComparator());
+		for (ConfigurableServiceProvider provider : providers) {
+			/*
+			 * Skip BioCatalogue's ConfigurableServiceProviderS as they should
+			 * not be used to add servcie directlry but rather though the
+			 * Service Catalogue perspective
+			 */
+			if (provider.getId().toLowerCase().contains("servicecatalogue"))
+				continue;
+
+			AddServiceProviderAction addAction = new AddServiceProviderAction(
+					provider, this);
+			addAction.setServiceDescriptionRegistry(serviceDescriptionRegistry);
+			addServiceMenu.add(addAction);
+			isEmpty = false;
+		}
+		if (isEmpty)
+			addServiceMenu.setEnabled(false);
+		return addServiceMenu;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/Filter.java
----------------------------------------------------------------------
diff --git a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/Filter.java b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/Filter.java
new file mode 100644
index 0000000..e67e8f5
--- /dev/null
+++ b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/Filter.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (C) 2007-2009 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.servicepanel.tree;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+public interface Filter {
+	boolean pass(DefaultMutableTreeNode node);
+
+	String filterRepresentation(String original);
+
+	void setSuperseded(boolean superseded);
+
+	boolean isSuperseded();
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeCellRenderer.java
----------------------------------------------------------------------
diff --git a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeCellRenderer.java b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeCellRenderer.java
new file mode 100644
index 0000000..21f43c5
--- /dev/null
+++ b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeCellRenderer.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (C) 2007-2009 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.servicepanel.tree;
+
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.folderClosedIcon;
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.folderOpenIcon;
+
+import java.awt.Component;
+
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+@SuppressWarnings("serial")
+public class FilterTreeCellRenderer extends DefaultTreeCellRenderer {
+	private Filter filter = null;
+
+	@Override
+	public Component getTreeCellRendererComponent(JTree tree, Object value,
+			boolean sel, boolean expanded, boolean leaf, int row,
+			boolean hasFocus) {
+
+		super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf,
+				row, hasFocus);
+		Filter filter = getFilter();
+		if (filter != null)
+			setText(filter.filterRepresentation(getText()));
+		if (expanded)
+			setIcon(folderOpenIcon);
+		else
+			setIcon(folderClosedIcon);
+		return this;
+	}
+
+	public Filter getFilter() {
+		return filter;
+	}
+
+	public void setFilter(Filter currentFilter) {
+		this.filter = currentFilter;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeModel.java
----------------------------------------------------------------------
diff --git a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeModel.java b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeModel.java
new file mode 100644
index 0000000..191ed66
--- /dev/null
+++ b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeModel.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (C) 2007-2009 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.servicepanel.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreePath;
+
+import org.apache.log4j.Logger;
+
+public final class FilterTreeModel extends DefaultTreeModel {
+	private static final long serialVersionUID = -8931308369832839862L;
+	private static final Logger logger = Logger
+			.getLogger(FilterTreeModel.class);
+	
+	Filter currentFilter;
+
+	public FilterTreeModel(FilterTreeNode node) {
+		this(node, null);
+	}
+	
+	public FilterTreeModel(FilterTreeNode node, Filter filter) {
+		super(node);
+		currentFilter = filter;
+		node.setFilter(filter);
+	}
+
+	public void setFilter(Filter filter) {
+		if (root != null) {
+			currentFilter = filter;
+			((FilterTreeNode) root).setFilter(filter);
+			Object[] path = { root };
+			fireTreeStructureChanged(this, path, null, null);
+		}
+	}
+
+	@Override
+	public int getChildCount(Object parent) {
+		if (parent instanceof FilterTreeNode)
+			return (((FilterTreeNode) parent).getChildCount());
+		return 0;
+	}
+
+	@Override
+	public Object getChild(Object parent, int index) {
+		if (parent instanceof FilterTreeNode)
+			return (((FilterTreeNode) parent).getChildAt(index));
+		return null;
+	}
+
+	/**
+	 * @return the currentFilter
+	 */
+	public Filter getCurrentFilter() {
+		return currentFilter;
+	}
+
+	public TreePath getTreePathForObjectPath(List<Object> path) {
+		List<FilterTreeNode> resultList = new ArrayList<>();
+		FilterTreeNode current = (FilterTreeNode) root;
+		resultList.add(current);
+		for (int i = 1; (i < path.size()) && (current != null); i++) {
+			logger.debug("Looking in " + current.getUserObject() + " for " + path.get(i));
+			current = current.getChildForObject(path.get(i));
+			if (current != null)
+				resultList.add(current);
+		}
+		if (current != null)
+			return new TreePath(resultList.toArray());
+		return null;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeNode.java
----------------------------------------------------------------------
diff --git a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeNode.java b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeNode.java
new file mode 100644
index 0000000..83fd439
--- /dev/null
+++ b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeNode.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (C) 2007-2009 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.servicepanel.tree;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+import org.apache.log4j.Logger;
+
+public class FilterTreeNode extends DefaultMutableTreeNode {
+	private static final long serialVersionUID = 1933553584349932151L;
+	@SuppressWarnings("unused")
+	private static Logger logger = Logger.getLogger(FilterTreeNode.class);
+	
+	private Filter filter;
+	private boolean passed = true;
+	private List<FilterTreeNode> filteredChildren = new ArrayList<>();
+
+	public FilterTreeNode(Object userObject) {
+		super(userObject);
+		userObject.toString();
+	}
+
+	public Filter getFilter() {
+		return filter;
+	}
+	
+	public void setFilter(Filter filter) {
+		if ((filter == null) || !filter.isSuperseded()) {
+			this.filter = filter;
+			passed = false;
+			filteredChildren.clear();
+			if (filter == null) {
+				passed = true;
+				passFilterDown(null);
+			} else if (filter.pass(this)) {
+				passed = true;
+				passFilterDown(null);
+			} else {
+				passFilterDown(filter);
+				passed = filteredChildren.size() != 0;
+			}
+		}
+	}
+
+	private void passFilterDown(Filter filter) {
+		int realChildCount = super.getChildCount();
+		for (int i = 0; i < realChildCount; i++) {
+			FilterTreeNode realChild = (FilterTreeNode) super.getChildAt(i);
+			realChild.setFilter(filter);
+			if (realChild.isPassed())
+				filteredChildren.add(realChild);
+		}
+	}
+
+	public void add(FilterTreeNode node) {
+		super.add(node);
+		node.setFilter(filter);
+		// TODO work up
+		if (node.isPassed())
+			filteredChildren.add(node);
+	}
+	
+	@Override
+	public void remove(int childIndex) {
+		if (filter != null)
+			// as child indexes might be inconsistent..
+			throw new IllegalStateException("Can't remove while the filter is active");
+		super.remove(childIndex);
+	}
+
+	@Override
+	public int getChildCount() {
+		if (filter == null)
+			return super.getChildCount();
+		return filteredChildren.size();
+	}
+
+	@Override
+	public FilterTreeNode getChildAt(int index) {
+		if (filter == null)
+			return (FilterTreeNode) super.getChildAt(index);
+		return filteredChildren.get(index);
+	}
+
+	public boolean isPassed() {
+		return passed;
+	}
+	
+	public Set<FilterTreeNode> getLeaves() {
+		Set<FilterTreeNode> result = new HashSet<>();
+		if (super.getChildCount() == 0) {
+			result.add(this);
+			return result;
+		}
+
+		for (int i = 0; i < super.getChildCount(); i++) {
+			FilterTreeNode child = (FilterTreeNode) super.getChildAt(i);
+			result.addAll(child.getLeaves());
+		}
+		return result;
+	}
+
+	public FilterTreeNode getChildForObject(Object userObject) {
+		FilterTreeNode result = null;
+		for (int i=0; (i < super.getChildCount()) && (result == null); i++) {
+			FilterTreeNode child = (FilterTreeNode) super.getChildAt(i);
+			Object nodeObject = child.getUserObject();
+//			logger.info("nodeObject is a " + nodeObject.getClass() + " - " +
+//					"userObject is a " + userObject.getClass());
+			if (nodeObject.toString().equals(userObject.toString())) {
+				result = child;
+//				logger.info(nodeObject + " is equal to " + userObject);
+//			} else {
+//				logger.info(nodeObject + " is not equal to " + userObject);
+			}
+		}
+		return result;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeSelectionModel.java
----------------------------------------------------------------------
diff --git a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeSelectionModel.java b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeSelectionModel.java
new file mode 100644
index 0000000..a5adfe9
--- /dev/null
+++ b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeSelectionModel.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.servicepanel.tree;
+
+import javax.swing.tree.DefaultTreeSelectionModel;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.TreeSelectionModel;
+
+public class FilterTreeSelectionModel extends DefaultTreeSelectionModel{
+	private static final long serialVersionUID = 3127644524735089630L;
+	
+	public FilterTreeSelectionModel(){
+		super();
+		setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+	}
+	
+	@Override
+	public void setSelectionPath(TreePath path) {
+		/*
+		 * Nothing happens here - only calls to mySetSelectionPath() will have
+		 * the effect of a node being selected.
+		 */
+	}
+	
+	public void mySetSelectionPath(TreePath path) {
+		super.setSelectionPath(path);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/MyFilter.java
----------------------------------------------------------------------
diff --git a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/MyFilter.java b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/MyFilter.java
new file mode 100644
index 0000000..8baa0eb
--- /dev/null
+++ b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/MyFilter.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (C) 2007-2009 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.servicepanel.tree;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+public class MyFilter implements Filter {
+	private static final String HTML_MATCH_END = "</font><font color=\"black\">";
+	private static final String HTML_MATCH_START = "</font><font color=\"red\">";
+	private static final String HTML_POSTFIX = "</font></html>";
+	private static final String HTML_PREFIX = "<html><font color=\"black\">";
+
+	private String filterString;
+	private boolean superseded;
+	private String filterLowerCase;
+
+	public MyFilter(String filterString) {
+		this.filterString = filterString;
+		this.filterLowerCase = filterString.toLowerCase();
+		this.superseded = false;
+	}
+
+	private boolean basicFilter(DefaultMutableTreeNode node) {
+		if (filterString.isEmpty())
+			return true;
+		return node.getUserObject().toString().toLowerCase()
+				.contains(filterLowerCase);
+	}
+
+	@Override
+	public boolean pass(DefaultMutableTreeNode node) {
+		return basicFilter(node);
+	}
+
+	@Override
+	public String filterRepresentation(String original) {
+		StringBuilder sb = new StringBuilder(HTML_PREFIX);
+		int from = 0;
+		String originalLowerCase = original.toLowerCase();
+		int index = originalLowerCase.indexOf(filterLowerCase, from);
+		while (index > -1) {
+			sb.append(original.substring(from, index));
+			sb.append(HTML_MATCH_START);
+			sb.append(original.substring(index,
+					index + filterLowerCase.length()));
+			sb.append(HTML_MATCH_END);
+			from = index + filterLowerCase.length();
+			index = originalLowerCase.indexOf(filterLowerCase, from);
+		}
+		if (from < original.length())
+			sb.append(original.substring(from, original.length()));
+		return sb.append(HTML_POSTFIX).toString();
+	}
+
+	/**
+	 * @return the superseded
+	 */
+	@Override
+	public boolean isSuperseded() {
+		return superseded;
+	}
+
+	/**
+	 * @param superseded
+	 *            the superseded to set
+	 */
+	@Override
+	public void setSuperseded(boolean superseded) {
+		this.superseded = superseded;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/TreePanel.java
----------------------------------------------------------------------
diff --git a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/TreePanel.java b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/TreePanel.java
new file mode 100644
index 0000000..46eca53
--- /dev/null
+++ b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/TreePanel.java
@@ -0,0 +1,371 @@
+/*******************************************************************************
+ * Copyright (C) 2007-2009 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.servicepanel.tree;
+
+import static java.awt.BorderLayout.CENTER;
+import static java.awt.BorderLayout.NORTH;
+import static java.awt.BorderLayout.WEST;
+import static java.awt.Color.GRAY;
+import static java.awt.GridBagConstraints.HORIZONTAL;
+import static java.awt.GridBagConstraints.NONE;
+import static javax.swing.SwingUtilities.invokeLater;
+import static net.sf.taverna.t2.lang.ui.EdgeLineBorder.TOP;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.JTree;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.event.TreeExpansionEvent;
+import javax.swing.event.TreeExpansionListener;
+import javax.swing.tree.TreeCellRenderer;
+import javax.swing.tree.TreePath;
+
+import net.sf.taverna.t2.lang.ui.EdgeLineBorder;
+
+import org.apache.log4j.Logger;
+
+@SuppressWarnings("serial")
+public abstract class TreePanel extends JPanel {
+	private static int MAX_EXPANSION = 100;
+	private static final int SEARCH_WIDTH = 15;
+	private static Logger logger = Logger.getLogger(TreePanel.class);
+
+	protected Set<List<Object>> expandedPaths = new HashSet<>();
+	protected FilterTreeModel filterTreeModel;
+	protected JTextField searchField = new JTextField(SEARCH_WIDTH);
+	protected JTree tree = new JTree();
+	protected JScrollPane treeScrollPane;
+
+	private String availableObjectsString = "";
+	private String matchingObjectsString = "";
+	private String noMatchingObjectsString = "";
+
+	private TreeExpandCollapseListener treeExpandListener = new TreeExpandCollapseListener();
+	private Object filterLock = new Object();
+
+	public TreePanel(FilterTreeModel treeModel) {
+		filterTreeModel = treeModel;
+	}
+
+	public void expandTreePaths() throws InterruptedException,
+			InvocationTargetException {
+//		Filter appliedFilter = filterTreeModel.getCurrentFilter();
+//		if (appliedFilter == null) {
+			for (int i = 0; (i < tree.getRowCount()) && (i < MAX_EXPANSION); i++)
+				tree.expandRow(i);
+//		} else {
+//			boolean rowsFinished = false;
+//			for (int i = 0; (!appliedFilter.isSuperseded()) && (!rowsFinished)
+//					&& (i < MAX_EXPANSION); i++) {
+//				TreePath tp = tree.getPathForRow(i);
+//				if (tp == null) {
+//					rowsFinished = true;
+//				} else {
+//					if (!appliedFilter.pass((DefaultMutableTreeNode) tp
+//							.getLastPathComponent())) {
+//						tree.expandRow(i);
+//					}
+//				}
+//			}
+//		}
+	}
+
+	public void expandAll(FilterTreeNode node, boolean expand) {
+        @SuppressWarnings("unused")
+		FilterTreeNode root = (FilterTreeNode) tree.getModel().getRoot();
+
+        // Traverse tree from root
+        expandAll(new TreePath(node.getPath()), expand);
+    }
+
+    @SuppressWarnings("rawtypes")
+	private void expandAll(TreePath parent, boolean expand) {
+        // Traverse children
+        FilterTreeNode node = (FilterTreeNode) parent.getLastPathComponent();
+        if (node.getChildCount() >= 0)
+            for (Enumeration e=node.children(); e.hasMoreElements(); ) {
+                FilterTreeNode n = (FilterTreeNode) e.nextElement();
+                TreePath path = parent.pathByAddingChild(n);
+                expandAll(path, expand);
+            }
+
+        // Expansion or collapse must be done bottom-up
+        if (expand)
+            tree.expandPath(parent);
+        else
+            tree.collapsePath(parent);
+    }
+
+	protected void initialize() {
+		setLayout(new BorderLayout());
+		treeScrollPane = new JScrollPane(tree);
+		tree.setModel(filterTreeModel);
+		tree.addTreeExpansionListener(treeExpandListener);
+		tree.setCellRenderer(createCellRenderer());
+		tree.setSelectionModel(new FilterTreeSelectionModel());
+
+		JPanel topPanel = new JPanel();
+		topPanel.setBorder(new CompoundBorder(new EdgeLineBorder(TOP, GRAY), new EmptyBorder(10, 5, 0, 5)));
+		topPanel.setLayout(new GridBagLayout());
+		GridBagConstraints c = new GridBagConstraints();
+
+		JLabel filterLabel = new JLabel("Filter:  ");
+		c.fill = NONE;
+		c.gridx = 0;
+		c.gridy = 0;
+		c.weightx = 0.0;
+		c.anchor = GridBagConstraints.LINE_START;
+		topPanel.add(filterLabel, c);
+
+		c.fill = HORIZONTAL;
+		c.gridx = 1;
+		c.gridy = 0;
+		c.weightx = 1.0;
+		topPanel.add(searchField, c);
+
+
+		c.fill = NONE;
+		c.gridx = 2;
+		c.gridy = 0;
+		c.weightx = 0.0;
+		final JButton clearButton = new JButton("Clear");
+		clearButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				searchField.setText("");
+				invokeLater(new RunFilter());
+				clearButton.getParent().requestFocusInWindow();// so that the button does not stay focused after it is clicked on and did its action
+			}
+		});
+		topPanel.add(clearButton, c);
+
+		c.gridx = 3;
+		c.weightx = 0.2;
+		topPanel.add(new JPanel(), c);
+
+		JPanel topExtraPanel = new JPanel(new BorderLayout());
+
+		topExtraPanel.add(topPanel, NORTH);
+
+		Component extraComponent = createExtraComponent();
+		if (extraComponent != null) {
+			JPanel extraPanel  = new JPanel();
+			extraPanel.setLayout(new BorderLayout());
+			extraPanel.add(extraComponent, WEST);
+			topExtraPanel.add(extraPanel, CENTER);
+		}
+
+		add(topExtraPanel, NORTH);
+		add(treeScrollPane, CENTER);
+
+		searchField.addKeyListener(new SearchFieldKeyAdapter());
+	}
+
+	protected Component createExtraComponent() {
+		return null;
+	}
+
+	protected TreeCellRenderer createCellRenderer() {
+		return new FilterTreeCellRenderer();
+	}
+
+	public void runFilter() throws InterruptedException,
+			InvocationTargetException {
+		/*
+		 * Special lock object, don't do a synchronized model, as the lock on
+		 * JComponent might deadlock when painting the panel - see comments at
+		 * http://www.mygrid.org.uk/dev/issues/browse/T2-1438
+		 */
+		synchronized (filterLock) {
+			tree.removeTreeExpansionListener(treeExpandListener);
+			String text = searchField.getText();
+			FilterTreeNode root = (FilterTreeNode) tree.getModel().getRoot();
+			if (text.isEmpty()) {
+				setFilter(null);
+				root.setUserObject(getAvailableObjectsString());
+				filterTreeModel.nodeChanged(root);
+				for (List<Object> tp : expandedPaths) {
+	//				for (int i = 0; i < tp.length; i++)
+	//					logger.info("Trying to expand " + tp[i]);
+					tree.expandPath(filterTreeModel.getTreePathForObjectPath(tp));
+				}
+			} else {
+				setFilter(createFilter(text));
+				root.setUserObject(root.getChildCount() > 0 ? getMatchingObjectsString()
+						: getNoMatchingObjectsString());
+				filterTreeModel.nodeChanged(root);
+				expandTreePaths();
+			}
+			tree.addTreeExpansionListener(treeExpandListener);
+		}
+	}
+
+	/**
+	 * @return the availableObjectsString
+	 */
+	public String getAvailableObjectsString() {
+		return availableObjectsString;
+	}
+
+	/**
+	 * @param availableObjectsString the availableObjectsString to set
+	 */
+	public void setAvailableObjectsString(String availableObjectsString) {
+		this.availableObjectsString = availableObjectsString;
+	}
+
+	/**
+	 * @return the matchingObjectsString
+	 */
+	public String getMatchingObjectsString() {
+		return matchingObjectsString;
+	}
+
+	/**
+	 * @param matchingObjectsString the matchingObjectsString to set
+	 */
+	public void setMatchingObjectsString(String matchingObjectsString) {
+		this.matchingObjectsString = matchingObjectsString;
+	}
+
+	/**
+	 * @return the noMatchingObjectsString
+	 */
+	public String getNoMatchingObjectsString() {
+		return noMatchingObjectsString;
+	}
+
+	/**
+	 * @param noMatchingObjectsString the noMatchingObjectsString to set
+	 */
+	public void setNoMatchingObjectsString(String noMatchingObjectsString) {
+		this.noMatchingObjectsString = noMatchingObjectsString;
+	}
+
+	public Filter createFilter(String text) {
+		return new MyFilter(text);
+	}
+
+	public void setFilter(Filter filter) {
+		if (tree.getCellRenderer() instanceof FilterTreeCellRenderer)
+			((FilterTreeCellRenderer)tree.getCellRenderer()).setFilter(filter);
+		filterTreeModel.setFilter(filter);
+	}
+
+	protected class ExpandRowRunnable implements Runnable {
+		int rowNumber;
+
+		public ExpandRowRunnable(int rowNumber) {
+			this.rowNumber = rowNumber;
+		}
+
+		@Override
+		public void run() {
+			tree.expandRow(rowNumber);
+		}
+	}
+
+	protected class RunFilter implements Runnable {
+		@Override
+		public void run() {
+			Filter oldFilter = filterTreeModel.getCurrentFilter();
+			if (oldFilter != null)
+				oldFilter.setSuperseded(true);
+			try {
+				runFilter();
+			} catch (InterruptedException e) {
+				Thread.interrupted();
+			} catch (InvocationTargetException e) {
+				logger.error("", e);
+			}
+		}
+	}
+
+	protected class SearchFieldKeyAdapter extends KeyAdapter {
+		private final Runnable runFilterRunnable;
+		Timer timer = new Timer("Search field timer", true);
+
+		private SearchFieldKeyAdapter() {
+			this.runFilterRunnable = new RunFilter();
+		}
+
+		@Override
+		public void keyReleased(KeyEvent e) {
+			timer.cancel();
+			timer = new Timer();
+			timer.schedule(new TimerTask() {
+				@Override
+				public void run() {
+					invokeLater(runFilterRunnable);
+				}
+			}, 500);
+		}
+	}
+
+	private void noteExpansions() {
+		expandedPaths.clear();
+		TreePath rootPath = new TreePath(filterTreeModel.getRoot());
+		for (Enumeration<TreePath> e = tree.getExpandedDescendants(rootPath); e.hasMoreElements();) {
+			List<Object> userObjects = new ArrayList<>();
+			Object[] expandedPath = e.nextElement().getPath();
+			for (int i = 0; i < expandedPath.length; i++) {
+				FilterTreeNode node = (FilterTreeNode) expandedPath[i];
+//				logger.info("The object in the path is a " + expandedPath[i].getClass());
+				userObjects.add(node.getUserObject());
+//				logger.info("Added " + node.getUserObject() + " to path");
+			}
+			expandedPaths.add(userObjects);
+		}
+	}
+	
+	protected class TreeExpandCollapseListener implements TreeExpansionListener {
+		@Override
+		public void treeCollapsed(TreeExpansionEvent event) {
+			noteExpansions();
+		}
+
+		@Override
+		public void treeExpanded(TreeExpansionEvent event) {
+			noteExpansions();
+		}
+	}
+}

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

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-activity-palette-ui/src/main/resources/META-INF/spring/activity-palette-ui-context-osgi.xml
----------------------------------------------------------------------
diff --git a/taverna-activity-palette-ui/src/main/resources/META-INF/spring/activity-palette-ui-context-osgi.xml b/taverna-activity-palette-ui/src/main/resources/META-INF/spring/activity-palette-ui-context-osgi.xml
new file mode 100644
index 0000000..2d96b28
--- /dev/null
+++ b/taverna-activity-palette-ui/src/main/resources/META-INF/spring/activity-palette-ui-context-osgi.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans:beans xmlns="http://www.springframework.org/schema/osgi" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:beans="http://www.springframework.org/schema/beans"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans.xsd
+                      http://www.springframework.org/schema/osgi
+                      http://www.springframework.org/schema/osgi/spring-osgi.xsd">
+
+	<service ref="ServiceDescriptionConfigUIFactory" interface="uk.org.taverna.configuration.ConfigurationUIFactory" />
+
+	<service ref="ServicePanelComponentFactory" interface="net.sf.taverna.t2.workbench.ui.zaria.UIComponentFactorySPI" />
+
+	<reference id="editManager" interface="net.sf.taverna.t2.workbench.edits.EditManager" />
+	<reference id="menuManager" interface="net.sf.taverna.t2.ui.menu.MenuManager" />
+	<reference id="selectionManager" interface="net.sf.taverna.t2.workbench.selection.SelectionManager" />
+	<reference id="serviceDescriptionRegistry" interface="net.sf.taverna.t2.servicedescriptions.ServiceDescriptionRegistry"/>
+	<reference id="serviceDescriptionsConfiguration" interface="net.sf.taverna.t2.servicedescriptions.ServiceDescriptionsConfiguration"/>
+	<reference id="serviceRegistry" interface="uk.org.taverna.commons.services.ServiceRegistry" />
+
+</beans:beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-activity-palette-ui/src/main/resources/META-INF/spring/activity-palette-ui-context.xml
----------------------------------------------------------------------
diff --git a/taverna-activity-palette-ui/src/main/resources/META-INF/spring/activity-palette-ui-context.xml b/taverna-activity-palette-ui/src/main/resources/META-INF/spring/activity-palette-ui-context.xml
new file mode 100644
index 0000000..f0a11c1
--- /dev/null
+++ b/taverna-activity-palette-ui/src/main/resources/META-INF/spring/activity-palette-ui-context.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<bean id="ServiceDescriptionConfigUIFactory"
+		class="net.sf.taverna.t2.workbench.ui.servicepanel.config.ServiceDescriptionConfigUIFactory">
+		<property name="serviceDescriptionRegistry" ref="serviceDescriptionRegistry" />
+		<property name="serviceDescriptionsConfiguration" ref="serviceDescriptionsConfiguration" />
+	</bean>
+
+	<bean id="ServicePanelComponentFactory"
+		class="net.sf.taverna.t2.workbench.ui.servicepanel.ServicePanelComponentFactory">
+		<property name="editManager" ref="editManager" />
+		<property name="menuManager" ref="menuManager" />
+		<property name="selectionManager" ref="selectionManager" />
+		<property name="serviceDescriptionRegistry" ref="serviceDescriptionRegistry" />
+		<property name="serviceRegistry" ref="serviceRegistry" />
+	</bean>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-activity-tools/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-activity-tools/pom.xml b/taverna-activity-tools/pom.xml
new file mode 100644
index 0000000..53619a4
--- /dev/null
+++ b/taverna-activity-tools/pom.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.taverna.workbench</groupId>
+		<artifactId>taverna-workbench</artifactId>
+		<version>3.1.0-incubating-SNAPSHOT</version>
+	</parent>
+	<artifactId>taverna-activity-tools</artifactId>
+	<packaging>bundle</packaging>
+	<name>Apache Taverna Activity tools</name>
+	<dependencies>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>taverna-menu-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>taverna-workbench-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.taverna.language</groupId>
+			<artifactId>taverna-scufl2-api</artifactId>
+			<version>${taverna.language.version}</version>
+		</dependency>
+	</dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-activity-tools/src/main/java/net/sf/taverna/t2/workbench/activitytools/AbstractConfigureActivityMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-activity-tools/src/main/java/net/sf/taverna/t2/workbench/activitytools/AbstractConfigureActivityMenuAction.java b/taverna-activity-tools/src/main/java/net/sf/taverna/t2/workbench/activitytools/AbstractConfigureActivityMenuAction.java
new file mode 100644
index 0000000..4744774
--- /dev/null
+++ b/taverna-activity-tools/src/main/java/net/sf/taverna/t2/workbench/activitytools/AbstractConfigureActivityMenuAction.java
@@ -0,0 +1,64 @@
+package net.sf.taverna.t2.workbench.activitytools;
+
+import static javax.swing.Action.NAME;
+
+import java.awt.Frame;
+import java.net.URI;
+
+import javax.swing.Action;
+
+import uk.org.taverna.scufl2.api.activity.Activity;
+import uk.org.taverna.scufl2.api.common.Scufl2Tools;
+import uk.org.taverna.scufl2.api.core.Processor;
+import uk.org.taverna.scufl2.api.profiles.ProcessorBinding;
+import uk.org.taverna.scufl2.api.profiles.Profile;
+import net.sf.taverna.t2.ui.menu.AbstractContextualMenuAction;
+import net.sf.taverna.t2.workbench.ui.Utils;
+
+public abstract class AbstractConfigureActivityMenuAction extends AbstractContextualMenuAction {
+	private static final URI configureSection = URI
+			.create("http://taverna.sf.net/2009/contextMenu/configure");
+
+	protected Scufl2Tools scufl2Tools = new Scufl2Tools();
+	protected final URI activityType;
+
+	public AbstractConfigureActivityMenuAction(URI activityType) {
+		super(configureSection, 50);
+		this.activityType = activityType;
+	}
+
+	@Override
+	public boolean isEnabled() {
+		return super.isEnabled() && findActivity() != null;
+	}
+
+	protected Activity findActivity() {
+		if (getContextualSelection() == null)
+			return null;
+		Object selection = getContextualSelection().getSelection();
+		if (selection instanceof Activity) {
+			Activity activity = (Activity) selection;
+			if (activity.getType().equals(activityType))
+				return activity;
+		}
+		if (selection instanceof Processor) {
+			Processor processor = (Processor) selection;
+			Profile profile = processor.getParent().getParent().getMainProfile();
+			for (ProcessorBinding processorBinding : scufl2Tools.processorBindingsForProcessor(processor, profile))
+				if (processorBinding.getBoundActivity().getType().equals(activityType))
+					return processorBinding.getBoundActivity();
+		}
+		return null;
+	}
+
+	protected Frame getParentFrame() {
+		return Utils.getParentFrame(getContextualSelection()
+				.getRelativeToComponent());
+	}
+
+	protected void addMenuDots(Action configAction) {
+		String oldName = (String) configAction.getValue(NAME);
+		if (!oldName.endsWith(".."))
+			configAction.putValue(NAME, oldName + "...");
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-configuration-api/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-configuration-api/pom.xml b/taverna-configuration-api/pom.xml
new file mode 100644
index 0000000..83ca7eb
--- /dev/null
+++ b/taverna-configuration-api/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.taverna.workbench</groupId>
+		<artifactId>taverna-workbench</artifactId>
+		<version>3.1.0-incubating-SNAPSHOT</version>
+	</parent>
+	<artifactId>taverna-configuration-ui-api</artifactId>
+	<packaging>bundle</packaging>
+	<name>Apache Taverna Configuration Management UI API</name>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.taverna.osgi</groupId>
+			<artifactId>taverna-configuration-api</artifactId>
+			<version>${taverna.osgi.version}</version>
+		</dependency>
+	</dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/colour/ColourManager.java
----------------------------------------------------------------------
diff --git a/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/colour/ColourManager.java b/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/colour/ColourManager.java
new file mode 100644
index 0000000..4d5356f
--- /dev/null
+++ b/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/colour/ColourManager.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (C) 2011 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.configuration.colour;
+
+import java.awt.Color;
+
+import uk.org.taverna.configuration.Configurable;
+
+/**
+ * @author David Withers
+ */
+public interface ColourManager extends Configurable {
+	/**
+	 * Builds a Color that has been configured and associated with the given
+	 * String (usually an object type).
+	 * 
+	 * @return the associated Color, or if nothing is associated returns
+	 *         {@link Color#WHITE}.
+	 */
+	Color getPreferredColour(String itemKey);
+
+	void setPreferredColour(String itemKey, Color colour);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/mimetype/MimeTypeManager.java
----------------------------------------------------------------------
diff --git a/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/mimetype/MimeTypeManager.java b/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/mimetype/MimeTypeManager.java
new file mode 100644
index 0000000..f0ae0d3
--- /dev/null
+++ b/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/mimetype/MimeTypeManager.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.configuration.mimetype;
+
+import java.util.Map;
+
+import uk.org.taverna.configuration.Configurable;
+
+public interface MimeTypeManager extends Configurable {
+	@Override
+	String getCategory();
+
+	@Override
+	Map<String, String> getDefaultPropertyMap();
+
+	@Override
+	String getUUID();
+
+	@Override
+	String getDisplayName();
+
+	@Override
+	String getFilePrefix();
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/workbench/WorkbenchConfiguration.java
----------------------------------------------------------------------
diff --git a/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/workbench/WorkbenchConfiguration.java b/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/workbench/WorkbenchConfiguration.java
new file mode 100644
index 0000000..461ba5c
--- /dev/null
+++ b/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/workbench/WorkbenchConfiguration.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (C) 2011 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.configuration.workbench;
+
+import uk.org.taverna.configuration.Configurable;
+
+/**
+ * @author David Withers
+ */
+public interface WorkbenchConfiguration extends Configurable {
+	boolean getCaptureConsole();
+
+	void setCaptureConsole(boolean captureConsole);
+
+	boolean getWarnInternalErrors();
+
+	void setWarnInternalErrors(boolean warnInternalErrors);
+
+	int getMaxMenuItems();
+
+	void setMaxMenuItems(int maxMenuItems);
+
+	String getDotLocation();
+
+	void setDotLocation(String dotLocation);
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/workbench/ui/T2ConfigurationFrame.java
----------------------------------------------------------------------
diff --git a/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/workbench/ui/T2ConfigurationFrame.java b/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/workbench/ui/T2ConfigurationFrame.java
new file mode 100644
index 0000000..577484f
--- /dev/null
+++ b/taverna-configuration-api/src/main/java/net/sf/taverna/t2/workbench/configuration/workbench/ui/T2ConfigurationFrame.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.configuration.workbench.ui;
+
+/**
+ * @author David Withers
+ */
+public interface T2ConfigurationFrame {
+	void showFrame();
+
+	void showConfiguration(String name);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-configuration-impl/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-configuration-impl/pom.xml b/taverna-configuration-impl/pom.xml
new file mode 100644
index 0000000..56b57df
--- /dev/null
+++ b/taverna-configuration-impl/pom.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.taverna.workbench</groupId>
+		<artifactId>taverna-workbench</artifactId>
+		<version>3.1.0-incubating-SNAPSHOT</version>
+	</parent>
+	<artifactId>taverna-configuration-ui-impl</artifactId>
+	<packaging>bundle</packaging>
+	<name>Apache Taverna Configuration Management UI Impl</name>
+	<dependencies>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>taverna-menu-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>taverna-helper-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>${project.parent.groupId}</groupId>
+			<artifactId>taverna-configuration-ui-api</artifactId>
+			<version>${project.parent.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.taverna.osgi</groupId>
+			<artifactId>taverna-configuration-api</artifactId>
+			<version>${taverna.osgi.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.taverna.osgi</groupId>
+			<artifactId>taverna-app-configuration-api</artifactId>
+			<version>${taverna.osgi.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>${junit.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.taverna.osgi</groupId>
+			<artifactId>taverna-configuration-impl</artifactId>
+			<version>${taverna.osgi.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.taverna.osgi</groupId>
+			<artifactId>taverna-app-configuration-impl</artifactId>
+			<version>${taverna.osgi.version}</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-configuration-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/configuration/WorkbenchConfigurationImpl.java
----------------------------------------------------------------------
diff --git a/taverna-configuration-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/configuration/WorkbenchConfigurationImpl.java b/taverna-configuration-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/configuration/WorkbenchConfigurationImpl.java
new file mode 100644
index 0000000..0e63a4a
--- /dev/null
+++ b/taverna-configuration-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/configuration/WorkbenchConfigurationImpl.java
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.impl.configuration;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sf.taverna.t2.workbench.configuration.workbench.WorkbenchConfiguration;
+
+import org.apache.log4j.Logger;
+
+import uk.org.taverna.configuration.AbstractConfigurable;
+import uk.org.taverna.configuration.ConfigurationManager;
+import uk.org.taverna.configuration.app.ApplicationConfiguration;
+
+/**
+ * An implementation of Configurable for general Workbench configuration
+ * properties
+ * 
+ * @author Stuart Owen
+ * @author Stian Soiland-Reyes
+ */
+public class WorkbenchConfigurationImpl extends AbstractConfigurable implements
+		WorkbenchConfiguration {
+	private static Logger logger = Logger
+			.getLogger(WorkbenchConfiguration.class);
+	private static final int DEFAULT_MAX_MENU_ITEMS = 20;
+	public static final String TAVERNA_DOTLOCATION = "taverna.dotlocation";
+	public static final String MAX_MENU_ITEMS = "taverna.maxmenuitems";
+	public static final String WARN_INTERNAL_ERRORS = "taverna.warninternal";
+	public static final String CAPTURE_CONSOLE = "taverna.captureconsole";
+	private static final String BIN = "bin";
+	private static final String BUNDLE_CONTENTS = "Contents";
+	private static final String BUNDLE_MAC_OS = "MacOS";
+	private static final String DOT_EXE = "dot.exe";
+	private static final String DOT_FALLBACK = "dot";
+	public static String uuid = "c14856f0-5967-11dd-ae16-0800200c9a66";
+	private static final String MAC_OS_X = "Mac OS X";
+	private static final String WIN32I386 = "win32i386";
+	private static final String WINDOWS = "Windows";
+
+	private ApplicationConfiguration applicationConfiguration;
+
+	/**
+	 * Constructs a new <code>WorkbenchConfigurationImpl</code>.
+	 * 
+	 * @param configurationManager
+	 */
+	public WorkbenchConfigurationImpl(ConfigurationManager configurationManager) {
+		super(configurationManager);
+	}
+
+	Map<String, String> defaultWorkbenchProperties = null;
+	Map<String, String> workbenchProperties = new HashMap<String, String>();
+
+	@Override
+	public String getCategory() {
+		return "general";
+	}
+
+	@Override
+	public Map<String, String> getDefaultPropertyMap() {
+		if (defaultWorkbenchProperties == null) {
+			defaultWorkbenchProperties = new HashMap<>();
+			String dotLocation = System.getProperty(TAVERNA_DOTLOCATION) != null ? System
+					.getProperty(TAVERNA_DOTLOCATION) : getDefaultDotLocation();
+			if (dotLocation != null)
+				defaultWorkbenchProperties
+						.put(TAVERNA_DOTLOCATION, dotLocation);
+			defaultWorkbenchProperties.put(MAX_MENU_ITEMS,
+					Integer.toString(DEFAULT_MAX_MENU_ITEMS));
+			defaultWorkbenchProperties.put(WARN_INTERNAL_ERRORS,
+					Boolean.FALSE.toString());
+			defaultWorkbenchProperties.put(CAPTURE_CONSOLE,
+					Boolean.TRUE.toString());
+		}
+		return defaultWorkbenchProperties;
+	}
+
+	@Override
+	public String getDisplayName() {
+		return "Workbench";
+	}
+
+	@Override
+	public String getFilePrefix() {
+		return "Workbench";
+	}
+
+	@Override
+	public String getUUID() {
+		return uuid;
+	}
+
+	@Override
+	public boolean getWarnInternalErrors() {
+		String property = getProperty(WARN_INTERNAL_ERRORS);
+		return Boolean.parseBoolean(property);
+	}
+
+	@Override
+	public boolean getCaptureConsole() {
+		String property = getProperty(CAPTURE_CONSOLE);
+		return Boolean.parseBoolean(property);
+	}
+
+	@Override
+	public void setWarnInternalErrors(boolean warnInternalErrors) {
+		setProperty(WARN_INTERNAL_ERRORS, Boolean.toString(warnInternalErrors));
+	}
+
+	@Override
+	public void setCaptureConsole(boolean captureConsole) {
+		setProperty(CAPTURE_CONSOLE, Boolean.toString(captureConsole));
+	}
+
+	@Override
+	public void setMaxMenuItems(int maxMenuItems) {
+		if (maxMenuItems < 2)
+			throw new IllegalArgumentException(
+					"Maximum menu items must be at least 2");
+		setProperty(MAX_MENU_ITEMS, Integer.toString(maxMenuItems));
+	}
+
+	@Override
+	public int getMaxMenuItems() {
+		String property = getProperty(MAX_MENU_ITEMS);
+		try {
+			int maxMenuItems = Integer.parseInt(property);
+			if (maxMenuItems >= 2)
+				return maxMenuItems;
+			logger.warn(MAX_MENU_ITEMS + " can't be less than 2");
+		} catch (NumberFormatException ex) {
+			logger.warn("Invalid number for " + MAX_MENU_ITEMS + ": "
+					+ property);
+		}
+		// We'll return the default instead
+		return DEFAULT_MAX_MENU_ITEMS;
+	}
+
+	@Override
+	public String getDotLocation() {
+		return getProperty(TAVERNA_DOTLOCATION);
+	}
+
+	@Override
+	public void setDotLocation(String dotLocation) {
+		setProperty(TAVERNA_DOTLOCATION, dotLocation);
+	}
+
+	private String getDefaultDotLocation() {
+		if (applicationConfiguration == null)
+			return null;
+		File startupDir = applicationConfiguration.getStartupDir();
+		if (startupDir == null)
+			return DOT_FALLBACK;
+
+		String os = System.getProperty("os.name");
+		if (os.equals(MAC_OS_X))
+			if (startupDir.getParentFile() != null) {
+				File contentsDir = startupDir.getParentFile().getParentFile();
+				if (contentsDir != null
+						&& contentsDir.getName().equalsIgnoreCase(
+								BUNDLE_CONTENTS)) {
+					File dot = new File(new File(contentsDir, BUNDLE_MAC_OS),
+							DOT_FALLBACK);
+					if (dot.exists())
+						return dot.getAbsolutePath();
+				}
+			} else if (os.startsWith(WINDOWS)) {
+				File binWin386Dir = new File(new File(startupDir, BIN),
+						WIN32I386);
+				File dot = new File(binWin386Dir, DOT_EXE);
+				if (dot.exists())
+					return dot.getAbsolutePath();
+			}
+		return DOT_FALLBACK;
+	}
+
+	/**
+	 * Sets the applicationConfiguration.
+	 * 
+	 * @param applicationConfiguration
+	 *            the new value of applicationConfiguration
+	 */
+	public void setApplicationConfiguration(
+			ApplicationConfiguration applicationConfiguration) {
+		this.applicationConfiguration = applicationConfiguration;
+		defaultWorkbenchProperties = null;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-configuration-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/configuration/WorkbenchConfigurationPanel.java
----------------------------------------------------------------------
diff --git a/taverna-configuration-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/configuration/WorkbenchConfigurationPanel.java b/taverna-configuration-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/configuration/WorkbenchConfigurationPanel.java
new file mode 100644
index 0000000..ecddc35
--- /dev/null
+++ b/taverna-configuration-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/configuration/WorkbenchConfigurationPanel.java
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.impl.configuration;
+
+import static java.awt.GridBagConstraints.*;
+import static javax.swing.JFileChooser.APPROVE_OPTION;
+import static javax.swing.JOptionPane.INFORMATION_MESSAGE;
+import static javax.swing.JOptionPane.WARNING_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static net.sf.taverna.t2.workbench.helper.Helper.showHelp;
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.openIcon;
+
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.border.EmptyBorder;
+
+import net.sf.taverna.t2.workbench.configuration.workbench.WorkbenchConfiguration;
+
+import org.apache.log4j.Logger;
+
+@SuppressWarnings("serial")
+public class WorkbenchConfigurationPanel extends JPanel {
+	private static final String RESTART_MSG = "For the new configuration to be fully applied, it is advised to restart Taverna.";
+	private static final String DOT_PATH_MSG = "Path to Graphviz executable <code>dot</code>:";
+	private static final String CONTEXT_MENU_SIZE_MSG = "Maximum number of services/ports in right-click menu:";
+	private static Logger logger = Logger
+			.getLogger(WorkbenchConfigurationUIFactory.class);
+
+	private JTextField dotLocation = new JTextField(25);
+	private JTextField menuItems = new JTextField(10);
+	private JCheckBox warnInternal = new JCheckBox("Warn on internal errors");
+	private JCheckBox captureConsole = new JCheckBox(
+			"Capture output on stdout/stderr to log file");
+
+	private final WorkbenchConfiguration workbenchConfiguration;
+
+	public WorkbenchConfigurationPanel(
+			WorkbenchConfiguration workbenchConfiguration) {
+		super();
+		this.workbenchConfiguration = workbenchConfiguration;
+		initComponents();
+	}
+
+	private static JLabel htmlLabel(String html) {
+		return new JLabel("<html><body>" + html + "</body></html>");
+	}
+
+	private void initComponents() {
+		this.setLayout(new GridBagLayout());
+		GridBagConstraints gbc = new GridBagConstraints();
+
+		// Title describing what kind of settings we are configuring here
+		JTextArea descriptionText = new JTextArea(
+				"General Workbench configuration");
+		descriptionText.setLineWrap(true);
+		descriptionText.setWrapStyleWord(true);
+		descriptionText.setEditable(false);
+		descriptionText.setFocusable(false);
+		descriptionText.setBorder(new EmptyBorder(10, 10, 10, 10));
+		gbc.anchor = WEST;
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.gridwidth = 2;
+		gbc.weightx = 1.0;
+		gbc.weighty = 0.0;
+		gbc.fill = HORIZONTAL;
+		this.add(descriptionText, gbc);
+
+		gbc.gridx = 0;
+		gbc.gridy = 1;
+		gbc.gridwidth = 2;
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.insets = new Insets(10, 5, 0, 0);
+		gbc.fill = NONE;
+		this.add(htmlLabel(DOT_PATH_MSG), gbc);
+
+		dotLocation.setText(workbenchConfiguration.getDotLocation());
+		gbc.gridy++;
+		gbc.gridwidth = 1;
+		gbc.weightx = 1.0;
+		gbc.insets = new Insets(0, 0, 0, 0);
+		gbc.fill = HORIZONTAL;
+		this.add(dotLocation, gbc);
+
+		JButton browseButton = new JButton();
+		gbc.gridx = 1;
+		gbc.weightx = 0.0;
+		gbc.fill = NONE;
+		this.add(browseButton, gbc);
+		browseButton.setAction(new AbstractAction() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				System.setProperty("com.apple.macos.use-file-dialog-packages",
+						"false");
+				JFileChooser fileChooser = new JFileChooser();
+				fileChooser.putClientProperty(
+						"JFileChooser.appBundleIsTraversable", "always");
+				fileChooser.putClientProperty(
+						"JFileChooser.packageIsTraversable", "always");
+
+				fileChooser.setDialogTitle("Browse for dot");
+
+				fileChooser.resetChoosableFileFilters();
+				fileChooser.setAcceptAllFileFilterUsed(false);
+
+				fileChooser.setMultiSelectionEnabled(false);
+
+				int returnVal = fileChooser
+						.showOpenDialog(WorkbenchConfigurationPanel.this);
+				if (returnVal == APPROVE_OPTION)
+					dotLocation.setText(fileChooser.getSelectedFile()
+							.getAbsolutePath());
+			}
+		});
+		browseButton.setIcon(openIcon);
+
+		gbc.gridx = 0;
+		gbc.gridy++;
+		gbc.gridwidth = 2;
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.insets = new Insets(10, 5, 0, 0);
+		gbc.fill = HORIZONTAL;
+		this.add(htmlLabel(CONTEXT_MENU_SIZE_MSG), gbc);
+
+		menuItems.setText(Integer.toString(workbenchConfiguration
+				.getMaxMenuItems()));
+		gbc.gridy++;
+		gbc.weightx = 1.0;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(0, 0, 0, 0);
+		gbc.fill = HORIZONTAL;
+		this.add(menuItems, gbc);
+
+		gbc.gridx = 0;
+		gbc.gridy++;
+		gbc.gridwidth = 2;
+		gbc.weightx = 1.0;
+		gbc.fill = HORIZONTAL;
+		gbc.insets = new Insets(10, 0, 0, 0);
+		warnInternal
+				.setSelected(workbenchConfiguration.getWarnInternalErrors());
+		this.add(warnInternal, gbc);
+
+		gbc.gridy++;
+		gbc.insets = new Insets(0, 0, 10, 0);
+		captureConsole.setSelected(workbenchConfiguration.getCaptureConsole());
+		this.add(captureConsole, gbc);
+
+		// Add the buttons panel
+		gbc.gridx = 0;
+		gbc.gridy++;
+		gbc.gridwidth = 3;
+		gbc.weightx = 1.0;
+		gbc.weighty = 1.0;
+		gbc.fill = BOTH;
+		gbc.anchor = SOUTH;
+		this.add(getButtonsPanel(), gbc);
+	}
+
+	private Component getButtonsPanel() {
+		final JPanel panel = new JPanel();
+		panel.setLayout(new FlowLayout(FlowLayout.CENTER));
+
+		/**
+		 * The helpButton shows help about the current component
+		 */
+		JButton helpButton = new JButton(new AbstractAction("Help") {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				showHelp(panel);
+			}
+		});
+		panel.add(helpButton);
+
+		/**
+		 * The resetButton changes the property values shown to those
+		 * corresponding to the configuration currently applied.
+		 */
+		JButton resetButton = new JButton(new AbstractAction("Reset") {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				resetFields();
+			}
+		});
+		panel.add(resetButton);
+
+		JButton applyButton = new JButton(new AbstractAction("Apply") {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				String menus = menuItems.getText();
+				try {
+					workbenchConfiguration.setMaxMenuItems(Integer
+							.valueOf(menus));
+				} catch (IllegalArgumentException e) {
+					String message = "Invalid menu items number " + menus
+							+ ":\n" + e.getLocalizedMessage();
+					showMessageDialog(panel, message, "Invalid menu items",
+							WARNING_MESSAGE);
+					return;
+				}
+
+				workbenchConfiguration.setCaptureConsole(captureConsole
+						.isSelected());
+				workbenchConfiguration.setWarnInternalErrors(warnInternal
+						.isSelected());
+				workbenchConfiguration.setDotLocation(dotLocation.getText());
+				try {
+					showMessageDialog(panel, RESTART_MSG, "Restart adviced",
+							INFORMATION_MESSAGE);
+				} catch (Exception e) {
+					logger.error("Error storing updated configuration", e);
+				}
+			}
+		});
+		panel.add(applyButton);
+		return panel;
+	}
+
+	/**
+	 * Resets the shown field values to those currently set (last saved) in the
+	 * configuration.
+	 * 
+	 * @param configurable
+	 */
+	private void resetFields() {
+		menuItems.setText(Integer.toString(workbenchConfiguration
+				.getMaxMenuItems()));
+		dotLocation.setText(workbenchConfiguration.getDotLocation());
+		warnInternal
+				.setSelected(workbenchConfiguration.getWarnInternalErrors());
+		captureConsole.setSelected(workbenchConfiguration.getCaptureConsole());
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52fd79dd/taverna-configuration-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/configuration/WorkbenchConfigurationUIFactory.java
----------------------------------------------------------------------
diff --git a/taverna-configuration-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/configuration/WorkbenchConfigurationUIFactory.java b/taverna-configuration-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/configuration/WorkbenchConfigurationUIFactory.java
new file mode 100644
index 0000000..263233f
--- /dev/null
+++ b/taverna-configuration-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/configuration/WorkbenchConfigurationUIFactory.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.impl.configuration;
+
+import javax.swing.JPanel;
+
+import uk.org.taverna.configuration.Configurable;
+import uk.org.taverna.configuration.ConfigurationUIFactory;
+
+import net.sf.taverna.t2.workbench.configuration.workbench.WorkbenchConfiguration;
+
+public class WorkbenchConfigurationUIFactory implements ConfigurationUIFactory {
+	private WorkbenchConfiguration workbenchConfiguration;
+
+	@Override
+	public boolean canHandle(String uuid) {
+		return uuid.equals(workbenchConfiguration.getUUID());
+	}
+
+	@Override
+	public JPanel getConfigurationPanel() {
+		return new WorkbenchConfigurationPanel(workbenchConfiguration);
+	}
+
+	@Override
+	public Configurable getConfigurable() {
+		return workbenchConfiguration;
+	}
+
+	public void setWorkbenchConfiguration(
+			WorkbenchConfiguration workbenchConfiguration) {
+		this.workbenchConfiguration = workbenchConfiguration;
+	}
+}