blob: ce8b524d5196be2375ca0b02fd26a096ed5e9e3a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 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
*******************************************************************************/
package org.eclipse.ui.internal;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import org.eclipse.core.commands.common.EventManager;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;
import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IElementFactory;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPersistableElement;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetElementAdapter;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.IWorkingSetUpdater;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.dialogs.IWorkingSetEditWizard;
import org.eclipse.ui.dialogs.IWorkingSetNewWizard;
import org.eclipse.ui.dialogs.IWorkingSetPage;
import org.eclipse.ui.dialogs.IWorkingSetSelectionDialog;
import org.eclipse.ui.internal.dialogs.WorkingSetEditWizard;
import org.eclipse.ui.internal.dialogs.WorkingSetNewWizard;
import org.eclipse.ui.internal.dialogs.WorkingSetSelectionDialog;
import org.eclipse.ui.internal.misc.StatusUtil;
import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
import org.eclipse.ui.internal.registry.WorkingSetDescriptor;
import org.eclipse.ui.internal.registry.WorkingSetRegistry;
import org.eclipse.ui.internal.util.PrefUtil;
import org.eclipse.ui.progress.WorkbenchJob;
import org.eclipse.ui.statushandlers.StatusManager;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
/**
* Abstract implementation of <code>IWorkingSetManager</code>.
*/
public abstract class AbstractWorkingSetManager extends EventManager implements
IWorkingSetManager, BundleListener, IExtensionChangeHandler {
static abstract class WorkingSetRunnable implements ISafeRunnable {
@Override
public void handleException(Throwable exception) {
StatusManager.getManager().handle(
StatusUtil.newStatus(PlatformUI.PLUGIN_ID, exception));
}
}
private SortedSet<AbstractWorkingSet> workingSets = new TreeSet<>((o1, o2) -> o1.getUniqueId().compareTo(o2.getUniqueId()));
private List<IWorkingSet> recentWorkingSets = new ArrayList<>();
private BundleContext bundleContext;
private Map<String, IWorkingSetUpdater> updaters = new HashMap<>();
private Map<String, IWorkingSetElementAdapter> elementAdapters = new HashMap<>();
private static final IWorkingSetUpdater NULL_UPDATER = new IWorkingSetUpdater() {
@Override
public void add(IWorkingSet workingSet) {
}
@Override
public boolean remove(IWorkingSet workingSet) {
return true;
}
@Override
public boolean contains(IWorkingSet workingSet) {
return true;
}
@Override
public void dispose() {
}
};
private static final IWorkingSetElementAdapter IDENTITY_ADAPTER = new IWorkingSetElementAdapter() {
@Override
public IAdaptable[] adaptElements(IWorkingSet ws, IAdaptable[] elements) {
return elements;
}
@Override
public void dispose() {
}
};
/**
* Returns the descriptors for the given editable working set ids. If an id
* refers to a missing descriptor, or one that is non-editable, it is
* skipped. If <code>null</code> is passed, all editable descriptors are
* returned.
*
* @param supportedWorkingSetIds
* the ids for the working set descriptors, or <code>null</code>
* for all editable descriptors
* @return the descriptors corresponding to the given editable working set
* ids
*/
private static WorkingSetDescriptor[] getSupportedEditableDescriptors(String[] supportedWorkingSetIds) {
WorkingSetRegistry registry = WorkbenchPlugin.getDefault().getWorkingSetRegistry();
if (supportedWorkingSetIds == null) {
return registry.getNewPageWorkingSetDescriptors();
}
List<WorkingSetDescriptor> result = new ArrayList<>(supportedWorkingSetIds.length);
for (String supportedWorkingSetId : supportedWorkingSetIds) {
WorkingSetDescriptor desc = registry.getWorkingSetDescriptor(supportedWorkingSetId);
if (desc != null && desc.isEditable()) {
result.add(desc);
}
}
return result.toArray(new WorkingSetDescriptor[result.size()]);
}
protected AbstractWorkingSetManager(BundleContext context) {
bundleContext= context;
bundleContext.addBundleListener(this);
PlatformUI.getWorkbench().getExtensionTracker().registerHandler(this, ExtensionTracker
.createExtensionPointFilter(getExtensionPointFilter()));
}
/**
* Returns the working sets extension point.
*
* @return the working sets extension point
* @since 3.3
*/
private IExtensionPoint getExtensionPointFilter() {
return Platform.getExtensionRegistry().getExtensionPoint(
PlatformUI.PLUGIN_ID,
IWorkbenchRegistryConstants.PL_WORKINGSETS);
}
@Override
public void dispose() {
bundleContext.removeBundleListener(this);
for (IWorkingSetUpdater next : updaters.values()) {
SafeRunner.run(new WorkingSetRunnable() {
@Override
public void run() throws Exception {
next.dispose();
}
});
}
for (IWorkingSetElementAdapter next : elementAdapters.values()) {
SafeRunner.run(new WorkingSetRunnable() {
@Override
public void run() throws Exception {
next.dispose();
}
});
}
}
//---- working set creation -----------------------------------------------------
@Override
public IWorkingSet createWorkingSet(String name, IAdaptable[] elements) {
return new WorkingSet(name, name, elements);
}
@Override
public IWorkingSet createAggregateWorkingSet(String name, String label,
IWorkingSet[] components) {
return new AggregateWorkingSet(name, label, components);
}
@Override
public IWorkingSet createWorkingSet(IMemento memento) {
return restoreWorkingSet(memento);
}
//---- working set management ---------------------------------------------------
@Override
public void addWorkingSet(IWorkingSet workingSet) {
IWorkingSet wSet = getWorkingSet(workingSet.getName());
Assert.isTrue(wSet==null,"working set with same name already registered"); //$NON-NLS-1$
internalAddWorkingSet(workingSet);
}
private void internalAddWorkingSet(IWorkingSet workingSet) {
AbstractWorkingSet abstractWorkingSet = (AbstractWorkingSet) workingSet;
workingSets.add(abstractWorkingSet);
abstractWorkingSet.connect(this);
addToUpdater(workingSet);
firePropertyChange(CHANGE_WORKING_SET_ADD, null, workingSet);
}
protected boolean internalRemoveWorkingSet(IWorkingSet workingSet) {
boolean workingSetRemoved = workingSets.remove(workingSet);
boolean recentWorkingSetRemoved = recentWorkingSets.remove(workingSet);
if (workingSetRemoved) {
((AbstractWorkingSet)workingSet).disconnect();
removeFromUpdater(workingSet);
firePropertyChange(CHANGE_WORKING_SET_REMOVE, workingSet, null);
}
return workingSetRemoved || recentWorkingSetRemoved;
}
@Override
public IWorkingSet[] getWorkingSets() {
SortedSet<IWorkingSet> visibleSubset = new TreeSet<IWorkingSet>(WorkingSetComparator.getInstance());
for (IWorkingSet workingSet : workingSets) {
if (workingSet.isVisible()) {
visibleSubset.add(workingSet);
}
}
return visibleSubset.toArray(new IWorkingSet[visibleSubset.size()]);
}
@Override
public IWorkingSet[] getAllWorkingSets() {
IWorkingSet[] sets = workingSets.toArray(new IWorkingSet[workingSets.size()]);
Arrays.sort(sets, WorkingSetComparator.getInstance());
return sets;
}
@Override
public IWorkingSet getWorkingSet(String name) {
if (name == null || workingSets == null) {
return null;
}
for (IWorkingSet workingSet : workingSets) {
if (name.equals(workingSet.getName())) {
return workingSet;
}
}
return null;
}
// ---- recent working set management --------------------------------------
@Override
public IWorkingSet[] getRecentWorkingSets() {
return recentWorkingSets.toArray(new IWorkingSet[recentWorkingSets.size()]);
}
/**
* Adds the specified working set to the list of recently used
* working sets.
*
* @param workingSet working set to added to the list of recently
* used working sets.
*/
protected void internalAddRecentWorkingSet(IWorkingSet workingSet) {
if (!workingSet.isVisible()) {
return;
}
recentWorkingSets.remove(workingSet);
recentWorkingSets.add(0, workingSet);
sizeRecentWorkingSets();
}
//---- equals and hash code -----------------------------------------------
/**
* Tests the receiver and the object for equality
*
* @param object object to compare the receiver to
* @return true=the object equals the receiver, it has the same
* working sets. false otherwise
*/
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (!getClass().getName().equals(object.getClass().getName())) {
return false;
}
AbstractWorkingSetManager other= (AbstractWorkingSetManager)object;
return other.workingSets.equals(workingSets);
}
/**
* Returns the hash code.
*
* @return the hash code.
*/
@Override
public int hashCode() {
return workingSets.hashCode();
}
//---- property listeners -------------------------------------------------
@Override
public void addPropertyChangeListener(IPropertyChangeListener listener) {
addListenerObject(listener);
}
@Override
public void removePropertyChangeListener(IPropertyChangeListener listener) {
removeListenerObject(listener);
}
/**
* Notify property change listeners about a change to the list of
* working sets.
*
* @param changeId one of
* IWorkingSetManager#CHANGE_WORKING_SET_ADD
* IWorkingSetManager#CHANGE_WORKING_SET_REMOVE
* IWorkingSetManager#CHANGE_WORKING_SET_CONTENT_CHANGE
* IWorkingSetManager#CHANGE_WORKING_SET_NAME_CHANGE
* @param oldValue the removed working set or null if a working set
* was added or changed.
* @param newValue the new or changed working set or null if a working
* set was removed.
*/
protected void firePropertyChange(String changeId, Object oldValue,
Object newValue) {
final Object[] listeners = getListeners();
if (listeners.length == 0) {
return;
}
final PropertyChangeEvent event = new PropertyChangeEvent(this,
changeId, oldValue, newValue);
Runnable notifier = () -> {
for (Object listener : listeners) {
final IPropertyChangeListener propertyChangeListener = (IPropertyChangeListener) listener;
ISafeRunnable safetyWrapper = new ISafeRunnable() {
@Override
public void run() throws Exception {
propertyChangeListener.propertyChange(event);
}
@Override
public void handleException(Throwable exception) {
// logged by the runner
}
};
SafeRunner.run(safetyWrapper);
}
};
// Notifications are sent on the UI thread.
if (Display.getCurrent() != null) {
notifier.run();
} else {
// Use an asyncExec to avoid deadlocks.
Display.getDefault().asyncExec(notifier);
}
}
/**
* Fires a property change event for the changed working set. Should only be
* called by org.eclipse.ui.internal.WorkingSet.
*
* @param changedWorkingSet
* the working set that has changed
* @param propertyChangeId
* the changed property. one of
* CHANGE_WORKING_SET_CONTENT_CHANGE,
* CHANGE_WORKING_SET_LABEL_CHANGE, and
* CHANGE_WORKING_SET_NAME_CHANGE
* @param oldValue
* the old value
*/
public void workingSetChanged(IWorkingSet changedWorkingSet,
String propertyChangeId, Object oldValue) {
firePropertyChange(propertyChangeId, oldValue, changedWorkingSet);
}
// ---- Persistence
// ----------------------------------------------------------------
/**
* Saves all persistable working sets in the persistence store.
*
* @param memento the persistence store
* @see IPersistableElement
*/
public void saveWorkingSetState(IMemento memento) {
Iterator<AbstractWorkingSet> iterator = workingSets.iterator();
// break the sets into aggregates and non aggregates. The aggregates should be saved after the non-aggregates
// so that on restoration all necessary aggregate components can be found.
ArrayList<IWorkingSet> standardSets = new ArrayList<>();
ArrayList<IWorkingSet> aggregateSets = new ArrayList<>();
while (iterator.hasNext()) {
IWorkingSet set = iterator.next();
if (set instanceof AggregateWorkingSet) {
aggregateSets.add(set);
} else {
standardSets.add(set);
}
}
saveWorkingSetState(memento, standardSets);
saveWorkingSetState(memento, aggregateSets);
}
/**
* @param memento the memento to save to
* @param list the working sets to save
* @since 3.2
*/
private void saveWorkingSetState(final IMemento memento, List list) {
for (Iterator i = list.iterator(); i.hasNext();) {
final IPersistableElement persistable = (IWorkingSet) i.next();
SafeRunner.run(new WorkingSetRunnable() {
@Override
public void run() throws Exception {
// create a dummy node to write too - the write could fail so we
// shouldn't soil the final memento until we're sure it succeeds.
XMLMemento dummy = XMLMemento.createWriteRoot(IWorkbenchConstants.TAG_WORKING_SET);
dummy.putString(IWorkbenchConstants.TAG_FACTORY_ID,
persistable.getFactoryId());
persistable.saveState(dummy);
// if the dummy was created successfully copy it to the real output
IMemento workingSetMemento = memento
.createChild(IWorkbenchConstants.TAG_WORKING_SET);
workingSetMemento.putMemento(dummy);
}
});
}
}
/**
* Recreates all working sets from the persistence store
* and adds them to the receiver.
*
* @param memento the persistence store
*/
protected void restoreWorkingSetState(IMemento memento) {
for (IMemento child : memento.getChildren(IWorkbenchConstants.TAG_WORKING_SET)) {
AbstractWorkingSet workingSet = (AbstractWorkingSet) restoreWorkingSet(child);
if (workingSet != null) {
internalAddWorkingSet(workingSet);
}
}
}
/**
* Recreates a working set from the persistence store.
*
* @param memento the persistence store
* @return the working set created from the memento or null if
* creation failed.
*/
protected IWorkingSet restoreWorkingSet(final IMemento memento) {
String factoryID = memento
.getString(IWorkbenchConstants.TAG_FACTORY_ID);
if (factoryID == null) {
// if the factory id was not set in the memento
// then assume that the memento was created using
// IMemento.saveState, and should be restored using WorkingSetFactory
factoryID = AbstractWorkingSet.FACTORY_ID;
}
final IElementFactory factory = PlatformUI.getWorkbench().getElementFactory(
factoryID);
if (factory == null) {
WorkbenchPlugin
.log("Unable to restore working set - cannot instantiate factory: " + factoryID); //$NON-NLS-1$
return null;
}
final IAdaptable[] adaptable = new IAdaptable[1];
SafeRunner.run(new WorkingSetRunnable() {
@Override
public void run() throws Exception {
adaptable[0] = factory.createElement(memento);
}
});
if (adaptable[0] == null) {
WorkbenchPlugin
.log("Unable to restore working set - cannot instantiate working set: " + factoryID); //$NON-NLS-1$
return null;
}
if ((adaptable[0] instanceof IWorkingSet) == false) {
WorkbenchPlugin
.log("Unable to restore working set - element is not an IWorkingSet: " + factoryID); //$NON-NLS-1$
return null;
}
return (IWorkingSet) adaptable[0];
}
/**
* Saves the list of most recently used working sets in the persistence
* store.
*
* @param memento the persistence store
*/
protected void saveMruList(IMemento memento) {
Iterator iterator = recentWorkingSets.iterator();
while (iterator.hasNext()) {
IWorkingSet workingSet = (IWorkingSet) iterator.next();
IMemento mruMemento = memento
.createChild(IWorkbenchConstants.TAG_MRU_LIST);
mruMemento.putString(IWorkbenchConstants.TAG_NAME, workingSet
.getName());
}
}
/**
* Restores the list of most recently used working sets from the
* persistence store.
*
* @param memento the persistence store
*/
protected void restoreMruList(IMemento memento) {
IMemento[] mruWorkingSets = memento
.getChildren(IWorkbenchConstants.TAG_MRU_LIST);
for (int i = mruWorkingSets.length - 1; i >= 0; i--) {
String workingSetName = mruWorkingSets[i]
.getString(IWorkbenchConstants.TAG_NAME);
if (workingSetName != null) {
IWorkingSet workingSet = getWorkingSet(workingSetName);
if (workingSet != null) {
internalAddRecentWorkingSet(workingSet);
}
}
}
}
//---- user interface support -----------------------------------------------------
/**
* @see org.eclipse.ui.IWorkingSetManager#createWorkingSetEditWizard(org.eclipse.ui.IWorkingSet)
* @since 2.1
*/
@Override
public IWorkingSetEditWizard createWorkingSetEditWizard(
IWorkingSet workingSet) {
String editPageId = workingSet.getId();
WorkingSetRegistry registry = WorkbenchPlugin.getDefault()
.getWorkingSetRegistry();
IWorkingSetPage editPage = null;
if (editPageId != null) {
editPage = registry.getWorkingSetPage(editPageId);
}
// the following block kind of defeats IWorkingSet.isEditable() and it
// doesn't make sense for there to be a default page in such a case.
if (editPage == null) {
editPage = registry.getDefaultWorkingSetPage();
if (editPage == null) {
return null;
}
}
WorkingSetEditWizard editWizard = new WorkingSetEditWizard(editPage);
editWizard.setSelection(workingSet);
return editWizard;
}
/**
* @deprecated use createWorkingSetSelectionDialog(parent, true) instead
*/
@Deprecated
@Override
public IWorkingSetSelectionDialog createWorkingSetSelectionDialog(
Shell parent) {
return createWorkingSetSelectionDialog(parent, true);
}
@Override
public IWorkingSetSelectionDialog createWorkingSetSelectionDialog(
Shell parent, boolean multi) {
return createWorkingSetSelectionDialog(parent, multi, null);
}
/**
* {@inheritDoc}
*/
@Override
public IWorkingSetNewWizard createWorkingSetNewWizard(String[] workingSetIds) {
WorkingSetDescriptor[] descriptors= getSupportedEditableDescriptors(workingSetIds);
if (descriptors.length == 0) {
return null;
}
return new WorkingSetNewWizard(descriptors);
}
//---- working set delta handling -------------------------------------------------
@Override
public void bundleChanged(BundleEvent event) {
String symbolicName = event.getBundle().getSymbolicName();
if (symbolicName == null)
return;
// If the workbench isn't running anymore simply return.
if (!PlatformUI.isWorkbenchRunning()) {
return;
}
if (event.getBundle().getState() == Bundle.ACTIVE) {
final WorkingSetDescriptor[] descriptors = WorkbenchPlugin.getDefault()
.getWorkingSetRegistry().getUpdaterDescriptorsForNamespace(
symbolicName);
Job job = new WorkbenchJob(
NLS
.bind(
WorkbenchMessages.AbstractWorkingSetManager_updatersActivating,
symbolicName)) {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
synchronized (updaters) {
for (WorkingSetDescriptor descriptor : descriptors) {
List workingSets = getWorkingSetsForId(descriptor
.getId());
if (workingSets.size() == 0) {
continue;
}
final IWorkingSetUpdater updater = getUpdater(descriptor);
for (Iterator iter = workingSets.iterator(); iter
.hasNext();) {
final IWorkingSet workingSet = (IWorkingSet) iter
.next();
SafeRunner.run(new WorkingSetRunnable() {
@Override
public void run() throws Exception {
if (!updater.contains(workingSet)) {
updater.add(workingSet);
}
}
});
}
}
}
return Status.OK_STATUS;
}
};
job.setSystem(true);
job.schedule();
}
}
private List getWorkingSetsForId(String id) {
List result= new ArrayList();
for (IWorkingSet ws : workingSets) {
if (id.equals(ws.getId())) {
result.add(ws);
}
}
return result;
}
private void addToUpdater(final IWorkingSet workingSet) {
WorkingSetDescriptor descriptor= WorkbenchPlugin.getDefault()
.getWorkingSetRegistry().getWorkingSetDescriptor(workingSet.getId());
if (descriptor == null || !descriptor.isUpdaterClassLoaded()) {
return;
}
synchronized(updaters) {
final IWorkingSetUpdater updater= getUpdater(descriptor);
SafeRunner.run(new WorkingSetRunnable() {
@Override
public void run() throws Exception {
if (!updater.contains(workingSet)) {
updater.add(workingSet);
}
}});
}
}
private IWorkingSetUpdater getUpdater(WorkingSetDescriptor descriptor) {
IWorkingSetUpdater updater = updaters.get(descriptor.getId());
if (updater == null) {
updater = descriptor.createWorkingSetUpdater();
if (updater == null) {
updater = NULL_UPDATER;
} else {
firePropertyChange(CHANGE_WORKING_SET_UPDATER_INSTALLED, null, updater);
PlatformUI.getWorkbench().getExtensionTracker().registerObject(
descriptor.getConfigurationElement().getDeclaringExtension(), updater,
IExtensionTracker.REF_WEAK);
}
updaters.put(descriptor.getId(), updater);
}
return updater;
}
IWorkingSetElementAdapter getElementAdapter(WorkingSetDescriptor descriptor) {
IWorkingSetElementAdapter elementAdapter = elementAdapters.get(descriptor.getId());
if (elementAdapter == null) {
elementAdapter = descriptor.createWorkingSetElementAdapter();
if (elementAdapter == null) {
elementAdapter = IDENTITY_ADAPTER;
} else {
elementAdapters.put(descriptor.getId(), elementAdapter);
}
}
return elementAdapter;
}
private void removeFromUpdater(final IWorkingSet workingSet) {
synchronized (updaters) {
final IWorkingSetUpdater updater = updaters.get(workingSet.getId());
if (updater != null) {
SafeRunner.run(new WorkingSetRunnable() {
@Override
public void run() throws Exception {
updater.remove(workingSet);
}
});
}
}
}
@Override
public IWorkingSetSelectionDialog createWorkingSetSelectionDialog(Shell parent, boolean multi, String[] workingsSetIds) {
return new WorkingSetSelectionDialog(parent, multi, workingsSetIds);
}
/**
* Save the state to the state file.
*
* @param stateFile
* @throws IOException
*/
public void saveState(File stateFile) throws IOException {
XMLMemento memento = XMLMemento
.createWriteRoot(IWorkbenchConstants.TAG_WORKING_SET_MANAGER);
saveWorkingSetState(memento);
saveMruList(memento);
FileOutputStream stream = new FileOutputStream(stateFile);
OutputStreamWriter writer = new OutputStreamWriter(stream, StandardCharsets.UTF_8);
memento.save(writer);
writer.close();
}
@Override
public void addExtension(IExtensionTracker tracker, IExtension extension) {
// nothing - this is handled lazily. These items are only created as needed by the getUpdater() and getElementAdapter() methods
}
@Override
public void removeExtension(IExtension extension, Object[] objects) {
for (Object object : objects) {
if (object instanceof IWorkingSetUpdater) {
removeUpdater((IWorkingSetUpdater)object);
}
if (object instanceof IWorkingSetElementAdapter) {
removeElementAdapter((IWorkingSetElementAdapter) object);
}
}
}
/**
* Remove the element adapter from the manager and dispose of it.
*
* @param elementAdapter
* @since 3.3
*/
private void removeElementAdapter(
final IWorkingSetElementAdapter elementAdapter) {
SafeRunner.run(new WorkingSetRunnable() {
@Override
public void run() throws Exception {
elementAdapter.dispose();
}
});
synchronized (elementAdapters) {
elementAdapters.values().remove(elementAdapter);
}
}
/**
* Remove the updater from the manager and dispose of it.
*
* @param updater
* @since 3.3
*/
private void removeUpdater(final IWorkingSetUpdater updater) {
SafeRunner.run(new WorkingSetRunnable() {
@Override
public void run() throws Exception {
updater.dispose();
}
});
synchronized (updaters) {
updaters.values().remove(updater);
}
firePropertyChange(IWorkingSetManager.CHANGE_WORKING_SET_UPDATER_UNINSTALLED, updater, null);
}
@Override
public void addToWorkingSets(final IAdaptable element, IWorkingSet[] workingSets) {
// ideally this method would be in a static util class of some kind but
// we dont have any such beast for working sets and making one for one
// method is overkill.
for (final IWorkingSet workingSet : workingSets) {
SafeRunner.run(new WorkingSetRunnable() {
@Override
public void run() throws Exception {
IAdaptable[] adaptedNewElements = workingSet
.adaptElements(new IAdaptable[] { element });
if (adaptedNewElements.length == 1) {
IAdaptable[] elements = workingSet.getElements();
IAdaptable[] newElements = new IAdaptable[elements.length + 1];
System.arraycopy(elements, 0, newElements, 0,
elements.length);
newElements[newElements.length - 1] = adaptedNewElements[0];
workingSet.setElements(newElements);
}
}});
}
}
@Override
public void setRecentWorkingSetsLength(int length) {
if (length < 1 || length > 99)
throw new IllegalArgumentException("Invalid recent working sets length: " + length); //$NON-NLS-1$
IPreferenceStore store = PrefUtil.getAPIPreferenceStore();
store.setValue(IWorkbenchPreferenceConstants.RECENTLY_USED_WORKINGSETS_SIZE, length);
// adjust length
sizeRecentWorkingSets();
}
private void sizeRecentWorkingSets() {
int maxLength = getRecentWorkingSetsLength();
while (recentWorkingSets.size() > maxLength) {
int lastPosition = recentWorkingSets.size() - 1;
recentWorkingSets.remove(lastPosition);
}
}
@Override
public int getRecentWorkingSetsLength() {
IPreferenceStore store = PrefUtil.getAPIPreferenceStore();
return store.getInt(IWorkbenchPreferenceConstants.RECENTLY_USED_WORKINGSETS_SIZE);
}
}