/******************************************************************************* * Copyright (c) 2006, 2015 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.ui.internal.navigator; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.ui.internal.navigator.filters.CommonFilterDescriptor; import org.eclipse.ui.internal.navigator.filters.CommonFilterDescriptorManager; import org.eclipse.ui.internal.navigator.filters.SkeletonViewerFilter; import org.eclipse.ui.navigator.ICommonFilterDescriptor; import org.eclipse.ui.navigator.INavigatorFilterService; /** * @since 3.2 * */ public class NavigatorFilterService implements INavigatorFilterService { private static final ViewerFilter[] NO_FILTERS = new ViewerFilter[0]; private static final String ACTIVATION_KEY = ".filterActivation"; //$NON-NLS-1$ private static final String DELIM = ":"; //$NON-NLS-1$ private final NavigatorContentService contentService; /* Map of (ICommonFilterDescriptor, ViewerFilter)-pairs */ private final Map<ICommonFilterDescriptor, ViewerFilter> declaredViewerFilters = new HashMap<ICommonFilterDescriptor, ViewerFilter>(); /* Set of ViewerFilters enforced from visible/active content extensions */ private final Set enforcedViewerFilters = new HashSet(); /* A set of active filter String ids */ private final Set<String> activeFilters = new HashSet<String>(); /** * @param aContentService * The corresponding content service */ public NavigatorFilterService(NavigatorContentService aContentService) { contentService = aContentService; restoreFilterActivation(); } private synchronized void restoreFilterActivation() { SafeRunner.run(new NavigatorSafeRunnable() { @Override public void run() throws Exception { IEclipsePreferences prefs = NavigatorContentService.getPreferencesRoot(); if (prefs.get(getFilterActivationPreferenceKey(), null) != null) { String activatedFiltersPreferenceValue = prefs.get( getFilterActivationPreferenceKey(), null); String[] activeFilterIds = activatedFiltersPreferenceValue.split(DELIM); for (String activeFilterId : activeFilterIds) { activeFilters.add(activeFilterId); } } else { ICommonFilterDescriptor[] visibleFilterDescriptors = getVisibleFilterDescriptors(); for (ICommonFilterDescriptor visibleFilterDescriptor : visibleFilterDescriptors) { if (visibleFilterDescriptor.isActiveByDefault()) { activeFilters.add(visibleFilterDescriptor.getId()); } } } } }); } @Override public void persistFilterActivationState() { synchronized (activeFilters) { CommonFilterDescriptorManager dm = CommonFilterDescriptorManager .getInstance(); /* * by creating a StringBuffer with DELIM, we ensure the string is * not empty when persisted. */ StringBuffer activatedFiltersPreferenceValue = new StringBuffer(DELIM); for (String id : activeFilters) { if (!dm.getFilterById(id).isVisibleInUi()) continue; activatedFiltersPreferenceValue.append(id).append(DELIM); } IEclipsePreferences prefs = NavigatorContentService.getPreferencesRoot(); prefs.put(getFilterActivationPreferenceKey(), activatedFiltersPreferenceValue.toString()); NavigatorContentService.flushPreferences(prefs); } } /** * Used for the tests */ public void resetFilterActivationState() { IEclipsePreferences prefs = NavigatorContentService.getPreferencesRoot(); prefs.remove(getFilterActivationPreferenceKey()); NavigatorContentService.flushPreferences(prefs); } /** * @return The correct filter activation preference key for the * corresponding content service. */ private String getFilterActivationPreferenceKey() { return contentService.getViewerId() + ACTIVATION_KEY; } @Override public ViewerFilter[] getVisibleFilters(boolean toReturnOnlyActiveFilters) { CommonFilterDescriptor[] descriptors = CommonFilterDescriptorManager .getInstance().findVisibleFilters(contentService); List<ViewerFilter> filters = new ArrayList<ViewerFilter>(); ViewerFilter instance; for (CommonFilterDescriptor descriptor : descriptors) { if (!toReturnOnlyActiveFilters || isActive(descriptor.getId())) { instance = getViewerFilter(descriptor); if (instance != null) { filters.add(instance); } } } /* return the enforced viewer filters always */ filters.addAll(enforcedViewerFilters); if (filters.size() == 0) { return NO_FILTERS; } return filters .toArray(new ViewerFilter[filters.size()]); } /** * @param descriptor * A key into the viewerFilters map. * @return A non-null ViewerFilter from the extension (or * {@link SkeletonViewerFilter#INSTANCE}). */ @Override public ViewerFilter getViewerFilter(ICommonFilterDescriptor descriptor) { ViewerFilter filter = null; synchronized (declaredViewerFilters) { filter = declaredViewerFilters.get(descriptor); if (filter == null) { declaredViewerFilters.put(descriptor, (filter = ((CommonFilterDescriptor) descriptor) .createFilter())); } } return filter; } @Override public ICommonFilterDescriptor[] getVisibleFilterDescriptors() { return CommonFilterDescriptorManager.getInstance().findVisibleFilters( contentService); } /** * @return the visible filter descriptors for the UI */ public ICommonFilterDescriptor[] getVisibleFilterDescriptorsForUI() { return CommonFilterDescriptorManager.getInstance().findVisibleFilters( contentService, CommonFilterDescriptorManager.FOR_UI); } @Override public boolean isActive(String aFilterId) { synchronized (activeFilters) { return activeFilters.contains(aFilterId); } } @Override public void setActiveFilterIds(String[] theFilterIds) { Assert.isNotNull(theFilterIds); synchronized (activeFilters) { activeFilters.clear(); activeFilters.addAll(Arrays.asList(theFilterIds)); } } @Override public void activateFilterIdsAndUpdateViewer(String[] filterIdsToActivate) { boolean updateFilterActivation = false; // we sort the array in order to use Array.binarySearch(); Arrays.sort(filterIdsToActivate); CommonFilterDescriptor[] visibleFilterDescriptors = (CommonFilterDescriptor[]) getVisibleFilterDescriptors(); int indexofFilterIdToBeActivated; List<String> nonUiVisible = null; /* is there a delta? */ for (int i = 0; i < visibleFilterDescriptors.length; i++) { indexofFilterIdToBeActivated = Arrays.binarySearch(filterIdsToActivate, visibleFilterDescriptors[i].getId()); /* * Either we have a filter that should be active that isn't XOR a * filter that shouldn't be active that is currently */ if (indexofFilterIdToBeActivated >= 0 ^ isActive(visibleFilterDescriptors[i].getId())) { updateFilterActivation = true; } // We don't turn of non-UI visible filters here, they have to be manipulated explicitly if (!visibleFilterDescriptors[i].isVisibleInUi()) { if (nonUiVisible == null) nonUiVisible = new ArrayList<String>(); nonUiVisible.add(visibleFilterDescriptors[i].getId()); } } /* If so, update */ if (updateFilterActivation) { if (nonUiVisible != null) { for (String filterIdToActivate : filterIdsToActivate) nonUiVisible.add(filterIdToActivate); filterIdsToActivate = nonUiVisible.toArray(new String[]{}); } setActiveFilterIds(filterIdsToActivate); persistFilterActivationState(); updateViewer(); // the action providers may no longer be enabled, so we // reset the selection. StructuredViewer commonViewer = (StructuredViewer) contentService.getViewer(); commonViewer.setSelection(StructuredSelection.EMPTY); } } /** * Updates the viewer filters to match the active filters. */ public void updateViewer() { StructuredViewer commonViewer = (StructuredViewer) contentService.getViewer(); ViewerFilter[] visibleFilters = getVisibleFilters(true); commonViewer.setFilters(visibleFilters); } /** * Activate the given array without disabling all other filters. * * @param theFilterIds * The filter ids to activate. */ public void addActiveFilterIds(String[] theFilterIds) { Assert.isNotNull(theFilterIds); synchronized (activeFilters) { activeFilters.addAll(Arrays.asList(theFilterIds)); } } /** * * @param aFilterId The id of the filter to activate or deactivate * @param toMakeActive True to make the filter active, false to make the filter inactive */ public void setActive(String aFilterId, boolean toMakeActive) { synchronized (activeFilters) { boolean isActive = activeFilters.contains(aFilterId); if(isActive ^ toMakeActive) { if(toMakeActive) activeFilters.add(aFilterId); else activeFilters.remove(aFilterId); } } } }