http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/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
deleted file mode 100644
index 8746b54..0000000
--- 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/config/ServiceDescriptionConfigUIFactory.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*******************************************************************************
- * 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/a9a52bd5/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
deleted file mode 100644
index f975778..0000000
--- 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/menu/AddServiceProviderMenu.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*******************************************************************************
- * 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/a9a52bd5/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
deleted file mode 100644
index e67e8f5..0000000
--- 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/Filter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*******************************************************************************
- * 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/a9a52bd5/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
deleted file mode 100644
index 21f43c5..0000000
--- 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeCellRenderer.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*******************************************************************************
- * 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/a9a52bd5/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
deleted file mode 100644
index 191ed66..0000000
--- 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeModel.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*******************************************************************************
- * 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/a9a52bd5/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
deleted file mode 100644
index 83fd439..0000000
--- 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeNode.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*******************************************************************************
- * 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/a9a52bd5/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
deleted file mode 100644
index a5adfe9..0000000
--- 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/FilterTreeSelectionModel.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- * 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/a9a52bd5/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
deleted file mode 100644
index 8baa0eb..0000000
--- 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/MyFilter.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*******************************************************************************
- * 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/a9a52bd5/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
deleted file mode 100644
index 46eca53..0000000
--- 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/tree/TreePanel.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*******************************************************************************
- * 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/a9a52bd5/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/PathElementFilterTreeNode.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/PathElementFilterTreeNode.java
 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/PathElementFilterTreeNode.java
new file mode 100644
index 0000000..8a4a247
--- /dev/null
+++ 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/PathElementFilterTreeNode.java
@@ -0,0 +1,33 @@
+/*
+* 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.servicepanel;
+
+import org.apache.taverna.workbench.ui.servicepanel.tree.FilterTreeNode;
+
+/**
+ * @author alanrw
+ */
+public class PathElementFilterTreeNode extends FilterTreeNode {
+       private static final long serialVersionUID = 6491242031931630314L;
+
+       public PathElementFilterTreeNode(String userObject) {
+               super(userObject);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/RootFilterTreeNode.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/RootFilterTreeNode.java
 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/RootFilterTreeNode.java
new file mode 100644
index 0000000..8ae210e
--- /dev/null
+++ 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/RootFilterTreeNode.java
@@ -0,0 +1,33 @@
+/*
+* 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.servicepanel;
+
+import org.apache.taverna.workbench.ui.servicepanel.tree.FilterTreeNode;
+
+/**
+ * @author alanrw
+ */
+public class RootFilterTreeNode extends FilterTreeNode {
+       private static final long serialVersionUID = 1047743498806473971L;
+
+       public RootFilterTreeNode(String userObject) {
+               super(userObject);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceFilter.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceFilter.java
 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceFilter.java
new file mode 100644
index 0000000..c4dd75a
--- /dev/null
+++ 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceFilter.java
@@ -0,0 +1,157 @@
+/*
+* 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.servicepanel;
+
+import static java.beans.Introspector.getBeanInfo;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+import org.apache.taverna.servicedescriptions.ServiceDescription;
+import org.apache.taverna.workbench.ui.servicepanel.tree.Filter;
+
+import org.apache.log4j.Logger;
+
+public class ServiceFilter implements Filter {
+       private static Logger logger = Logger.getLogger(ServiceFilter.class);
+
+       private String filterString;
+       private boolean superseded;
+       private String[] filterLowerCaseSplit;
+       private final Object rootToIgnore;
+
+       public ServiceFilter(String filterString, Object rootToIgnore) {
+               this.filterString = filterString;
+               this.rootToIgnore = rootToIgnore;
+               this.filterLowerCaseSplit = filterString.toLowerCase().split(" 
");
+               this.superseded = false;
+       }
+
+       private boolean basicFilter(DefaultMutableTreeNode node) {
+               if (node == rootToIgnore)
+                       return false;
+               if (filterString.isEmpty())
+                       return true;
+
+               if (node.getUserObject() instanceof ServiceDescription) {
+                       ServiceDescription serviceDescription = 
(ServiceDescription) node
+                                       .getUserObject();
+                       for (String searchTerm : filterLowerCaseSplit) {
+                               if (superseded)
+                                       return false;
+                               String[] typeSplit = searchTerm.split(":", 2);
+                               String type;
+                               String keyword;
+                               if (typeSplit.length == 2) {
+                                       type = typeSplit[0];
+                                       keyword = typeSplit[1].toLowerCase();
+                               } else {
+                                       type = null;
+                                       keyword = searchTerm.toLowerCase();
+                               }
+                               try {
+                                       if 
(!doesPropertySatisfy(serviceDescription, type, keyword))
+                                               return false;
+                               } catch (IntrospectionException | 
IllegalArgumentException
+                                               | IllegalAccessException | 
InvocationTargetException e) {
+                                       logger.error(
+                                                       "failed to get 
properties of service description",
+                                                       e);
+                                       return false;
+                               }
+                       }
+                       return true;
+               }
+               for (String searchString : filterLowerCaseSplit)
+                       if 
(!node.getUserObject().toString().toLowerCase().contains(
+                                       searchString))
+                               return false;
+               return true;
+       }
+
+       /**
+        * Determine whether a service description satisfies a search term.
+        * 
+        * @param serviceDescription
+        *            The service description bean to look in.
+        * @param type
+        *            The name of the property to look in, or <tt>null</tt> to
+        *            search in all public non-expert properties.
+        * @param searchTerm
+        *            The string to search for.
+        * @return <tt>true</tt> if-and-only-if the description matches.
+        */
+       private boolean doesPropertySatisfy(ServiceDescription 
serviceDescription,
+                       String type, String searchTerm) throws 
IllegalAccessException,
+                       IllegalArgumentException, InvocationTargetException,
+                       IntrospectionException {
+               BeanInfo beanInfo = getBeanInfo(serviceDescription.getClass());
+               for (PropertyDescriptor property : 
beanInfo.getPropertyDescriptors()) {
+                       if (superseded)
+                               return false;
+                       if ((type == null && !property.isHidden() && 
!property.isExpert())
+                                       || 
property.getName().equalsIgnoreCase(type)) {
+                               Method readMethod = property.getReadMethod();
+                               if (readMethod == null)
+                                       continue;
+                               Object readProperty = 
readMethod.invoke(serviceDescription,
+                                               new Object[0]);
+                               if (readProperty == null)
+                                       continue;
+                               if 
(readProperty.toString().toLowerCase().contains(searchTerm))
+                                       return true;
+                               // Dig deeper?
+                       }
+               }
+               return false;
+       }
+
+       @Override
+       public boolean pass(DefaultMutableTreeNode node) {
+               return basicFilter(node);
+       }
+
+       @Override
+       public String filterRepresentation(String original) {
+               return original;
+       }
+
+       /**
+        * @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/a9a52bd5/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceFilterTreeNode.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceFilterTreeNode.java
 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceFilterTreeNode.java
new file mode 100644
index 0000000..ef7811e
--- /dev/null
+++ 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceFilterTreeNode.java
@@ -0,0 +1,39 @@
+/*
+* 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.servicepanel;
+
+import org.apache.taverna.servicedescriptions.ServiceDescription;
+import org.apache.taverna.workbench.ui.servicepanel.tree.FilterTreeNode;
+
+/**
+ * @author alanrw
+ */
+public class ServiceFilterTreeNode extends FilterTreeNode {
+       private static final long serialVersionUID = 6066698619971305454L;
+       
+       public ServiceFilterTreeNode(ServiceDescription userObject) {
+               super(userObject);
+       }
+
+       @Override
+       public ServiceDescription getUserObject() {
+               return (ServiceDescription) super.getUserObject();
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServicePanel.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServicePanel.java
 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServicePanel.java
new file mode 100644
index 0000000..e95869f
--- /dev/null
+++ 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServicePanel.java
@@ -0,0 +1,410 @@
+/*
+* 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.servicepanel;
+
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static javax.swing.SwingUtilities.invokeLater;
+import static 
org.apache.taverna.servicedescriptions.ServiceDescription.LOCAL_SERVICES;
+import static 
org.apache.taverna.servicedescriptions.ServiceDescription.SERVICE_TEMPLATES;
+
+import java.awt.BorderLayout;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+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.ServiceDescriptionProvider;
+import org.apache.taverna.servicedescriptions.ServiceDescriptionRegistry;
+import org.apache.taverna.servicedescriptions.events.AbstractProviderEvent;
+import 
org.apache.taverna.servicedescriptions.events.AbstractProviderNotification;
+import 
org.apache.taverna.servicedescriptions.events.PartialServiceDescriptionsNotification;
+import org.apache.taverna.servicedescriptions.events.ProviderErrorNotification;
+import org.apache.taverna.servicedescriptions.events.RemovedProviderEvent;
+import 
org.apache.taverna.servicedescriptions.events.ServiceDescriptionProvidedEvent;
+import 
org.apache.taverna.servicedescriptions.events.ServiceDescriptionRegistryEvent;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.ui.servicepanel.tree.FilterTreeModel;
+import org.apache.taverna.workbench.ui.servicepanel.tree.FilterTreeNode;
+import org.apache.taverna.workbench.ui.zaria.UIComponentSPI;
+
+import org.apache.log4j.Logger;
+
+import org.apache.taverna.commons.services.ServiceRegistry;
+
+/**
+ * A panel of available services
+ *
+ * @author Stian Soiland-Reyes
+ */
+@SuppressWarnings("serial")
+public class ServicePanel extends JPanel implements UIComponentSPI {
+       private static Logger logger = Logger.getLogger(ServicePanel.class);
+       private static final int INITIAL_BLANK_OUT_COUNTER = 2;
+       public static final String AVAILABLE_SERVICES = "Available services";
+       public static final String MATCHING_SERVIES = "Matching services";
+       public static final String NO_MATCHING_SERVICES = "No matching 
services";
+       public static final String MOBY_OBJECTS = "MOBY Objects";
+       /**
+        * A Comparable constant to be used with buildPathMap
+        */
+       private static final String SERVICES = 
"4DA84170-7746-4817-8C2E-E29AF8B2984D";
+       private static final int STATUS_LINE_MESSAGE_MS = 600;
+       private static ServicePathElementComparator 
servicePathElementComparator = new ServicePathElementComparator();
+
+       public int blankOutCounter = 0;
+       private TreeUpdaterThread updaterThread;
+       private RootFilterTreeNode root = new 
RootFilterTreeNode(AVAILABLE_SERVICES);
+       private ServiceTreePanel serviceTreePanel;
+       private JLabel statusLine;
+       private FilterTreeModel treeModel;
+       protected Timer statusUpdateTimer;
+
+       private final ServiceDescriptionRegistry serviceDescriptionRegistry;
+       protected final ServiceDescriptionRegistryObserver 
serviceDescriptionRegistryObserver = new ServiceDescriptionRegistryObserver();
+       protected final Object updateLock = new Object();
+       private final EditManager editManager;
+       private final MenuManager menuManager;
+       private final SelectionManager selectionManager;
+       private final ServiceRegistry serviceRegistry;
+
+       public ServicePanel(ServiceDescriptionRegistry 
serviceDescriptionRegistry,
+                       EditManager editManager, MenuManager menuManager,
+                       SelectionManager selectionManager, ServiceRegistry 
serviceRegistry) {
+               this.serviceDescriptionRegistry = serviceDescriptionRegistry;
+               this.editManager = editManager;
+               this.menuManager = menuManager;
+               this.selectionManager = selectionManager;
+               this.serviceRegistry = serviceRegistry;
+               
serviceDescriptionRegistry.addObserver(serviceDescriptionRegistryObserver);
+               initialise();
+       }
+
+       @Override
+       public ImageIcon getIcon() {
+               return null;
+       }
+
+       @Override
+       public String getName() {
+               return "Service panel";
+       }
+
+       @Override
+       public void onDisplay() {
+       }
+
+       @Override
+       public void onDispose() {
+       }
+
+       public void providerStatus(ServiceDescriptionProvider provider, String 
message) {
+               logger.info(message + " " + provider);
+               final String htmlMessage = "<small>" + message + " [" + 
provider + "]</small>";
+
+               invokeLater(new Runnable() {
+                       @Override
+                       public void run() {
+                               blankOutCounter = INITIAL_BLANK_OUT_COUNTER;
+                               statusLine.setText("<html>" + htmlMessage + 
"</html>");
+                               statusLine.setVisible(true);
+                       }
+               });
+       }
+
+       protected void initialise() {
+               removeAll();
+               setLayout(new BorderLayout());
+               treeModel = new FilterTreeModel(root);
+               serviceTreePanel = new ServiceTreePanel(treeModel, 
serviceDescriptionRegistry, editManager, menuManager, selectionManager, 
serviceRegistry);
+               serviceTreePanel.setAvailableObjectsString(AVAILABLE_SERVICES);
+               serviceTreePanel.setMatchingObjectsString(MATCHING_SERVIES);
+               
serviceTreePanel.setNoMatchingObjectsString(NO_MATCHING_SERVICES);
+               add(serviceTreePanel);
+               statusLine = new JLabel();
+               add(statusLine, BorderLayout.SOUTH);
+               if (statusUpdateTimer != null)
+                       statusUpdateTimer.cancel();
+               statusUpdateTimer = new Timer("Clear status line", true);
+               statusUpdateTimer
+                               .scheduleAtFixedRate(new 
UpdateStatusLineTask(), 0, STATUS_LINE_MESSAGE_MS);
+               updateTree();
+       }
+
+       protected void updateTree() {
+               synchronized (updateLock) {
+                       if (updaterThread != null && updaterThread.isAlive()) {
+                               return;
+                       }
+                       updaterThread = new TreeUpdaterThread();
+                       updaterThread.start();
+               }
+       }
+
+       protected static class ServicePathElementComparator implements 
Comparator<Object> {
+               @Override
+               public int compare(Object o1, Object o2) {
+                       if ((o1 instanceof String) && (o2 instanceof String)) {
+                               if (o1.equals(SERVICE_TEMPLATES))
+                                       return -1;
+                               else if (o2.equals(SERVICE_TEMPLATES))
+                                       return 1;
+                               if (o1.equals(LOCAL_SERVICES))
+                                       return -1;
+                               else if (o2.equals(LOCAL_SERVICES))
+                                       return 1;
+                               if (o1.equals(MOBY_OBJECTS))
+                                       return -1;
+                               else if (o2.equals(MOBY_OBJECTS))
+                                       return 1;
+                       }
+                       return o1.toString().compareToIgnoreCase(o2.toString());
+               }
+       }
+
+       @SuppressWarnings({ "rawtypes", "unchecked" })
+       //FIXME this class is type-disastrous! Really bad.
+       public class TreeUpdaterThread extends Thread {
+               private boolean aborting = false;
+
+               private TreeUpdaterThread() {
+                       super("Updating service panel");
+                       setDaemon(true);
+               }
+
+               public void abort() {
+                       aborting = true;
+                       interrupt();
+               }
+
+               @Override
+               public void run() {
+                       Map<Comparable, Map> pathMap = buildPathMap();
+                       populateChildren(root, pathMap);
+                       invokeLater(new Runnable() {
+                               @Override
+                               public void run() {
+                                       try {
+                                               serviceTreePanel.runFilter();
+                                       } catch (InterruptedException | 
InvocationTargetException e) {
+                                               logger.error("failed to 
filter", e);
+                                       }
+                               }
+                       });
+               }
+
+               protected Map<Comparable, Map> buildPathMap() {
+                       Map<Comparable, Map> paths = new TreeMap<>();
+                       for (ServiceDescription serviceDescription : 
serviceDescriptionRegistry
+                                       .getServiceDescriptions()) {
+                               if (aborting)
+                                       return paths;
+                               Map currentPath = paths;
+                               for (Object pathElem : 
serviceDescription.getPath()) {
+                                       Map pathEntry = (Map) 
currentPath.get(pathElem);
+                                       if (pathEntry == null) {
+                                               pathEntry = new TreeMap();
+                                               currentPath.put(pathElem, 
pathEntry);
+                                       }
+                                       currentPath = pathEntry;
+                               }
+                               TreeMap<String, Set<ServiceDescription>> 
services = (TreeMap) currentPath
+                                               .get(SERVICES);
+                               if (services == null) {
+                                       services = new TreeMap<>();
+                                       currentPath.put(SERVICES, services);
+                               }
+                               String serviceDescriptionName = 
serviceDescription.getName();
+                               if 
(!services.containsKey(serviceDescriptionName)) {
+                                       Set<ServiceDescription> serviceSet = 
new HashSet<>();
+                                       services.put(serviceDescriptionName, 
serviceSet);
+                               }
+                               
services.get(serviceDescriptionName).add(serviceDescription);
+                       }
+                       return paths;
+               }
+
+               protected void populateChildren(FilterTreeNode node, Map 
pathMap) {
+                       if (aborting)
+                               return;
+                       if (node == root) {
+                               // Clear top root
+                               invokeLater(new Runnable() {
+                                       @Override
+                                       public void run() {
+                                               if (aborting)
+                                                       return;
+                                               
serviceTreePanel.setFilter(null);
+                                               root.removeAllChildren();
+                                       }
+                               });
+                       }
+
+                       Set<Comparable> paths = new 
TreeSet<>(servicePathElementComparator);
+                       Map<String, Set<ServiceDescription>> services = (Map) 
pathMap
+                                       .get(SERVICES);
+                       if (services == null)
+                               services = new TreeMap<>();
+                       paths.addAll(pathMap.keySet());
+                       paths.addAll(services.keySet());
+
+                       for (Comparable pathElement : paths) {
+                               if (aborting)
+                                       return;
+                               if (pathElement.equals(SERVICES))
+                                       continue;
+                               Set<FilterTreeNode> childNodes = new 
HashSet<>();
+                               if (services.containsKey(pathElement)) {
+                                       for (ServiceDescription sd : 
services.get(pathElement))
+                                               childNodes.add(new 
ServiceFilterTreeNode(sd));
+                               } else
+                                       childNodes.add(new 
PathElementFilterTreeNode((String) pathElement));
+                               invokeLater(new AddNodeRunnable(node, 
childNodes));
+                               if ((pathMap.containsKey(pathElement)) && 
!childNodes.isEmpty())
+                                       
populateChildren(childNodes.iterator().next(), (Map) pathMap.get(pathElement));
+                       }
+                       // if (!services.isEmpty()) {
+                       // Collections.sort(services, serviceComparator);
+                       // for (String serviceName : services.keySet()) {
+                       // if (aborting) {
+                       // return;
+                       // }
+                       // if (pathMap.containsKey(serviceName)) {
+                       // continue;
+                       // }
+                       // SwingUtilities.invokeLater(new AddNodeRunnable(node,
+                       // new 
ServiceFilterTreeNode(services.get(serviceName))));
+                       // }
+                       // }
+               }
+
+               public class AddNodeRunnable implements Runnable {
+                       private final Set<FilterTreeNode> nodes;
+                       private final FilterTreeNode root;
+
+                       public AddNodeRunnable(FilterTreeNode root, 
Set<FilterTreeNode> nodes) {
+                               this.root = root;
+                               this.nodes = nodes;
+                       }
+
+                       @Override
+                       public void run() {
+                               if (aborting)
+                                       return;
+                               for (FilterTreeNode n : nodes)
+                                       root.add(n);
+                       }
+               }
+       }
+
+       public static class RemoveNodeRunnable implements Runnable {
+               private final FilterTreeNode root;
+
+               public RemoveNodeRunnable(FilterTreeNode root) {
+                       this.root = root;
+               }
+
+               @Override
+               public void run() {
+                       root.removeFromParent();
+               }
+       }
+
+       private final class ServiceDescriptionRegistryObserver implements
+                       Observer<ServiceDescriptionRegistryEvent> {
+               Set<ServiceDescriptionProvider> alreadyComplainedAbout = new 
HashSet<>();
+
+               @Override
+               public void notify(Observable<ServiceDescriptionRegistryEvent> 
sender,
+                               ServiceDescriptionRegistryEvent message) throws 
Exception {
+                       if (message instanceof ProviderErrorNotification)
+                               
reportServiceProviderError((ProviderErrorNotification) message);
+                       else if (message instanceof 
ServiceDescriptionProvidedEvent
+                                       || message instanceof 
RemovedProviderEvent) {
+                               AbstractProviderEvent ape = 
(AbstractProviderEvent) message;
+                               
alreadyComplainedAbout.remove(ape.getProvider());
+                       }
+
+                       if (message instanceof AbstractProviderNotification) {
+                               AbstractProviderNotification 
abstractProviderNotification = (AbstractProviderNotification) message;
+                               
providerStatus(abstractProviderNotification.getProvider(),
+                                               
abstractProviderNotification.getMessage());
+                       }
+                       if (message instanceof 
PartialServiceDescriptionsNotification)
+                               /*
+                                * TODO: Support other events and only update 
relevant parts of
+                                * tree, or at least select the recently added 
provider
+                                */
+                               updateTree();
+                       else if (message instanceof RemovedProviderEvent)
+                               updateTree();
+               }
+
+               private void reportServiceProviderError(
+                               final ProviderErrorNotification pen) {
+                       ServiceDescriptionProvider provider = pen.getProvider();
+                       if (serviceDescriptionRegistry
+                                       
.getDefaultServiceDescriptionProviders().contains(provider))
+                               return;
+                       if (alreadyComplainedAbout.contains(provider))
+                               return;
+
+                       alreadyComplainedAbout.add(provider);
+                       invokeLater(new Runnable() {
+                               @Override
+                               public void run() {
+                                       showMessageDialog(ServicePanel.this, 
pen.getMessage()
+                                                       + "\n" + 
pen.getProvider(), "Import service error",
+                                                       ERROR_MESSAGE);
+                               }
+                       });
+               }
+       }
+
+       private final class UpdateStatusLineTask extends TimerTask {
+               @Override
+               public void run() {
+                       if (blankOutCounter < 0 || blankOutCounter-- > 0)
+                               // Only clear it once
+                               return;
+                       invokeLater(new Runnable() {
+                               @Override
+                               public void run() {
+                                       if (blankOutCounter < 0)
+                                               statusLine.setVisible(false);
+                               }
+                       });
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServicePanelComponentFactory.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServicePanelComponentFactory.java
 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServicePanelComponentFactory.java
new file mode 100644
index 0000000..1bd92a5
--- /dev/null
+++ 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServicePanelComponentFactory.java
@@ -0,0 +1,81 @@
+/*
+* 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.servicepanel;
+
+import javax.swing.ImageIcon;
+
+import org.apache.taverna.commons.services.ServiceRegistry;
+
+import org.apache.taverna.servicedescriptions.ServiceDescriptionRegistry;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.ui.zaria.UIComponentFactorySPI;
+import org.apache.taverna.workbench.ui.zaria.UIComponentSPI;
+
+/**
+ * Service panel factory
+ * 
+ * @author Stian Soiland-Reyes
+ */
+public class ServicePanelComponentFactory implements UIComponentFactorySPI {
+       private ServiceDescriptionRegistry serviceDescriptionRegistry;
+       private EditManager editManager;
+       private MenuManager menuManager;
+       private SelectionManager selectionManager;
+       private ServiceRegistry serviceRegistry;
+
+       @Override
+       public UIComponentSPI getComponent() {
+               return new ServicePanel(serviceDescriptionRegistry, editManager,
+                               menuManager, selectionManager, serviceRegistry);
+       }
+
+       @Override
+       public ImageIcon getIcon() {
+               return null;
+       }
+
+       @Override
+       public String getName() {
+               return "Service panel";
+       }
+
+       public void setServiceDescriptionRegistry(
+                       ServiceDescriptionRegistry serviceDescriptionRegistry) {
+               this.serviceDescriptionRegistry = serviceDescriptionRegistry;
+       }
+
+       public void setEditManager(EditManager editManager) {
+               this.editManager = editManager;
+       }
+
+       public void setMenuManager(MenuManager menuManager) {
+               this.menuManager = menuManager;
+       }
+
+       public void setSelectionManager(SelectionManager selectionManager) {
+               this.selectionManager = selectionManager;
+       }
+
+       public void setServiceRegistry(ServiceRegistry serviceRegistry) {
+               this.serviceRegistry = serviceRegistry;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceTreeCellRenderer.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceTreeCellRenderer.java
 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceTreeCellRenderer.java
new file mode 100644
index 0000000..e5f65a9
--- /dev/null
+++ 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceTreeCellRenderer.java
@@ -0,0 +1,76 @@
+/*
+* 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.servicepanel;
+
+import static 
org.apache.taverna.workbench.activityicons.DefaultActivityIcon.getDefaultIcon;
+
+import java.awt.Component;
+
+import javax.swing.Icon;
+import javax.swing.JTree;
+
+import org.apache.taverna.servicedescriptions.ServiceDescription;
+import 
org.apache.taverna.workbench.ui.servicepanel.tree.FilterTreeCellRenderer;
+import org.apache.taverna.workbench.ui.servicepanel.tree.FilterTreeNode;
+
+@SuppressWarnings("serial")
+public class ServiceTreeCellRenderer extends FilterTreeCellRenderer {
+       @Override
+       public Component getTreeCellRendererComponent(JTree tree, Object value,
+                       boolean sel, boolean expanded, boolean leaf, int row,
+                       boolean hasFocus) {
+               Component result = super.getTreeCellRendererComponent(tree, 
value, sel,
+                               expanded, leaf, row, hasFocus);
+               if (result instanceof ServiceTreeCellRenderer
+                               && value instanceof FilterTreeNode
+                               && ((FilterTreeNode) value).getUserObject() 
instanceof ServiceDescription)
+                       prettifyServiceTreeCell((ServiceTreeCellRenderer) 
result,
+                                       (ServiceDescription) ((FilterTreeNode) 
value)
+                                                       .getUserObject());
+               else {
+                       // Commented out - these are ugly, use the default 
folder icons instead
+                       /*
+                        * if (expanded) { ((ServiceTreeCellRenderer) result)
+                        * .setIcon(WorkbenchIcons.folderOpenIcon); } else {
+                        * ((ServiceTreeCellRenderer) result)
+                        * .setIcon(WorkbenchIcons.folderClosedIcon); }
+                        */
+               }
+               return result;
+       }
+
+       private void prettifyServiceTreeCell(ServiceTreeCellRenderer renderer,
+                       ServiceDescription item) {
+               String name = item.getName();
+               if (getFilter() != null)
+                       name = getFilter().filterRepresentation(name);
+               // serviceTreeCellRenderer.setForeground(Color.red);
+               String displayName = name;
+
+               String textualDescription = item.getDescription();
+               if (textualDescription != null && !textualDescription.isEmpty())
+                       displayName = displayName + " - " + textualDescription;
+               renderer.setText(displayName);
+
+               Icon activityIcon = item.getIcon();
+               renderer.setIcon(activityIcon != null ? activityIcon
+                               : getDefaultIcon());
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceTreeClickListener.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceTreeClickListener.java
 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceTreeClickListener.java
new file mode 100644
index 0000000..8109cdc
--- /dev/null
+++ 
b/taverna-activity-palette-ui/src/main/java/org/apache/taverna/workbench/ui/servicepanel/ServiceTreeClickListener.java
@@ -0,0 +1,251 @@
+/*
+* 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.servicepanel;
+
+import static java.awt.Color.RED;
+import static javax.swing.SwingUtilities.invokeLater;
+import static org.apache.taverna.lang.ui.ShadedLabel.BLUE;
+import static org.apache.taverna.lang.ui.ShadedLabel.GREEN;
+import static org.apache.taverna.lang.ui.ShadedLabel.ORANGE;
+import static org.apache.taverna.lang.ui.ShadedLabel.halfShade;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.minusIcon;
+import static org.apache.taverna.workbench.icons.WorkbenchIcons.plusIcon;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import javax.swing.AbstractAction;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JTree;
+import javax.swing.tree.TreePath;
+
+import org.apache.taverna.lang.ui.ShadedLabel;
+import org.apache.taverna.servicedescriptions.ConfigurableServiceProvider;
+import org.apache.taverna.servicedescriptions.ServiceDescription;
+import org.apache.taverna.servicedescriptions.ServiceDescriptionProvider;
+import org.apache.taverna.servicedescriptions.ServiceDescriptionRegistry;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import 
org.apache.taverna.workbench.ui.servicepanel.actions.ExportServiceDescriptionsAction;
+import 
org.apache.taverna.workbench.ui.servicepanel.actions.ImportServiceDescriptionsFromFileAction;
+import 
org.apache.taverna.workbench.ui.servicepanel.actions.ImportServiceDescriptionsFromURLAction;
+import 
org.apache.taverna.workbench.ui.servicepanel.actions.RemoveDefaultServicesAction;
+import 
org.apache.taverna.workbench.ui.servicepanel.actions.RemoveUserServicesAction;
+import 
org.apache.taverna.workbench.ui.servicepanel.actions.RestoreDefaultServicesAction;
+import org.apache.taverna.workbench.ui.servicepanel.tree.FilterTreeNode;
+import 
org.apache.taverna.workbench.ui.servicepanel.tree.FilterTreeSelectionModel;
+import org.apache.taverna.workbench.ui.servicepanel.tree.TreePanel;
+import org.apache.taverna.workbench.ui.workflowview.WorkflowView;
+
+import org.apache.log4j.Logger;
+
+import org.apache.taverna.commons.services.ServiceRegistry;
+
+/**
+ * @author alanrw
+ */
+public class ServiceTreeClickListener extends MouseAdapter {
+       private static Logger logger = 
Logger.getLogger(ServiceTreeClickListener.class);
+
+       private JTree tree;
+       private TreePanel panel;
+       private final ServiceDescriptionRegistry serviceDescriptionRegistry;
+       private final EditManager editManager;
+       private final MenuManager menuManager;
+       private final SelectionManager selectionManager;
+       private final ServiceRegistry serviceRegistry;
+
+       public ServiceTreeClickListener(JTree tree, TreePanel panel,
+                       ServiceDescriptionRegistry serviceDescriptionRegistry, 
EditManager editManager,
+                       MenuManager menuManager, SelectionManager 
selectionManager, ServiceRegistry serviceRegistry) {
+               this.tree = tree;
+               this.panel = panel;
+               this.serviceDescriptionRegistry = serviceDescriptionRegistry;
+               this.editManager = editManager;
+               this.menuManager = menuManager;
+               this.selectionManager = selectionManager;
+               this.serviceRegistry = serviceRegistry;
+       }
+
+       @SuppressWarnings("serial")
+       private void handleMouseEvent(MouseEvent evt) {
+               FilterTreeSelectionModel selectionModel = 
(FilterTreeSelectionModel) tree
+                               .getSelectionModel();
+               // Discover the tree row that was clicked on
+               int selRow = tree.getRowForLocation(evt.getX(), evt.getY());
+               if (selRow == -1)
+                       return;
+
+               // Get the selection path for the row
+               TreePath selectionPath = tree
+                               .getPathForLocation(evt.getX(), evt.getY());
+               if (selectionPath == null)
+                       return;
+
+               // Get the selected node
+               final FilterTreeNode selectedNode = (FilterTreeNode) 
selectionPath
+                               .getLastPathComponent();
+
+               selectionModel.clearSelection();
+               selectionModel.mySetSelectionPath(selectionPath);
+
+               if (evt.isPopupTrigger()) {
+                       JPopupMenu menu = new JPopupMenu();
+                       Object selectedObject = selectedNode.getUserObject();
+                       logger.info(selectedObject.getClass().getName());
+                       if (!(selectedObject instanceof ServiceDescription)) {
+                               menu.add(new ShadedLabel("Tree", BLUE));
+                               menu.add(new JMenuItem(new 
AbstractAction("Expand all",
+                                               plusIcon) {
+                                       @Override
+                                       public void actionPerformed(ActionEvent 
evt) {
+                                               invokeLater(new Runnable() {
+                                                       @Override
+                                                       public void run() {
+                                                               
panel.expandAll(selectedNode, true);
+                                                       }
+                                               });
+                                       }
+                               }));
+                               menu.add(new JMenuItem(new 
AbstractAction("Collapse all",
+                                               minusIcon) {
+                                       @Override
+                                       public void actionPerformed(ActionEvent 
evt) {
+                                               invokeLater(new Runnable() {
+                                                       @Override
+                                                       public void run() {
+                                                               
panel.expandAll(selectedNode, false);
+                                                       }
+                                               });
+                                       }
+                               }));
+                       }
+
+                       if (selectedObject instanceof ServiceDescription) {
+                               final ServiceDescription sd = 
(ServiceDescription) selectedObject;
+                               menu.add(new ShadedLabel(sd.getName(), ORANGE));
+                               menu.add(new AbstractAction("Add to workflow") {
+                                       @Override
+                                       public void actionPerformed(ActionEvent 
e) {
+                                               
WorkflowView.importServiceDescription(sd, false, editManager,
+                                                               menuManager, 
selectionManager, serviceRegistry);
+                                       }
+                               });
+                               menu.add(new AbstractAction("Add to workflow 
with name...") {
+                                       @Override
+                                       public void actionPerformed(ActionEvent 
e) {
+                                               
WorkflowView.importServiceDescription(sd, true, editManager,
+                                                               menuManager, 
selectionManager, serviceRegistry);
+                                       }
+                               });
+                       }
+
+                       Map<String, ServiceDescriptionProvider> nameMap = 
getServiceDescriptionProviderMap(selectedNode);
+
+                       boolean first = true;
+                       for (String name : nameMap.keySet()) {
+                               final ServiceDescriptionProvider sdp = 
nameMap.get(name);
+                               if (!(sdp instanceof 
ConfigurableServiceProvider))
+                                       continue;
+                               if (first) {
+                                       menu.add(new ShadedLabel(
+                                                       "Remove individual 
service provider", GREEN));
+                                       first = false;
+                               }
+                               menu.add(new AbstractAction(name) {
+                                       @Override
+                                       public void actionPerformed(ActionEvent 
e) {
+                                               serviceDescriptionRegistry
+                                                               
.removeServiceDescriptionProvider(sdp);
+                                       }
+                               });
+                       }
+
+                       if (selectedNode.isRoot()) { // Root "Available 
services"
+                               menu.add(new ShadedLabel("Default and added 
service providers",
+                                               ORANGE));
+                               menu.add(new RemoveUserServicesAction(
+                                               serviceDescriptionRegistry));
+                               menu.add(new RemoveDefaultServicesAction(
+                                               serviceDescriptionRegistry));
+                               menu.add(new RestoreDefaultServicesAction(
+                                               serviceDescriptionRegistry));
+
+                               menu.add(new ShadedLabel("Import/export 
services", halfShade(RED)));
+                               menu.add(new 
ImportServiceDescriptionsFromFileAction(
+                                               serviceDescriptionRegistry));
+                               menu.add(new 
ImportServiceDescriptionsFromURLAction(
+                                               serviceDescriptionRegistry));
+                               menu.add(new ExportServiceDescriptionsAction(
+                                               serviceDescriptionRegistry));
+                       }
+
+                       menu.show(evt.getComponent(), evt.getX(), evt.getY());
+               }
+       }
+
+       private Map<String, ServiceDescriptionProvider> 
getServiceDescriptionProviderMap(
+                       FilterTreeNode selectedNode) {
+               Set<ServiceDescriptionProvider> providers;
+
+               if (selectedNode.isRoot())
+                       providers = serviceDescriptionRegistry
+                                       .getServiceDescriptionProviders();
+               else {
+                       providers = new HashSet<>();
+                       for (FilterTreeNode leaf : selectedNode.getLeaves()) {
+                               if (!leaf.isLeaf())
+                                       logger.info("Not a leaf");
+                               if (!(leaf.getUserObject() instanceof 
ServiceDescription)) {
+                                       
logger.info(leaf.getUserObject().getClass()
+                                                       .getCanonicalName());
+                                       
logger.info(leaf.getUserObject().toString());
+                                       continue;
+                               }
+                               providers
+                                               
.addAll(serviceDescriptionRegistry
+                                                               
.getServiceDescriptionProviders((ServiceDescription) leaf
+                                                                               
.getUserObject()));
+                       }
+               }
+
+               TreeMap<String, ServiceDescriptionProvider> nameMap = new 
TreeMap<>();
+               for (ServiceDescriptionProvider sdp : providers)
+                       nameMap.put(sdp.toString(), sdp);
+               return nameMap;
+       }
+
+       @Override
+       public void mousePressed(MouseEvent evt) {
+               handleMouseEvent(evt);
+       }
+
+       @Override
+       public void mouseReleased(MouseEvent evt) {
+               handleMouseEvent(evt);
+       }
+}

Reply via email to