/******************************************************************************* * 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.henshin.tggeditor.editparts.graphical; import java.util.ArrayList; import java.util.List; import org.eclipse.draw2d.ChopboxAnchor; import org.eclipse.draw2d.ConnectionAnchor; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.MouseEvent; import org.eclipse.draw2d.MouseListener; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.henshin.model.Edge; import org.eclipse.emf.henshin.model.Formula; import org.eclipse.emf.henshin.model.HenshinPackage; import org.eclipse.emf.henshin.model.Mapping; import org.eclipse.emf.henshin.model.NestedCondition; import org.eclipse.emf.henshin.model.Node; import org.eclipse.gef.ConnectionEditPart; import org.eclipse.gef.EditPolicy; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gef.Request; import org.eclipse.jface.viewers.ICellEditorValidator; import de.tub.tfs.henshin.tgg.TNode; import de.tub.tfs.henshin.tgg.TggPackage; import de.tub.tfs.henshin.tgg.interpreter.util.RuleUtil; //import de.tub.tfs.henshin.tgg.TNode; import de.tub.tfs.henshin.tggeditor.editpolicies.graphical.NodeComponentEditPolicy; import de.tub.tfs.henshin.tggeditor.editpolicies.graphical.NodeGraphicalEditPolicy; import de.tub.tfs.henshin.tggeditor.editpolicies.graphical.NodeLayoutEditPolicy; import de.tub.tfs.henshin.tggeditor.figures.NodeFigure; import de.tub.tfs.henshin.tggeditor.util.GraphicalNodeUtil; import de.tub.tfs.muvitor.gef.directedit.IDirectEditPart.IGraphicalDirectEditPart; import de.tub.tfs.muvitor.gef.editparts.AdapterGraphicalEditPart; /** * The Class NodeEditPart. */ public class TNodeObjectEditPart extends AdapterGraphicalEditPart<TNode> implements org.eclipse.gef.NodeEditPart, IGraphicalDirectEditPart, MouseListener { /** The NAC or Rule mapping in NodeRuleEditPath */ protected Mapping mapping; /** Index to show mapping */ protected int index = -1; /** The node, which is the model object */ TNode node; /** * Instantiates a new node edit part. * * @param model the model */ public TNodeObjectEditPart(TNode model) { super(model); node = (TNode) model; setNacMapping(model); } /** * Iterates over all mappings and looks for mapping which have given model as image. If it's * found it sets the mapping, registers it as adapter and refresh the index * @param model the given model */ protected void setNacMapping(Node model) { if (getCastedModel().getGraph().eContainer() instanceof Formula) { Formula f = (Formula) getCastedModel().getGraph().eContainer(); EList<Mapping> maps = ((NestedCondition)f).getMappings(); for (Mapping m : maps) { if (m.getImage() == model) { this.mapping = m; registerAdapter(m); // Mapping numbers were different in RHS and NAC. So take the lhsnode, // not the original node (which is the rhsnode). //this.index = m.getOrigin().getGraph().getNodes().indexOf(m.getOrigin()); Node rhsNode = RuleUtil.getRHSNode(m.getOrigin()); this.index = rhsNode.getGraph().getNodes().indexOf(rhsNode); return; } } } } /** * gets the current nac mapping * @return current nac mapping */ public Mapping getNacMapping() { return this.mapping; } /** * sets the nac mapping of model * @param m the new nac mapping */ public void setNacMapping(Mapping m) { this.mapping = m; } @Override protected void notifyChanged(Notification notification) { if (!this.isActive()) return; if (notification.getNotifier() instanceof Node) { int type = notification.getEventType(); final Object newValue = notification.getNewValue(); final Object oldValue = notification.getOldValue(); switch (type) { case Notification.SET: case Notification.UNSET: refreshVisuals(); break; case Notification.ADD: if (newValue instanceof Mapping && ((Mapping) newValue).getImage() == getModel()) { this.mapping = (Mapping) newValue; if (this.index == -1) this.index = this.mapping.getOrigin().getGraph().getNodes().indexOf(this.mapping.getOrigin()); refreshFigureName(); refreshVisuals(); return; } break; case Notification.REMOVE: if (this.mapping == oldValue) { this.mapping = null; this.index = -1; refreshFigureName(); refreshVisuals(); return; } break; } final int featureId2 = notification.getFeatureID(HenshinPackage.class); switch (featureId2) { case HenshinPackage.NODE__NAME: updateValueDisplay(""); refreshVisuals(); break; case HenshinPackage.NODE__INCOMING: refreshTargetConnections(); refreshVisuals(); break; case HenshinPackage.NODE__OUTGOING: refreshSourceConnections(); refreshVisuals(); break; case HenshinPackage.NODE__TYPE: refreshVisuals(); break; case HenshinPackage.NODE__ATTRIBUTES: refreshChildren(); refreshVisuals(); //((NodeFigure)getFigure()).updatePos(); } if (notification.getNotifier() instanceof TNode) { final int featureId3 = notification .getFeatureID(TggPackage.class); switch (featureId3) { case TggPackage.TNODE__COMPONENT: case TggPackage.TNODE__X: refreshBG(); break; case TggPackage.TNODE__MARKER_TYPE: refreshMarker(); break; } } } if (notification.getNotifier() instanceof Mapping) { int featureId = notification.getFeatureID(HenshinPackage.class); switch (featureId) { case HenshinPackage.MAPPING__IMAGE: int type = notification.getEventType(); final Object newValue = notification.getNewValue(); final Object oldValue = notification.getOldValue(); switch (type) { case Notification.ADD: if (newValue instanceof Mapping && ((Mapping) newValue).getImage() == getModel()) { this.mapping = (Mapping) newValue; refreshFigureName(); refreshVisuals(); } break; case Notification.REMOVE: if (this.mapping == oldValue) { this.mapping = null; this.index = -1; refreshFigureName(); refreshVisuals(); } break; } } } //System.out.println("node update: " + ((System.nanoTime() - s) / 1000000) + " ms."); } /** * refreshes the name display on figure of this model */ protected void refreshFigureName() { this.setName(this.getName()); } /** * Sets the name in visual figure * * @param name the new name */ public void setName(String name) { if (figure != null && figure instanceof NodeFigure) { ((NodeFigure) figure).setName(name); } } /** * Gets the name of model * @return node name */ public String getName() { if (this.index == -1) return getCastedModel().getName()+":"+(getCastedModel().getType() == null ? "null" : getCastedModel().getType().getName()); else return "[" + this.index + "] " + getCastedModel().getName()+":"+(getCastedModel().getType() == null ? "null" : getCastedModel().getType().getName()); } /* * (non-Javadoc) * * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure() */ @Override protected IFigure createFigure() { figure = new NodeFigure(getCastedModel()); return figure; } @Override public int getDirectEditFeatureID() { return HenshinPackage.NODE__NAME; } @Override public ICellEditorValidator getDirectEditValidator() { return null; } @Override public void mousePressed(MouseEvent me) { } @Override public void mouseReleased(MouseEvent me) { } @Override public void mouseDoubleClicked(MouseEvent me) { } @Override public Rectangle getValueLabelTextBounds() { return ((NodeFigure)getFigure()).getValueLabelTextBounds(); } @Override public void updateValueDisplay(String value) { this.refreshFigureName(); } @Override protected List<Edge> getModelSourceConnections() { return getCastedModel().getOutgoing(); } @Override protected List<Edge> getModelTargetConnections() { return getCastedModel().getIncoming(); } @Override protected List<EObject> getModelChildren() { List<EObject> list = new ArrayList<EObject>(); list.addAll(getCastedModel().getAttributes()); return list; } @Override public IFigure getContentPane() { return ((NodeFigure)getFigure()).getAttributePane(); } @Override public ConnectionAnchor getSourceConnectionAnchor( ConnectionEditPart connection) { return new ChopboxAnchor(getFigure()); } @Override public ConnectionAnchor getTargetConnectionAnchor( ConnectionEditPart connection) { return new ChopboxAnchor(getFigure()); } @Override public ConnectionAnchor getSourceConnectionAnchor(Request request) { return new ChopboxAnchor(getFigure()); } @Override public ConnectionAnchor getTargetConnectionAnchor(Request request) { return new ChopboxAnchor(getFigure()); } @Override protected void createEditPolicies() { installEditPolicy(EditPolicy.LAYOUT_ROLE, new NodeLayoutEditPolicy()); installEditPolicy(EditPolicy.COMPONENT_ROLE, new NodeComponentEditPolicy()); installEditPolicy(EditPolicy.NODE_ROLE, new NodeGraphicalEditPolicy()); } @Override protected void refreshVisuals() { if (node==null) return; NodeFigure figure = this.getNodeFigure(); if(figure == null) return; final Rectangle bounds = new Rectangle(node.getX(), node.getY(),-1,-1); if (getFigure().getParent() != null){ ((GraphicalEditPart) getParent()).setLayoutConstraint(this,figure, bounds); } this.refreshFigureName(); figure.updateMarker(); figure.repaint(); //refreshBG(); super.refreshVisuals(); } protected void refreshBG() { if (node==null) return; NodeFigure figure = this.getNodeFigure(); if(figure == null) return; figure.updateBG(); } protected void refreshMarker() { if (node==null) return; NodeFigure figure = this.getNodeFigure(); if(figure == null) return; figure.updateMarker(); } /** * gets the figure of model as NodeFigure * @return the casted figure */ protected NodeFigure getNodeFigure(){ return (NodeFigure) getFigure(); } /** * sets the number for mappings * @param index the number for mappings */ public void setNumberForMapping(int index){ this.index = index; } @Override public void setSelected(int selectionMode) { super.setSelected(selectionMode); // change color on node figure ((NodeFigure)getFigure()).setSelectionMode(selectionMode); } }