Bug 437478 - [context spy] the search should propose an option to
display only the results 

Change-Id: Ieb6dac27cad93c166e538c12a1d91337a5a98672
Signed-off-by: Olivier Prouvost <olivier.prouvost@opcoach.com>
diff --git a/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextDataFilter.java b/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextDataFilter.java
new file mode 100644
index 0000000..54ee7fe
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextDataFilter.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2014 OPCoach.
+ * 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:
+ *     OPCoach - initial API and implementation for bug #437478
+ *******************************************************************************/
+package org.eclipse.e4.internal.tools.context.spy;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Creatable;
+import org.eclipse.e4.core.internal.contexts.Computation;
+import org.eclipse.e4.core.internal.contexts.EclipseContext;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+
+@Creatable
+@Singleton
+public class ContextDataFilter extends ViewerFilter
+{
+	
+	@Inject
+	Logger log;
+
+	private String pattern;
+
+	// Implements the filter for the data table content
+	@Override
+	public boolean select(Viewer viewer, Object parentElement, Object element)
+	{
+		if ((element == ContextDataProvider.LOCAL_VALUE_NODE) || (element == ContextDataProvider.INHERITED_INJECTED_VALUE_NODE))
+			return true;
+
+		// Must only select objects matching the pattern or objects under a kept
+		// node (to see where it is injected)
+		TreeViewer tv = (TreeViewer) viewer;
+		ContextDataProvider lpkey = (ContextDataProvider) tv.getLabelProvider(0);
+		ContextDataProvider lpval = (ContextDataProvider) tv.getLabelProvider(1);
+
+		// If the text matches in one of the column, must keep it...
+		String skey = lpkey.getText(element);
+		String sval = lpval.getText(element);
+
+		// Must also keep the listener elements if the parent is selected ->
+		// Must compute parent keys
+		String sparentkey = lpkey.getText(parentElement);
+		String sparentval = lpval.getText(parentElement);
+
+		Set<Computation> listeners = lpkey.getListeners(parentElement);
+		boolean mustKeepParent = (matchText(sparentkey) || matchText(sparentval)) && (listeners != null)
+				&& (listeners.size() > 0);
+		boolean mustKeepElement = matchText(skey) || matchText(sval);
+
+		return mustKeepElement || (!mustKeepElement && mustKeepParent);
+
+	}
+
+
+
+	/** Set the pattern and use it as lowercase */
+	public void setPattern(String newPattern)
+	{
+		if ((newPattern == null) || (newPattern.length() == 0))
+			pattern = null;
+		else
+			pattern = newPattern.toLowerCase();
+	}
+
+	/**
+	 * This method search for an object and check if it contains the text or a
+	 * pattern matching this text
+	 */
+	public boolean containsText(IEclipseContext ctx)
+	{
+		// It is useless to store the values in a map, because context changes
+		// everytime and it should be tracked.
+		Collection<String> values = computeValues(ctx);
+
+		// Search if string is just in one of the values... manage ignore case
+		// and contain...
+		boolean found = false;
+		for (String s : values)
+		{
+			if (matchText(s))
+			{
+				found = true;
+				break;
+			}
+		}
+		return found;
+	}
+
+	public boolean matchText(String text)
+	{
+		return ((text == null) || (pattern == null)) ? false : text.toLowerCase().contains(pattern);
+	}
+
+	/**
+	 * Extract all string values in context
+	 * 
+	 * @param ctx
+	 * @return
+	 */
+	@SuppressWarnings("restriction")
+	private Collection<String> computeValues(IEclipseContext ctx)
+	{
+		Collection<String> result = new ArrayList<String>();
+		if (ctx instanceof EclipseContext)
+		{
+			// Search for all strings in this context (values and context
+			// function)
+
+			EclipseContext currentContext = (EclipseContext) ctx;
+			extractStringsFromMap(currentContext.localData(), result);
+
+			// Search also in context functions
+			extractStringsFromMap(currentContext.localContextFunction(), result);
+
+			// Search for the inherited values injected using this context but
+			// defined in
+			// parent
+			// Keep only the names that are not already displayed in local
+			// values
+			Collection<String> localKeys = currentContext.localData().keySet();
+			Collection<String> localContextFunctionsKeys = currentContext.localContextFunction().keySet();
+
+			if (currentContext.getRawListenerNames() != null)
+			{
+				for (String name : currentContext.getRawListenerNames())
+				{
+					if (!localKeys.contains(name) && !localContextFunctionsKeys.contains(name))
+						result.add(name);
+				}
+			}
+
+		} else
+		{
+			log.warn("Warning : the received EclipseContext has not the expected type. It is a : " + ctx.getClass().toString());
+		}
+
+		return result;
+	}
+
+	/**
+	 * 
+	 * @param map
+	 *            the map to extract the strings (keys and values)
+	 * @param result
+	 *            the result to fill with strings
+	 */
+	private void extractStringsFromMap(Map<String, Object> map, Collection<String> result)
+	{
+		for (Map.Entry<String, Object> entry : map.entrySet())
+		{
+			result.add(entry.getKey().toString());
+			Object value = entry.getValue();
+			if (value != null)
+			{
+				result.add(value.toString());
+			}
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextDataPart.java b/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextDataPart.java
index da18729..5f55704 100644
--- a/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextDataPart.java
+++ b/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextDataPart.java
@@ -27,6 +27,7 @@
 import org.eclipse.jface.viewers.TreeViewerColumn;
 import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.jface.viewers.ViewerFilter;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
@@ -215,4 +216,12 @@
 		contextDataViewer.refresh(refreshLabel);
 	}
 
+	
+	private static final ViewerFilter[] NO_FILTER = new ViewerFilter[0];
+	public void setFilter(ViewerFilter filter)
+	{
+		
+		contextDataViewer.setFilters((filter == null) ? NO_FILTER : new ViewerFilter[] { filter });
+	}
+
 }
diff --git a/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextDataProvider.java b/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextDataProvider.java
index 218a48b..22d4a4c 100644
--- a/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextDataProvider.java
+++ b/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextDataProvider.java
@@ -20,7 +20,6 @@
 
 import org.eclipse.e4.core.internal.contexts.Computation;
 import org.eclipse.e4.core.internal.contexts.EclipseContext;
-import org.eclipse.e4.internal.tools.context.spy.search.ContextRegistry;
 import org.eclipse.jface.resource.FontRegistry;
 import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.jface.resource.ImageRegistry;
@@ -71,7 +70,7 @@
 	private ImageRegistry imgReg;
 
 	@Inject
-	private ContextRegistry contextRegistry;
+	private ContextDataFilter contextFilter;
 
 	/** Store the selected context (initialized in inputChanged) */
 	@SuppressWarnings("restriction")
@@ -215,7 +214,7 @@
 			return COLOR_IF_NOT_COMPUTED;
 
 		// Return blue color if the string matches the search
-		return (contextRegistry.matchText(s)) ? COLOR_IF_FOUND : null;
+		return (contextFilter.matchText(s)) ? COLOR_IF_FOUND : null;
 	}
 
 	/** Get the bold font for keys that are computed with ContextFunction */
@@ -361,9 +360,8 @@
 	}
 
 	@SuppressWarnings({ "restriction", "unchecked" })
-	private Set<Computation> getListeners(Object element)
+	Set<Computation> getListeners(Object element)
 	{
-
 		if (selectedContext != null)
 		{
 			if (element instanceof Map.Entry)
diff --git a/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextSpyProvider.java b/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextSpyProvider.java
index c938b3f..6d82469 100644
--- a/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextSpyProvider.java
+++ b/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/ContextSpyProvider.java
@@ -16,7 +16,6 @@
 
 import org.eclipse.e4.core.contexts.IEclipseContext;
 import org.eclipse.e4.core.internal.contexts.EclipseContext;
-import org.eclipse.e4.internal.tools.context.spy.search.ContextRegistry;
 import org.eclipse.e4.ui.model.application.MApplication;
 import org.eclipse.jface.viewers.IColorProvider;
 import org.eclipse.jface.viewers.ITreeContentProvider;
@@ -36,7 +35,7 @@
 {
 
 	@Inject
-	private ContextRegistry contextRegistry;
+	private ContextDataFilter contextFilter;
 
 	@Inject
 	public ContextSpyProvider()
@@ -104,7 +103,7 @@
 	public Color getForeground(Object element)
 	{
 		// Return a color if a text contained in this node contains the text.
-		if (element instanceof IEclipseContext && contextRegistry.containsText((IEclipseContext) element))
+		if (element instanceof IEclipseContext && contextFilter.containsText((IEclipseContext) element))
 		{
 			return Display.getCurrent().getSystemColor(SWT.COLOR_BLUE);
 		}
diff --git a/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/search/ContextRegistry.java b/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/search/ContextRegistry.java
deleted file mode 100644
index ee3f2c7..0000000
--- a/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/search/ContextRegistry.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2013 OPCoach.
- * 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:
- *     OPCoach - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.internal.tools.context.spy.search;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Map;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import org.eclipse.e4.core.contexts.IEclipseContext;
-import org.eclipse.e4.core.di.annotations.Creatable;
-import org.eclipse.e4.core.internal.contexts.EclipseContext;
-import org.eclipse.e4.core.services.log.Logger;
-
-/**
- * Register for each context in the application, all strings for keys and values
- * so as to filter the tree the main map contains : an IEclipseContext as a key
- * a list of strings present in this context *
- * 
- * @author olivier
- * 
- */
-@Creatable
-@Singleton
-public class ContextRegistry
-{
-
-	@Inject
-	Logger log;
-
-	private StringMatcher matcher;
-
-	private String pattern;
-
-	private boolean ignoreCase;
-
-	private boolean ignoreWildCards;
-
-
-	public void setPattern(String newPattern)
-	{
-		pattern = newPattern;
-	}
-
-	public void setIgnoreCase(boolean newIgnoreCase)
-	{
-		ignoreCase = newIgnoreCase;
-	}
-
-	public void setIgnoreWildCards(boolean ignoreWildCards)
-	{
-		this.ignoreWildCards = ignoreWildCards;
-	}
-	
-
-
-	/**
-	 * This method search for an object and check if it contains the text or a
-	 * pattern matching this text
-	 */
-	public boolean containsText(IEclipseContext ctx)
-	{
-		if (pattern == null)
-		{
-			pattern = "";
-		}
-		matcher = new StringMatcher(pattern, ignoreCase, ignoreWildCards);
-
-		// It is useless to store the values in a map, because context changes
-		// everytime and it should be tracked.
-		Collection<String> values = computeValues(ctx);
-
-		// Search for a string matching the pattern
-		boolean found = false;
-		for (String s : values)
-		{
-			if (matchText(s))
-			{
-				found = true;
-				break;
-			}
-		}
-		return found;
-	}
-
-	public boolean matchText(String text)
-	{
-		return (matcher != null) && matcher.match(text);
-	}
-	
-
-
-	/**
-	 * Extract all string values in context
-	 * 
-	 * @param ctx
-	 * @return
-	 */
-	@SuppressWarnings("restriction")
-	private Collection<String> computeValues(IEclipseContext ctx)
-	{
-		Collection<String> result = new ArrayList<String>();
-		if (ctx instanceof EclipseContext)
-		{
-			// Search for all strings in this context (values and context function)
-			
-			EclipseContext currentContext = (EclipseContext) ctx;
-			extractStringsFromMap(currentContext.localData(), result);
-
-			// Search also in context functions
-				extractStringsFromMap(currentContext.localContextFunction(), result);
-			
-			
-			// Search for the inherited values injected using this context but defined in
-			// parent
-			// Keep only the names that are not already displayed in local
-			// values
-			Collection<String> localKeys = currentContext.localData().keySet();
-			Collection<String> localContextFunctionsKeys = currentContext.localContextFunction().keySet();
-
-			if (currentContext.getRawListenerNames() != null)
-			{
-				for (String name : currentContext.getRawListenerNames())
-				{
-					if (!localKeys.contains(name) && !localContextFunctionsKeys.contains(name))
-						result.add(name);
-				}
-			}
-
-		} else
-		{
-			log.warn("Warning : the received EclipseContext has not the expected type. It is a : " + ctx.getClass().toString());
-		}
-		
-		return result;
-	}
-
-	/**
-	 * 
-	 * @param map the map to extract the strings (keys and values)
-	 * @param result the result to fill with strings
-	 */
-	private void extractStringsFromMap(Map<String, Object> map, Collection<String> result)
-	{
-		for (Map.Entry<String, Object> entry : map.entrySet())
-		{
-			result.add(entry.getKey().toString());
-			Object value = entry.getValue();
-			if (value != null)
-			{
-				result.add(value.toString());
-			}
-		}
-	}
-
-}
diff --git a/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/search/StringMatcher.java b/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/search/StringMatcher.java
deleted file mode 100644
index ebfd27c..0000000
--- a/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/internal/tools/context/spy/search/StringMatcher.java
+++ /dev/null
@@ -1,452 +0,0 @@
-package org.eclipse.e4.internal.tools.context.spy.search;
-
-/*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation 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:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-import java.util.Vector;
-
-/**
- * A string pattern matcher, suppporting "*" and "?" wildcards.
- */
-public class StringMatcher {
-    protected String fPattern;
-
-    protected int fLength; // pattern length
-
-    protected boolean fIgnoreWildCards;
-
-    protected boolean fIgnoreCase;
-
-    protected boolean fHasLeadingStar;
-
-    protected boolean fHasTrailingStar;
-
-    protected String fSegments[]; //the given pattern is split into * separated segments
-
-    /* boundary value beyond which we don't need to search in the text */
-    protected int fBound = 0;
-
-    protected static final char fSingleWildCard = '\u0000';
-
-    public static class Position {
-        int start; //inclusive
-
-        int end; //exclusive
-
-        public Position(int start, int end) {
-            this.start = start;
-            this.end = end;
-        }
-
-        public int getStart() {
-            return start;
-        }
-
-        public int getEnd() {
-            return end;
-        }
-    }
-
-    /**
-     * StringMatcher constructor takes in a String object that is a simple 
-     * pattern which may contain '*' for 0 and many characters and
-     * '?' for exactly one character.  
-     *
-     * Literal '*' and '?' characters must be escaped in the pattern 
-     * e.g., "\*" means literal "*", etc.
-     *
-     * Escaping any other character (including the escape character itself), 
-     * just results in that character in the pattern.
-     * e.g., "\a" means "a" and "\\" means "\"
-     *
-     * If invoking the StringMatcher with string literals in Java, don't forget
-     * escape characters are represented by "\\".
-     *
-     * @param pattern the pattern to match text against
-     * @param ignoreCase if true, case is ignored
-     * @param ignoreWildCards if true, wild cards and their escape sequences are ignored
-     * 		  (everything is taken literally).
-     */
-    public StringMatcher(String pattern, boolean ignoreCase,
-            boolean ignoreWildCards) {
-        if (pattern == null) {
-			throw new IllegalArgumentException();
-		}
-        fIgnoreCase = ignoreCase;
-        fIgnoreWildCards = ignoreWildCards;
-        fPattern = pattern;
-        fLength = pattern.length();
-
-        if (fIgnoreWildCards) {
-            parseNoWildCards();
-        } else {
-            parseWildCards();
-        }
-    }
-
-    /**
-     * Find the first occurrence of the pattern between <code>start</code)(inclusive) 
-     * and <code>end</code>(exclusive).  
-     * @param text the String object to search in 
-     * @param start the starting index of the search range, inclusive
-     * @param end the ending index of the search range, exclusive
-     * @return an <code>StringMatcher.Position</code> object that keeps the starting 
-     * (inclusive) and ending positions (exclusive) of the first occurrence of the 
-     * pattern in the specified range of the text; return null if not found or subtext
-     * is empty (start==end). A pair of zeros is returned if pattern is empty string
-     * Note that for pattern like "*abc*" with leading and trailing stars, position of "abc"
-     * is returned. For a pattern like"*??*" in text "abcdf", (1,3) is returned
-     */
-    public StringMatcher.Position find(String text, int start, int end) {
-        if (text == null) {
-			throw new IllegalArgumentException();
-		}
-
-        int tlen = text.length();
-        if (start < 0) {
-			start = 0;
-		}
-        if (end > tlen) {
-			end = tlen;
-		}
-        if (end < 0 || start >= end) {
-			return null;
-		}
-        if (fLength == 0) {
-			return new Position(start, start);
-		}
-        if (fIgnoreWildCards) {
-            int x = posIn(text, start, end);
-            if (x < 0) {
-				return null;
-			}
-            return new Position(x, x + fLength);
-        }
-
-        int segCount = fSegments.length;
-        if (segCount == 0) {
-			return new Position(start, end);
-		}
-
-        int curPos = start;
-        int matchStart = -1;
-        int i;
-        for (i = 0; i < segCount && curPos < end; ++i) {
-            String current = fSegments[i];
-            int nextMatch = regExpPosIn(text, curPos, end, current);
-            if (nextMatch < 0) {
-				return null;
-			}
-            if (i == 0) {
-				matchStart = nextMatch;
-			}
-            curPos = nextMatch + current.length();
-        }
-        if (i < segCount) {
-			return null;
-		}
-        return new Position(matchStart, curPos);
-    }
-
-    /**
-     * match the given <code>text</code> with the pattern 
-     * @return true if matched otherwise false
-     * @param text a String object 
-     */
-    public boolean match(String text) {
-    	if(text == null) {
-			return false;
-		}
-        return match(text, 0, text.length());
-    }
-
-    /**
-     * Given the starting (inclusive) and the ending (exclusive) positions in the   
-     * <code>text</code>, determine if the given substring matches with aPattern  
-     * @return true if the specified portion of the text matches the pattern
-     * @param text a String object that contains the substring to match 
-     * @param start marks the starting position (inclusive) of the substring
-     * @param end marks the ending index (exclusive) of the substring 
-     */
-    public boolean match(String text, int start, int end) {
-        if (null == text) {
-			throw new IllegalArgumentException();
-		}
-
-        if (start > end) {
-			return false;
-		}
-
-        if (fIgnoreWildCards) {
-			return (end - start == fLength)
-                    && fPattern.regionMatches(fIgnoreCase, 0, text, start,
-                            fLength);
-		}
-        int segCount = fSegments.length;
-        if (segCount == 0 && (fHasLeadingStar || fHasTrailingStar)) {
-			return true;
-		}
-        if (start == end) {
-			return fLength == 0;
-		}
-        if (fLength == 0) {
-			return start == end;
-		}
-
-        int tlen = text.length();
-        if (start < 0) {
-			start = 0;
-		}
-        if (end > tlen) {
-			end = tlen;
-		}
-
-        int tCurPos = start;
-        int bound = end - fBound;
-        if (bound < 0) {
-			return false;
-		}
-        int i = 0;
-        String current = fSegments[i];
-        int segLength = current.length();
-
-        /* process first segment */
-        if (!fHasLeadingStar) {
-            if (!regExpRegionMatches(text, start, current, 0, segLength)) {
-                return false;
-            } else {
-                ++i;
-                tCurPos = tCurPos + segLength;
-            }
-        }
-        if ((fSegments.length == 1) && (!fHasLeadingStar)
-                && (!fHasTrailingStar)) {
-            // only one segment to match, no wildcards specified
-            return tCurPos == end;
-        }
-        /* process middle segments */
-        while (i < segCount) {
-            current = fSegments[i];
-            int currentMatch;
-            int k = current.indexOf(fSingleWildCard);
-            if (k < 0) {
-                currentMatch = textPosIn(text, tCurPos, end, current);
-                if (currentMatch < 0) {
-					return false;
-				}
-            } else {
-                currentMatch = regExpPosIn(text, tCurPos, end, current);
-                if (currentMatch < 0) {
-					return false;
-				}
-            }
-            tCurPos = currentMatch + current.length();
-            i++;
-        }
-
-        /* process final segment */
-        if (!fHasTrailingStar && tCurPos != end) {
-            int clen = current.length();
-            return regExpRegionMatches(text, end - clen, current, 0, clen);
-        }
-        return i == segCount;
-    }
-
-    /**
-     * This method parses the given pattern into segments seperated by wildcard '*' characters.
-     * Since wildcards are not being used in this case, the pattern consists of a single segment.
-     */
-    private void parseNoWildCards() {
-        fSegments = new String[1];
-        fSegments[0] = fPattern;
-        fBound = fLength;
-    }
-
-    /**
-     * Parses the given pattern into segments seperated by wildcard '*' characters.
-     * @param p, a String object that is a simple regular expression with '*' and/or '?'
-     */
-    private void parseWildCards() {
-        if (fPattern.startsWith("*")) { //$NON-NLS-1$
-			fHasLeadingStar = true;
-		}
-        if (fPattern.endsWith("*")) {//$NON-NLS-1$
-            /* make sure it's not an escaped wildcard */
-            if (fLength > 1 && fPattern.charAt(fLength - 2) != '\\') {
-                fHasTrailingStar = true;
-            }
-        }
-
-        Vector<String> temp = new Vector<String>();
-
-        int pos = 0;
-        StringBuffer buf = new StringBuffer();
-        while (pos < fLength) {
-            char c = fPattern.charAt(pos++);
-            switch (c) {
-            case '\\':
-                if (pos >= fLength) {
-                    buf.append(c);
-                } else {
-                    char next = fPattern.charAt(pos++);
-                    /* if it's an escape sequence */
-                    if (next == '*' || next == '?' || next == '\\') {
-                        buf.append(next);
-                    } else {
-                        /* not an escape sequence, just insert literally */
-                        buf.append(c);
-                        buf.append(next);
-                    }
-                }
-                break;
-            case '*':
-                if (buf.length() > 0) {
-                    /* new segment */
-                    temp.addElement(buf.toString());
-                    fBound += buf.length();
-                    buf.setLength(0);
-                }
-                break;
-            case '?':
-                /* append special character representing single match wildcard */
-                buf.append(fSingleWildCard);
-                break;
-            default:
-                buf.append(c);
-            }
-        }
-
-        /* add last buffer to segment list */
-        if (buf.length() > 0) {
-            temp.addElement(buf.toString());
-            fBound += buf.length();
-        }
-
-        fSegments = new String[temp.size()];
-        temp.copyInto(fSegments);
-    }
-
-    /** 
-     * @param text a string which contains no wildcard
-     * @param start the starting index in the text for search, inclusive
-     * @param end the stopping point of search, exclusive
-     * @return the starting index in the text of the pattern , or -1 if not found 
-     */
-    protected int posIn(String text, int start, int end) {//no wild card in pattern
-        int max = end - fLength;
-
-        if (!fIgnoreCase) {
-            int i = text.indexOf(fPattern, start);
-            if (i == -1 || i > max) {
-				return -1;
-			}
-            return i;
-        }
-
-        for (int i = start; i <= max; ++i) {
-            if (text.regionMatches(true, i, fPattern, 0, fLength)) {
-				return i;
-			}
-        }
-
-        return -1;
-    }
-
-    /** 
-     * @param text a simple regular expression that may only contain '?'(s)
-     * @param start the starting index in the text for search, inclusive
-     * @param end the stopping point of search, exclusive
-     * @param p a simple regular expression that may contains '?'
-     * @return the starting index in the text of the pattern , or -1 if not found 
-     */
-    protected int regExpPosIn(String text, int start, int end, String p) {
-        int plen = p.length();
-
-        int max = end - plen;
-        for (int i = start; i <= max; ++i) {
-            if (regExpRegionMatches(text, i, p, 0, plen)) {
-				return i;
-			}
-        }
-        return -1;
-    }
-
-    /**
-     * 
-     * @return boolean
-     * @param text a String to match
-     * @param start int that indicates the starting index of match, inclusive
-     * @param end</code> int that indicates the ending index of match, exclusive
-     * @param p String,  String, a simple regular expression that may contain '?'
-     * @param ignoreCase boolean indicating wether code>p</code> is case sensitive
-     */
-    protected boolean regExpRegionMatches(String text, int tStart, String p,
-            int pStart, int plen) {
-        while (plen-- > 0) {
-            char tchar = text.charAt(tStart++);
-            char pchar = p.charAt(pStart++);
-
-            /* process wild cards */
-            if (!fIgnoreWildCards) {
-                /* skip single wild cards */
-                if (pchar == fSingleWildCard) {
-                    continue;
-                }
-            }
-            if (pchar == tchar) {
-				continue;
-			}
-            if (fIgnoreCase) {
-                if (Character.toUpperCase(tchar) == Character
-                        .toUpperCase(pchar)) {
-					continue;
-				}
-                // comparing after converting to upper case doesn't handle all cases;
-                // also compare after converting to lower case
-                if (Character.toLowerCase(tchar) == Character
-                        .toLowerCase(pchar)) {
-					continue;
-				}
-            }
-            return false;
-        }
-        return true;
-    }
-
-    /** 
-     * @param text the string to match
-     * @param start the starting index in the text for search, inclusive
-     * @param end the stopping point of search, exclusive
-     * @param p a pattern string that has no wildcard
-     * @return the starting index in the text of the pattern , or -1 if not found 
-     */
-    protected int textPosIn(String text, int start, int end, String p) {
-
-        int plen = p.length();
-        int max = end - plen;
-
-        if (!fIgnoreCase) {
-            int i = text.indexOf(p, start);
-            if (i == -1 || i > max) {
-				return -1;
-			}
-            return i;
-        }
-
-        for (int i = start; i <= max; ++i) {
-            if (text.regionMatches(true, i, p, 0, plen)) {
-				return i;
-			}
-        }
-
-        return -1;
-    }
-}
diff --git a/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/tools/context/spy/ContextSpyPart.java b/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/tools/context/spy/ContextSpyPart.java
index af0bb5b..55f29df 100644
--- a/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/tools/context/spy/ContextSpyPart.java
+++ b/bundles/org.eclipse.e4.tools.context.spy/src/org/eclipse/e4/tools/context/spy/ContextSpyPart.java
@@ -16,10 +16,10 @@
 
 import org.eclipse.e4.core.contexts.ContextInjectionFactory;
 import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.internal.tools.context.spy.ContextDataFilter;
 import org.eclipse.e4.internal.tools.context.spy.ContextDataPart;
 import org.eclipse.e4.internal.tools.context.spy.ContextSpyHelper;
 import org.eclipse.e4.internal.tools.context.spy.ContextSpyProvider;
-import org.eclipse.e4.internal.tools.context.spy.search.ContextRegistry;
 import org.eclipse.e4.ui.di.Focus;
 import org.eclipse.e4.ui.model.application.MApplication;
 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
@@ -33,11 +33,10 @@
 import org.eclipse.jface.viewers.ViewerSorter;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.KeyAdapter;
 import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.KeyListener;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Button;
@@ -46,12 +45,13 @@
 import org.osgi.framework.Bundle;
 import org.osgi.framework.FrameworkUtil;
 
-/** This class is the main part of the context spy. 
- * It creates a treeviewer and the context data part listening to context selection
+/**
+ * This class is the main part of the context spy. It creates a treeviewer and
+ * the context data part listening to context selection
  */
 public class ContextSpyPart
 {
-	
+
 	private static final String ICON_COLLAPSEALL = "icons/collapseall.gif";
 	private static final String ICON_EXPANDALL = "icons/expandall.gif";
 	private static final String ICON_REFRESH = "icons/refresh.gif";
@@ -68,12 +68,18 @@
 
 	private ImageRegistry imgReg;
 
+
 	@Inject
-	private ContextRegistry contextRegistry;
+	private ContextDataFilter contextFilter;
 
 	private ContextDataPart contextDataPart;
+	private Button showOnlyFilteredElements;
+	private Text filterText;
 
-		
+	/** Store the values to set it when it is reopened */
+	private static String lastFilterText = null;
+	private static boolean lastShowFiltered = false;
+
 	@Inject
 	private void initializeImageRegistry()
 	{
@@ -93,117 +99,90 @@
 		parent.setLayout(new GridLayout(1, false));
 
 		final Composite comp = new Composite(parent, SWT.NONE);
-		comp.setLayout(new GridLayout(6, false));
+		comp.setLayout(new GridLayout(7, false));
 
 		Button refreshButton = new Button(comp, SWT.FLAT);
 		refreshButton.setImage(imgReg.get(ICON_REFRESH));
 		refreshButton.setToolTipText("Refresh the contexts");
-		refreshButton.addSelectionListener(new SelectionListener()
+		refreshButton.addSelectionListener(new SelectionAdapter()
 			{
-
 				@Override
 				public void widgetSelected(SelectionEvent e)
 				{
 					contextTreeViewer.refresh(true);
-				}
-
-				@Override
-				public void widgetDefaultSelected(SelectionEvent e)
-				{
+					contextDataPart.refresh(true);
 				}
 			});
 
 		Button expandAll = new Button(comp, SWT.FLAT);
 		expandAll.setImage(imgReg.get(ICON_EXPANDALL));
 		expandAll.setToolTipText("Expand context nodes");
-		expandAll.addSelectionListener(new SelectionListener()
+		expandAll.addSelectionListener(new SelectionAdapter()
 			{
-
 				@Override
 				public void widgetSelected(SelectionEvent e)
 				{
 					contextTreeViewer.expandAll();
 				}
-
-				@Override
-				public void widgetDefaultSelected(SelectionEvent e)
-				{
-				}
 			});
 		Button collapseAll = new Button(comp, SWT.FLAT);
 		collapseAll.setImage(imgReg.get(ICON_COLLAPSEALL));
 		collapseAll.setToolTipText("Collapse context nodes");
-		collapseAll.addSelectionListener(new SelectionListener()
+		collapseAll.addSelectionListener(new SelectionAdapter()
 			{
-
 				@Override
 				public void widgetSelected(SelectionEvent e)
 				{
 					contextTreeViewer.collapseAll();
 				}
 
-				@Override
-				public void widgetDefaultSelected(SelectionEvent e)
-				{
-				}
 			});
 
-		// Do the search widget
-		final Text text = new Text(comp, SWT.SEARCH | SWT.ICON_SEARCH);
-		GridDataFactory.fillDefaults().hint(250, SWT.DEFAULT).applyTo(text);
-		text.setMessage("Search data");
-		text.setToolTipText("Highlight the contexts where the contained objects match this string pattern.\n"
-				+ "You can use patterns like : *selection*, or *NameOfYourClass*");
-		text.addKeyListener(new KeyListener()
+		filterText = new Text(comp, SWT.SEARCH | SWT.ICON_SEARCH);
+		GridDataFactory.fillDefaults().hint(200, SWT.DEFAULT).applyTo(filterText);
+		filterText.setMessage("Search data");
+		filterText.setToolTipText("Highlight the contexts where the contained objects contains this string pattern.\n"
+				+ "Case is ignored.");
+		if (lastFilterText != null)
+			filterText.setText(lastFilterText);
+		contextFilter.setPattern(lastFilterText);
+		filterText.addKeyListener(new KeyAdapter()
 			{
-
 				@Override
 				public void keyReleased(KeyEvent e)
 				{
-					contextRegistry.setPattern(text.getText());
+					String textToSearch = filterText.getText();
+					lastFilterText = textToSearch;
+					boolean enableButton = textToSearch.length() > 0;
+					// Enable/disable button for filtering
+					showOnlyFilteredElements.setEnabled(enableButton);
+
+					// Then update filters and viewers
+					contextFilter.setPattern(textToSearch);
+					setFilter();
 					contextTreeViewer.refresh(true);
 					contextDataPart.refresh(true);
 				}
 
-				@Override
-				public void keyPressed(KeyEvent e)
-				{
-					// TODO Auto-generated method stub
-
-				}
 			});
 
-		final Button ignoreCase = new Button(comp, SWT.CHECK);
-		ignoreCase.setText("Ignore case");
-		ignoreCase.setToolTipText("Ignore case in the search pattern");
-		ignoreCase.addSelectionListener(new SelectionAdapter()
+		showOnlyFilteredElements = new Button(comp, SWT.CHECK);
+		showOnlyFilteredElements.setText("Show Only Filtered");
+		showOnlyFilteredElements.setToolTipText("Show only the filtered items in the table view");
+		showOnlyFilteredElements.setEnabled((lastFilterText != null) && (lastFilterText.length() > 0));
+		showOnlyFilteredElements.setSelection(lastShowFiltered);
+		showOnlyFilteredElements.addSelectionListener(new SelectionAdapter()
 			{
 				@Override
 				public void widgetSelected(SelectionEvent e)
 				{
-					contextRegistry.setIgnoreCase(ignoreCase.getSelection());
-					contextTreeViewer.refresh(true);
-					contextDataPart.refresh(true);
-				}
-			});
-
-		final Button ignoreWildCards = new Button(comp, SWT.CHECK);
-		ignoreWildCards.setText("Ignore WildCards");
-		ignoreWildCards.setToolTipText("Ignore wildcards in the search pattern");
-		ignoreWildCards.addSelectionListener(new SelectionAdapter()
-			{
-				@Override
-				public void widgetSelected(SelectionEvent e)
-				{
-					contextRegistry.setIgnoreWildCards(ignoreWildCards.getSelection());
-					contextTreeViewer.refresh(true);
-					contextDataPart.refresh(true);
+					lastShowFiltered = showOnlyFilteredElements.getSelection();
+					setFilter();
 				}
 			});
 
 		SashForm sashForm = new SashForm(parent, SWT.VERTICAL | SWT.V_SCROLL | SWT.H_SCROLL);
 		sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-		
 
 		// TreeViewer on the top
 		contextTreeViewer = new TreeViewer(sashForm);
@@ -228,6 +207,7 @@
 		IEclipseContext subCtx = ctx.createChild("Context for ContextDataPart");
 		subCtx.set(Composite.class, sashForm);
 		contextDataPart = ContextInjectionFactory.make(ContextDataPart.class, subCtx);
+		setFilter();
 
 		// Set the correct weight for SashForm
 		sashForm.setWeights(new int[] { 35, 65 });
@@ -237,6 +217,14 @@
 
 	}
 
+	/** Set the filter on context data part */
+	public void setFilter()
+	{
+		if (showOnlyFilteredElements.isEnabled() && showOnlyFilteredElements.getSelection())
+			contextDataPart.setFilter(contextFilter);
+		else
+			contextDataPart.setFilter(null);
+	}
 
 	@PreDestroy
 	public void dispose()