Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.eclipse.emf.edit.provider.DelegatingWrapperItemProvider Maven / Gradle / Ivy
/**
* Copyright (c) 2004-2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* IBM - Initial API and implementation
*/
package org.eclipse.emf.edit.provider;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandWrapper;
import org.eclipse.emf.common.command.UnexecutableCommand;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.command.CommandActionDelegate;
import org.eclipse.emf.edit.command.CommandParameter;
import org.eclipse.emf.edit.command.DragAndDropCommand;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor.OverrideableCommandOwner;
/**
* A wrapper for model objects and other wrappers. This handles most of the item provider methods by delegating to the
* item provider returned by adapting on the value, but it returns the {@link org.eclipse.emf.edit.provider.WrapperItemProvider#getParent(Object) owner}
* as the parent, and it has to decorate the children, property descriptors, and commands that it returns.
*/
public class DelegatingWrapperItemProvider extends WrapperItemProvider
implements
IStructuredItemContentProvider,
ITreeItemContentProvider,
IItemLabelProvider,
IItemFontProvider,
IItemColorProvider,
ITableItemLabelProvider,
ITableItemFontProvider,
ITableItemColorProvider,
IItemPropertySource,
IEditingDomainItemProvider,
IChangeNotifier,
INotifyChangedListener
{
/**
* The wrapped value's item provider, to which most methods are delegated.
*/
protected Object delegateItemProvider;
/**
* The wrapped children are cached here, keyed by the children returned by the delegate item provider.
*/
protected Map childrenMap;
/**
* The collection of children last returned by the delegate item provider is cached here.
*/
protected Collection> delegateChildren;
/**
* The decorated property descriptors are cached here.
*/
protected List propertyDescriptors;
/**
* Records any listeners for this wrapper and fires notifications to them.
*/
protected IChangeNotifier changeNotifier;
/**
* Creates an instance for the given value. A decorator for the object's item provider is created, and
* set up to repeat notifications, decorating them, so that they will update this wrapper, rather than the model
* object they originate from.
* If the adapter factory is an {@link IChangeNotifier},
* a listener is added to it,
* so it's important to call {@link #dispose()}.
*
* @exception IllegalArgumentException If the specified value is null.
*/
public DelegatingWrapperItemProvider(Object value, Object owner, EStructuralFeature feature, int index, AdapterFactory adapterFactory)
{
super(value, owner, feature, index, adapterFactory);
if (value == null)
{
throw new IllegalArgumentException("value=null");
}
Object delegateValue = getDelegateValue();
if (delegateValue != null)
{
delegateItemProvider = getRootAdapterFactory().adapt(delegateValue, IStructuredItemContentProvider.class);
if (delegateItemProvider instanceof IChangeNotifier)
{
((IChangeNotifier)delegateItemProvider).addListener(this);
}
}
}
/**
* Creates an instance for the given value, when the feature and index that specify the value are unknown.
*
* @exception IllegalArgumentException If the specified value is null.
*
* @deprecated As of EMF 2.0.1, replaced by {@link #DelegatingWrapperItemProvider(Object, org.eclipse.emf.ecore.EObject, EStructuralFeature, int, AdapterFactory)
* this form}. This constructor will be removed as public API, but remain available as a protected method.
*/
@Deprecated
public DelegatingWrapperItemProvider(Object value, Object owner, AdapterFactory adapterFactory)
{
this(value, owner, null, CommandParameter.NO_INDEX, adapterFactory);
}
/**
* Deactivates notification repeating and disposes any wrappers it is maintaining for its children.
*/
@Override
public void dispose()
{
if (delegateItemProvider instanceof IChangeNotifier)
{
((IChangeNotifier)delegateItemProvider).removeListener(this);
}
if (childrenMap != null)
{
for (IDisposable object : childrenMap.values())
{
object.dispose();
}
}
}
/**
* Returns the value from which to obtain and which to pass to a delegate item provider. If this returns null,
* no delegate item provider should ever be obtained. This implementation simply returns the value of the wrapper,
* though subclasses may override it to return something else.
*/
protected Object getDelegateValue()
{
return value;
}
/**
* Uses the delegate item provider to return the delegate value's elements.
*/
@Override
public Collection> getElements(Object object)
{
return delegateItemProvider instanceof IStructuredItemContentProvider ?
((IStructuredItemContentProvider)delegateItemProvider).getElements(getDelegateValue()) :
Collections.emptyList();
}
/**
* Uses the delegate item provider to return the delegate value's children, with appropriate wrappers to ensure that
* this wrapper is considered their parent. Each child is replaced by the corresponding wrapper from {@link
* #childrenMap}, after updating it by calling {@link #updateChildren updateChildren}.
*/
@Override
public Collection> getChildren(Object object)
{
updateChildren();
Collection result = new ArrayList(delegateChildren.size());
for (Object delegateChild : delegateChildren)
{
result.add(childrenMap.get(delegateChild));
}
return result;
}
/**
* Uses the delegate item provider to get the delegate value's children, assigning the collection to {@link
* #delegateChildren}, and to update the {@link #childrenMap}. New children are wrapped by calling {@link
* #createWrapper createWrapper} and added to the map; Wrappers for children that have been removed are disposed.
*/
protected void updateChildren()
{
if (delegateItemProvider instanceof ITreeItemContentProvider)
{
boolean changed = false;
Set oldDelegateChildren = delegateChildren != null ? new HashSet(delegateChildren) : Collections.emptySet();
delegateChildren = ((ITreeItemContentProvider)delegateItemProvider).getChildren(getDelegateValue());
if (childrenMap == null && !delegateChildren.isEmpty())
{
childrenMap = new HashMap();
}
// Wrap any new children and add them to the map. Remove each current child from the set of old children.
//
for (Object child : delegateChildren)
{
if (!childrenMap.containsKey(child))
{
IWrapperItemProvider wrapper = createWrapper(child, this, adapterFactory);
childrenMap.put(child, wrapper);
changed = true;
}
oldDelegateChildren.remove(child);
}
// Remove and dispose any wrappers for remaining old children.
//
if (!oldDelegateChildren.isEmpty())
{
changed = true;
for (Object child : oldDelegateChildren)
{
IWrapperItemProvider wrapper = childrenMap.remove(child);
if (wrapper != null)
{
wrapper.dispose();
}
}
}
// If any children were added or removed, reset the indices.
if (changed)
{
int index = 0;
for (Object delegateChild : delegateChildren)
{
childrenMap.get(delegateChild).setIndex(index++);
}
}
}
else
{
delegateChildren = Collections.emptyList();
}
}
/**
* Creates a new instance of this wrapper for the given value, owner, and adapter factory.
*/
protected IWrapperItemProvider createWrapper(Object value, Object owner, AdapterFactory adapterFactory)
{
return new DelegatingWrapperItemProvider(value, owner, adapterFactory);
}
/**
* Uses the delegate item provider to test whether the delegate value has children.
*/
@Override
public boolean hasChildren(Object object)
{
return delegateItemProvider instanceof ITreeItemContentProvider ?
((ITreeItemContentProvider)delegateItemProvider).hasChildren(getDelegateValue()) :
false;
}
/**
* Uses the delegate item provider to return the delegate value's text.
*/
@Override
public String getText(Object object)
{
return delegateItemProvider instanceof IItemLabelProvider ?
((IItemLabelProvider)delegateItemProvider).getText(getDelegateValue()) :
null;
}
/**
* Uses the delegate item provider to return the delegate value's image.
*/
@Override
public Object getImage(Object object)
{
return delegateItemProvider instanceof IItemLabelProvider ?
((IItemLabelProvider)delegateItemProvider).getImage(getDelegateValue()) :
null;
}
/**
* Uses the delegate item provider to return the delegate value's font.
*/
@Override
public Object getFont(Object object)
{
return
delegateItemProvider instanceof IItemFontProvider ?
((IItemFontProvider)delegateItemProvider).getFont(getDelegateValue()) :
null;
}
/**
* Uses the delegate item provider to return the delegate value's foreground color.
*/
@Override
public Object getForeground(Object object)
{
return
delegateItemProvider instanceof IItemColorProvider ?
((IItemColorProvider)delegateItemProvider).getForeground(getDelegateValue()) :
null;
}
/**
* Uses the delegate item provider to return the delegate value's background color.
*/
@Override
public Object getBackground(Object object)
{
return
delegateItemProvider instanceof IItemColorProvider ?
((IItemColorProvider)delegateItemProvider).getBackground(getDelegateValue()) :
null;
}
/**
* Uses the delegate item provider to return the delegate value's column text.
*/
public String getColumnText(Object object, int columnIndex)
{
return
delegateItemProvider instanceof ITableItemLabelProvider ?
((ITableItemLabelProvider)delegateItemProvider).getColumnText(getDelegateValue(), columnIndex) :
getText(object);
}
/**
* Uses the delegate item provider to return the delegate value's column image.
*/
public Object getColumnImage(Object object, int columnIndex)
{
return
delegateItemProvider instanceof ITableItemLabelProvider ?
((ITableItemLabelProvider)delegateItemProvider).getColumnImage(getDelegateValue(), columnIndex) :
getImage(object);
}
/**
* Uses the delegate item provider to return the delegate value's font.
*/
public Object getFont(Object object, int columnIndex)
{
return
delegateItemProvider instanceof ITableItemFontProvider ?
((ITableItemFontProvider)delegateItemProvider).getFont(getDelegateValue(), columnIndex) :
getFont(object);
}
/**
* Uses the delegate item provider to return the delegate value's foreground color.
*/
public Object getForeground(Object object, int columnIndex)
{
return
delegateItemProvider instanceof ITableItemColorProvider ?
((ITableItemColorProvider)delegateItemProvider).getForeground(getDelegateValue(), columnIndex) :
getFont(object);
}
/**
* Uses the delegate item provider to return the delegate value's background color.
*/
public Object getBackground(Object object, int columnIndex)
{
return
delegateItemProvider instanceof ITableItemColorProvider ?
((ITableItemColorProvider)delegateItemProvider).getBackground(getDelegateValue(), columnIndex) :
getFont(object);
}
/**
* Wraps the property descriptors returned by the delegate item provider, caching and returning them.
*/
@Override
public List getPropertyDescriptors(Object object)
{
if (propertyDescriptors == null)
{
if (delegateItemProvider instanceof IItemPropertySource)
{
List l = ((IItemPropertySource)delegateItemProvider).getPropertyDescriptors(getDelegateValue());
propertyDescriptors = new ArrayList(l.size());
for (IItemPropertyDescriptor desc : l)
{
propertyDescriptors.add(new DelegatingWrapperItemPropertyDescriptor(getDelegateValue(), desc));
}
}
else
{
propertyDescriptors = Collections.emptyList();
}
}
return propertyDescriptors;
}
/**
* Uses the delegate item provider to return an editable value.
*/
@Override
public Object getEditableValue(Object object)
{
return delegateItemProvider instanceof IItemPropertySource ?
((IItemPropertySource)delegateItemProvider).getEditableValue(getDelegateValue()) :
null;
}
/**
* Uses the delegate item provider to return the delegate value's new child descriptors.
*/
@Override
public Collection> getNewChildDescriptors(Object object, EditingDomain editingDomain, Object sibling)
{
return delegateItemProvider instanceof IEditingDomainItemProvider ?
((IEditingDomainItemProvider)delegateItemProvider).getNewChildDescriptors(getDelegateValue(), editingDomain, sibling) :
Collections.emptyList();
}
/**
* Uses the delegate item provider to create a command for the delegate value, and then calls {@link #wrapCommand
* wrapCommand} to return an appropriate wrapper-substituting command wrapper for it. Drag and drop commands are
* created directly by calling {@link WrapperItemProvider#createDragAndDropCommand createDragAndDropCommand}.
*/
@Override
public Command createCommand(Object object, EditingDomain domain, Class extends Command> commandClass, CommandParameter commandParameter)
{
if (commandClass == DragAndDropCommand.class)
{
DragAndDropCommand.Detail detail = (DragAndDropCommand.Detail)commandParameter.getFeature();
return createDragAndDropCommand(domain, commandParameter.getOwner(), detail.location, detail.operations, detail.operation, commandParameter.getCollection());
}
if (delegateItemProvider instanceof IEditingDomainItemProvider)
{
Object commandOwner = getDelegateValue();
Command result = null;
// A SetCommand needs to go through SetCommand.create() to ensure it can execute and undo.
//
if (commandClass == SetCommand.class)
{
Object feature = commandParameter.getFeature();
result = SetCommand.create(domain, commandOwner, feature, commandParameter.getValue(), commandParameter.getIndex());
// A set command without a feature sets the value of this wrapper, hence replacing it with a new wrapper. So,
// we need a special command wrapper that selects this new wrapper as the affected object.
//
if (feature == null)
{
return new ReplacementAffectedObjectCommand(result);
}
}
else
{
commandParameter.setOwner(commandOwner);
result = ((IEditingDomainItemProvider)delegateItemProvider).createCommand(commandOwner, domain, commandClass, commandParameter);
}
return wrapCommand(result, commandClass);
}
return UnexecutableCommand.INSTANCE;
}
/**
* Wraps the given command in an appropriate command that will substitute the delegating wrapper for its value and
* child wrappers for their corresponding values, whenever they appear in the affected objects. This implementation
* returns an {@link AffectedObjectsWrappingCommand} or an {@link AffectedObjectsWrappingCommandActionDelegate},
* depending on whether the given command implements {@link CommandActionDelegate}.
*/
protected Command wrapCommand(Command command, Class extends Command> commandClass)
{
return command instanceof CommandActionDelegate ?
new AffectedObjectsWrappingCommandActionDelegate((CommandActionDelegate)command) :
new AffectedObjectsWrappingCommand(command);
}
/**
* An AffectedObjectsWrappingCommand
wraps another command to substitute this wrapper for its value
* and child wrappers for their corresponding child values, whenever they appear in the affected objects.
*/
protected class AffectedObjectsWrappingCommand extends CommandWrapper
{
public AffectedObjectsWrappingCommand(Command command)
{
super(command);
}
@Override
public Collection> getAffectedObjects()
{
List result = new ArrayList(super.getAffectedObjects());
updateChildren();
for (ListIterator i = result.listIterator(); i.hasNext(); )
{
Object object = i.next();
if (object == getDelegateValue())
{
i.set(DelegatingWrapperItemProvider.this);
}
else if (childrenMap != null)
{
Object wrapper = childrenMap.get(object);
if (wrapper != null)
{
i.set(wrapper);
}
}
}
return result;
}
}
/**
* An AffectedObjectsWrappingCommandActionDelegate
wraps another command that also implements
* CommandActionDelegate
, to substitute this wrapper for its value and child wrappers for their
* corresponding child values, whenever they appear in the affected objects. Action delegate methods are delegated
* directly to the wrapped command.
*/
protected class AffectedObjectsWrappingCommandActionDelegate extends AffectedObjectsWrappingCommand
implements CommandActionDelegate
{
CommandActionDelegate commandActionDelegate;
/**
* Returns a new AffectedObjectsWrappingCommandActionDelegate
for the given command.
* @exception ClassCastException If the specified command does not implement {@link org.eclipse.emf.common.command.Command}.
*/
public AffectedObjectsWrappingCommandActionDelegate(CommandActionDelegate command)
{
super((Command)command);
commandActionDelegate = command;
}
@Override
public boolean canExecute()
{
return commandActionDelegate.canExecute();
}
public Object getImage()
{
return commandActionDelegate.getImage();
}
public String getText()
{
return commandActionDelegate.getText();
}
@Override
public String getDescription()
{
return commandActionDelegate.getDescription();
}
public String getToolTipText()
{
return commandActionDelegate.getToolTipText();
}
}
/**
* Adds a listener to receive this wrapper's repeated notifications.
*/
public void addListener(INotifyChangedListener listener)
{
if (changeNotifier == null)
{
changeNotifier = new ChangeNotifier();
}
changeNotifier.addListener(listener);
}
/**
* Removes a notification listener.
*/
public void removeListener(INotifyChangedListener listener)
{
if (changeNotifier != null)
{
changeNotifier.removeListener(listener);
}
}
/**
* Fires a notification to the adapter factory and any registered listeners.
*/
public void fireNotifyChanged(Notification notification)
{
if (adapterFactory instanceof IChangeNotifier)
{
IChangeNotifier adapterFactoryChangeNotifier = (IChangeNotifier)adapterFactory;
adapterFactoryChangeNotifier.fireNotifyChanged(notification);
}
if (changeNotifier != null)
{
changeNotifier.fireNotifyChanged(notification);
}
}
/**
* Called by {@link #delegateItemProvider} when it normally fires a notification to it's adapter factory; if the
* notification originated from the delegate value, this repeats the notification, using {@link #wrapNotification
* wrapNotification} to substitute this wrapper as the operative object.
*/
public void notifyChanged(Notification notification)
{
if (getRefreshElement(notification) == getDelegateValue())
{
fireNotifyChanged(wrapNotification(notification));
}
}
/**
* Returns the operative object of this notification, from which the viewer would be refreshed. If the notification
* is an {@link IViewerNotification}, the {@link IViewerNotification#getElement element} is returned. Otherwise, the
* {@link org.eclipse.emf.common.notify.Notification#getNotifier notifier} is returned.
*/
protected Object getRefreshElement(Notification notification)
{
if (notification instanceof IViewerNotification)
{
return ((IViewerNotification)notification).getElement();
}
return notification.getNotifier();
}
/**
* Wraps the given notification, substituting this wrapper as the operative object, by calling {@link
* ViewerNotification#wrapNotification ViewerNotification.wrapNotification}.
*/
protected Notification wrapNotification(Notification notification)
{
return ViewerNotification.wrapNotification(notification, this);
}
/**
* A DelegatingWrapperItemPropertyDescriptor
decorates an ItemPropertyDescriptor
and
* manages a command owner override. If its command owner is non-null, it ensures that the decorated descriptor,
* if it also implements OverrideableCommandOwner
, will have its command owner set to the same object
* when {@link #resetPropertyValue resetPropertyValue} or {@link #setPropertyValue setPropertyValue} is called.
* If its command owner is null, then the decorated descriptors's command owner will be set to this wrapper item
* provider.
*/
protected class DelegatingWrapperItemPropertyDescriptor extends ItemPropertyDescriptorDecorator
implements OverrideableCommandOwner
{
protected Object commandOwner;
public DelegatingWrapperItemPropertyDescriptor(Object object, IItemPropertyDescriptor itemPropertyDescriptor)
{
super(object, itemPropertyDescriptor);
}
/**
* Sets the override command owner and, if the decorated descriptor also implements {@link
* IItemPropertyDescriptor.OverrideableCommandOwner OverrideableCommandOwner}, updates its command owner.
*/
public void setCommandOwner(Object commandOwner)
{
this.commandOwner = commandOwner;
if (itemPropertyDescriptor instanceof OverrideableCommandOwner)
{
((OverrideableCommandOwner)itemPropertyDescriptor).setCommandOwner(commandOwner);
}
}
/**
* Returns the override command owner.
*/
public Object getCommandOwner()
{
return commandOwner;
}
/**
* Updates the decorated descriptor's command owner and invokes resetPropertyValue
on it.
*/
@Override
public void resetPropertyValue(Object thisObject)
{
boolean hasCommandOwner = commandOwner != null;
if (!hasCommandOwner)
{
setCommandOwner(DelegatingWrapperItemProvider.this);
}
itemPropertyDescriptor.resetPropertyValue(object);
if (!hasCommandOwner)
{
setCommandOwner(null);
}
}
/**
* Updates the decorated descriptor's command owner and invokes setPropertyValue
on it.
*/
@Override
public void setPropertyValue(Object thisObject, Object value)
{
boolean hasCommandOwner = commandOwner != null;
if (!hasCommandOwner)
{
setCommandOwner(DelegatingWrapperItemProvider.this);
}
itemPropertyDescriptor.setPropertyValue(object, value);
if (!hasCommandOwner)
{
setCommandOwner(null);
}
}
}
}