]>
Commit | Line | Data |
---|---|---|
1b2798f6 EK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2000, 2011 IBM Corporation and others. | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * IBM Corporation - initial API and implementation | |
10 | *******************************************************************************/ | |
11 | package org.eclipse.jdt.ui.actions; | |
12 | ||
13 | import java.util.ArrayList; | |
14 | import java.util.Arrays; | |
15 | import java.util.HashMap; | |
16 | import java.util.HashSet; | |
17 | import java.util.Iterator; | |
18 | import java.util.Map; | |
19 | import java.util.SortedSet; | |
20 | import java.util.Stack; | |
21 | import java.util.StringTokenizer; | |
22 | import java.util.TreeSet; | |
23 | ||
24 | import org.eclipse.swt.SWT; | |
25 | import org.eclipse.swt.events.SelectionAdapter; | |
26 | import org.eclipse.swt.events.SelectionEvent; | |
27 | import org.eclipse.swt.widgets.Menu; | |
28 | import org.eclipse.swt.widgets.MenuItem; | |
29 | ||
30 | import org.eclipse.core.runtime.Assert; | |
31 | ||
32 | import org.eclipse.jface.action.Action; | |
33 | import org.eclipse.jface.action.ContributionItem; | |
34 | import org.eclipse.jface.action.GroupMarker; | |
35 | import org.eclipse.jface.action.IContributionItem; | |
36 | import org.eclipse.jface.action.IMenuListener; | |
37 | import org.eclipse.jface.action.IMenuManager; | |
38 | import org.eclipse.jface.action.Separator; | |
39 | import org.eclipse.jface.preference.IPreferenceStore; | |
40 | import org.eclipse.jface.viewers.IContentProvider; | |
41 | import org.eclipse.jface.viewers.ITreeContentProvider; | |
42 | import org.eclipse.jface.viewers.StructuredViewer; | |
43 | import org.eclipse.jface.viewers.ViewerFilter; | |
44 | import org.eclipse.jface.window.Window; | |
45 | ||
46 | import org.eclipse.ui.IActionBars; | |
47 | import org.eclipse.ui.IMemento; | |
48 | import org.eclipse.ui.IViewPart; | |
49 | import org.eclipse.ui.actions.ActionGroup; | |
50 | ||
51 | import org.eclipse.jdt.core.IJavaModel; | |
52 | ||
53 | import org.eclipse.jdt.internal.ui.JavaPlugin; | |
54 | import org.eclipse.jdt.internal.ui.JavaPluginImages; | |
55 | import org.eclipse.jdt.internal.ui.filters.CustomFiltersDialog; | |
56 | import org.eclipse.jdt.internal.ui.filters.EmptyLibraryContainerFilter; | |
57 | import org.eclipse.jdt.internal.ui.filters.FilterDescriptor; | |
58 | import org.eclipse.jdt.internal.ui.filters.FilterMessages; | |
59 | import org.eclipse.jdt.internal.ui.filters.NamePatternFilter; | |
60 | ||
61 | /** | |
62 | * Action group to add the filter action to a view part's tool bar | |
63 | * menu. | |
64 | * <p> | |
65 | * This class may be instantiated; it is not intended to be subclassed. | |
66 | * </p> | |
67 | * | |
68 | * @since 2.0 | |
69 | * | |
70 | * @noextend This class is not intended to be subclassed by clients. | |
71 | */ | |
72 | public class CustomFiltersActionGroup extends ActionGroup { | |
73 | ||
74 | private static final String TAG_DUMMY_TO_TEST_EXISTENCE= "TAG_DUMMY_TO_TEST_EXISTENCE"; //$NON-NLS-1$ | |
75 | ||
76 | class ShowFilterDialogAction extends Action { | |
77 | ShowFilterDialogAction() { | |
78 | setText(FilterMessages.OpenCustomFiltersDialogAction_text); | |
79 | setImageDescriptor(JavaPluginImages.DESC_ELCL_FILTER); | |
80 | setDisabledImageDescriptor(JavaPluginImages.DESC_DLCL_FILTER); | |
81 | } | |
82 | ||
83 | @Override | |
84 | public void run() { | |
85 | openDialog(); | |
86 | } | |
87 | } | |
88 | ||
89 | /** | |
90 | * Menu contribution item which shows and lets check and uncheck filters. | |
91 | * | |
92 | * @since 3.0 | |
93 | */ | |
94 | class FilterActionMenuContributionItem extends ContributionItem { | |
95 | ||
96 | private int fItemNumber; | |
97 | private boolean fState; | |
98 | private String fFilterId; | |
99 | private String fFilterName; | |
100 | private CustomFiltersActionGroup fActionGroup; | |
101 | ||
102 | /** | |
103 | * Constructor for FilterActionMenuContributionItem. | |
104 | * | |
105 | * @param actionGroup the action group | |
106 | * @param filterId the id of the filter | |
107 | * @param filterName the name of the filter | |
108 | * @param state the initial state of the filter | |
109 | * @param itemNumber the menu item index | |
110 | */ | |
111 | public FilterActionMenuContributionItem(CustomFiltersActionGroup actionGroup, String filterId, String filterName, boolean state, int itemNumber) { | |
112 | super(filterId); | |
113 | Assert.isNotNull(actionGroup); | |
114 | Assert.isNotNull(filterId); | |
115 | Assert.isNotNull(filterName); | |
116 | fActionGroup= actionGroup; | |
117 | fFilterId= filterId; | |
118 | fFilterName= filterName; | |
119 | fState= state; | |
120 | fItemNumber= itemNumber; | |
121 | } | |
122 | ||
123 | /* | |
124 | * Overrides method from ContributionItem. | |
125 | */ | |
126 | @Override | |
127 | public void fill(Menu menu, int index) { | |
128 | MenuItem mi= new MenuItem(menu, SWT.CHECK, index); | |
129 | mi.setText("&" + fItemNumber + " " + fFilterName); //$NON-NLS-1$ //$NON-NLS-2$ | |
130 | /* | |
131 | * XXX: Don't set the image - would look bad because other menu items don't provide image | |
132 | * XXX: Get working set specific image name from XML - would need to cache icons | |
133 | */ | |
134 | // mi.setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_JAVA_WORKING_SET)); | |
135 | mi.setSelection(fState); | |
136 | mi.addSelectionListener(new SelectionAdapter() { | |
137 | @Override | |
138 | public void widgetSelected(SelectionEvent e) { | |
139 | fState= !fState; | |
140 | fActionGroup.setFilter(fFilterId, fState); | |
141 | } | |
142 | }); | |
143 | } | |
144 | ||
145 | /* | |
146 | * @see org.eclipse.jface.action.IContributionItem#isDynamic() | |
147 | */ | |
148 | @Override | |
149 | public boolean isDynamic() { | |
150 | return true; | |
151 | } | |
152 | } | |
153 | ||
154 | private static final String TAG_CUSTOM_FILTERS = "customFilters"; //$NON-NLS-1$ | |
155 | private static final String TAG_USER_DEFINED_PATTERNS_ENABLED= "userDefinedPatternsEnabled"; //$NON-NLS-1$ | |
156 | private static final String TAG_USER_DEFINED_PATTERNS= "userDefinedPatterns"; //$NON-NLS-1$ | |
157 | private static final String TAG_XML_DEFINED_FILTERS= "xmlDefinedFilters"; //$NON-NLS-1$ | |
158 | private static final String TAG_LRU_FILTERS = "lastRecentlyUsedFilters"; //$NON-NLS-1$ | |
159 | ||
160 | private static final String TAG_CHILD= "child"; //$NON-NLS-1$ | |
161 | private static final String TAG_PATTERN= "pattern"; //$NON-NLS-1$ | |
162 | private static final String TAG_FILTER_ID= "filterId"; //$NON-NLS-1$ | |
163 | private static final String TAG_IS_ENABLED= "isEnabled"; //$NON-NLS-1$ | |
164 | ||
165 | private static final String SEPARATOR= ","; //$NON-NLS-1$ | |
166 | ||
167 | private static final int MAX_FILTER_MENU_ENTRIES= 3; | |
168 | private static final String RECENT_FILTERS_GROUP_NAME= "recentFiltersGroup"; //$NON-NLS-1$ | |
169 | ||
170 | private static class FilterItem { | |
171 | boolean enabled; | |
172 | boolean previouslyEnabled; | |
173 | FilterDescriptor descriptor; | |
174 | String id; | |
175 | ||
176 | private ViewerFilter filterInstance= null; | |
177 | ||
178 | public FilterItem(FilterDescriptor descriptor) { | |
179 | this.descriptor= descriptor; | |
180 | this.id= descriptor.getId(); | |
181 | this.previouslyEnabled= false; | |
182 | this.enabled= descriptor.isEnabled(); | |
183 | } | |
184 | ||
185 | public ViewerFilter getFilterInstance() { | |
186 | if (filterInstance == null) { | |
187 | filterInstance= descriptor.createViewerFilter(); | |
188 | } | |
189 | return filterInstance; | |
190 | ||
191 | } | |
192 | } | |
193 | ||
194 | ||
195 | private final StructuredViewer fViewer; | |
196 | private final NamePatternFilter fPatternFilter; | |
197 | ||
198 | private boolean fUserDefinedPatternsEnabled; | |
199 | private String[] fUserDefinedPatterns; | |
200 | ||
201 | private String[] fPreviousPatterns; | |
202 | ||
203 | private final Map<String, FilterItem> fFilterItems; | |
204 | ||
205 | /** | |
206 | * Recently changed filter Ids stack with oldest on top (i.e. at the end). | |
207 | * | |
208 | * @since 3.0 | |
209 | */ | |
210 | private Stack<String> fLRUFilterIdsStack; | |
211 | /** | |
212 | * Handle to menu manager to dynamically update | |
213 | * the last recently used filters. | |
214 | * | |
215 | * @since 3.0 | |
216 | */ | |
217 | private IMenuManager fMenuManager; | |
218 | /** | |
219 | * The menu listener which dynamically updates | |
220 | * the last recently used filters. | |
221 | * | |
222 | * @since 3.0 | |
223 | */ | |
224 | private IMenuListener fMenuListener; | |
225 | /** | |
226 | * Filter Ids used in the last view menu invocation. | |
227 | * | |
228 | * @since 3.0 | |
229 | */ | |
230 | private String[] fFilterIdsUsedInLastViewMenu; | |
231 | ||
232 | private final String fTargetId; | |
233 | ||
234 | /** | |
235 | * Creates a new <code>CustomFiltersActionGroup</code>. | |
236 | * | |
237 | * @param part the view part that owns this action group | |
238 | * @param viewer the viewer to be filtered | |
239 | */ | |
240 | public CustomFiltersActionGroup(IViewPart part, StructuredViewer viewer) { | |
241 | this(part.getViewSite().getId(), viewer); | |
242 | } | |
243 | ||
244 | /** | |
245 | * Creates a new <code>CustomFiltersActionGroup</code>. | |
246 | * | |
247 | * @param ownerId the id of this action group's owner | |
248 | * @param viewer the viewer to be filtered | |
249 | */ | |
250 | public CustomFiltersActionGroup(String ownerId, StructuredViewer viewer) { | |
251 | Assert.isNotNull(ownerId); | |
252 | Assert.isNotNull(viewer); | |
253 | fTargetId= ownerId; | |
254 | fViewer= viewer; | |
255 | fPatternFilter= new NamePatternFilter(); | |
256 | ||
257 | fLRUFilterIdsStack= new Stack<String>(); | |
258 | ||
259 | fUserDefinedPatterns= new String[0]; | |
260 | fUserDefinedPatternsEnabled= false; | |
261 | fPreviousPatterns= new String[0]; | |
262 | ||
263 | fFilterItems= new HashMap<String, FilterItem>(); | |
264 | FilterDescriptor[] filterDescriptors= FilterDescriptor.getFilterDescriptors(fTargetId); | |
265 | for (int i= 0; i < filterDescriptors.length; i++) { | |
266 | FilterItem item= new FilterItem(filterDescriptors[i]); | |
267 | Object existing= fFilterItems.put(item.id, item); | |
268 | if (existing != null) { | |
269 | JavaPlugin.logErrorMessage("WARNING: Duplicate id for extension-point \"org.eclipse.jdt.ui.javaElementFilters\" in " + ownerId); //$NON-NLS-1$ | |
270 | } | |
271 | } | |
272 | ||
273 | initializeWithViewDefaults(); | |
274 | ||
275 | updateViewerFilters(); | |
276 | } | |
277 | ||
278 | /* | |
279 | * Method declared on ActionGroup. | |
280 | */ | |
281 | @Override | |
282 | public void fillActionBars(IActionBars actionBars) { | |
283 | fillViewMenu(actionBars.getMenuManager()); | |
284 | } | |
285 | ||
286 | /** | |
287 | * Returns a list of currently enabled filters. The filter | |
288 | * is identified by its id. | |
289 | * <p> | |
290 | * This method is for internal use only and should not | |
291 | * be called by clients outside of JDT/UI. | |
292 | * </p> | |
293 | * | |
294 | * @return a list of currently enabled filters | |
295 | * | |
296 | * @since 3.1 | |
297 | * | |
298 | * @noreference This method is not intended to be referenced by clients. | |
299 | */ | |
300 | public String[] internalGetEnabledFilterIds() { | |
301 | ArrayList<String> enabledFilterIds= new ArrayList<String>(); | |
302 | for (Iterator<FilterItem> iterator= fFilterItems.values().iterator(); iterator.hasNext();) { | |
303 | FilterItem item= iterator.next(); | |
304 | if (item.enabled) { | |
305 | enabledFilterIds.add(item.id); | |
306 | } | |
307 | } | |
308 | return enabledFilterIds.toArray(new String[enabledFilterIds.size()]); | |
309 | } | |
310 | ||
311 | /** | |
312 | * Removes filters for the given parent and element | |
313 | * | |
314 | * @param parent the parent of the element | |
315 | * @param element the element | |
316 | * @param contentProvider the content provider of the viewer from which | |
317 | * the filters will be removed | |
318 | * | |
319 | * @return the array of new filter ids | |
320 | */ | |
321 | public String[] removeFiltersFor(Object parent, Object element, IContentProvider contentProvider) { | |
322 | ArrayList<String> newFilters= new ArrayList<String>(); | |
323 | for (Iterator<FilterItem> iterator= fFilterItems.values().iterator(); iterator.hasNext();) { | |
324 | FilterItem item= iterator.next(); | |
325 | if (item.enabled) { | |
326 | ViewerFilter filter= item.getFilterInstance(); | |
327 | if (filter != null && isSelected(parent, element, contentProvider, filter)) | |
328 | newFilters.add(item.id); | |
329 | } | |
330 | } | |
331 | if (fUserDefinedPatternsEnabled && isSelected(parent, element, contentProvider, fPatternFilter)) | |
332 | newFilters.add(fPatternFilter.getClass().getName()); | |
333 | ||
334 | return newFilters.toArray(new String[newFilters.size()]); | |
335 | } | |
336 | ||
337 | /** | |
338 | * Sets the filters to the given array of new filters | |
339 | * | |
340 | * @param newFilters the new filters | |
341 | */ | |
342 | public void setFilters(String[] newFilters) { | |
343 | setEnabledFilterIds(newFilters); | |
344 | updateViewerFilters(); | |
345 | } | |
346 | ||
347 | private boolean isSelected(Object parent, Object element, IContentProvider contentProvider, ViewerFilter filter) { | |
348 | if (filter instanceof EmptyLibraryContainerFilter) // workaround for https://bugs.eclipse.org/341109 | |
349 | return true; | |
350 | if (contentProvider instanceof ITreeContentProvider) { | |
351 | // the element and all its parents have to be selected | |
352 | ITreeContentProvider provider = (ITreeContentProvider) contentProvider; | |
353 | while (element != null && !(element instanceof IJavaModel)) { | |
354 | if (!filter.select(fViewer, parent, element)) | |
355 | return false; | |
356 | element= provider.getParent( element); | |
357 | } | |
358 | return true; | |
359 | } | |
360 | return filter.select(fViewer, parent, element); | |
361 | } | |
362 | ||
363 | /** | |
364 | * Sets the enable state of the given filter. | |
365 | * | |
366 | * @param filterId the id of the filter | |
367 | * @param state the filter state | |
368 | */ | |
369 | private void setFilter(String filterId, boolean state) { | |
370 | // Renew filter id in LRU stack | |
371 | fLRUFilterIdsStack.remove(filterId); | |
372 | fLRUFilterIdsStack.add(0, filterId); | |
373 | ||
374 | FilterItem item= fFilterItems.get(filterId); | |
375 | if (item != null) { | |
376 | item.enabled= state; | |
377 | storeViewDefaults(); | |
378 | ||
379 | updateViewerFilters(); | |
380 | } | |
381 | } | |
382 | ||
383 | private void setEnabledFilterIds(String[] enabledIds) { | |
384 | // set all to false | |
385 | fUserDefinedPatternsEnabled= false; | |
386 | for (Iterator<FilterItem> iterator= fFilterItems.values().iterator(); iterator.hasNext();) { | |
387 | FilterItem item= iterator.next(); | |
388 | item.enabled= false; | |
389 | } | |
390 | // set enabled to true | |
391 | for (int i= 0; i < enabledIds.length; i++) { | |
392 | FilterItem item= fFilterItems.get(enabledIds[i]); | |
393 | if (item != null) { | |
394 | item.enabled= true; | |
395 | } | |
396 | if (fPatternFilter.getClass().getName().equals(enabledIds[i])) | |
397 | fUserDefinedPatternsEnabled= true; | |
398 | } | |
399 | } | |
400 | ||
401 | private void setUserDefinedPatterns(String[] patterns) { | |
402 | fUserDefinedPatterns= patterns; | |
403 | } | |
404 | ||
405 | /** | |
406 | * Sets the recently changed filters. | |
407 | * | |
408 | * @param changeHistory the change history | |
409 | * @since 3.0 | |
410 | */ | |
411 | private void setRecentlyChangedFilters(Stack<FilterDescriptor> changeHistory) { | |
412 | Stack<String> oldestFirstStack= new Stack<String>(); | |
413 | ||
414 | int length= Math.min(changeHistory.size(), MAX_FILTER_MENU_ENTRIES); | |
415 | for (int i= 0; i < length; i++) | |
416 | oldestFirstStack.push(changeHistory.pop().getId()); | |
417 | ||
418 | length= Math.min(fLRUFilterIdsStack.size(), MAX_FILTER_MENU_ENTRIES - oldestFirstStack.size()); | |
419 | int NEWEST= 0; | |
420 | for (int i= 0; i < length; i++) { | |
421 | String filter= fLRUFilterIdsStack.remove(NEWEST); | |
422 | if (!oldestFirstStack.contains(filter)) | |
423 | oldestFirstStack.push(filter); | |
424 | } | |
425 | fLRUFilterIdsStack= oldestFirstStack; | |
426 | } | |
427 | ||
428 | private boolean areUserDefinedPatternsEnabled() { | |
429 | return fUserDefinedPatternsEnabled; | |
430 | } | |
431 | ||
432 | private void setUserDefinedPatternsEnabled(boolean state) { | |
433 | fUserDefinedPatternsEnabled= state; | |
434 | } | |
435 | ||
436 | /** | |
437 | * Fills the given view menu with the entries managed by the | |
438 | * group. | |
439 | * | |
440 | * @param viewMenu the menu to fill | |
441 | */ | |
442 | public void fillViewMenu(IMenuManager viewMenu) { | |
443 | /* | |
444 | * Don't change the separator group name. | |
445 | * Using this name ensures that other filters | |
446 | * get contributed to the same group. | |
447 | */ | |
448 | viewMenu.add(new Separator("filters")); //$NON-NLS-1$ | |
449 | viewMenu.add(new GroupMarker(RECENT_FILTERS_GROUP_NAME)); | |
450 | viewMenu.add(new ShowFilterDialogAction()); | |
451 | ||
452 | fMenuManager= viewMenu; | |
453 | fMenuListener= new IMenuListener() { | |
454 | public void menuAboutToShow(IMenuManager manager) { | |
455 | removePreviousLRUFilterActions(manager); | |
456 | addLRUFilterActions(manager); | |
457 | } | |
458 | }; | |
459 | fMenuManager.addMenuListener(fMenuListener); | |
460 | } | |
461 | ||
462 | private void removePreviousLRUFilterActions(IMenuManager mm) { | |
463 | if (fFilterIdsUsedInLastViewMenu == null) | |
464 | return; | |
465 | ||
466 | for (int i= 0; i < fFilterIdsUsedInLastViewMenu.length; i++) | |
467 | mm.remove(fFilterIdsUsedInLastViewMenu[i]); | |
468 | } | |
469 | ||
470 | private void addLRUFilterActions(IMenuManager mm) { | |
471 | if (fLRUFilterIdsStack.isEmpty()) { | |
472 | fFilterIdsUsedInLastViewMenu= null; | |
473 | return; | |
474 | } | |
475 | ||
476 | SortedSet<String> sortedFilters= new TreeSet<String>(fLRUFilterIdsStack); | |
477 | String[] recentlyChangedFilterIds= sortedFilters.toArray(new String[sortedFilters.size()]); | |
478 | ||
479 | fFilterIdsUsedInLastViewMenu= new String[recentlyChangedFilterIds.length]; | |
480 | for (int i= 0; i < recentlyChangedFilterIds.length; i++) { | |
481 | String id= recentlyChangedFilterIds[i]; | |
482 | fFilterIdsUsedInLastViewMenu[i]= id; | |
483 | FilterItem filterItem= fFilterItems.get(id); | |
484 | if (filterItem != null) { | |
485 | IContributionItem item= new FilterActionMenuContributionItem(this, id, filterItem.descriptor.getName(), filterItem.enabled, i+1); | |
486 | mm.insertBefore(RECENT_FILTERS_GROUP_NAME, item); | |
487 | } | |
488 | } | |
489 | } | |
490 | ||
491 | /* | |
492 | * Method declared on ActionGroup. | |
493 | */ | |
494 | @Override | |
495 | public void dispose() { | |
496 | if (fMenuManager != null) | |
497 | fMenuManager.removeMenuListener(fMenuListener); | |
498 | fFilterItems.clear(); | |
499 | super.dispose(); | |
500 | } | |
501 | ||
502 | // ---------- viewer filter handling ---------- | |
503 | ||
504 | private boolean updateViewerFilters() { | |
505 | ViewerFilter[] installedFilters= fViewer.getFilters(); | |
506 | ArrayList<ViewerFilter> viewerFilters= new ArrayList<ViewerFilter>(Arrays.asList(installedFilters)); | |
507 | HashSet<String> patterns= new HashSet<String>(); | |
508 | ||
509 | boolean hasChange= false; | |
510 | boolean patternChange= false; | |
511 | ||
512 | for (Iterator<FilterItem> iterator= fFilterItems.values().iterator(); iterator.hasNext();) { | |
513 | FilterItem item= iterator.next(); | |
514 | if (item.descriptor.isCustomFilter()) { | |
515 | if (item.enabled != item.previouslyEnabled) { | |
516 | ViewerFilter filter= item.getFilterInstance(); // only create when changed | |
517 | if (filter != null) { | |
518 | if (item.enabled) { | |
519 | viewerFilters.add(filter); | |
520 | } else { | |
521 | viewerFilters.remove(filter); | |
522 | } | |
523 | hasChange= true; | |
524 | } | |
525 | } | |
526 | } else if (item.descriptor.isPatternFilter()) { | |
527 | if (item.enabled) { | |
528 | patterns.add(item.descriptor.getPattern()); | |
529 | } | |
530 | patternChange |= (item.enabled != item.previouslyEnabled); | |
531 | } | |
532 | item.previouslyEnabled= item.enabled; | |
533 | } | |
534 | ||
535 | if (areUserDefinedPatternsEnabled()) { | |
536 | for (int i= 0; i < fUserDefinedPatterns.length; i++) { | |
537 | patterns.add(fUserDefinedPatterns[i]); | |
538 | } | |
539 | } | |
540 | if (!patternChange) { // no pattern change so far, test if the user patterns made a difference | |
541 | patternChange= hasChanges(patterns, fPreviousPatterns); | |
542 | } | |
543 | ||
544 | fPreviousPatterns= patterns.toArray(new String[patterns.size()]); | |
545 | if (patternChange) { | |
546 | fPatternFilter.setPatterns(fPreviousPatterns); | |
547 | if (patterns.isEmpty()) { | |
548 | viewerFilters.remove(fPatternFilter); | |
549 | } else if (!viewerFilters.contains(fPatternFilter)) { | |
550 | viewerFilters.add(fPatternFilter); | |
551 | } | |
552 | hasChange= true; | |
553 | } | |
554 | if (hasChange) { | |
555 | fViewer.setFilters(viewerFilters.toArray(new ViewerFilter[viewerFilters.size()])); // will refresh | |
556 | } | |
557 | return hasChange; | |
558 | } | |
559 | ||
560 | private boolean hasChanges(HashSet<String> patterns, String[] oldPatterns) { | |
561 | HashSet<String> copy= (HashSet<String>) patterns.clone(); | |
562 | for (int i= 0; i < oldPatterns.length; i++) { | |
563 | boolean found= copy.remove(oldPatterns[i]); | |
564 | if (!found) | |
565 | return true; | |
566 | } | |
567 | return !copy.isEmpty(); | |
568 | } | |
569 | ||
570 | // ---------- view kind/defaults persistency ---------- | |
571 | ||
572 | private void initializeWithViewDefaults() { | |
573 | // get default values for view | |
574 | IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); | |
575 | ||
576 | // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=22533 | |
577 | if (!store.contains(getPreferenceKey(TAG_DUMMY_TO_TEST_EXISTENCE))) | |
578 | return; | |
579 | ||
580 | fUserDefinedPatternsEnabled= store.getBoolean(getPreferenceKey(TAG_USER_DEFINED_PATTERNS_ENABLED)); | |
581 | setUserDefinedPatterns(CustomFiltersDialog.convertFromString(store.getString(getPreferenceKey(TAG_USER_DEFINED_PATTERNS)), SEPARATOR)); | |
582 | ||
583 | for (Iterator<FilterItem> iterator= fFilterItems.values().iterator(); iterator.hasNext();) { | |
584 | FilterItem item= iterator.next(); | |
585 | String id= item.id; | |
586 | // set default to value from plugin contributions (fixes https://bugs.eclipse.org/bugs/show_bug.cgi?id=73991 ): | |
587 | store.setDefault(id, item.descriptor.isEnabled()); | |
588 | item.enabled= store.getBoolean(id); | |
589 | } | |
590 | ||
591 | fLRUFilterIdsStack.clear(); | |
592 | String lruFilterIds= store.getString(TAG_LRU_FILTERS); | |
593 | StringTokenizer tokenizer= new StringTokenizer(lruFilterIds, SEPARATOR); | |
594 | while (tokenizer.hasMoreTokens()) { | |
595 | String id= tokenizer.nextToken(); | |
596 | if (fFilterItems.containsKey(id) && !fLRUFilterIdsStack.contains(id)) | |
597 | fLRUFilterIdsStack.push(id); | |
598 | } | |
599 | } | |
600 | ||
601 | private void storeViewDefaults() { | |
602 | // get default values for view | |
603 | IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); | |
604 | ||
605 | // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=22533 | |
606 | store.setValue(getPreferenceKey(TAG_DUMMY_TO_TEST_EXISTENCE), "storedViewPreferences");//$NON-NLS-1$ | |
607 | ||
608 | store.setValue(getPreferenceKey(TAG_USER_DEFINED_PATTERNS_ENABLED), fUserDefinedPatternsEnabled); | |
609 | store.setValue(getPreferenceKey(TAG_USER_DEFINED_PATTERNS), CustomFiltersDialog.convertToString(fUserDefinedPatterns ,SEPARATOR)); | |
610 | ||
611 | for (Iterator<FilterItem> iterator= fFilterItems.values().iterator(); iterator.hasNext();) { | |
612 | FilterItem item= iterator.next(); | |
613 | store.setValue(item.id, item.enabled); | |
614 | } | |
615 | ||
616 | StringBuffer buf= new StringBuffer(fLRUFilterIdsStack.size() * 20); | |
617 | Iterator<String> iter= fLRUFilterIdsStack.iterator(); | |
618 | while (iter.hasNext()) { | |
619 | buf.append(iter.next()); | |
620 | buf.append(SEPARATOR); | |
621 | } | |
622 | store.setValue(TAG_LRU_FILTERS, buf.toString()); | |
623 | } | |
624 | ||
625 | private String getPreferenceKey(String tag) { | |
626 | return "CustomFiltersActionGroup." + fTargetId + '.' + tag; //$NON-NLS-1$ | |
627 | } | |
628 | ||
629 | // ---------- view instance persistency ---------- | |
630 | ||
631 | /** | |
632 | * Saves the state of the custom filters in a memento. | |
633 | * | |
634 | * @param memento the memento into which the state is saved | |
635 | */ | |
636 | public void saveState(IMemento memento) { | |
637 | IMemento customFilters= memento.createChild(TAG_CUSTOM_FILTERS); | |
638 | customFilters.putString(TAG_USER_DEFINED_PATTERNS_ENABLED, Boolean.toString(fUserDefinedPatternsEnabled)); | |
639 | saveUserDefinedPatterns(customFilters); | |
640 | saveXmlDefinedFilters(customFilters); | |
641 | saveLRUFilters(customFilters); | |
642 | } | |
643 | ||
644 | private void saveXmlDefinedFilters(IMemento memento) { | |
645 | IMemento xmlDefinedFilters= memento.createChild(TAG_XML_DEFINED_FILTERS); | |
646 | ||
647 | for (Iterator<FilterItem> iterator= fFilterItems.values().iterator(); iterator.hasNext();) { | |
648 | FilterItem item= iterator.next(); | |
649 | ||
650 | IMemento child= xmlDefinedFilters.createChild(TAG_CHILD); | |
651 | child.putString(TAG_FILTER_ID, item.id); | |
652 | child.putString(TAG_IS_ENABLED, String.valueOf(item.enabled)); | |
653 | } | |
654 | } | |
655 | /** | |
656 | * Stores the last recently used filter Ids into | |
657 | * the given memento | |
658 | * | |
659 | * @param memento the memento into which to store the LRU filter Ids | |
660 | * @since 3.0 | |
661 | */ | |
662 | private void saveLRUFilters(IMemento memento) { | |
663 | if(fLRUFilterIdsStack != null && !fLRUFilterIdsStack.isEmpty()) { | |
664 | IMemento lruFilters= memento.createChild(TAG_LRU_FILTERS); | |
665 | Iterator<String> iter= fLRUFilterIdsStack.iterator(); | |
666 | while (iter.hasNext()) { | |
667 | String id= iter.next(); | |
668 | IMemento child= lruFilters.createChild(TAG_CHILD); | |
669 | child.putString(TAG_FILTER_ID, id); | |
670 | } | |
671 | } | |
672 | } | |
673 | ||
674 | private void saveUserDefinedPatterns(IMemento memento) { | |
675 | if(fUserDefinedPatterns != null && fUserDefinedPatterns.length > 0) { | |
676 | IMemento userDefinedPatterns= memento.createChild(TAG_USER_DEFINED_PATTERNS); | |
677 | for (int i= 0; i < fUserDefinedPatterns.length; i++) { | |
678 | IMemento child= userDefinedPatterns.createChild(TAG_CHILD); | |
679 | child.putString(TAG_PATTERN, fUserDefinedPatterns[i]); | |
680 | } | |
681 | } | |
682 | } | |
683 | ||
684 | /** | |
685 | * Restores the state of the filter actions from a memento. | |
686 | * <p> | |
687 | * Note: This method does not refresh the viewer. | |
688 | * </p> | |
689 | * | |
690 | * @param memento the memento from which the state is restored | |
691 | */ | |
692 | public void restoreState(IMemento memento) { | |
693 | if (memento == null) | |
694 | return; | |
695 | IMemento customFilters= memento.getChild(TAG_CUSTOM_FILTERS); | |
696 | if (customFilters == null) | |
697 | return; | |
698 | String userDefinedPatternsEnabled= customFilters.getString(TAG_USER_DEFINED_PATTERNS_ENABLED); | |
699 | if (userDefinedPatternsEnabled == null) | |
700 | return; | |
701 | ||
702 | fUserDefinedPatternsEnabled= Boolean.valueOf(userDefinedPatternsEnabled).booleanValue(); | |
703 | restoreUserDefinedPatterns(customFilters); | |
704 | restoreXmlDefinedFilters(customFilters); | |
705 | restoreLRUFilters(customFilters); | |
706 | ||
707 | updateViewerFilters(); | |
708 | } | |
709 | ||
710 | private void restoreUserDefinedPatterns(IMemento memento) { | |
711 | IMemento userDefinedPatterns= memento.getChild(TAG_USER_DEFINED_PATTERNS); | |
712 | if(userDefinedPatterns != null) { | |
713 | IMemento children[]= userDefinedPatterns.getChildren(TAG_CHILD); | |
714 | String[] patterns= new String[children.length]; | |
715 | for (int i = 0; i < children.length; i++) | |
716 | patterns[i]= children[i].getString(TAG_PATTERN); | |
717 | ||
718 | setUserDefinedPatterns(patterns); | |
719 | } else | |
720 | setUserDefinedPatterns(new String[0]); | |
721 | } | |
722 | ||
723 | private void restoreXmlDefinedFilters(IMemento memento) { | |
724 | IMemento xmlDefinedFilters= memento.getChild(TAG_XML_DEFINED_FILTERS); | |
725 | if(xmlDefinedFilters != null) { | |
726 | IMemento[] children= xmlDefinedFilters.getChildren(TAG_CHILD); | |
727 | for (int i= 0; i < children.length; i++) { | |
728 | String id= children[i].getString(TAG_FILTER_ID); | |
729 | Boolean isEnabled= Boolean.valueOf(children[i].getString(TAG_IS_ENABLED)); | |
730 | FilterItem item= fFilterItems.get(id); | |
731 | if (item != null) { | |
732 | item.enabled= isEnabled.booleanValue(); | |
733 | } | |
734 | } | |
735 | } | |
736 | } | |
737 | ||
738 | private void restoreLRUFilters(IMemento memento) { | |
739 | IMemento lruFilters= memento.getChild(TAG_LRU_FILTERS); | |
740 | fLRUFilterIdsStack.clear(); | |
741 | if(lruFilters != null) { | |
742 | IMemento[] children= lruFilters.getChildren(TAG_CHILD); | |
743 | for (int i= 0; i < children.length; i++) { | |
744 | String id= children[i].getString(TAG_FILTER_ID); | |
745 | if (fFilterItems.containsKey(id) && !fLRUFilterIdsStack.contains(id)) | |
746 | fLRUFilterIdsStack.push(id); | |
747 | } | |
748 | } | |
749 | } | |
750 | ||
751 | // ---------- dialog related code ---------- | |
752 | ||
753 | private void openDialog() { | |
754 | CustomFiltersDialog dialog= new CustomFiltersDialog( | |
755 | fViewer.getControl().getShell(), | |
756 | fTargetId, | |
757 | areUserDefinedPatternsEnabled(), | |
758 | fUserDefinedPatterns, | |
759 | internalGetEnabledFilterIds()); | |
760 | ||
761 | if (dialog.open() == Window.OK) { | |
762 | setEnabledFilterIds(dialog.getEnabledFilterIds()); | |
763 | setUserDefinedPatternsEnabled(dialog.areUserDefinedPatternsEnabled()); | |
764 | setUserDefinedPatterns(dialog.getUserDefinedPatterns()); | |
765 | setRecentlyChangedFilters(dialog.getFilterDescriptorChangeHistory()); | |
766 | ||
767 | storeViewDefaults(); | |
768 | ||
769 | updateViewerFilters(); | |
770 | } | |
771 | } | |
772 | } |