fix navigator filtering
diff --git a/org.eclipse.mylyn.context.ui/schema/bridges.exsd b/org.eclipse.mylyn.context.ui/schema/bridges.exsd
index c53dcab..b08f28b 100644
--- a/org.eclipse.mylyn.context.ui/schema/bridges.exsd
+++ b/org.eclipse.mylyn.context.ui/schema/bridges.exsd
@@ -13,7 +13,7 @@
    <element name="extension">
       <complexType>
          <sequence>
-            <element ref="uiBridge" minOccurs="1" maxOccurs="unbounded"/>
+            <element ref="uiBridge" minOccurs="0" maxOccurs="unbounded"/>
             <element ref="labelProvider" minOccurs="0" maxOccurs="unbounded"/>
             <element ref="preservedFilters" minOccurs="0" maxOccurs="unbounded"/>
          </sequence>
diff --git a/org.eclipse.mylyn.context.ui/src/org/eclipse/mylyn/internal/context/ui/views/CommonNavigatorFilterBar.java b/org.eclipse.mylyn.context.ui/src/org/eclipse/mylyn/internal/context/ui/views/CommonNavigatorFilterBar.java
new file mode 100644
index 0000000..c837c75
--- /dev/null
+++ b/org.eclipse.mylyn.context.ui/src/org/eclipse/mylyn/internal/context/ui/views/CommonNavigatorFilterBar.java
@@ -0,0 +1,833 @@
+package org.eclipse.mylar.internal.context.ui.views;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.mylar.context.ui.InterestFilter;
+import org.eclipse.mylar.internal.tasks.ui.views.AdaptiveRefreshPolicy;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.IWorkbenchPreferenceConstants;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PatternFilter;
+import org.eclipse.ui.internal.WorkbenchMessages;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.ui.progress.WorkbenchJob;
+
+/**
+ * Based on @see{FilteredTree}
+ * 
+ * @author Mik Kersten
+ */
+public class CommonNavigatorFilterBar extends Composite {
+
+	private InterestFilter suppressedFilter = null;
+
+	private AdaptiveRefreshPolicy refreshPolicy;
+
+	public CommonNavigatorFilterBar(TreeViewer treeViewer, Composite parent, CommonNavigatorPatternFilter filter) {
+		super(parent, SWT.NONE);
+		this.treeViewer = treeViewer;
+		patternFilter = filter;
+		// TODO: keep virtual?
+		createControl(parent, SWT.VIRTUAL | SWT.BORDER);
+		createRefreshJob();
+		setInitialText("");
+		setFont(parent.getFont());
+		refreshPolicy = new AdaptiveRefreshPolicy(refreshJob, filterText);
+	}
+
+	protected void textChanged() {
+		
+		defaultTextChanged();
+		
+		int textLength = filterText.getText().length();
+		InterestFilter interestFilter = getInterestFilters();
+		List<ViewerFilter> existingFilters = Arrays.asList(getViewer().getFilters());
+		if (textLength > 0 && interestFilter != null && suppressedFilter == null) {
+			suppressedFilter = interestFilter;
+			getViewer().removeFilter(interestFilter);
+			
+		} else if (textLength == 0 && suppressedFilter != null) {
+			if (!existingFilters.contains(interestFilter)) {
+				getViewer().addFilter(suppressedFilter);
+			}
+			getViewer().expandAll();
+			suppressedFilter = null;
+		}
+
+//		narrowingDown = previousFilterText==null || getFilterString().startsWith(previousFilterText);
+//    	previousFilterText = getFilterString();
+//		if (refreshPolicy != null) {
+//			refreshPolicy.textChanged(filterText.getText());
+//		}
+	}
+	
+	/**
+     * Update the receiver after the text has changed.
+     */
+    protected void defaultTextChanged() {
+    	narrowingDown = previousFilterText==null || getFilterString().startsWith(previousFilterText);
+    	previousFilterText = getFilterString();
+    	// cancel currently running job first, to prevent unnecessary redraw
+    	refreshJob.cancel();
+    	refreshJob.schedule(200);
+    }
+
+	private InterestFilter getInterestFilters() {
+		if (getViewer() == null) {
+			return null;
+		}
+		ViewerFilter[] filters = getViewer().getFilters();
+		for (int i = 0; i < filters.length; i++) {
+			ViewerFilter filter = filters[i];
+			if (filter instanceof InterestFilter) {
+				return (InterestFilter) filter;
+			}
+		}
+		return null;
+	}
+
+	public AdaptiveRefreshPolicy getRefreshPolicy() {
+		return refreshPolicy;
+	}
+	
+	// ----------------- below based on FilteredTree ---------------
+
+	/**
+	 * The filter text widget to be used by this tree. This value may be
+	 * <code>null</code> if there is no filter widget, or if the controls have
+	 * not yet been created.
+	 */
+    protected Text filterText;
+    
+	/**
+	 * The control representing the clear button for the filter text entry. This
+	 * value may be <code>null</code> if no such button exists, or if the
+	 * controls have not yet been created.
+	 */
+    protected ToolBarManager filterToolBar;
+
+	/**
+	 * The viewer for the filtered tree. This value should never be <code>null</code>
+	 * after the widget creation methods are complete.
+	 */
+    protected TreeViewer treeViewer;
+
+    /**
+     * The Composite on which the filter controls are created. This is used to set 
+     * the background color of the filter controls to match the surrounding controls.
+     */
+    protected Composite filterComposite;
+    
+	/**
+	 * The pattern filter for the tree. This value must not be <code>null</code>.
+	 */ 
+    private CommonNavigatorPatternFilter patternFilter;
+
+    /**
+     * The text to initially show in the filter text control. 
+     */
+    protected String initialText = ""; //$NON-NLS-1$
+    
+    /**
+     * The job used to refresh the tree.
+     */
+    private Job refreshJob;
+    
+    /**
+     * The parent composite of the filtered tree.
+     */
+    protected Composite parent;
+
+    /**
+     * Whether or not to show the filter controls (text and clear button).
+     * The default is to show these controls.  This can be overridden by 
+     * providing a setting in the product configuration file.  The setting  
+     * to add to not show these controls is:
+     * 
+     * org.eclipse.ui/SHOW_FILTERED_TEXTS=false
+     */
+    protected boolean showFilterControls;
+
+	protected Composite treeComposite;
+    
+    /**
+     * Image descriptor for enabled clear button.
+     */
+    private static final String CLEAR_ICON = "org.eclipse.ui.internal.dialogs.CLEAR_ICON"; //$NON-NLS-1$
+
+    /**
+     * Image descriptor for disabled clear button.
+     */
+    private static final String DCLEAR_ICON = "org.eclipse.ui.internal.dialogs.DCLEAR_ICON"; //$NON-NLS-1$
+
+    /**
+     * Maximum time spent expanding the tree after the filter text has been updated
+     * (this is only used if we were able to at least expand the visible nodes)
+     */
+	private static final long SOFT_MAX_EXPAND_TIME = 200;
+
+    /**
+     * Get image descriptors for the clear button.
+     */
+    static {
+        ImageDescriptor descriptor = AbstractUIPlugin
+                .imageDescriptorFromPlugin(PlatformUI.PLUGIN_ID,
+                        "$nl$/icons/full/etool16/clear_co.gif"); //$NON-NLS-1$
+        if (descriptor != null) {
+            JFaceResources.getImageRegistry().put(CLEAR_ICON, descriptor);
+        }
+        descriptor = AbstractUIPlugin.imageDescriptorFromPlugin(
+                PlatformUI.PLUGIN_ID, "$nl$/icons/full/dtool16/clear_co.gif"); //$NON-NLS-1$
+        if (descriptor != null) {
+            JFaceResources.getImageRegistry().put(DCLEAR_ICON, descriptor);
+        }
+    }
+
+//    /**
+//	 * Create a new instance of the receiver.
+//	 * 
+//	 * @param parent
+//	 *            the parent <code>Composite</code>
+//	 * @param treeStyle
+//	 *            the style bits for the <code>Tree</code>
+//	 * @param filter
+//	 *            the filter to be used
+//	 */
+//	public FilteredTree(Composite parent, int treeStyle, PatternFilter filter) {
+//		super(parent, SWT.NONE);
+//		this.parent = parent;
+//		init(treeStyle, filter);
+//	}
+
+//	/**
+//	 * Create a new instance of the receiver. Subclasses that wish to override
+//	 * the default creation behavior may use this constructor, but must ensure
+//	 * that the <code>init(composite, int, PatternFilter)</code> method is
+//	 * called in the overriding constructor.
+//	 * 
+//	 * @param parent
+//	 *            the parent <code>Composite</code>
+//	 * @see #init(int, PatternFilter)
+//	 * 
+//	 * @since 3.3
+//	 */
+//	protected FilteredTree(Composite parent) {
+//		super(parent, SWT.NONE);
+//		this.parent = parent;
+//	}
+
+	/**
+	 * Create the filtered tree.
+	 * 
+	 * @param treeStyle
+	 *            the style bits for the <code>Tree</code>
+	 * @param filter
+	 *            the filter to be used
+	 * 
+	 * @since 3.3
+	 */
+	protected void init(int treeStyle, CommonNavigatorPatternFilter filter) {
+		patternFilter = filter;
+		showFilterControls = PlatformUI.getPreferenceStore().getBoolean(
+				IWorkbenchPreferenceConstants.SHOW_FILTERED_TEXTS);
+		createControl(parent, treeStyle);
+		createRefreshJob();
+		setInitialText(WorkbenchMessages.FilteredTree_FilterMessage);
+		setFont(parent.getFont());
+	}
+
+	protected void createControl(Composite parent, int treeStyle) {
+		GridLayout layout = new GridLayout();
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		setLayout(layout);
+		setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+		filterComposite = new Composite(this, SWT.NONE);
+		GridLayout filterLayout = new GridLayout(2, false);
+		filterLayout.marginHeight = 0;
+		filterLayout.marginWidth = 0;
+		filterComposite.setLayout(filterLayout);
+		filterComposite.setFont(parent.getFont());
+
+		createFilterControls(filterComposite);
+		filterComposite.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
+	}
+//    /**
+//     * Create the filtered tree's controls.  
+//     * Subclasses should override.
+//     * 
+//     * @param parent
+//     * @param treeStyle
+//     */
+//    protected void createControl(Composite parent, int treeStyle){
+//    	GridLayout layout = new GridLayout();
+//		layout.marginHeight = 0;
+//		layout.marginWidth = 0;
+//		setLayout(layout);
+//		setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+//
+//        if (showFilterControls){
+//        	filterComposite = new Composite(this, SWT.NONE);
+//            GridLayout filterLayout = new GridLayout(2, false);
+//            filterLayout.marginHeight = 0;
+//            filterLayout.marginWidth = 0;
+//            filterComposite.setLayout(filterLayout);
+//            filterComposite.setFont(parent.getFont());
+//            
+//        	createFilterControls(filterComposite);
+//        	filterComposite.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING,
+//					true, false));
+//        }
+//        
+//        treeComposite = new Composite(this, SWT.NONE);
+//        GridLayout treeCompositeLayout = new GridLayout();
+//        treeCompositeLayout.marginHeight = 0;
+//        treeCompositeLayout.marginWidth = 0;
+//		treeComposite.setLayout(treeCompositeLayout);
+//        GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+//        treeComposite.setLayoutData(data);
+//        createTreeControl(treeComposite, treeStyle); 
+//    }
+    
+    /**
+     * Create the filter controls.  By default, a text and corresponding tool bar 
+     * button that clears the contents of the text is created.
+     * Subclasses may override.  
+     * 
+     * @param parent parent <code>Composite</code> of the filter controls
+     * @return the <code>Composite</code> that contains the filter controls
+     */
+    protected Composite createFilterControls(Composite parent){
+        createFilterText(parent);
+        createClearText(parent);
+
+        filterToolBar.update(false);
+        // initially there is no text to clear
+        filterToolBar.getControl().setVisible(false);
+        return parent;
+    }
+    
+    /**
+	 * Creates and set up the tree and tree viewer. This method calls
+	 * {@link #doCreateTreeViewer(Composite, int)} to create the tree viewer.
+	 * Subclasses should override {@link #doCreateTreeViewer(Composite, int)}
+	 * instead of overriding this method.
+	 * 
+	 * @param parent
+	 *            parent <code>Composite</code>
+	 * @param style
+	 *            SWT style bits used to create the tree
+	 * @return the tree
+	 */
+    protected Control createTreeControl(Composite parent, int style){
+        treeViewer = doCreateTreeViewer(parent, style);
+        GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+        treeViewer.getControl().setLayoutData(data);
+        treeViewer.getControl().addDisposeListener(new DisposeListener(){
+        	/* (non-Javadoc)
+        	 * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
+        	 */
+        	public void widgetDisposed(DisposeEvent e) {
+        		refreshJob.cancel();
+        	}
+        });
+        treeViewer.addFilter(patternFilter);  
+        return treeViewer.getControl();
+    }
+
+	/**
+	 * Creates the tree viewer.  Subclasses may override.
+	 * 
+	 * @param parent the parent composite
+	 * @param style SWT style bits used to create the tree viewer
+	 * @return the tree viewer
+	 * 
+	 * @since 3.3
+	 */
+	protected TreeViewer doCreateTreeViewer(Composite parent, int style) {
+		return new TreeViewer(parent, style);
+	}
+    
+    /**
+     * Return the first item in the tree that matches the filter pattern.
+     * 
+     * @param items
+     * @return the first matching TreeItem
+     */
+    private TreeItem getFirstMatchingItem(TreeItem[] items){
+		for (int i = 0; i < items.length; i++){
+			if (patternFilter.isLeafMatch(treeViewer, items[i].getData())
+					&& patternFilter.isElementSelectable(items[i].getData())) {
+				return items[i];
+			}
+			return getFirstMatchingItem(items[i].getItems());
+		}
+		return null;
+    }
+    
+    /**
+     * Create the refresh job for the receiver.
+     *
+     */
+	private void createRefreshJob() {
+		refreshJob = new WorkbenchJob("Refresh Filter"){//$NON-NLS-1$
+			/* (non-Javadoc)
+			 * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
+			 */
+			public IStatus runInUIThread(IProgressMonitor monitor) {
+				if(treeViewer.getControl().isDisposed()) {
+					return Status.CANCEL_STATUS;
+				}
+				
+				String text = getFilterString();
+				if (text == null) {
+					return Status.OK_STATUS;
+				}
+				
+		        boolean initial = initialText != null && initialText.equals(text); 
+		        if (initial) {
+		            patternFilter.setPattern(null);
+		        } else if (text != null){
+		            patternFilter.setPattern(text);
+		        }
+		        
+		        Control redrawFalseControl = treeComposite != null ? treeComposite : treeViewer.getControl();
+		        try {
+			        // don't want the user to see updates that will be made to the tree
+		        	// we are setting redraw(false) on the composite to avoid dancing scrollbar
+		        	redrawFalseControl.setRedraw(false);
+			        if (!narrowingDown) {
+				        // collapse all
+				        TreeItem[] is = treeViewer.getTree().getItems();
+				        for (int i = 0; i < is.length; i++) {
+							TreeItem item = is[i];
+							if (item.getExpanded()) {
+								treeViewer.setExpandedState(item.getData(), false);
+							}
+						}
+			        }
+			        treeViewer.refresh(true);
+			       
+			        if (text.length() > 0 && !initial) {
+			        	/* Expand elements one at a time.  After each is expanded, check
+			        	 * to see if the filter text has been modified.  If it has, then 
+			        	 * cancel the refresh job so the user doesn't have to endure 
+			        	 * expansion of all the nodes.
+			        	 */
+						TreeItem[] items = getViewer().getTree().getItems();
+						int treeHeight = getViewer().getTree().getBounds().height;
+						int numVisibleItems = treeHeight / getViewer().getTree().getItemHeight();
+						long stopTime = SOFT_MAX_EXPAND_TIME + System.currentTimeMillis();
+						if (items.length > 0
+								&& recursiveExpand(items, monitor, stopTime, new int[] { numVisibleItems })) {
+							return Status.CANCEL_STATUS;
+						}
+			            
+			            // enabled toolbar - there is text to clear
+			            // and the list is currently being filtered		
+			            updateToolbar(true);
+			        } else {
+						// disabled toolbar - there is no text to clear
+				        // and the list is currently not filtered		        	
+			        	updateToolbar(false);
+			        }
+	        	}
+	        	finally {
+			        // done updating the tree - set redraw back to true
+			        TreeItem[] items = getViewer().getTree().getItems();
+			        if (items.length > 0) {
+			        	treeViewer.getTree().setTopItem(items[0]);
+			        }
+			        redrawFalseControl.setRedraw(true);
+	        	}	
+		        return Status.OK_STATUS;
+			}
+
+			/**
+			 * Returns true if the job should be canceled (because of timeout or actual cancellation).
+			 * @param items
+			 * @param provider 
+			 * @param monitor
+			 * @param cancelTime
+			 * @param numItemsLeft 
+			 * @return true if canceled
+			 */
+			private boolean recursiveExpand(TreeItem[] items,
+					IProgressMonitor monitor, long cancelTime, int[] numItemsLeft) {
+				boolean canceled = false;
+				for (int i = 0; !canceled && i < items.length; i++) {
+					TreeItem item = items[i];
+					boolean visible = numItemsLeft[0]-- >= 0;
+					if (monitor.isCanceled()
+							|| (!visible && System.currentTimeMillis() > cancelTime)) {
+						canceled = true;
+					} else {
+						Object itemData = item.getData();
+						if (itemData != null) {
+							if (!item.getExpanded()) {
+								// do the expansion through the viewer so that it can refresh children appropriately.
+								treeViewer.setExpandedState(itemData, true);
+							}
+							TreeItem[] children = item.getItems();
+							if (items.length > 0) {
+								canceled = recursiveExpand(children,
+										monitor, cancelTime, numItemsLeft);
+							}
+						}
+					}
+				}
+				return canceled;
+			}
+			
+		};
+		refreshJob.setSystem(true);
+	}
+
+	protected void updateToolbar(boolean visible){
+		if (filterToolBar != null) {
+			filterToolBar.getControl().setVisible(visible);
+		}
+	}
+	
+	/**
+	 * Creates the filter text and adds listeners. This method calls
+	 * {@link #doCreateFilterText(Composite)} to create the text control.
+	 * Subclasses should override {@link #doCreateFilterText(Composite)}
+	 * instead of overriding this method.
+	 * 
+	 * @param parent <code>Composite</code> of the filter text
+	 */
+	protected void createFilterText(Composite parent) {
+		filterText =  doCreateFilterText(parent);
+		filterText.getAccessible().addAccessibleListener(
+				new AccessibleAdapter(){
+					/* (non-Javadoc)
+					 * @see org.eclipse.swt.accessibility.AccessibleListener#getName(org.eclipse.swt.accessibility.AccessibleEvent)
+					 */
+					public void getName(AccessibleEvent e) {
+						String filterTextString = filterText.getText();
+						if(filterTextString.length() == 0){
+							e.result = initialText;
+						} else {
+							e.result = filterTextString;
+						}
+					}
+				});
+
+		filterText.addFocusListener(
+				new FocusAdapter(){
+					/* (non-Javadoc)
+					 * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
+					 */
+					public void focusGained(FocusEvent e) {
+						/* Running in an asyncExec because the selectAll() does not   
+						 * appear to work when using mouse to give focus to text.
+						 */
+						Display display = filterText.getDisplay();
+						display.asyncExec(new Runnable() {
+		                    public void run() {
+		                    	if (!filterText.isDisposed()){
+									if (getInitialText().equals(filterText.getText().trim())){
+										filterText.selectAll();
+									}
+		                    	}
+		                    }
+						});
+					}
+				});
+		
+        filterText.addKeyListener(new KeyAdapter() {
+            /*
+             * (non-Javadoc)
+             * 
+             * @see org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt.events.KeyEvent)
+             */
+            public void keyPressed(KeyEvent e) {
+            	// on a CR we want to transfer focus to the list
+            	boolean hasItems = getViewer().getTree().getItemCount() > 0;
+            	if(hasItems && e.keyCode == SWT.ARROW_DOWN){
+                    	treeViewer.getTree().setFocus();
+            	} else if (e.character == SWT.CR){
+					return;
+            	}
+            }
+        });
+        
+        // enter key set focus to tree
+        filterText.addTraverseListener(new TraverseListener () {
+			public void keyTraversed(TraverseEvent e) {
+				if (e.detail == SWT.TRAVERSE_RETURN) {
+					e.doit = false;
+					if (getViewer().getTree().getItemCount() == 0) {
+						Display.getCurrent().beep();
+					} else {
+						// if the initial filter text hasn't changed, do not try to match
+						boolean hasFocus = getViewer().getTree().setFocus();
+						boolean textChanged = !getInitialText().equals(
+								filterText.getText().trim());
+						if (hasFocus && textChanged
+								&& filterText.getText().trim().length() > 0) {
+							TreeItem item = getFirstMatchingItem(getViewer()
+									.getTree().getItems());
+							if (item != null) {
+								getViewer().getTree().setSelection(
+										new TreeItem[] { item });
+								ISelection sel = getViewer().getSelection();
+								getViewer().setSelection(sel, true);
+							}
+						}						
+					} 
+				}
+			}
+		});
+        
+        filterText.addModifyListener(new ModifyListener(){
+        	/* (non-Javadoc)
+        	 * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
+        	 */
+        	public void modifyText(ModifyEvent e) {
+        		textChanged();
+        	}
+        });
+
+        filterText.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
+	}
+
+	/**
+	 * Creates the text control for entering the filter text.  Subclasses may override.
+	 * 
+	 * @param parent the parent composite
+	 * @return the text widget
+	 * 
+	 * @since 3.3
+	 */
+	protected Text doCreateFilterText(Composite parent) {
+		return new Text(parent, SWT.SINGLE | SWT.BORDER);
+	}
+
+	private String previousFilterText;
+
+	private boolean narrowingDown;
+	
+//	/**
+//     * Update the receiver after the text has changed.
+//     */
+//    protected void textChanged() {
+//    	narrowingDown = previousFilterText==null || getFilterString().startsWith(previousFilterText);
+//    	previousFilterText = getFilterString();
+//    	// cancel currently running job first, to prevent unnecessary redraw
+//    	refreshJob.cancel();
+//    	refreshJob.schedule(200);
+//    }
+
+    /**
+     * Set the background for the widgets that support the filter text area.
+     * 
+     * @param background background <code>Color</code> to set
+     */
+    public void setBackground(Color background) {
+        super.setBackground(background);
+        if (filterComposite != null) {
+			filterComposite.setBackground(background);
+		}
+        if (filterToolBar != null && filterToolBar.getControl() != null) {
+			filterToolBar.getControl().setBackground(background);
+		}
+    }
+
+    /**
+     * Create the button that clears the text.
+     * 
+     * @param parent parent <code>Composite</code> of toolbar button 
+     */
+    private void createClearText(Composite parent) {
+        ToolBar toolBar = new ToolBar(parent, SWT.FLAT | SWT.HORIZONTAL);
+        filterToolBar = new ToolBarManager(toolBar);
+
+        IAction clearTextAction = new Action("", IAction.AS_PUSH_BUTTON) {//$NON-NLS-1$
+            /*
+             * (non-Javadoc)
+             * 
+             * @see org.eclipse.jface.action.Action#run()
+             */
+            public void run() {
+                clearText();
+            }
+        };
+
+        clearTextAction
+				.setToolTipText(WorkbenchMessages.FilteredTree_ClearToolTip);
+        clearTextAction.setImageDescriptor(JFaceResources.getImageRegistry()
+                .getDescriptor(CLEAR_ICON));
+        clearTextAction.setDisabledImageDescriptor(JFaceResources
+                .getImageRegistry().getDescriptor(DCLEAR_ICON));
+
+        filterToolBar.add(clearTextAction);
+    }
+
+    /**
+     * Clears the text in the filter text widget.  Also removes the optional 
+     * additional filter that is provided via addFilter(ViewerFilter).
+     */
+    protected void clearText() {
+        setFilterText(""); //$NON-NLS-1$
+        textChanged();
+    }
+
+    /**
+     * Set the text in the filter control.
+	 * @param string 
+	 */
+	protected void setFilterText(String string) {
+		if (filterText != null){
+			filterText.setText(string);
+			selectAll();		
+		}
+	}
+
+	/**
+	 * Returns the pattern filter used by this tree.
+	 * 
+	 * @return The pattern filter; never <code>null</code>.
+	 */
+	public final PatternFilter getPatternFilter() {
+		return patternFilter;
+	}
+	
+	/**
+     * Get the tree viewer of the receiver.
+     * 
+     * @return the tree viewer
+     */
+    public TreeViewer getViewer() {
+        return treeViewer;
+    }
+
+    /**
+     * Get the filter text for the receiver, if it was created. 
+     * Otherwise return <code>null</code>.
+     * 
+     * @return the filter Text, or null if it was not created
+     */
+    public Text getFilterControl() {
+        return filterText;
+    }
+    
+    /**
+     * Convenience method to return the text of the filter control.
+     * If the text widget is not created, then null is returned.
+     * 
+     * @return String in the text, or null if the text does not exist
+     */
+    protected String getFilterString(){
+    	return filterText != null ? filterText.getText() : null;
+    }
+
+    /**
+     * Set the text that will be shown until the first focus.
+     * A default value is provided, so this method only need be 
+     * called if overriding the default initial text is desired.
+     * 
+     * @param text initial text to appear in text field
+     */
+    public void setInitialText(String text) {
+        initialText = text;
+    	setFilterText(initialText);
+        textChanged();
+    }
+
+    /**
+     * Select all text in the filter text field.
+     *
+     */
+	protected void selectAll() {
+		if (filterText != null) {
+			filterText.selectAll();
+		}
+	}
+
+	/**
+	 * Get the initial text for the receiver.
+	 * @return String
+	 */
+	protected String getInitialText() {
+		return initialText;
+	}
+
+//	/**
+//	 * Return a bold font if the given element matches the given pattern.
+//	 * Clients can opt to call this method from a Viewer's label provider to get
+//	 * a bold font for which to highlight the given element in the tree.
+//	 * 
+//	 * @param element
+//	 *            element for which a match should be determined
+//	 * @param tree
+//	 *            FilteredTree in which the element resides
+//	 * @param filter
+//	 *            PatternFilter which determines a match
+//	 * 
+//	 * @return bold font
+//	 */
+//	public static Font getBoldFont(Object element, FilteredTree tree,
+//			PatternFilter filter) {
+//		String filterText = tree.getFilterString();
+//
+//		if (filterText == null) {
+//			return null;
+//		}
+//		
+//		// Do nothing if it's empty string
+//		String initialText = tree.getInitialText();
+//		if (!("".equals(filterText) || initialText.equals(filterText))) {//$NON-NLS-1$
+//			boolean initial = initialText != null
+//					&& initialText.equals(filterText);
+//			if (initial) {
+//				filter.setPattern(null);
+//			} else if (filterText != null){
+//				filter.setPattern(filterText);
+//			}
+//
+//			if (filter.isElementVisible(tree.getViewer(), element) && 
+//					filter.isLeafMatch(tree.getViewer(),element)) {
+//				return JFaceResources.getFontRegistry().getBold(
+//						JFaceResources.DIALOG_FONT);
+//			}
+//		}
+//		return null;
+//	}
+}
diff --git a/org.eclipse.mylyn.context.ui/src/org/eclipse/mylyn/internal/context/ui/views/CommonNavigatorPatternFilter.java b/org.eclipse.mylyn.context.ui/src/org/eclipse/mylyn/internal/context/ui/views/CommonNavigatorPatternFilter.java
new file mode 100644
index 0000000..defac52
--- /dev/null
+++ b/org.eclipse.mylyn.context.ui/src/org/eclipse/mylyn/internal/context/ui/views/CommonNavigatorPatternFilter.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2004 - 2006 University Of British Columbia and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     University Of British Columbia - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylar.internal.context.ui.views;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.mylar.internal.tasks.ui.TaskListPatternFilter;
+
+/**
+ * @author Mik Kersten
+ */
+public class CommonNavigatorPatternFilter extends TaskListPatternFilter {
+	@Override
+	protected boolean isLeafMatch(Viewer viewer, Object element) {
+		return super.isLeafMatch(viewer, element);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.mylyn.context.ui/src/org/eclipse/mylyn/internal/context/ui/views/NavigatorFilterBar.java b/org.eclipse.mylyn.context.ui/src/org/eclipse/mylyn/internal/context/ui/views/NavigatorFilterBar.java
deleted file mode 100644
index 41ee9b3..0000000
--- a/org.eclipse.mylyn.context.ui/src/org/eclipse/mylyn/internal/context/ui/views/NavigatorFilterBar.java
+++ /dev/null
@@ -1,467 +0,0 @@
-package org.eclipse.mylar.internal.context.ui.views;
-
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.action.ToolBarManager;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.jface.resource.JFaceResources;
-import org.eclipse.jface.viewers.AbstractTreeViewer;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerFilter;
-import org.eclipse.mylar.context.ui.InterestFilter;
-import org.eclipse.mylar.internal.tasks.ui.TaskListPatternFilter;
-import org.eclipse.mylar.internal.tasks.ui.views.AdaptiveRefreshPolicy;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.accessibility.AccessibleAdapter;
-import org.eclipse.swt.accessibility.AccessibleEvent;
-import org.eclipse.swt.events.FocusAdapter;
-import org.eclipse.swt.events.FocusEvent;
-import org.eclipse.swt.events.KeyAdapter;
-import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.TraverseEvent;
-import org.eclipse.swt.events.TraverseListener;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.swt.widgets.ToolBar;
-import org.eclipse.swt.widgets.TreeItem;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.dialogs.PatternFilter;
-import org.eclipse.ui.internal.WorkbenchMessages;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.eclipse.ui.progress.WorkbenchJob;
-
-/**
- * Based on
- * 
- * @see{FilteredTree}
- */
-public class NavigatorFilterBar extends Composite {
-
-	protected Job refreshJob;
-
-	private InterestFilter suppressedFilter = null;
-
-	private AdaptiveRefreshPolicy refreshPolicy;
-
-	public static class ResourcePatternFilter extends TaskListPatternFilter {
-		@Override
-		protected boolean isLeafMatch(Viewer viewer, Object element) {
-			return super.isLeafMatch(viewer, element);
-		}
-	}
-
-	public NavigatorFilterBar(TreeViewer treeViewer, Composite parent, ResourcePatternFilter filter) {
-		super(parent, SWT.NONE);
-		this.treeViewer = treeViewer;
-		patternFilter = filter;
-		createControl(parent);
-		createRefreshJob();
-		setInitialText("");
-		setFont(parent.getFont());
-		refreshPolicy = new AdaptiveRefreshPolicy(refreshJob, filterText);
-	}
-
-	protected void textChanged() {
-		int textLength = filterText.getText().length();
-		InterestFilter interestFilter = getInterestFilter();
-		if (textLength > 0 && interestFilter != null && suppressedFilter == null) {
-			suppressedFilter = interestFilter;
-			getViewer().removeFilter(interestFilter);
-		} else if (textLength == 0 && suppressedFilter != null) {
-			getViewer().addFilter(suppressedFilter);
-			getViewer().expandAll();
-			suppressedFilter = null;
-		}
-		if (refreshPolicy != null) {
-			refreshPolicy.textChanged(filterText.getText());
-		}
-		// super.textChanged();
-	}
-
-	private InterestFilter getInterestFilter() {
-		if (getViewer() == null) {
-			return null;
-		}
-		ViewerFilter[] filters = getViewer().getFilters();
-		for (int i = 0; i < filters.length; i++) {
-			ViewerFilter filter = filters[i];
-			if (filter instanceof InterestFilter) {
-				return (InterestFilter) filter;
-			}
-		}
-		return null;
-	}
-
-	// ----------------- below based on FilteredTree ---------------
-
-	protected Text filterText;
-
-	protected ToolBarManager filterToolBar;
-
-	protected TreeViewer treeViewer;
-
-	protected Composite filterComposite;
-
-	private ResourcePatternFilter patternFilter;
-
-	protected String initialText = "";
-
-	private static final String CLEAR_ICON = "org.eclipse.ui.internal.dialogs.CLEAR_ICON"; //$NON-NLS-1$
-
-	private static final String DCLEAR_ICON = "org.eclipse.ui.internal.dialogs.DCLEAR_ICON"; //$NON-NLS-1$
-
-	static {
-		ImageDescriptor descriptor = AbstractUIPlugin.imageDescriptorFromPlugin(PlatformUI.PLUGIN_ID,
-				"$nl$/icons/full/etool16/clear_co.gif"); //$NON-NLS-1$
-		if (descriptor != null) {
-			JFaceResources.getImageRegistry().put(CLEAR_ICON, descriptor);
-		}
-		descriptor = AbstractUIPlugin.imageDescriptorFromPlugin(PlatformUI.PLUGIN_ID,
-				"$nl$/icons/full/dtool16/clear_co.gif"); //$NON-NLS-1$
-		if (descriptor != null) {
-			JFaceResources.getImageRegistry().put(DCLEAR_ICON, descriptor);
-		}
-	}
-
-	protected void createControl(Composite parent) {
-		GridLayout layout = new GridLayout();
-		layout.marginHeight = 0;
-		layout.marginWidth = 0;
-		setLayout(layout);
-		setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
-		filterComposite = new Composite(this, SWT.NONE);
-		GridLayout filterLayout = new GridLayout(2, false);
-		filterLayout.marginHeight = 0;
-		filterLayout.marginWidth = 0;
-		filterComposite.setLayout(filterLayout);
-		filterComposite.setFont(parent.getFont());
-
-		createFilterControls(filterComposite);
-		filterComposite.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
-	}
-
-	protected Composite createFilterControls(Composite parent) {
-		createFilterText(parent);
-		createClearText(parent);
-
-		filterToolBar.update(false);
-		// initially there is no text to clear
-		filterToolBar.getControl().setVisible(false);
-		return parent;
-	}
-
-//	private TreeItem getFirstMatchingItem(TreeItem[] items) {
-//		for (int i = 0; i < items.length; i++) {
-//			if (patternFilter.isLeafMatch(treeViewer, items[i].getData())
-//					&& patternFilter.isElementSelectable(items[i].getData())) {
-//				return items[i];
-//			}
-//			return getFirstMatchingItem(items[i].getItems());
-//		}
-//		return null;
-//	}
-
-	private void createRefreshJob() {
-		refreshJob = new WorkbenchJob("Refresh Filter") {//$NON-NLS-1$
-			/*
-			 * (non-Javadoc)
-			 * 
-			 * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
-			 */
-			@Override
-			public IStatus runInUIThread(IProgressMonitor monitor) {
-				if (treeViewer.getControl().isDisposed()) {
-					return Status.CANCEL_STATUS;
-				}
-
-				String text = getFilterString();
-				if (text == null) {
-					return Status.OK_STATUS;
-				}
-
-				boolean initial = initialText != null && initialText.equals(text);
-				if (initial) {
-					patternFilter.setPattern(null);
-				} else if (text != null) {
-					patternFilter.setPattern(text);
-				}
-
-				try {
-					// don't want the user to see updates that will be made to
-					// the tree
-					treeViewer.getControl().setRedraw(false);
-					treeViewer.refresh(true);
-
-					if (text.length() > 0 && !initial) {
-						/*
-						 * Expand elements one at a time. After each is
-						 * expanded, check to see if the filter text has been
-						 * modified. If it has, then cancel the refresh job so
-						 * the user doesn't have to endure expansion of all the
-						 * nodes.
-						 */
-						IStructuredContentProvider provider = (IStructuredContentProvider) treeViewer
-								.getContentProvider();
-						Object[] elements = provider.getElements(treeViewer.getInput());
-						for (int i = 0; i < elements.length; i++) {
-							if (monitor.isCanceled()) {
-								return Status.CANCEL_STATUS;
-							}
-							treeViewer.expandToLevel(elements[i], AbstractTreeViewer.ALL_LEVELS);
-						}
-
-						TreeItem[] items = getViewer().getTree().getItems();
-						if (items.length > 0) {
-							// to prevent scrolling
-							treeViewer.getTree().showItem(items[0]);
-						}
-
-						// enabled toolbar - there is text to clear
-						// and the list is currently being filtered
-						updateToolbar(true);
-					} else {
-						// disabled toolbar - there is no text to clear
-						// and the list is currently not filtered
-						updateToolbar(false);
-					}
-				} finally {
-					// done updating the tree - set redraw back to true
-					treeViewer.getControl().setRedraw(true);
-				}
-				return Status.OK_STATUS;
-			}
-
-		};
-		refreshJob.setSystem(true);
-	}
-
-	protected void updateToolbar(boolean visible) {
-		if (filterToolBar != null) {
-			filterToolBar.getControl().setVisible(visible);
-		}
-	}
-
-	protected void createFilterText(Composite parent) {
-		filterText = new Text(parent, SWT.SINGLE | SWT.BORDER);
-		filterText.getAccessible().addAccessibleListener(new AccessibleAdapter() {
-			/*
-			 * (non-Javadoc)
-			 * 
-			 * @see org.eclipse.swt.accessibility.AccessibleListener#getName(org.eclipse.swt.accessibility.AccessibleEvent)
-			 */
-			@Override
-			public void getName(AccessibleEvent e) {
-				String filterTextString = filterText.getText();
-				if (filterTextString.length() == 0) {
-					e.result = initialText;
-				} else {
-					e.result = filterTextString;
-				}
-			}
-		});
-
-		filterText.addFocusListener(new FocusAdapter() {
-			/*
-			 * (non-Javadoc)
-			 * 
-			 * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
-			 */
-			@Override
-			public void focusGained(FocusEvent e) {
-				/*
-				 * Running in an asyncExec because the selectAll() does not
-				 * appear to work when using mouse to give focus to text.
-				 */
-				Display display = filterText.getDisplay();
-				display.asyncExec(new Runnable() {
-					public void run() {
-						if (!filterText.isDisposed()) {
-							if (getInitialText().equals(filterText.getText().trim())) {
-								filterText.selectAll();
-							}
-						}
-					}
-				});
-			}
-		});
-
-		filterText.addKeyListener(new KeyAdapter() {
-			@Override
-			public void keyPressed(KeyEvent e) {
-				// on a CR we want to transfer focus to the list
-				boolean hasItems = getViewer().getTree().getItemCount() > 0;
-				if (hasItems && e.keyCode == SWT.ARROW_DOWN) {
-					// treeViewer.getTree().setFocus();
-				} else if (e.character == SWT.CR) {
-					textChanged();
-					// return;
-				} else if (e.character == SWT.ESC) {
-					setFilterText("");
-					textChanged();
-				}
-			}
-		});
-
-		// enter key set focus to tree
-		filterText.addTraverseListener(new TraverseListener() {
-			public void keyTraversed(TraverseEvent e) {
-				if (e.detail == SWT.TRAVERSE_RETURN) {
-					e.doit = false;
-					if (getViewer().getTree().getItemCount() == 0) {
-						Display.getCurrent().beep();
-					} else {
-						// if the initial filter text hasn't changed, do not try
-						// to match
-						// boolean hasFocus = getViewer().getTree().setFocus();
-						// boolean textChanged =
-						// !getInitialText().equals(filterText.getText().trim());
-						// if (hasFocus && textChanged &&
-						// filterText.getText().trim().length() > 0) {
-						// TreeItem item =
-						// getFirstMatchingItem(getViewer().getTree().getItems());
-						// if (item != null) {
-						// getViewer().getTree().setSelection(new TreeItem[] {
-						// item });
-						// ISelection sel = getViewer().getSelection();
-						// getViewer().setSelection(sel, true);
-						// }
-						// }
-					}
-				}
-			}
-		});
-
-		filterText.addModifyListener(new ModifyListener() {
-			/*
-			 * (non-Javadoc)
-			 * 
-			 * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
-			 */
-			public void modifyText(ModifyEvent e) {
-				// textChanged();
-			}
-		});
-		filterText.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
-	}
-
-	@Override
-	public void setBackground(Color background) {
-		super.setBackground(background);
-		if (filterComposite != null) {
-			filterComposite.setBackground(background);
-		}
-		if (filterToolBar != null && filterToolBar.getControl() != null) {
-			filterToolBar.getControl().setBackground(background);
-		}
-	}
-
-	private void createClearText(Composite parent) {
-		ToolBar toolBar = new ToolBar(parent, SWT.FLAT | SWT.HORIZONTAL);
-		filterToolBar = new ToolBarManager(toolBar);
-
-		IAction clearTextAction = new Action("", IAction.AS_PUSH_BUTTON) {//$NON-NLS-1$
-			/*
-			 * (non-Javadoc)
-			 * 
-			 * @see org.eclipse.jface.action.Action#run()
-			 */
-			@Override
-			public void run() {
-				clearText();
-			}
-		};
-
-		clearTextAction.setToolTipText(WorkbenchMessages.FilteredTree_ClearToolTip);
-		clearTextAction.setImageDescriptor(JFaceResources.getImageRegistry().getDescriptor(CLEAR_ICON));
-		clearTextAction.setDisabledImageDescriptor(JFaceResources.getImageRegistry().getDescriptor(DCLEAR_ICON));
-
-		filterToolBar.add(clearTextAction);
-	}
-
-	protected void clearText() {
-		setFilterText(""); //$NON-NLS-1$
-		textChanged();
-	}
-
-	protected void setFilterText(String string) {
-		if (filterText != null) {
-			filterText.setText(string);
-			selectAll();
-		}
-	}
-
-	public final PatternFilter getPatternFilter() {
-		return patternFilter;
-	}
-
-	public TreeViewer getViewer() {
-		return treeViewer;
-	}
-
-	public Text getFilterControl() {
-		return filterText;
-	}
-
-	protected String getFilterString() {
-		return filterText != null ? filterText.getText() : null;
-	}
-
-	public void setInitialText(String text) {
-		initialText = text;
-		setFilterText(initialText);
-		textChanged();
-	}
-
-	protected void selectAll() {
-		if (filterText != null) {
-			filterText.selectAll();
-		}
-	}
-
-	protected String getInitialText() {
-		return initialText;
-	}
-
-	public static Font getBoldFont(Object element, NavigatorFilterBar tree, ResourcePatternFilter filter) {
-		String filterText = tree.getFilterString();
-
-		if (filterText == null) {
-			return null;
-		}
-
-		// Do nothing if it's empty string
-		String initialText = tree.getInitialText();
-		if (!("".equals(filterText) || initialText.equals(filterText))) {//$NON-NLS-1$
-			boolean initial = initialText != null && initialText.equals(filterText);
-			if (initial) {
-				filter.setPattern(null);
-			} else if (filterText != null) {
-				filter.setPattern(filterText);
-			}
-
-			if (filter.isElementVisible(tree.getViewer(), element) && filter.isLeafMatch(tree.getViewer(), element)) {
-				return JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT);
-			}
-		}
-		return null;
-	}
-
-	public AdaptiveRefreshPolicy getRefreshPolicy() {
-		return refreshPolicy;
-	}
-
-}
diff --git a/org.eclipse.mylyn.ide.ui/plugin.xml b/org.eclipse.mylyn.ide.ui/plugin.xml
index 83f6e14..ad6dd33 100644
--- a/org.eclipse.mylyn.ide.ui/plugin.xml
+++ b/org.eclipse.mylyn.ide.ui/plugin.xml
@@ -72,7 +72,7 @@
 		id="org.eclipse.mylar.ui.resource.navigator.filter" 
    		targetID="org.eclipse.ui.views.ResourceNavigator">
     	<action
-           class="org.eclipse.mylar.internal.ide.ui.actions.FocusNavigatorAction"
+           class="org.eclipse.mylar.internal.ide.ui.actions.FocusResourceNavigatorAction"
            enablesFor="*"
            icon="icons/elcl16/interest-filtering.gif"
            id="org.eclipse.mylar.ui.actions.FilterResourceNavigatorAction"
diff --git a/org.eclipse.mylyn.ide.ui/src/org/eclipse/mylyn/internal/ide/ui/actions/FocusProjectExplorerAction.java b/org.eclipse.mylyn.ide.ui/src/org/eclipse/mylyn/internal/ide/ui/actions/FocusProjectExplorerAction.java
index ae909cb..7715505 100644
--- a/org.eclipse.mylyn.ide.ui/src/org/eclipse/mylyn/internal/ide/ui/actions/FocusProjectExplorerAction.java
+++ b/org.eclipse.mylyn.ide.ui/src/org/eclipse/mylyn/internal/ide/ui/actions/FocusProjectExplorerAction.java
@@ -14,33 +14,16 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
-import org.eclipse.jface.text.ITextSelection;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.StructuredSelection;
 import org.eclipse.jface.viewers.StructuredViewer;
 import org.eclipse.mylar.context.ui.InterestFilter;
-import org.eclipse.mylar.internal.context.ui.actions.AbstractAutoFocusViewAction;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IEditorPart;
+import org.eclipse.mylar.internal.resources.ui.FocusCommonNavigatorAction;
 import org.eclipse.ui.IViewPart;
-import org.eclipse.ui.internal.navigator.NavigatorContentService;
-import org.eclipse.ui.internal.navigator.extensions.LinkHelperService;
 import org.eclipse.ui.navigator.CommonNavigator;
-import org.eclipse.ui.navigator.ILinkHelper;
 
 /**
  * @author Mik Kersten
  */
-public class FocusProjectExplorerAction extends AbstractAutoFocusViewAction {
-
-	private LinkHelperService linkService;
-
-	private CommonNavigator commonNavigator;
-
-	// private boolean wasLinkingEnabled = false;
+public class FocusProjectExplorerAction extends FocusCommonNavigatorAction {
 
 	public FocusProjectExplorerAction() {
 		super(new InterestFilter(), true, true, true);
@@ -50,138 +33,6 @@
 		super(filter, true, true, true);
 	}
 
-	// @Override
-	// public void init(IAction action) {
-	// super.init(action);
-	// }
-
-	@Override
-	protected ISelection resolveSelection(IEditorPart editor, ITextSelection changedSelection, StructuredViewer viewer)
-			throws CoreException {
-		if (commonNavigator == null) {
-			commonNavigator = (CommonNavigator) super.getPartForAction();
-		}
-		if (linkService == null) {
-			linkService = new LinkHelperService((NavigatorContentService) commonNavigator.getCommonViewer()
-					.getNavigatorContentService());
-		}
-
-		IEditorInput input = editor.getEditorInput();
-		ILinkHelper[] helpers = linkService.getLinkHelpersFor(editor.getEditorInput());
-
-		IStructuredSelection selection = StructuredSelection.EMPTY;
-		IStructuredSelection newSelection = StructuredSelection.EMPTY;
-
-		for (int i = 0; i < helpers.length; i++) {
-			selection = helpers[i].findSelection(input);
-			if (selection != null && !selection.isEmpty()) {
-				newSelection = mergeSelection(newSelection, selection);
-			}
-		}
-		if (!newSelection.isEmpty()) {
-			return newSelection;
-		}
-		return null;
-	}
-	
-	@Override
-	protected void select(StructuredViewer viewer, ISelection toSelect) {
-		if (commonNavigator == null) {
-			commonNavigator = (CommonNavigator) super.getPartForAction();
-		}
-		if (commonNavigator != null) {
-			commonNavigator.selectReveal(toSelect);
-		}
-	}
-
-	@Override
-	protected void setDefaultLinkingEnabled(boolean on) {
-		IViewPart part = super.getPartForAction();
-		if (part instanceof CommonNavigator) {
-			((CommonNavigator) part).setLinkingEnabled(on);
-		}
-	}
-
-	@Override
-	protected boolean isDefaultLinkingEnabled() {
-		IViewPart part = super.getPartForAction();
-		if (part instanceof CommonNavigator) {
-			return ((CommonNavigator) part).isLinkingEnabled();
-		}
-		return false;
-	}
-
-	// @Override
-	// public void run(IAction action) {
-	// super.run(action);
-	// updateSelection();
-	// updateLinking();
-	// }
-
-	// private void updateLinking() {
-	// IViewPart view = super.getPartForAction();
-	// if (view instanceof CommonNavigator) {
-	// CommonNavigator navigator = (CommonNavigator) view;
-	// if (super.isChecked()) {
-	// wasLinkingEnabled = navigator.isLinkingEnabled();
-	// navigator.setLinkingEnabled(false);
-	// } else {
-	// navigator.setLinkingEnabled(wasLinkingEnabled);
-	// }
-	// }
-	// }
-
-	// private void updateSelection() {
-	// if (commonNavigator == null) {
-	// commonNavigator = (CommonNavigator) super.getPartForAction();
-	// }
-	// if (linkService == null) {
-	// linkService = new LinkHelperService((NavigatorContentService)
-	// commonNavigator.getCommonViewer()
-	// .getNavigatorContentService());
-	// }
-	//
-	// IEditorPart activeEditor =
-	// PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
-	// .getActiveEditor();
-	// if (activeEditor != null) {
-	// ILinkHelper[] helpers =
-	// linkService.getLinkHelpersFor(activeEditor.getEditorInput());
-	// IEditorInput input = activeEditor.getEditorInput();
-	//
-	// IStructuredSelection selection = StructuredSelection.EMPTY;
-	// IStructuredSelection newSelection = StructuredSelection.EMPTY;
-	//
-	// for (int i = 0; i < helpers.length; i++) {
-	// selection = helpers[i].findSelection(input);
-	// if (selection != null && !selection.isEmpty()) {
-	// newSelection = mergeSelection(newSelection, selection);
-	// }
-	// }
-	// if (!newSelection.isEmpty()) {
-	// commonNavigator.selectReveal(newSelection);
-	// }
-	// }
-	// }
-
-	/**
-	 * Copied from
-	 * 
-	 * @{link LinkEditorAction}
-	 */
-	@SuppressWarnings("unchecked")
-	private IStructuredSelection mergeSelection(IStructuredSelection aBase, IStructuredSelection aSelectionToAppend) {
-		if (aBase == null || aBase.isEmpty()) {
-			return (aSelectionToAppend != null) ? aSelectionToAppend : StructuredSelection.EMPTY;
-		} else if (aSelectionToAppend == null || aSelectionToAppend.isEmpty()) {
-			return aBase;
-		} else {
-			List newItems = new ArrayList(aBase.toList());
-			newItems.addAll(aSelectionToAppend.toList());
-			return new StructuredSelection(newItems);
-		}
-	}
-
 	@Override
 	public List<StructuredViewer> getViewers() {
 		List<StructuredViewer> viewers = new ArrayList<StructuredViewer>();
@@ -194,8 +45,4 @@
 		return viewers;
 	}
 
-	public void propertyChange(PropertyChangeEvent event) {
-		// TODO Auto-generated method stub
-	}
-
 }
diff --git a/org.eclipse.mylyn.ide.ui/src/org/eclipse/mylyn/internal/ide/ui/actions/FocusNavigatorAction.java b/org.eclipse.mylyn.ide.ui/src/org/eclipse/mylyn/internal/ide/ui/actions/FocusResourceNavigatorAction.java
similarity index 95%
rename from org.eclipse.mylyn.ide.ui/src/org/eclipse/mylyn/internal/ide/ui/actions/FocusNavigatorAction.java
rename to org.eclipse.mylyn.ide.ui/src/org/eclipse/mylyn/internal/ide/ui/actions/FocusResourceNavigatorAction.java
index c53252c..7025e5a 100644
--- a/org.eclipse.mylyn.ide.ui/src/org/eclipse/mylyn/internal/ide/ui/actions/FocusNavigatorAction.java
+++ b/org.eclipse.mylyn.ide.ui/src/org/eclipse/mylyn/internal/ide/ui/actions/FocusResourceNavigatorAction.java
@@ -31,9 +31,9 @@
 /**
  * @author Mik Kersten
  */
-public class FocusNavigatorAction extends AbstractAutoFocusViewAction {
+public class FocusResourceNavigatorAction extends AbstractAutoFocusViewAction {
 
-	public FocusNavigatorAction() {
+	public FocusResourceNavigatorAction() {
 		super(new InterestFilter(), true, true, true);
 	}
 
diff --git a/org.eclipse.mylyn.java.ui/plugin.xml b/org.eclipse.mylyn.java.ui/plugin.xml
index 1665767..0a93fbf 100644
--- a/org.eclipse.mylyn.java.ui/plugin.xml
+++ b/org.eclipse.mylyn.java.ui/plugin.xml
@@ -40,7 +40,7 @@
           <filter
                 class="org.eclipse.jdt.internal.ui.filters.ClosedProjectFilter">
           </filter>
-      </preservedFilters>
+        </preservedFilters>
         <preservedFilters
               viewId="org.eclipse.ui.navigator.ProjectExplorer">
            <filter