/******************************************************************************* * Copyright (c) 2011 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 *******************************************************************************/ package org.eclipse.wst.sse.ui.views.contentoutline; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.window.Window; import org.eclipse.wst.sse.ui.internal.filter.OutlineCustomFiltersDialog; import org.eclipse.wst.sse.ui.internal.filter.OutlineFilterDescriptor; import org.eclipse.wst.sse.ui.internal.filter.OutlineNamePatternFilter; /** * Action group to add the filter action to a view part's tool bar menu. * <p> * This class may be instantiated; it is not intended to be subclassed. * </p> * * @noextend This class is not intended to be subclassed by clients. */ public class ContentOutlineFilterProcessor { private static final String SEPARATOR = ","; //$NON-NLS-1$ private final String TAG_USER_DEFINED_PATTERNS_ENABLED = "userDefinedPatternsEnabled"; //$NON-NLS-1$ private final String TAG_USER_DEFINED_PATTERNS = "userDefinedPatterns"; //$NON-NLS-1$ private static class FilterItem { boolean enabled; boolean previouslyEnabled; OutlineFilterDescriptor descriptor; String id; private ViewerFilter filterInstance = null; public FilterItem(OutlineFilterDescriptor descriptor) { this.descriptor = descriptor; this.id = descriptor.getId(); this.previouslyEnabled = false; this.enabled = descriptor.isEnabled(); } public ViewerFilter getFilterInstance() { if (filterInstance == null) { filterInstance = descriptor.createViewerFilter(); } return filterInstance; } } private final StructuredViewer fViewer; private final OutlineNamePatternFilter fPatternFilter; private boolean fUserDefinedPatternsEnabled; private String[] fUserDefinedPatterns; private String[] fPreviousPatterns; private final Map fFilterItems; private final String fTargetId; private IPreferenceStore fStore; /** * Creates a new <code>CustomFilterAction</code>. * * @param store * the preference Store * @param ownerId * the id of this action group's owner * @param viewer * the viewer to be filtered */ public ContentOutlineFilterProcessor(IPreferenceStore store, String ownerId, StructuredViewer viewer) { Assert.isNotNull(ownerId); Assert.isNotNull(viewer); fStore = store; fTargetId = ownerId; fViewer = viewer; fPatternFilter = new OutlineNamePatternFilter(); fUserDefinedPatterns = new String[0]; fUserDefinedPatternsEnabled = false; fPreviousPatterns = new String[0]; fFilterItems = new HashMap(); OutlineFilterDescriptor[] filterDescriptors = OutlineFilterDescriptor.getFilterDescriptors(fTargetId); for (int i = 0; i < filterDescriptors.length; i++) { FilterItem item = new FilterItem(filterDescriptors[i]); fFilterItems.put(item.id, item); } initializeWithViewDefaults(); updateViewerFilters(); } /* * @see org.eclipse.jface.action.IContributionItem#isDynamic() */ public boolean isDynamic() { return true; } /** * Returns a list of currently enabled filters. The filter is identified by * its id. * <p> * This method is for internal use only and should not be called by clients * outside of JDT/UI. * </p> * * @return a list of currently enabled filters * * @noreference This method is not intended to be referenced by clients. */ public String[] internalGetEnabledFilterIds() { ArrayList enabledFilterIds = new ArrayList(); for (Iterator iterator = fFilterItems.values().iterator(); iterator.hasNext();) { FilterItem item = (FilterItem) iterator.next(); if (item.enabled) { enabledFilterIds.add(item.id); } } return (String[]) enabledFilterIds.toArray(new String[enabledFilterIds.size()]); } private void setEnabledFilterIds(String[] enabledIds) { // set all to false fUserDefinedPatternsEnabled = false; for (Iterator iterator = fFilterItems.values().iterator(); iterator.hasNext();) { FilterItem item = (FilterItem) iterator.next(); item.enabled = false; } // set enabled to true for (int i = 0; i < enabledIds.length; i++) { FilterItem item = (FilterItem) fFilterItems.get(enabledIds[i]); if (item != null) { item.enabled = true; } if (fPatternFilter.getClass().getName().equals(enabledIds[i])) fUserDefinedPatternsEnabled = true; } } private void setUserDefinedPatterns(String[] patterns) { fUserDefinedPatterns = patterns; } private boolean areUserDefinedPatternsEnabled() { return fUserDefinedPatternsEnabled; } private void setUserDefinedPatternsEnabled(boolean state) { fUserDefinedPatternsEnabled = state; } // ---------- viewer filter handling ---------- private boolean updateViewerFilters() { ViewerFilter[] installedFilters = fViewer.getFilters(); ArrayList viewerFilters = new ArrayList(installedFilters.length); HashSet patterns = new HashSet(); boolean hasChange = false; boolean patternChange = false; for (Iterator iterator = fFilterItems.values().iterator(); iterator.hasNext();) { FilterItem item = (FilterItem) iterator.next(); if (item.descriptor.isCustomFilter()) { if (item.enabled != item.previouslyEnabled) { hasChange = true; } if (item.enabled) { ViewerFilter filter = item.getFilterInstance(); // only // create // when // changed if (filter != null) { viewerFilters.add(filter); } } } else if (item.descriptor.isPatternFilter()) { if (item.enabled) { patterns.add(item.descriptor.getPattern()); } patternChange |= (item.enabled != item.previouslyEnabled); } item.previouslyEnabled = item.enabled; } if (areUserDefinedPatternsEnabled()) { for (int i = 0; i < fUserDefinedPatterns.length; i++) { patterns.add(fUserDefinedPatterns[i]); } } if (!patternChange) { // no pattern change so far, test if the user // patterns made a difference patternChange = hasChanges(patterns, fPreviousPatterns); } fPreviousPatterns = (String[]) patterns.toArray(new String[patterns.size()]); if (patternChange || hasChange) { fPatternFilter.setPatterns(fPreviousPatterns); if (patterns.isEmpty()) { viewerFilters.remove(fPatternFilter); } else if (!viewerFilters.contains(fPatternFilter)) { boolean contains = false; for (int i = 0; i < viewerFilters.size(); i++) { if (viewerFilters.get(i) instanceof OutlineNamePatternFilter) { OutlineNamePatternFilter filter = (OutlineNamePatternFilter) viewerFilters.get(i); String[] a1 = filter.getPatterns(); String[] a2 = fPatternFilter.getPatterns(); if (a1[0].equals(a2[0])) contains = true; else { viewerFilters.remove(i); } break; } } if (!contains) viewerFilters.add(fPatternFilter); } hasChange = true; } if (hasChange) { fViewer.setFilters((ViewerFilter[]) viewerFilters.toArray(new ViewerFilter[viewerFilters.size()])); // will // refresh } return hasChange; } private boolean hasChanges(HashSet patterns, String[] oldPatterns) { HashSet copy = (HashSet) patterns.clone(); for (int i = 0; i < oldPatterns.length; i++) { boolean found = copy.remove(oldPatterns[i]); if (!found) return true; } return !copy.isEmpty(); } // ---------- view kind/defaults persistency ---------- private void initializeWithViewDefaults() { // get default values for view fUserDefinedPatternsEnabled = fStore.getBoolean(getPreferenceKey(TAG_USER_DEFINED_PATTERNS_ENABLED)); setUserDefinedPatterns(OutlineCustomFiltersDialog.convertFromString(fStore.getString(getPreferenceKey(TAG_USER_DEFINED_PATTERNS)), SEPARATOR)); for (Iterator iterator = fFilterItems.values().iterator(); iterator.hasNext();) { FilterItem item = (FilterItem) iterator.next(); String id = item.id; // set default to value from plugin contributions (fixes // https://bugs.eclipse.org/bugs/show_bug.cgi?id=73991 ): fStore.setDefault(id, item.descriptor.isEnabled()); item.enabled = fStore.getBoolean(id); } } private void storeViewDefaults() { // get default values for view fStore.setValue(getPreferenceKey(TAG_USER_DEFINED_PATTERNS_ENABLED), fUserDefinedPatternsEnabled); fStore.setValue(getPreferenceKey(TAG_USER_DEFINED_PATTERNS), OutlineCustomFiltersDialog.convertToString(fUserDefinedPatterns, SEPARATOR)); boolean fFilterSelected = false; for (Iterator iterator = fFilterItems.values().iterator(); iterator.hasNext();) { FilterItem item = (FilterItem) iterator.next(); fStore.setValue(item.id, item.enabled); if (item.enabled) fFilterSelected = true; } fStore.setValue(fTargetId, fUserDefinedPatternsEnabled || fFilterSelected); } private String getPreferenceKey(String tag) { return "CustomFiltersActionGroup." + fTargetId + '.' + tag; //$NON-NLS-1$ } public void openDialog() { OutlineCustomFiltersDialog dialog = new OutlineCustomFiltersDialog(fViewer.getControl().getShell(), fTargetId, areUserDefinedPatternsEnabled(), fUserDefinedPatterns, internalGetEnabledFilterIds()); if (dialog.open() == Window.OK) { setEnabledFilterIds(dialog.getEnabledFilterIds()); setUserDefinedPatternsEnabled(dialog.areUserDefinedPatternsEnabled()); setUserDefinedPatterns(dialog.getUserDefinedPatterns()); storeViewDefaults(); updateViewerFilters(); } else { storeViewDefaults(); } } }