Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 187200
Collapse All | Expand All

(-)Eclipse UI/org/eclipse/ui/dialogs/FilteredTree.java (-1 / +101 lines)
Lines 19-24 Link Here
19
import org.eclipse.jface.action.ToolBarManager;
19
import org.eclipse.jface.action.ToolBarManager;
20
import org.eclipse.jface.resource.ImageDescriptor;
20
import org.eclipse.jface.resource.ImageDescriptor;
21
import org.eclipse.jface.resource.JFaceResources;
21
import org.eclipse.jface.resource.JFaceResources;
22
import org.eclipse.jface.viewers.IContentProvider;
22
import org.eclipse.jface.viewers.ISelection;
23
import org.eclipse.jface.viewers.ISelection;
23
import org.eclipse.jface.viewers.TreeViewer;
24
import org.eclipse.jface.viewers.TreeViewer;
24
import org.eclipse.swt.SWT;
25
import org.eclipse.swt.SWT;
Lines 282-287 Link Here
282
        		refreshJob.cancel();
283
        		refreshJob.cancel();
283
        	}
284
        	}
284
        });
285
        });
286
        if (treeViewer instanceof NotifyingTreeViewer) {
287
        	patternFilter.setUseCache(true);
288
        }
285
        treeViewer.addFilter(patternFilter);  
289
        treeViewer.addFilter(patternFilter);  
286
        return treeViewer.getControl();
290
        return treeViewer.getControl();
287
    }
291
    }
Lines 296-302 Link Here
296
	 * @since 3.3
300
	 * @since 3.3
297
	 */
301
	 */
298
	protected TreeViewer doCreateTreeViewer(Composite parent, int style) {
302
	protected TreeViewer doCreateTreeViewer(Composite parent, int style) {
299
		return new TreeViewer(parent, style);
303
		return new NotifyingTreeViewer(parent, style);
300
	}
304
	}
301
    
305
    
302
    /**
306
    /**
Lines 757-760 Link Here
757
		return null;
761
		return null;
758
	}
762
	}
759
	
763
	
764
	/**
765
	 * Custom tree viewer subclass that clears the caches in patternFilter on
766
	 * any change to the tree. See bug 187200.
767
	 * 
768
	 * @since 3.3
769
	 *
770
	 */
771
	class NotifyingTreeViewer extends TreeViewer {
772
773
		/**
774
		 * @param parent
775
		 * @param style
776
		 */
777
		public NotifyingTreeViewer(Composite parent, int style) {
778
			super(parent, style);
779
		}
780
781
		public void add(Object parentElementOrTreePath, Object childElement) {
782
			getPatternFilter().clearCaches();
783
			super.add(parentElementOrTreePath, childElement);
784
		}
785
786
		public void add(Object parentElementOrTreePath, Object[] childElements) {
787
			getPatternFilter().clearCaches();
788
			super.add(parentElementOrTreePath, childElements);
789
		}
790
		
791
		protected void inputChanged(Object input, Object oldInput) {
792
			getPatternFilter().clearCaches();
793
			super.inputChanged(input, oldInput);
794
		}
795
796
		public void insert(Object parentElementOrTreePath, Object element,
797
				int position) {
798
			getPatternFilter().clearCaches();
799
			super.insert(parentElementOrTreePath, element, position);
800
		}
801
802
		public void refresh() {
803
			getPatternFilter().clearCaches();
804
			super.refresh();
805
		}
806
807
		public void refresh(boolean updateLabels) {
808
			getPatternFilter().clearCaches();
809
			super.refresh(updateLabels);
810
		}
811
812
		public void refresh(Object element) {
813
			getPatternFilter().clearCaches();
814
			super.refresh(element);
815
		}
816
817
		public void refresh(Object element, boolean updateLabels) {
818
			getPatternFilter().clearCaches();
819
			super.refresh(element, updateLabels);
820
		}
821
822
		public void remove(Object elementsOrTreePaths) {
823
			getPatternFilter().clearCaches();
824
			super.remove(elementsOrTreePaths);
825
		}
826
827
		public void remove(Object parent, Object[] elements) {
828
			getPatternFilter().clearCaches();
829
			super.remove(parent, elements);
830
		}
831
832
		public void remove(Object[] elementsOrTreePaths) {
833
			getPatternFilter().clearCaches();
834
			super.remove(elementsOrTreePaths);
835
		}
836
837
		public void replace(Object parentElementOrTreePath, int index,
838
				Object element) {
839
			getPatternFilter().clearCaches();
840
			super.replace(parentElementOrTreePath, index, element);
841
		}
842
843
		public void setChildCount(Object elementOrTreePath, int count) {
844
			getPatternFilter().clearCaches();
845
			super.setChildCount(elementOrTreePath, count);
846
		}
847
848
		public void setContentProvider(IContentProvider provider) {
849
			getPatternFilter().clearCaches();
850
			super.setContentProvider(provider);
851
		}
852
853
		public void setHasChildren(Object elementOrTreePath, boolean hasChildren) {
854
			getPatternFilter().clearCaches();
855
			super.setHasChildren(elementOrTreePath, hasChildren);
856
		}
857
		
858
	}
859
    
760
}
860
}
(-)Eclipse UI/org/eclipse/ui/dialogs/PatternFilter.java (-13 / +53 lines)
Lines 45-50 Link Here
45
     */
45
     */
46
    private Map foundAnyCache = new HashMap();
46
    private Map foundAnyCache = new HashMap();
47
    
47
    
48
    private boolean useCache = false;
49
    
48
	/**
50
	/**
49
	 * Whether to include a leading wildcard for all provided patterns.  A
51
	 * Whether to include a leading wildcard for all provided patterns.  A
50
	 * trailing wildcard is always included.
52
	 * trailing wildcard is always included.
Lines 56-62 Link Here
56
	 */
58
	 */
57
    private StringMatcher matcher;
59
    private StringMatcher matcher;
58
    
60
    
59
    private boolean useFilterOptimization = true;
61
    private boolean useEarlyReturnIfMatcherIsNull = true;
60
    
62
    
61
    private static Object[] EMPTY = new Object[0];
63
    private static Object[] EMPTY = new Object[0];
62
64
Lines 67-76 Link Here
67
    	// we don't want to optimize if we've extended the filter ... this
69
    	// we don't want to optimize if we've extended the filter ... this
68
    	// needs to be addressed in 3.4
70
    	// needs to be addressed in 3.4
69
    	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=186404
71
    	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=186404
70
        if (matcher == null && useFilterOptimization) {
72
        if (matcher == null && useEarlyReturnIfMatcherIsNull) {
71
			return elements;
73
			return elements;
72
		}
74
		}
73
75
76
        if (!useCache) {
77
        	return super.filter(viewer, parent, elements);
78
        }
79
        
74
        Object[] filtered = (Object[]) cache.get(parent);
80
        Object[] filtered = (Object[]) cache.get(parent);
75
        if (filtered == null) {
81
        if (filtered == null) {
76
        	Boolean foundAny = (Boolean) foundAnyCache.get(parent);
82
        	Boolean foundAny = (Boolean) foundAnyCache.get(parent);
Lines 85-91 Link Here
85
    }
91
    }
86
92
87
    /**
93
    /**
88
     * Returns true if any of the elements makes it through the filter. 
94
     * Returns true if any of the elements makes it through the filter.
95
     * This method uses caching if enabled; the computation is done in
96
     * computeAnyVisible.
97
     *  
89
     * @param viewer
98
     * @param viewer
90
     * @param parent
99
     * @param parent
91
     * @param elements the elements (must not be an empty array)
100
     * @param elements the elements (must not be an empty array)
Lines 96-117 Link Here
96
    		return true;
105
    		return true;
97
    	}
106
    	}
98
    	
107
    	
108
    	if (!useCache) {
109
    		return computeAnyVisible(viewer, elements);
110
    	}
111
    	
99
    	Object[] filtered = (Object[]) cache.get(parent);
112
    	Object[] filtered = (Object[]) cache.get(parent);
100
    	if (filtered != null) {
113
    	if (filtered != null) {
101
    		return filtered.length > 0;
114
    		return filtered.length > 0;
102
    	}
115
    	}
103
    	Boolean foundAny = (Boolean) foundAnyCache.get(parent);
116
    	Boolean foundAny = (Boolean) foundAnyCache.get(parent);
104
    	if (foundAny == null) {
117
    	if (foundAny == null) {
105
    		boolean elementFound = false;
118
    		foundAny = computeAnyVisible(viewer, elements) ? Boolean.TRUE : Boolean.FALSE;
106
    		for (int i = 0; i < elements.length && !elementFound; i++) {
107
				Object element = elements[i];
108
	    		elementFound = isElementVisible(viewer, element);
109
			}
110
    		foundAny = elementFound ? Boolean.TRUE : Boolean.FALSE;
111
    		foundAnyCache.put(parent, foundAny);
119
    		foundAnyCache.put(parent, foundAny);
112
    	}
120
    	}
113
    	return foundAny.booleanValue();
121
    	return foundAny.booleanValue();
114
    }
122
    }
123
124
	/**
125
	 * Returns true if any of the elements makes it through the filter.
126
	 * @param viewer
127
	 * @param elements
128
	 * @return
129
	 */
130
	private boolean computeAnyVisible(Viewer viewer, Object[] elements) {
131
		boolean elementFound = false;
132
		for (int i = 0; i < elements.length && !elementFound; i++) {
133
			Object element = elements[i];
134
			elementFound = isElementVisible(viewer, element);
135
		}
136
		return elementFound;
137
	}
115
    
138
    
116
    /* (non-Javadoc)
139
    /* (non-Javadoc)
117
     * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
140
     * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
Lines 143-156 Link Here
143
    	// these 2 strings allow the PatternFilter to be extended in
166
    	// these 2 strings allow the PatternFilter to be extended in
144
    	// 3.3 - https://bugs.eclipse.org/bugs/show_bug.cgi?id=186404
167
    	// 3.3 - https://bugs.eclipse.org/bugs/show_bug.cgi?id=186404
145
    	if ("org.eclipse.ui.keys.optimization.true".equals(patternString)) { //$NON-NLS-1$
168
    	if ("org.eclipse.ui.keys.optimization.true".equals(patternString)) { //$NON-NLS-1$
146
    		useFilterOptimization = true;
169
    		useEarlyReturnIfMatcherIsNull = true;
147
    		return;
170
    		return;
148
    	} else if ("org.eclipse.ui.keys.optimization.false".equals(patternString)) { //$NON-NLS-1$
171
    	} else if ("org.eclipse.ui.keys.optimization.false".equals(patternString)) { //$NON-NLS-1$
149
    		useFilterOptimization = false;
172
    		useEarlyReturnIfMatcherIsNull = false;
150
    		return;
173
    		return;
151
    	}
174
    	}
152
        cache.clear();
175
        clearCaches();
153
        foundAnyCache.clear();
154
        if (patternString == null || patternString.equals("")) { //$NON-NLS-1$
176
        if (patternString == null || patternString.equals("")) { //$NON-NLS-1$
155
			matcher = null;
177
			matcher = null;
156
		} else {
178
		} else {
Lines 162-167 Link Here
162
		}
184
		}
163
    }
185
    }
164
186
187
	/**
188
	 * Clears the caches used for optimizing this filter. Needs to be called whenever
189
	 * the tree content changes.
190
	 */
191
	/* package */ void clearCaches() {
192
		cache.clear();
193
        foundAnyCache.clear();
194
	}
195
165
    /**
196
    /**
166
     * Answers whether the given String matches the pattern.
197
     * Answers whether the given String matches the pattern.
167
     * 
198
     * 
Lines 311-315 Link Here
311
		}
342
		}
312
343
313
		return false;
344
		return false;
345
	}
346
347
	/**
348
	 * Can be called by the filtered tree to turn on caching.
349
	 * 
350
	 * @param useCache The useCache to set.
351
	 */
352
	void setUseCache(boolean useCache) {
353
		this.useCache = useCache;
314
	}    
354
	}    
315
}
355
}

Return to bug 187200