/// <summary> /// Callback for the 'duplicate node' context menu option. /// </summary> /// <remarks> /// Does this belong in the presenter? /// </remarks> /// <param name="sender">Sending object.</param> /// <param name="args">Event data.</param> private void OnDuplicateNode(object sender, EventArgs args) { try { if (graphView.SelectedObject is DGNode node) { List <StateNode> nodes = Nodes; List <RuleAction> arcs = Arcs; // Create a copy of the existing node. StateNode newNode = new StateNode(node.ToNode()); newNode.Location = new System.Drawing.Point(newNode.Location.X + node.Width / 2, newNode.Location.Y); newNode.Name = graphView.DirectedGraph.NextNodeID(); if (nodeDescriptions.ContainsKey(node.Name)) { newNode.Description = nodeDescriptions[node.Name]; } nodes.Add(newNode); // Copy all arcs moving to/from the existing node. DirectedGraph graph = graphView.DirectedGraph; foreach (var arc in graphView.DirectedGraph.Arcs.FindAll(arc => arc.SourceName == node.Name)) { RuleAction newArc = new RuleAction(arc); newArc.Name = graph.NextArcID(); newArc.SourceName = newNode.Name; if (rules.ContainsKey(arc.Name)) { newArc.Conditions = rules[arc.Name]; } if (actions.ContainsKey(arc.Name)) { newArc.Actions = actions[arc.Name]; } arcs.Add(newArc); // Add the arc to the local copy of the directed graph. // Need to do this to ensure that NextArcID() doesn't // generate the same name when we call it multiple times. graph.AddArc(newArc); } foreach (var arc in graphView.DirectedGraph.Arcs.FindAll(arc => arc.DestinationName == graphView.SelectedObject.Name)) { RuleAction newArc = new RuleAction(arc); newArc.Name = graph.NextArcID(); newArc.DestinationName = newNode.Name; if (rules.ContainsKey(arc.Name)) { newArc.Conditions = rules[arc.Name]; } if (actions.ContainsKey(arc.Name)) { newArc.Actions = actions[arc.Name]; } arcs.Add(newArc); // Add the arc to the local copy of the directed graph. // Need to do this to ensure that NextArcID() doesn't // generate the same name when we call it multiple times. graph.AddArc(newArc); } OnGraphChanged?.Invoke(this, new GraphChangedEventArgs(arcs, nodes)); } } catch (Exception err) { ShowError(err); } }