/**
* Copyright (c) 2006, 2007 Borland Software Corporation
*
* 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:
* bblajer - initial API and implementation
*/
package org.eclipse.gmf.runtime.lite.edit.parts.tree;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.gef.editparts.AbstractTreeEditPart;
import org.eclipse.gef.tools.CellEditorLocator;
import org.eclipse.gmf.runtime.lite.edit.parts.labels.AbstractLabelTextDisplayer;
import org.eclipse.gmf.runtime.lite.edit.parts.labels.ILabelController;
import org.eclipse.gmf.runtime.lite.edit.parts.labels.ILabelTextDisplayer;
import org.eclipse.gmf.runtime.lite.edit.parts.labels.ItemProviderLabelTextDisplayer;
import org.eclipse.gmf.runtime.lite.edit.parts.update.IExternallyUpdatableEditPart;
import org.eclipse.gmf.runtime.lite.edit.parts.update.IUpdatableEditPart;
import org.eclipse.gmf.runtime.lite.edit.parts.update.RefreshAdapter;
import org.eclipse.gmf.runtime.lite.edit.parts.update.TransactionalUpdateManager;
import org.eclipse.gmf.runtime.lite.services.TreeDirectEditManager;
import org.eclipse.gmf.runtime.notation.NotationPackage;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.TreeItem;
/**
* Base implementation for {@link org.eclipse.gef.TreeEditPart} used by the generated editors.
*/
public class BaseTreeEditPart extends AbstractTreeEditPart implements IUpdatableEditPart, IExternallyUpdatableEditPart, ILabelController {
private Image myImage;
private ImageDescriptor myImageDescriptor;
private AdapterFactory myAdapterFactory;
private ILabelTextDisplayer myLabelTextDisplayer;
private RefreshAdapter myDomainModelRefresher = new RefreshAdapter(this);
private TreeDirectEditManager directEditManager;
public BaseTreeEditPart(View view, AdapterFactory adapterFactory) {
setModel(view);
myAdapterFactory = adapterFactory;
}
public View getNotationView() {
return (View) getModel();
}
public EObject getElement() {
return getNotationView().getElement();
}
@Override
public void activate() {
super.activate();
if (getElement() != null) {
TransactionalUpdateManager updateManager = getTransactionalUpdateManager();
if (updateManager == null) {
getElement().eAdapters().add(myDomainModelRefresher);
} else {
updateManager.addUpdatableEditPart(getElement(), this);
}
}
}
@Override
public void deactivate() {
TransactionalUpdateManager updateManager = getTransactionalUpdateManager();
if (getElement() != null) {
if (updateManager == null) {
getElement().eAdapters().remove(myDomainModelRefresher);
} else {
updateManager.removeUpdatableEditPart(getElement(), this);
}
}
super.deactivate();
}
protected TransactionalUpdateManager getTransactionalUpdateManager() {
if (getParent() instanceof BaseTreeEditPart) {
return ((BaseTreeEditPart) getParent()).getTransactionalUpdateManager();
}
return null;
}
@SuppressWarnings("unchecked")
protected List getModelChildren() {
return getNotationView().getVisibleChildren();
}
protected Image getImage() {
ImageDescriptor descriptor = getImageDescriptor();
if (descriptor == null) {
disposeImage();
myImageDescriptor = null;
return null;
}
if (myImageDescriptor != descriptor) {
disposeImage();
myImageDescriptor = descriptor;
return createImage();
}
if (myImage == null || myImage.isDisposed()) {
return createImage();
}
return myImage;
}
public final ILabelTextDisplayer getLabelTextDisplayer() {
if (myLabelTextDisplayer == null) {
myLabelTextDisplayer = createLabelTextDisplayer();
if (myLabelTextDisplayer == null) {
myLabelTextDisplayer = new NullLabelTextDisplayer();
}
}
return myLabelTextDisplayer;
}
protected ILabelTextDisplayer createLabelTextDisplayer() {
return new ItemProviderLabelTextDisplayer(myAdapterFactory);
}
public void setLabelText(String text) {
if (text == null || text.length() == 0) {
text = getDefaultLabelText();
}
setWidgetText(text);
}
/**
* @return The text to use if an empty string would be displayed otherwise
*/
protected String getDefaultLabelText() {
return ""; //$NON-NLS-1$
}
private Image createImage() {
disposeImage();
myImage = myImageDescriptor.createImage();
return myImage;
}
private void disposeImage() {
if (myImage != null && !myImage.isDisposed()) {
myImage.dispose();
}
myImage = null;
}
/**
* Returns the image descriptor provided by the given adapter factory.
* Subclasses may override.
*/
protected ImageDescriptor getImageDescriptor() {
if (getElement() == null) {
return null;
}
IItemLabelProvider labelProvider = (IItemLabelProvider) myAdapterFactory.adapt(getElement(), IItemLabelProvider.class);
if (labelProvider != null) {
return ExtendedImageRegistry.getInstance().getImageDescriptor(labelProvider.getImage(getElement()));
}
return null;
}
/**
* Returns the text provided by the given adapter factory.
* Subclasses may override.
*/
protected String getText() {
String result = getLabelTextDisplayer().getDisplayText(getElement());
if (result == null || result.length() == 0) {
return getDefaultLabelText();
}
return result;
}
private HashMap<EStructuralFeature, Refresher> structuralFeatures2Refresher;
public Refresher getRefresher(EStructuralFeature feature, Notification msg) {
if (structuralFeatures2Refresher == null) {
createRefreshers();
}
return (Refresher) structuralFeatures2Refresher.get(feature);
}
protected void createRefreshers() {
structuralFeatures2Refresher = new HashMap<EStructuralFeature, Refresher>();
Refresher childrenRefresher = new Refresher() {
public void refresh() {
refreshChildren();
}
};
registerRefresher(NotationPackage.eINSTANCE.getView_PersistedChildren(), childrenRefresher);
registerRefresher(NotationPackage.eINSTANCE.getView_TransientChildren(), childrenRefresher);
registerRefresher(NotationPackage.eINSTANCE.getView_Visible(), childrenRefresher);
registerRefresher(NotationPackage.eINSTANCE.getView_Styles(), childrenRefresher);
registerRefresher(NotationPackage.eINSTANCE.getDrawerStyle_Collapsed(), childrenRefresher);
//Source edges are shown as children
registerRefresher(NotationPackage.eINSTANCE.getView_SourceEdges(), childrenRefresher);
}
private Collection<ExternalRefresher> myExternalRefreshers;
public Collection<ExternalRefresher> getExternalRefreshers() {
if (myExternalRefreshers == null) {
myExternalRefreshers = createExternalRefreshers();
}
return myExternalRefreshers;
}
protected Collection<ExternalRefresher> createExternalRefreshers() {
return Collections.<ExternalRefresher>singleton(new ILabelController.ExternalRefresherAdapter(this, getElement()));
}
protected final void registerRefresher(EStructuralFeature feature, Refresher refresher) {
Refresher oldRefresher = (Refresher) structuralFeatures2Refresher.get(feature);
if (oldRefresher == null) {
structuralFeatures2Refresher.put(feature, refresher);
} else {
CompositeRefresher compositeRefresher = new CompositeRefresher();
compositeRefresher.addRefresher(oldRefresher);
compositeRefresher.addRefresher(refresher);
structuralFeatures2Refresher.put(feature, compositeRefresher);
}
}
public void performRequest(org.eclipse.gef.Request req) {
if (org.eclipse.gef.RequestConstants.REQ_DIRECT_EDIT == req.getType() && understandsRequest(req)) {
performDirectEdit();
} else {
super.performRequest(req);
}
}
protected TreeDirectEditManager getDirectEditManager() {
if (directEditManager == null) {
directEditManager = new TreeDirectEditManager(this, getCellEditorClass(), new CellEditorLocator() {
public void relocate(CellEditor celleditor) {
if (checkTreeItem()) {
celleditor.getControl().setFont(((TreeItem) getWidget()).getFont());
celleditor.getControl().setBounds(((TreeItem) getWidget()).getBounds());
}
}
}) {
protected void initCellEditor() {
getCellEditor().setValue(getLabelTextDisplayer().getEditText(getElement()));
}
};
}
return directEditManager;
}
protected Class<? extends CellEditor> getCellEditorClass() {
return TextCellEditor.class;
}
protected void performDirectEdit() {
if (isReadOnly()) {
return;
}
getDirectEditManager().show();
}
/**
* Returns whether the element is read only. This is used to determine if direct edit should be invoked or not.
*/
protected boolean isReadOnly() {
if (getElement() == null) {
return true;
}
Resource notationResource = getNotationView().eResource();
TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(notationResource);
if (editingDomain == null) {
return false;
}
if (editingDomain.isReadOnly(notationResource)) {
return true;
}
Resource domainResource = getElement().eResource();
if (domainResource == null) {
return false;
}
return editingDomain.isReadOnly(domainResource);
}
private class NullLabelTextDisplayer extends AbstractLabelTextDisplayer {
private NullLabelTextDisplayer() {}
public String getDisplayText(EObject source) {
return getDefaultLabelText();
}
public boolean isAffectingEvent(Notification notification) {
return false;
}
}
}