/******************************************************************************* * Copyright (c) 2010-2015 Henshin developers. 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: * TU Berlin, University of Luxembourg, SES S.A. *******************************************************************************/ package de.tub.tfs.muvitor.gef.editparts; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.LayoutManager; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.impl.AdapterImpl; import org.eclipse.emf.ecore.EObject; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPolicy; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gef.Request; import org.eclipse.gef.RequestConstants; import org.eclipse.gef.TreeEditPart; import org.eclipse.gef.editparts.AbstractGraphicalEditPart; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.swt.widgets.Widget; import org.eclipse.ui.views.properties.IPropertySource; import de.tub.tfs.muvitor.gef.directedit.IDirectEditPart.IGraphicalDirectEditPart; import de.tub.tfs.muvitor.gef.directedit.MuvitorDirectEditManager; import de.tub.tfs.muvitor.gef.directedit.MuvitorDirectEditPolicy; import de.tub.tfs.muvitor.properties.EObjectPropertySource; import de.tub.tfs.muvitor.ui.MuvitorTreeEditor; import de.tub.tfs.muvitor.ui.utils.MuvitorNotifierService; /** * This edit part is a convenience implementation with the following frequently * used features for EObjects: * * <ul> * <li>On activation of this edit part, an EMF adapter is being installed on a * this edit parts' model, listening for model changes and passing the * notifications to {@link #notifyChanged(Notification)} and to the * {@link MuvitorNotifierService}. More adapters can freely be installed which * will be removed on deactivation. * <li>In {@link #createPropertySource()} an default * {@link EObjectPropertySource} showing all model features is created for this * edit part. {@link #getAdapter(Class)} provides the property source the the * properties view. Subclasses may override both. * <li>This edit part is prepared for GEF direct editing. Subclasses just need * to implement {@link IGraphicalDirectEditPart} to enable this feature. * <li> {@link #performDirectEdit()} and {@link #performOpen()} may be overridden * to handle direct edit or open requests differently. By default, * {@link #performOpen()} will try to open a view with the model, * {@link #performDirectEdit()} will try to directly edit the property of the * specified feature ID specified by implementing * {@link IGraphicalDirectEditPart}. * </ul> * * @author Tony Modica */ abstract public class AdapterGraphicalEditPart<T extends EObject> extends AbstractGraphicalEditPart { /** * The {@link Adapter}s that have been associated to some {@link EObject}s. * * @see #registerAdapter(Adapter, EObject) */ final protected Map<Adapter, EObject> adapters = new HashMap<Adapter, EObject>(); /** * By default, an Adapter will be installed on the model, passing the * notifications to {@link #notifyChanged(Notification)} and to the * {@link MuvitorNotifierService}. * * @param model * the model of this editpart */ public AdapterGraphicalEditPart(final T model) { setModel(model); installEditPolicy(EditPolicy.DIRECT_EDIT_ROLE, new MuvitorDirectEditPolicy()); registerAdapter(new AdapterImpl() { @Override public final void notifyChanged(final Notification msg) { AdapterGraphicalEditPart.this.notifyChanged(msg); MuvitorNotifierService.notifyListeners(msg); } }); } /** * Removes this edit part's adapters from the model. Subclasses may override * but must call super implementation! * * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#deactivate() */ @Override public void deactivate() { if (isActive()) { for (final Entry<Adapter, EObject> entry : adapters.entrySet()) { entry.getValue().eAdapters().remove(entry.getKey()); } super.deactivate(); } } /** * Subclasses may override but must call super implementation! * * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) */ @Override public Object getAdapter(final Class key) { if (IPropertySource.class == key) { return createPropertySource(); } return super.getAdapter(key); } /** * Convenience method that casts the model to the appropriate type. * * @return The model of this EditPart appropriately casted. */ @SuppressWarnings("unchecked") public final T getCastedModel() { return (T) getModel(); } /** * Handles the standard GEF requests "direct edit" and "open" on this edit * part. * * @see #performDirectEdit() * @see #performOpen() * @see org.eclipse.gef.editparts.AbstractEditPart#performRequest(org.eclipse.gef.Request) */ @Override public void performRequest(final Request request) { if (RequestConstants.REQ_DIRECT_EDIT == request.getType()) { performDirectEdit(); } else if (RequestConstants.REQ_OPEN == request.getType()) { performOpen(); } } /** * Convenience method to register an {@link Adapter} on this editpart's * model. * * @param adapter * an {@link Adapter} to register on this editpart's model * @see #registerAdapter(Adapter, EObject) */ public final void registerAdapter(final Adapter adapter) { registerAdapter(adapter, getCastedModel()); } /** * Via this method subclasses can install {@link Adapter}s in * {@link #activate()} listening to changes on a specific {@link EObject}. * All registered adapters will be deregistered by default in * {@link #deactivate()}. * * @param adapter * an {@link Adapter} to register on the model * @param model * an {@link EObject} to observe with the passed adapter */ public final void registerAdapter(final Adapter adapter, final EObject model) { adapters.put(adapter, model); model.eAdapters().add(adapter); } /** * Convenience method to let {@link #notifyChanged(Notification)} receive * notifications from additional EObjects. This method registers an * {@link Adapter} on some EObject that just forwards its notifications. * * @param adapter * an {@link Adapter} to register on this editpart's model * @see #registerAdapter(Adapter, EObject) */ public final void registerAdapter(final EObject model) { registerAdapter(new AdapterImpl() { @Override public final void notifyChanged(final Notification msg) { AdapterGraphicalEditPart.this.notifyChanged(msg); } }, model); } /** * Creates a default {@link EObjectPropertySource} showing all model * features for this edit part. Subclasses may override. * * @return the property source for this edit part */ protected IPropertySource createPropertySource() { return new EObjectPropertySource(getCastedModel()); } /** * By default, an Adapter will be registered with this editpart's model that * passes notifications to this method, which subclasses are expected to * override. This can be extended to receive notifications from other * EObjects as well with {@link #registerAdapter(EObject)}. */ protected void notifyChanged(final Notification notification) { } /** * Creates and opens a {@link MuvitorDirectEditManager} by default, handling * direct editing, if this edit part implements * {@link IGraphicalDirectEditPart}. Subclasses may override to perform some * other action here. */ protected void performDirectEdit() { if (this instanceof IGraphicalDirectEditPart) { new MuvitorDirectEditManager(this).show(); } } /** * Calls MuvitorTreeEditor.showView(getCastedModel) by default. Subclasses * may override to perform some other action here. */ protected void performOpen() { MuvitorTreeEditor.showView(getCastedModel()); } }