/******************************************************************************* * Copyright (c) 2006, 2016 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 * anton.leherbauer@windriver.com - bug 212389 [CommonNavigator] working set issues: * missing project, window working set inconsistency * Mickael Istria (Red Hat Inc.) - [266030] Allow "others" working set *******************************************************************************/ package org.eclipse.ui.internal.navigator.resources.actions; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IAggregateWorkingSet; import org.eclipse.ui.IMemento; import org.eclipse.ui.IWorkbenchPreferenceConstants; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ResourceWorkingSetFilter; import org.eclipse.ui.actions.WorkingSetFilterActionGroup; import org.eclipse.ui.internal.navigator.NavigatorFilterService; import org.eclipse.ui.internal.navigator.resources.plugin.WorkbenchNavigatorMessages; import org.eclipse.ui.internal.navigator.resources.plugin.WorkbenchNavigatorPlugin; import org.eclipse.ui.internal.navigator.workingsets.WorkingSetsContentProvider; import org.eclipse.ui.navigator.CommonActionProvider; import org.eclipse.ui.navigator.CommonViewer; import org.eclipse.ui.navigator.ICommonActionExtensionSite; import org.eclipse.ui.navigator.IExtensionActivationListener; import org.eclipse.ui.navigator.IExtensionStateModel; import org.eclipse.ui.navigator.INavigatorContentService; /** * @since 3.2 * */ public class WorkingSetActionProvider extends CommonActionProvider { private static final String TAG_CURRENT_WORKING_SET_NAME = "currentWorkingSetName"; //$NON-NLS-1$ private static final String WORKING_SET_FILTER_ID = "org.eclipse.ui.navigator.resources.filters.workingSet"; //$NON-NLS-1$ private boolean contributedToViewMenu = false; private CommonViewer viewer; private INavigatorContentService contentService; private NavigatorFilterService filterService; private WorkingSetFilterActionGroup workingSetActionGroup; private WorkingSetRootModeActionGroup workingSetRootModeActionGroup; private Object originalViewerInput = ResourcesPlugin.getWorkspace().getRoot(); private IExtensionStateModel extensionStateModel; private boolean emptyWorkingSet; private IWorkingSet workingSet; private IPropertyChangeListener topLevelModeListener; private boolean ignoreFilterChangeEvents; /** * Provides a smart listener to monitor changes to the Working Set Manager. * */ public class WorkingSetManagerListener implements IPropertyChangeListener { private boolean listening = false; @Override public void propertyChange(PropertyChangeEvent event) { String property = event.getProperty(); Object newValue = event.getNewValue(); Object oldValue = event.getOldValue(); String newLabel = null; if (IWorkingSetManager.CHANGE_WORKING_SET_REMOVE.equals(property) && oldValue == workingSet) { newLabel = ""; //$NON-NLS-1$ setWorkingSet(null); } else if (IWorkingSetManager.CHANGE_WORKING_SET_NAME_CHANGE.equals(property) && newValue == workingSet) { newLabel = workingSet.getLabel(); } else if (IWorkingSetManager.CHANGE_WORKING_SET_CONTENT_CHANGE.equals(property) && newValue == workingSet) { if (workingSet.isAggregateWorkingSet() && workingSet.isEmpty()) { // act as if the working set has been made null if (!emptyWorkingSet) { emptyWorkingSet = true; setWorkingSetFilter(null); newLabel = null; } } else { // we've gone from empty to non-empty on our set. // Restore it. if (emptyWorkingSet) { emptyWorkingSet = false; setWorkingSetFilter(workingSet); newLabel = workingSet.getLabel(); } } } if (viewer != null) { if (newLabel != null) viewer.getCommonNavigator().setWorkingSetLabel(newLabel); viewer.getFrameList().reset(); viewer.refresh(); } } /** * Begin listening to the correct source if not already listening. */ public synchronized void listen() { if (!listening) { PlatformUI.getWorkbench().getWorkingSetManager().addPropertyChangeListener(managerChangeListener); listening = true; } } /** * Begin listening to the correct source if not already listening. */ public synchronized void ignore() { if (listening) { PlatformUI.getWorkbench().getWorkingSetManager().removePropertyChangeListener(managerChangeListener); listening = false; } } } private IPropertyChangeListener filterChangeListener = new IPropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent event) { if (ignoreFilterChangeEvents) return; IWorkingSet newWorkingSet = (IWorkingSet) event.getNewValue(); setWorkingSet(newWorkingSet); if (newWorkingSet != null) { if (!contentService.isActive(WorkingSetsContentProvider.EXTENSION_ID)) { contentService.getActivationService().activateExtensions( new String[] { WorkingSetsContentProvider.EXTENSION_ID }, false); contentService.getActivationService().persistExtensionActivations(); } if (newWorkingSet.isAggregateWorkingSet()) { IAggregateWorkingSet agWs = (IAggregateWorkingSet) newWorkingSet; IWorkingSet[] comps = agWs.getComponents(); if (comps.length > 1) { viewer.getCommonNavigator().setWorkingSetLabel( WorkbenchNavigatorMessages.WorkingSetActionProvider_multipleWorkingSets); } else if (comps.length > 0) { viewer.getCommonNavigator().setWorkingSetLabel(comps[0].getLabel()); } else { viewer.getCommonNavigator().setWorkingSetLabel(null); } } else viewer.getCommonNavigator().setWorkingSetLabel(workingSet.getLabel()); } else { viewer.getCommonNavigator().setWorkingSetLabel(null); } viewer.getFrameList().reset(); } }; private WorkingSetManagerListener managerChangeListener = new WorkingSetManagerListener(); private IExtensionActivationListener activationListener = new IExtensionActivationListener() { private IWorkingSet savedWorkingSet; @Override public void onExtensionActivation(String aViewerId, String[] theNavigatorExtensionIds, boolean isActive) { for (String theNavigatorExtensionId : theNavigatorExtensionIds) { if (WorkingSetsContentProvider.EXTENSION_ID.equals(theNavigatorExtensionId)) { if (isActive) { extensionStateModel = contentService.findStateModel(WorkingSetsContentProvider.EXTENSION_ID); workingSetRootModeActionGroup.setStateModel(extensionStateModel); extensionStateModel.addPropertyChangeListener(topLevelModeListener); if (savedWorkingSet != null) { setWorkingSet(savedWorkingSet); } managerChangeListener.listen(); } else { savedWorkingSet = workingSet; setWorkingSet(null); viewer.getCommonNavigator().setWorkingSetLabel(null); managerChangeListener.ignore(); workingSetRootModeActionGroup.setShowTopLevelWorkingSets(false); extensionStateModel.removePropertyChangeListener(topLevelModeListener); } } } } }; @Override public void init(ICommonActionExtensionSite aSite) { viewer = (CommonViewer) aSite.getStructuredViewer(); contentService = aSite.getContentService(); filterService = (NavigatorFilterService) contentService.getFilterService(); extensionStateModel = contentService.findStateModel(WorkingSetsContentProvider.EXTENSION_ID); workingSetActionGroup = new WorkingSetFilterActionGroup(aSite.getViewSite().getShell(), filterChangeListener); workingSetRootModeActionGroup = new WorkingSetRootModeActionGroup(viewer, extensionStateModel); topLevelModeListener = new IPropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent event) { setWorkingSet(workingSet); viewer.getFrameList().reset(); } }; if (contentService.isActive(WorkingSetsContentProvider.EXTENSION_ID)) { managerChangeListener.listen(); extensionStateModel.addPropertyChangeListener(topLevelModeListener); } contentService.getActivationService().addExtensionActivationListener(activationListener); } /** * Restores the working set filter from the persistence store. */ protected void initWorkingSetFilter(String workingSetName) { IWorkingSet workingSet = null; if (workingSetName != null && workingSetName.length() > 0) { IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager(); workingSet = workingSetManager.getWorkingSet(workingSetName); } else if (PlatformUI.getPreferenceStore().getBoolean( IWorkbenchPreferenceConstants.USE_WINDOW_WORKING_SET_BY_DEFAULT)) { // use the window set by default if the global preference is set workingSet = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getAggregateWorkingSet(); } if (workingSet != null) { setWorkingSet(workingSet); } } private void setWorkingSetFilter(IWorkingSet workingSet) { setWorkingSetFilter(workingSet, FIRST_TIME); } private static final boolean FIRST_TIME = true; private void setWorkingSetFilter(IWorkingSet workingSet, boolean firstTime) { ResourceWorkingSetFilter workingSetFilter = null; ViewerFilter[] filters = viewer.getFilters(); for (ViewerFilter filter : filters) { if (filter instanceof ResourceWorkingSetFilter) { workingSetFilter = (ResourceWorkingSetFilter) filter; break; } } if (workingSetFilter == null) { if (firstTime) { filterService.addActiveFilterIds(new String[] { WORKING_SET_FILTER_ID }); filterService.updateViewer(); setWorkingSetFilter(workingSet, !FIRST_TIME); return; } WorkbenchNavigatorPlugin.log("Required filter " + WORKING_SET_FILTER_ID + //$NON-NLS-1$ " is not present. Working set support will not function correctly.", //$NON-NLS-1$ new Status(IStatus.ERROR, WorkbenchNavigatorPlugin.PLUGIN_ID, "")); //$NON-NLS-1$ return; } if (extensionStateModel.getBooleanProperty(WorkingSetsContentProvider.SHOW_TOP_LEVEL_WORKING_SETS) && extensionStateModel.getBooleanProperty(WorkingSetsContentProvider.SHOW_OTHERS_WORKING_SET)) { // do not need filter when working sets are used for grouping // a filter would hide the "Others" working set content workingSetFilter.setWorkingSet(null); } else { workingSetFilter.setWorkingSet(emptyWorkingSet ? null : workingSet); } } /** * Set current active working set. * * @param workingSet * working set to be activated, may be <code>null</code> */ protected void setWorkingSet(IWorkingSet workingSet) { this.workingSet = workingSet; emptyWorkingSet = workingSet != null && workingSet.isAggregateWorkingSet() && workingSet.isEmpty(); ignoreFilterChangeEvents = true; try { workingSetActionGroup.setWorkingSet(workingSet); } finally { ignoreFilterChangeEvents = false; } if (viewer != null) { setWorkingSetFilter(workingSet); if (workingSet == null || emptyWorkingSet || !extensionStateModel.getBooleanProperty(WorkingSetsContentProvider.SHOW_TOP_LEVEL_WORKING_SETS)) { if (viewer.getInput() != originalViewerInput) { viewer.setInput(originalViewerInput); } else { viewer.refresh(); } } else { if (!workingSet.isAggregateWorkingSet()) { IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager(); viewer.setInput(workingSetManager.createAggregateWorkingSet( "", "", new IWorkingSet[] { workingSet })); //$NON-NLS-1$ //$NON-NLS-2$ } else { viewer.setInput(workingSet); } } } } @Override public void restoreState(final IMemento aMemento) { super.restoreState(aMemento); // Need to run this async to avoid being reentered when processing a selection change viewer.getControl().getShell().getDisplay().asyncExec(new Runnable() { @Override public void run() { boolean showWorkingSets = true; if (aMemento != null) { Integer showWorkingSetsInt = aMemento .getInteger(WorkingSetsContentProvider.SHOW_TOP_LEVEL_WORKING_SETS); showWorkingSets = showWorkingSetsInt == null || showWorkingSetsInt.intValue() == 1; extensionStateModel.setBooleanProperty(WorkingSetsContentProvider.SHOW_TOP_LEVEL_WORKING_SETS, showWorkingSets); workingSetRootModeActionGroup.setShowTopLevelWorkingSets(showWorkingSets); String lastWorkingSetName = aMemento.getString(TAG_CURRENT_WORKING_SET_NAME); initWorkingSetFilter(lastWorkingSetName); } else { showWorkingSets = false; extensionStateModel.setBooleanProperty(WorkingSetsContentProvider.SHOW_TOP_LEVEL_WORKING_SETS, showWorkingSets); workingSetRootModeActionGroup.setShowTopLevelWorkingSets(showWorkingSets); } } }); } @Override public void saveState(IMemento aMemento) { super.saveState(aMemento); if (aMemento != null) { int showWorkingSets = extensionStateModel .getBooleanProperty(WorkingSetsContentProvider.SHOW_TOP_LEVEL_WORKING_SETS) ? 1 : 0; aMemento.putInteger(WorkingSetsContentProvider.SHOW_TOP_LEVEL_WORKING_SETS, showWorkingSets); if (workingSet != null) { aMemento.putString(TAG_CURRENT_WORKING_SET_NAME, workingSet.getName()); } } } @Override public void fillActionBars(IActionBars actionBars) { if (!contributedToViewMenu) { try { super.fillActionBars(actionBars); workingSetActionGroup.fillActionBars(actionBars); if (workingSetRootModeActionGroup != null) { workingSetRootModeActionGroup.fillActionBars(actionBars); } } finally { contributedToViewMenu = true; } } } @Override public void dispose() { super.dispose(); workingSetActionGroup.dispose(); if (workingSetRootModeActionGroup != null) { workingSetRootModeActionGroup.dispose(); } managerChangeListener.ignore(); extensionStateModel.removePropertyChangeListener(topLevelModeListener); contentService.getActivationService().removeExtensionActivationListener(activationListener); } /** * This is used only for the tests. * * @return a PropertyChangeListener */ public IPropertyChangeListener getFilterChangeListener() { return filterChangeListener; } }