/* * 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: * Richard Gronback (Borland) - initial API and implementation */ package org.eclipse.gmf.examples.mindmap.rcp.edit.parts; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.eclipse.draw2d.FreeformLayer; import org.eclipse.draw2d.FreeformLayout; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.MarginBorder; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.transaction.NotificationFilter; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.transaction.util.TransactionUtil; import org.eclipse.gef.EditPolicy; import org.eclipse.gef.SnapToGrid; import org.eclipse.gef.SnapToHelper; import org.eclipse.gef.TreeEditPart; import org.eclipse.gef.editparts.AbstractGraphicalEditPart; import org.eclipse.gef.editpolicies.RootComponentEditPolicy; import org.eclipse.gmf.examples.mindmap.Map; import org.eclipse.gmf.examples.mindmap.MindmapPackage; import org.eclipse.gmf.examples.mindmap.Relationship; import org.eclipse.gmf.examples.mindmap.Resource; import org.eclipse.gmf.examples.mindmap.Topic; import org.eclipse.gmf.examples.mindmap.rcp.edit.policies.MapLayoutEditPolicy; import org.eclipse.gmf.examples.mindmap.rcp.part.MindmapDiagramEditorPlugin; import org.eclipse.gmf.examples.mindmap.rcp.part.MindmapVisualIDRegistry; import org.eclipse.gmf.examples.mindmap.rcp.view.factories.Relationship2ViewFactory; import org.eclipse.gmf.examples.mindmap.rcp.view.factories.Relationship3ViewFactory; import org.eclipse.gmf.examples.mindmap.rcp.view.factories.RelationshipViewFactory; import org.eclipse.gmf.examples.mindmap.rcp.view.factories.ResourceViewFactory; import org.eclipse.gmf.examples.mindmap.rcp.view.factories.TopicViewFactory; import org.eclipse.gmf.runtime.lite.commands.CreateNotationalEdgeCommand; import org.eclipse.gmf.runtime.lite.commands.CreateNotationalElementCommand; import org.eclipse.gmf.runtime.lite.commands.CreateNotationalNodeCommand; import org.eclipse.gmf.runtime.lite.commands.WrappingCommand; import org.eclipse.gmf.runtime.lite.edit.parts.tree.BaseTreeEditPart; 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.RefreshersRegistry; import org.eclipse.gmf.runtime.lite.edit.parts.update.TransactionalUpdateManager; import org.eclipse.gmf.runtime.lite.edit.parts.update.UpdaterUtil; import org.eclipse.gmf.runtime.lite.edit.parts.update.canonical.ChildNotationModelRefresher; import org.eclipse.gmf.runtime.lite.edit.parts.update.canonical.EditPartRegistryBasedViewService; import org.eclipse.gmf.runtime.lite.edit.parts.update.canonical.ElementDescriptor; import org.eclipse.gmf.runtime.lite.edit.parts.update.canonical.IViewService; import org.eclipse.gmf.runtime.lite.edit.parts.update.canonical.LinkDescriptor; import org.eclipse.gmf.runtime.lite.edit.parts.update.canonical.OwnedLinksNotationModelRefresher; import org.eclipse.gmf.runtime.lite.services.IViewDecorator; import org.eclipse.gmf.runtime.notation.CanonicalStyle; import org.eclipse.gmf.runtime.notation.Diagram; import org.eclipse.gmf.runtime.notation.Edge; import org.eclipse.gmf.runtime.notation.NotationPackage; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.swt.widgets.Widget; /** * @generated */ public class MapEditPart extends AbstractGraphicalEditPart implements IUpdatableEditPart { /** * @generated */ public static String MODEL_ID = "Mindmap"; //$NON-NLS-1$ /** * @generated */ public static final int VISUAL_ID = 1000; /** * @generated */ public MapEditPart(Diagram model) { setModel(model); } /** * @generated */ public Diagram getDiagram() { return (Diagram) getModel(); } /** * @generated */ protected void registerModel() { super.registerModel(); View view = (View) getModel(); if (view != null && view.isSetElement() && view.getElement() != null) { getViewer().getEditPartRegistry().put(view.getElement(), this); } } /** * @generated */ protected void unregisterModel() { super.unregisterModel(); View view = (View) getModel(); if (view != null && view.isSetElement() && view.getElement() != null && getViewer().getEditPartRegistry().get(view.getElement()) == this) { getViewer().getEditPartRegistry().remove(view.getElement()); } } /** * @generated */ protected void createEditPolicies() { installEditPolicy(EditPolicy.COMPONENT_ROLE, new RootComponentEditPolicy()); installEditPolicy(EditPolicy.LAYOUT_ROLE, new MapLayoutEditPolicy()); installNotationModelRefresher(); installLinkNotationModelRefresher(); } /** * @generated */ protected IFigure createFigure() { IFigure f = new FreeformLayer(); f.setBorder(new MarginBorder(5)); f.setLayoutManager(new FreeformLayout()); return f; } /** * @generated */ public Object getAdapter(Class key) { if (SnapToHelper.class == key) { return new SnapToGrid(this); } if (TreeEditPart.class == key) { return getTreeEditPartAdapter(); } return super.getAdapter(key); } /** * @generated */ private TreeEditPartAdapter myTreeEditPartAdapter; /** * @generated */ private TreeEditPartAdapter getTreeEditPartAdapter() { if (myTreeEditPartAdapter == null) { myTreeEditPartAdapter = new TreeEditPartAdapter(); } return myTreeEditPartAdapter; } /** * @generated */ protected List getModelChildren() { return getDiagram().getVisibleChildren(); } /** * @generated */ private RefreshersRegistry myRefreshersRegistry; /** * @generated */ public Refresher getRefresher(EStructuralFeature feature, Notification msg) { if (myRefreshersRegistry == null) { createRefreshers(); } return myRefreshersRegistry.getRefresher(feature, msg); } /** * @generated */ private void createRefreshers() { myRefreshersRegistry = new RefreshersRegistry(); Refresher childrenRefresher = new IExternallyUpdatableEditPart.ExternalRefresher() { public void refresh() { if (!isActive()) { return; } refreshChildren(); } public boolean isAffectingEvent(Notification msg) { if (NotationPackage.eINSTANCE.getView_PersistedChildren() == msg .getFeature() || NotationPackage.eINSTANCE .getView_TransientChildren() == msg .getFeature() || NotationPackage.eINSTANCE.getDrawerStyle_Collapsed() == msg .getFeature()) { return true; } if (NotationPackage.eINSTANCE.getView_Styles() == msg .getFeature()) { return UpdaterUtil.affects(msg, NotationPackage.eINSTANCE .getDrawerStyle()); } if (NotationPackage.eINSTANCE.getView_Visible() == msg .getFeature()) { return msg.getNotifier() != getDiagram(); } return false; } }; myRefreshersRegistry.add(NotationPackage.eINSTANCE .getView_PersistedChildren(), childrenRefresher); myRefreshersRegistry.add(NotationPackage.eINSTANCE .getView_TransientChildren(), childrenRefresher); myRefreshersRegistry.add(NotationPackage.eINSTANCE.getView_Styles(), childrenRefresher); myRefreshersRegistry.add(NotationPackage.eINSTANCE .getDrawerStyle_Collapsed(), childrenRefresher); myRefreshersRegistry.add(NotationPackage.eINSTANCE.getView_Visible(), childrenRefresher); } /** * @generated */ public void activate() { super.activate(); getTransactionalUpdateManager().addUpdatableEditPart( getDiagram().getElement(), this); installNotationModelRefresher(); installLinkNotationModelRefresher(); getTransactionalUpdateManager().install( TransactionUtil.getEditingDomain(getDiagram())); } /** * @generated */ public void deactivate() { getTransactionalUpdateManager().uninstall(); uninstallLinkNotationModelRefresher(); uninstallNotationModelRefresher(); getTransactionalUpdateManager().removeUpdatableEditPart( getDiagram().getElement(), this); super.deactivate(); } /** * @generated */ private void installNotationModelRefresher() { ChildNotationModelRefresher refresher = getNotationModelRefresher(); getTransactionalUpdateManager().addNotationModelRefresher(refresher); } /** * @generated */ private void uninstallNotationModelRefresher() { ChildNotationModelRefresher refresher = getNotationModelRefresher(); getTransactionalUpdateManager().removeNotationModelRefresher(refresher); } /** * @generated */ private ChildNotationModelRefresher notationModelRefresher; /** * @generated */ private ChildNotationModelRefresher getNotationModelRefresher() { if (notationModelRefresher == null) { notationModelRefresher = new NotationModelRefresher(); } return notationModelRefresher; } /** * @generated */ protected void refreshNotationModel() { ChildNotationModelRefresher childRefresher = getNotationModelRefresher(); if (!childRefresher.isInstalled()) { return; } Command command = childRefresher.buildRefreshNotationModelCommand(); if (command == null) { return; } TransactionalEditingDomain domainModelEditDomain = TransactionUtil .getEditingDomain(getDiagram().getElement()); getViewer().getEditDomain().getCommandStack().execute( new WrappingCommand(domainModelEditDomain, command)); } /** * @generated */ private class NotationModelRefresher extends ChildNotationModelRefresher { /** * Creates a notification filter which filters notifications that may possibly affect the notational model * @generated */ protected NotificationFilter createFilter() { NotificationFilter filter = NotificationFilter .createFeatureFilter(MindmapPackage.eINSTANCE .getMap_RootTopics()); filter = filter.or(NotificationFilter .createFeatureFilter(MindmapPackage.eINSTANCE .getMap_Resources())); filter = filter.and(NotificationFilter .createNotifierFilter(getDiagram().getElement())); return filter; } /** * @generated */ protected CreateNotationalElementCommand getCreateNotationalElementCommand( ElementDescriptor descriptor) { EObject domainElement = descriptor.getElement(); int nodeVisualID = descriptor.getVisualID(); switch (nodeVisualID) { case TopicEditPart.VISUAL_ID: if (domainElement instanceof Topic) { return new CreateNotationalNodeCommand(getHost(), domainElement, new Rectangle(0, 0, 40, 40), TopicViewFactory.INSTANCE, false); } return null; case ResourceEditPart.VISUAL_ID: if (domainElement instanceof Resource) { return new CreateNotationalNodeCommand(getHost(), domainElement, new Rectangle(0, 0, 40, 60), ResourceViewFactory.INSTANCE, false); } return null; default: return null; } } /** * @generated */ protected List getSemanticChildNodes() { List result = new LinkedList(); View viewObject = getHost(); EObject modelObject = viewObject.getElement(); EObject nextValue; int nodeVID; for (Iterator it = ((Map) modelObject).getRootTopics().iterator(); it .hasNext();) { nextValue = (EObject) it.next(); nodeVID = MindmapVisualIDRegistry.getNodeVisualID(viewObject, nextValue); if (TopicEditPart.VISUAL_ID == nodeVID) { result.add(new ElementDescriptor(nextValue, nodeVID)); } } for (Iterator it = ((Map) modelObject).getResources().iterator(); it .hasNext();) { nextValue = (EObject) it.next(); nodeVID = MindmapVisualIDRegistry.getNodeVisualID(viewObject, nextValue); if (ResourceEditPart.VISUAL_ID == nodeVID) { result.add(new ElementDescriptor(nextValue, nodeVID)); } } return result; } /** * Returns whether a notational element should be created for the given domain element. * The generated code respects canonical style. If the canonycal style is not present, true is always returned. * User can change implementation of this method to handle a more sophisticated logic. * @generated */ protected boolean shouldCreateView(ElementDescriptor descriptor) { CanonicalStyle style = (CanonicalStyle) getDiagram().getStyle( NotationPackage.eINSTANCE.getCanonicalStyle()); if (style == null) { return true; } return style.isCanonical(); } /** * @generated */ protected View getHost() { return getDiagram(); } } /** * @generated */ private void installLinkNotationModelRefresher() { LinkNotationModelRefresher refresher = getLinkNotationModelRefresher(); getTransactionalUpdateManager().addNotationModelRefresher(refresher); } /** * @generated */ private void uninstallLinkNotationModelRefresher() { LinkNotationModelRefresher refresher = getLinkNotationModelRefresher(); getTransactionalUpdateManager().removeNotationModelRefresher(refresher); } /** * @generated */ private LinkNotationModelRefresher linkNotationModelRefresher; /** * @generated */ private LinkNotationModelRefresher getLinkNotationModelRefresher() { if (linkNotationModelRefresher == null) { linkNotationModelRefresher = new LinkNotationModelRefresher( getViewService()); } return linkNotationModelRefresher; } /** * Service to find a notational element that corresponds to the given underlying domain element. * @generated */ private IViewService viewService; /** * @generated */ private IViewService getViewService() { if (viewService == null) { viewService = new EditPartRegistryBasedViewService(getViewer()); } return viewService; } /** * @generated */ protected void refreshLinkNotationModel() { LinkNotationModelRefresher linkRefresher = getLinkNotationModelRefresher(); if (!linkRefresher.isInstalled()) { return; } Command command = linkRefresher.buildRefreshNotationModelCommand(); if (command == null) { return; } TransactionalEditingDomain domainModelEditDomain = TransactionUtil .getEditingDomain(getDiagram().getElement()); getViewer().getEditDomain().getCommandStack().execute( new WrappingCommand(domainModelEditDomain, command)); } /** * @generated */ private class LinkNotationModelRefresher extends OwnedLinksNotationModelRefresher { /** * @generated */ public LinkNotationModelRefresher(IViewService viewService) { super(viewService); } /** * TODO: Child links of this element are selected based on constraint declared in org.eclipse.gmf.examples.mindmap.rcp.part.MindmapVisualIDRegistry. * Since no assumptions may be made concerning the runtime behavior of the constraint, <b>any</b> non-touch notification may result in * notational model having to be updated. * <p/>User is encouraged to change implementation of this method to provide an optimization if it is safe to assume that not all notifications * result in such an update. * @generated */ private NotificationFilter getConstrainedChildLinksFilter() { return NotificationFilter.NOT_TOUCH; } /** * Creates a notification filter which filters notifications that may possibly result in uncontained links. * @generated */ private NotificationFilter createUncontainedLinksFilter() { return NotificationFilter .createEventTypeFilter(Notification.SET) .or( NotificationFilter .createEventTypeFilter(Notification.UNSET) .or( NotificationFilter .createEventTypeFilter( Notification.REMOVE) .or( NotificationFilter .createEventTypeFilter(Notification.REMOVE_MANY)))); } /** * Creates a notification filter which filters notifications that may possibly affect the notational model * @generated */ protected NotificationFilter createFilter() { NotificationFilter filter = NotificationFilter .createFeatureFilter(MindmapPackage.eINSTANCE .getMap_Relations()); filter = filter.or(NotificationFilter .createFeatureFilter(MindmapPackage.eINSTANCE .getRelationship_Source())); filter = filter.or(NotificationFilter .createFeatureFilter(MindmapPackage.eINSTANCE .getRelationship_Target())); filter = getConstrainedChildLinksFilter().or(filter); filter = filter.or(createUncontainedLinksFilter()); return filter; } /** * @generated */ protected List getSemanticChildLinks() { List result = new LinkedList(); EObject modelObject = getHost().getElement(); EObject nextValue; int linkVID; for (Iterator it = ((Map) modelObject).getRelations().iterator(); it .hasNext();) { nextValue = (EObject) it.next(); linkVID = MindmapVisualIDRegistry .getLinkWithClassVisualID(nextValue); switch (linkVID) { case RelationshipEditPart.VISUAL_ID: { EObject source = (EObject) ((Relationship) nextValue) .getSource(); EObject target = (EObject) ((Relationship) nextValue) .getTarget(); if (source != null && target != null) { result.add(new LinkDescriptor(source, target, nextValue, linkVID)); } break; } case Relationship2EditPart.VISUAL_ID: { EObject source = (EObject) ((Relationship) nextValue) .getSource(); EObject target = (EObject) ((Relationship) nextValue) .getTarget(); if (source != null && target != null) { result.add(new LinkDescriptor(source, target, nextValue, linkVID)); } break; } case Relationship3EditPart.VISUAL_ID: { EObject source = (EObject) ((Relationship) nextValue) .getSource(); EObject target = (EObject) ((Relationship) nextValue) .getTarget(); if (source != null && target != null) { result.add(new LinkDescriptor(source, target, nextValue, linkVID)); } break; } } } return result; } /** * @generated */ protected List getNotationalChildLinks() { List result = new LinkedList(); List allLinks = getDiagram().getEdges(); for (Iterator it = allLinks.iterator(); it.hasNext();) { Edge next = (Edge) it.next(); if (next.isSetElement() && next.getElement() != null && next.getElement().eResource() == null) { result.add(next); continue; } View source = next.getSource(); if (source == null || (source.isSetElement() && source.getElement() != null && source .getElement().eResource() == null)) { result.add(next); continue; } View target = next.getTarget(); if (target == null || (target.isSetElement() && target.getElement() != null && target .getElement().eResource() == null)) { result.add(next); continue; } if (next.isSetElement() && next.getElement() != null) { if (next.getElement().eContainer() == getDiagram() .getElement()) { int linkVID = MindmapVisualIDRegistry.getVisualID(next); switch (linkVID) { case RelationshipEditPart.VISUAL_ID: case Relationship2EditPart.VISUAL_ID: case Relationship3EditPart.VISUAL_ID: result.add(next); break; } } } } return result; } /** * @generated */ protected CreateNotationalElementCommand getCreateNotationalElementCommand( ElementDescriptor descriptor) { LinkDescriptor linkDescriptor = (LinkDescriptor) descriptor; View sourceView = getViewService().findView( linkDescriptor.getSource()); View targetView = getViewService().findView( linkDescriptor.getDestination()); IViewDecorator decorator = null; if (sourceView == null || targetView == null) { return null; } String sourceModelID = MindmapVisualIDRegistry .getModelID(sourceView); if (!org.eclipse.gmf.examples.mindmap.rcp.edit.parts.MapEditPart.MODEL_ID .equals(sourceModelID)) { return null; } String targetModelID = MindmapVisualIDRegistry .getModelID(targetView); if (!org.eclipse.gmf.examples.mindmap.rcp.edit.parts.MapEditPart.MODEL_ID .equals(targetModelID)) { return null; } switch (linkDescriptor.getVisualID()) { case RelationshipEditPart.VISUAL_ID: if (linkDescriptor.getElement() instanceof Relationship) { decorator = RelationshipViewFactory.INSTANCE; } break; case Relationship2EditPart.VISUAL_ID: if (linkDescriptor.getElement() instanceof Relationship) { decorator = Relationship2ViewFactory.INSTANCE; } break; case Relationship3EditPart.VISUAL_ID: if (linkDescriptor.getElement() instanceof Relationship) { decorator = Relationship3ViewFactory.INSTANCE; } break; } if (decorator == null) { return null; } return new CreateNotationalEdgeCommand(getHost().getDiagram(), linkDescriptor.getElement(), sourceView, targetView, decorator); } /** * Returns whether a notational edge should be created for the given domain element. * The generated code respects canonical style. If the canonycal style is not present, true is always returned. * User can change implementation of this method to handle a more sophisticated logic. * @generated */ protected boolean shouldCreateView(ElementDescriptor descriptor) { CanonicalStyle style = (CanonicalStyle) getDiagram().getStyle( NotationPackage.eINSTANCE.getCanonicalStyle()); if (style == null) { return true; } return style.isCanonical(); } /** * @generated */ protected View getHost() { return getDiagram(); } } /** * @generated */ private TransactionalUpdateManager getTransactionalUpdateManager() { return (TransactionalUpdateManager) getViewer().getProperty( TransactionalUpdateManager.class.getName()); } /** * @generated */ private class TreeEditPartAdapter extends BaseTreeEditPart { /** * @generated */ public TreeEditPartAdapter() { super(getDiagram(), MindmapDiagramEditorPlugin.getInstance() .getItemProvidersAdapterFactory()); } /** * @generated */ protected void createEditPolicies() { installEditPolicy(EditPolicy.COMPONENT_ROLE, new RootComponentEditPolicy()); } /** * @generated */ public void activate() { myUpdateManager = new TransactionalUpdateManager(getViewer()); getViewer().setProperty(TransactionalUpdateManager.class.getName(), myUpdateManager); super.activate(); getTransactionalUpdateManager().install( TransactionUtil.getEditingDomain(getNotationView())); } /** * @generated */ public void deactivate() { getTransactionalUpdateManager().uninstall(); super.deactivate(); TransactionalUpdateManager updateManager = (TransactionalUpdateManager) getViewer() .getProperty(TransactionalUpdateManager.class.getName()); if (updateManager != null) { updateManager.dispose(); } } /** * @generated */ protected TransactionalUpdateManager getTransactionalUpdateManager() { return myUpdateManager; } /** * @generated */ private TransactionalUpdateManager myUpdateManager; /** * @generated */ public void setWidget(Widget widget) { if (widget == null) { myTreeEditPartAdapter = null; } super.setWidget(widget); } } }