blob: 26c003868e1742fa46030bf5b420aca64f83d610 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2015 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Tomasz Zarna <tomasz.zarna@tasktop.com> - Bug 37183
*******************************************************************************/
package org.eclipse.ui.internal;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.ui.IElementFactory;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPersistableElement;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.IWorkingSetUpdater;
import org.eclipse.ui.IWorkingSetUpdater2;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.misc.Policy;
import org.eclipse.ui.internal.registry.WorkingSetDescriptor;
import org.eclipse.ui.internal.registry.WorkingSetRegistry;
/**
* A working set holds a number of IAdaptable elements. A working set is
* intended to group elements for presentation to the user or for operations on
* a set of elements.
*
* @see org.eclipse.ui.IWorkingSet
* @since 2.0
*/
public class WorkingSet extends AbstractWorkingSet {
private static final String DEFAULT_ID = "org.eclipse.ui.resourceWorkingSetPage"; //$NON-NLS-1$
private String editPageId;
/**
* Creates a new working set.
*
* @param name the name of the new working set. Should not have leading or
* trailing whitespace.
* @param label the label of the new working set
* @param elements the content of the new working set. May be empty but not
* <code>null</code>.
*/
public WorkingSet(String name, String label, IAdaptable[] elements) {
super(name, label);
internalSetElements(elements);
}
/**
* Creates a new working set from a memento.
*
* @param name the name of the new working set. Should not have leading or
* trailing whitespace.
* @param memento persistence memento containing the elements of the working
* set.
*/
protected WorkingSet(String name, String label, IMemento memento) {
super(name, label);
workingSetMemento = memento;
if (workingSetMemento != null) {
String uniqueId = workingSetMemento.getString(IWorkbenchConstants.TAG_ID);
if (uniqueId != null) {
setUniqueId(uniqueId);
}
}
}
/**
* Tests the receiver and the object for equality
*
* @param object object to compare the receiver to
* @return true=the object equals the receiver, the name is the same. false
* otherwise
*/
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof WorkingSet) {
WorkingSet workingSet = (WorkingSet) object;
return Objects.equals(workingSet.getName(), getName())
&& Objects.equals(workingSet.getId(), getId())
&& Objects.equals(workingSet.getElementsArray(), getElementsArray());
}
return false;
}
@Override
public String toString() {
return "WS [name=" + getName() + ", elements=" + getElementsArray() + ", id=" + getId() + "]"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
}
/**
* {@inheritDoc}
*/
@Override
public boolean isEditable() {
WorkingSetDescriptor descriptor = getDescriptor(null);
return descriptor != null && descriptor.isEditable();
}
@Override
public String getId() {
return editPageId;
}
@Override
public ImageDescriptor getImageDescriptor() {
WorkingSetDescriptor descriptor = getDescriptor(DEFAULT_ID);
if (descriptor == null) {
return null;
}
return descriptor.getIcon();
}
/**
* Returns the hash code.
*
* @return the hash code.
*/
@Override
public int hashCode() {
int hashCode = getName().hashCode();
if (editPageId != null) {
hashCode &= editPageId.hashCode();
}
return hashCode;
}
/**
* Recreates the working set elements from the persistence memento on first working set access.
*/
@Override
void restoreWorkingSet() {
IWorkingSetUpdater2 updater = getUpdater();
IAdaptable[] itemsArray;
if (updater != null && updater.isManagingPersistenceOf(this)) {
itemsArray = updater.restore(this);
} else {
itemsArray = restoreFromMemento();
}
internalSetElements(itemsArray);
}
private IAdaptable[] restoreFromMemento() {
IMemento[] itemMementos = workingSetMemento.getChildren(IWorkbenchConstants.TAG_ITEM);
Set<IAdaptable> items = new LinkedHashSet<>();
for (final IMemento itemMemento : itemMementos) {
final String factoryID = itemMemento.getString(IWorkbenchConstants.TAG_FACTORY_ID);
if (factoryID == null) {
WorkbenchPlugin.log("Unable to restore working set item - no factory ID."); //$NON-NLS-1$
continue;
}
final IElementFactory factory = PlatformUI.getWorkbench().getElementFactory(factoryID);
if (factory == null) {
WorkbenchPlugin.log("Unable to restore working set item - cannot instantiate factory: " + factoryID); //$NON-NLS-1$
continue;
}
SafeRunner.run(new SafeRunnable(
"Unable to restore working set item - exception while invoking factory: " + factoryID) { //$NON-NLS-1$
@Override
public void run() throws Exception {
IAdaptable item = factory.createElement(itemMemento);
if (item == null) {
if (Policy.DEBUG_WORKING_SETS) {
WorkbenchPlugin
.log("Unable to restore working set item - cannot instantiate item: " + factoryID); //$NON-NLS-1$
}
} else {
items.add(item);
}
}
});
}
return items.toArray(new IAdaptable[items.size()]);
}
/**
* Implements IPersistableElement. Persist the working set name and working set
* contents. The contents has to be either IPersistableElements or provide
* adapters for it to be persistent.
*
* @see org.eclipse.ui.IPersistableElement#saveState(IMemento)
*/
@Override
public void saveState(IMemento memento) {
if (workingSetMemento != null) {
// just re-save the previous memento if the working set has
// not been restored
memento.putMemento(workingSetMemento);
} else {
memento.putString(IWorkbenchConstants.TAG_NAME, getName());
memento.putString(IWorkbenchConstants.TAG_LABEL, getLabel());
memento.putString(IWorkbenchConstants.TAG_ID, getUniqueId());
memento.putString(IWorkbenchConstants.TAG_EDIT_PAGE_ID, editPageId);
IWorkingSetUpdater2 updater = getUpdater();
if (updater != null && updater.isManagingPersistenceOf(this)) {
return;
}
for (IAdaptable adaptable : elements) {
final IPersistableElement persistable = Adapters.adapt(adaptable, IPersistableElement.class);
if (persistable != null) {
final IMemento itemMemento = memento.createChild(IWorkbenchConstants.TAG_ITEM);
itemMemento.putString(IWorkbenchConstants.TAG_FACTORY_ID, persistable.getFactoryId());
SafeRunner.run(new SafeRunnable("Problems occurred while saving persistable item state") { //$NON-NLS-1$
@Override
public void run() throws Exception {
persistable.saveState(itemMemento);
}
});
}
}
}
}
@Override
public void setElements(IAdaptable[] newElements) {
AbstractWorkingSet oldWorkingSet = clone();
internalSetElements(newElements);
fireWorkingSetChanged(IWorkingSetManager.CHANGE_WORKING_SET_CONTENT_CHANGE, oldWorkingSet);
}
@Override
public void setId(String pageId) {
editPageId = pageId;
}
@Override
public boolean isVisible() {
return true;
}
@Override
public boolean isSelfUpdating() {
WorkingSetDescriptor descriptor = getDescriptor(null);
return descriptor != null && descriptor.getUpdaterClassName() != null;
}
@Override
public boolean isAggregateWorkingSet() {
return false;
}
/**
* Return the working set descriptor for this working set.
*
* @param defaultId the default working set type ID to use if this set has no
* defined type
* @return the descriptor for this working set or <code>null</code> if it cannot
* be determined
* @since 3.3
*/
private WorkingSetDescriptor getDescriptor(String defaultId) {
WorkingSetRegistry registry = WorkbenchPlugin.getDefault().getWorkingSetRegistry();
String id = getId();
if (id == null)
id = defaultId;
if (id == null)
return null;
return registry.getWorkingSetDescriptor(id);
}
@Override
public IAdaptable[] adaptElements(IAdaptable[] objects) {
WorkingSetManager manager = getWorkingSetManager();
if (manager != null) {
WorkingSetDescriptor descriptor = getDescriptor();
if (descriptor == null || !descriptor.isElementAdapterClassLoaded()) {
return objects;
}
return manager.getElementAdapter(descriptor).adaptElements(this, objects);
}
return objects;
}
private WorkingSetManager getWorkingSetManager() {
IWorkingSetManager manager = getManager();
if (manager instanceof WorkingSetManager) {
return (WorkingSetManager) manager;
}
return null;
}
private WorkingSetDescriptor getDescriptor() {
return getDescriptor(null);
}
private IWorkingSetUpdater2 getUpdater() {
WorkingSetManager manager = getWorkingSetManager();
if (manager != null) {
WorkingSetDescriptor descriptor = getDescriptor();
if (descriptor != null) {
IWorkingSetUpdater updater = manager.getUpdater(descriptor);
if (updater instanceof IWorkingSetUpdater2) {
return (IWorkingSetUpdater2) updater;
}
}
}
return null;
}
}