/******************************************************************************* * 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.editor.commands.graph; import java.util.LinkedList; import org.eclipse.draw2d.geometry.Point; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.henshin.model.Graph; import org.eclipse.emf.henshin.model.HenshinFactory; import org.eclipse.emf.henshin.model.HenshinPackage; import org.eclipse.emf.henshin.model.Mapping; import org.eclipse.emf.henshin.model.Node; import org.eclipse.emf.henshin.model.Rule; import org.eclipse.gef.commands.Command; import org.eclipse.gef.commands.CompoundCommand; import de.tub.tfs.henshin.editor.commands.SimpleAddEObjectCommand; import de.tub.tfs.henshin.editor.util.HenshinLayoutUtil; import de.tub.tfs.henshin.editor.util.ModelUtil; import de.tub.tfs.henshin.model.layout.HenshinLayoutFactory; import de.tub.tfs.henshin.model.layout.LayoutSystem; import de.tub.tfs.henshin.model.layout.NodeLayout; /** * The Class CreateNodeCommand. */ public class CreateNodeCommand extends Command { /** * A default x-coordinate of the new created {@link Node}'s * {@link NodeLayout} */ public static final int X_DEFAULT = 30; /** * A default y-coordinate of the new created {@link Node}'s * {@link NodeLayout} */ public static final int Y_DEFAULT = 30; /** The graph. */ private final Graph graph; /** The node. */ private Node node; /** The node layout. */ private NodeLayout nodeLayout; /** The type. */ private EClass type; /** The layout system. */ private LayoutSystem layoutSystem; /** The x. */ private int x; /** The y. */ private int y; /** Stores the value whether a node layout is enabled or not. */ private boolean enabled; /** Stores the value if a node is a multi node or a single node. */ private boolean multi; private org.eclipse.gef.commands.CompoundCommand multiNodeCommands = new org.eclipse.gef.commands.CompoundCommand(); private LinkedList<Node> multiNodes = new LinkedList<Node>(); /** * Instantiates a new command to create a node with the given parameters and * initially, the node is only a single node and the node layout is enabled. * * @param graph * the graph * @param node * the node * @param x * the Coordinate x * @param y * the Coordinate y */ public CreateNodeCommand(Graph graph, Node node, int x, int y) { this(graph, node, null, x, y, true, false); } /** * Instantiates a new command to create a node with the given parameters and * initially, the node is only a single node. * * @param graph * the graph * @param eClass * the e class */ public CreateNodeCommand(Graph graph, EClass eClass) { this(graph, eClass, false); } /** * Instantiates a new command to create a node with the given parameters and * default x and y positions * * @param graph * the graph * @param eClass * the e class */ public CreateNodeCommand(Graph graph, EClass eClass, boolean multi) { super("Creating Node"); Point pos = HenshinLayoutUtil.INSTANCE.calcNodeInsertPosition(graph, X_DEFAULT, Y_DEFAULT); this.graph = graph; this.node = HenshinFactory.eINSTANCE.createNode(); this.type = eClass; this.x = pos.x; this.y = pos.y; this.multi = multi; } /** * Instantiates a new command to create a node with the given parameters. * * @param graph * the graph * @param node * the node * @param x * the Coordinate x * @param y * the Coordinate y */ public CreateNodeCommand(Graph graph, Node node, int x, int y, boolean enabled, boolean multi) { super("Creating Node"); this.graph = graph; this.node = node; this.type = node.getType(); this.x = x; this.y = y; this.enabled = enabled; this.multi = multi; } /** * Default constructor. Initializes all required parameters with the given * ones. * * @param graph * the containing {@link Graph} of the new {@link Node} * @param node * the new {@link Node} to be created. * @param type * a type as {@link EClass} for the new {@link Node}. * @param x * the x-coordinate to layout the new {@link Node} in the * graphical view * @param y * the y-coordinate to layout the new {@link Node} in the * graphical view * @param enabled * sets the proper {@link NodeLayout} being enabled * @param multi * sets the proper {@link NodeLayout} as a single or multi node */ public CreateNodeCommand(Graph graph, Node node, EClass type, int x, int y, boolean enabled, boolean multi) { super("Creating Node"); this.graph = graph; this.node = node; this.type = type; this.x = x; this.y = y; this.enabled = enabled; this.multi = multi; } /* * (non-Javadoc) * * @see org.eclipse.gef.commands.Command#execute() */ @Override public void execute() { if (type != null) { node.setType(type); } this.layoutSystem = ModelUtil.getModelRoot(graph, LayoutSystem.class); nodeLayout = getNodeLayout(); nodeLayout.setX(x); nodeLayout.setY(y); nodeLayout.setEnabled(enabled); nodeLayout.setColor(0); nodeLayout.setMulti(multi); layoutSystem.getLayouts().add(nodeLayout); graph.getNodes().add(node); multiNodeCommands = new CompoundCommand(); if (graph.getRule() != null && (!graph.getRule().getAllMultiRules().isEmpty() )){ if (graph.isRhs()){ for (Rule multiRule : graph.getRule().getMultiRules()) { CreateNodeCommand c = new CreateNodeCommand(multiRule.getRhs(), node.getType(),false); Mapping m = HenshinFactory.eINSTANCE.createMapping(node, c.getNode()); SimpleAddEObjectCommand<Rule, Mapping> mappingCommand = new SimpleAddEObjectCommand<Rule, Mapping>(m, HenshinPackage.Literals.RULE__MULTI_MAPPINGS, multiRule); multiNodeCommands.add(mappingCommand); multiNodeCommands.add(c); } } else { for (Rule multiRule : graph.getRule().getMultiRules()) { CreateNodeCommand c = new CreateNodeCommand(multiRule.getLhs(), node.getType(),false); Mapping m = HenshinFactory.eINSTANCE.createMapping(node, c.getNode()); SimpleAddEObjectCommand<Rule, Mapping> mappingCommand = new SimpleAddEObjectCommand<Rule, Mapping>(m, HenshinPackage.Literals.RULE__MULTI_MAPPINGS, multiRule); multiNodeCommands.add(mappingCommand); multiNodeCommands.add(c); } } } multiNodeCommands.execute(); } /* * (non-Javadoc) * * @see org.eclipse.gef.commands.Command#undo() */ @Override public void undo() { multiNodeCommands.undo(); graph.getNodes().remove(node); layoutSystem.getLayouts().remove(nodeLayout); } /* * (non-Javadoc) * * @see org.eclipse.gef.commands.Command#canExecute() */ @Override public boolean canExecute() { return graph != null; } /* * (non-Javadoc) * * @see org.eclipse.gef.commands.Command#canUndo() */ @Override public boolean canUndo() { return graph != null; } /** * Sets the node type. * * @param type * the new node type */ public void setNodeType(EClass type) { this.type = type; } /* * (non-Javadoc) * * @see org.eclipse.gef.commands.Command#redo() */ @Override public void redo() { layoutSystem.getLayouts().add(nodeLayout); graph.getNodes().add(node); } public Node getNode() { return node; } /** * @return the nodeLayout */ public NodeLayout getNodeLayout() { if (nodeLayout == null) { nodeLayout = HenshinLayoutFactory.eINSTANCE.createNodeLayout(); } nodeLayout.setModel(this.node); return nodeLayout; } }