internal void ConvertNodesToCodeInternal(EngineController engineController, INamingProvider namingProvider)
{
var selectedNodes = DynamoSelection.Instance
.Selection
.OfType<NodeModel>()
.Where(n => n.IsConvertible);
if (!selectedNodes.Any())
return;
var cliques = NodeToCodeCompiler.GetCliques(selectedNodes).Where(c => !(c.Count == 1 && c.First() is CodeBlockNodeModel));
var codeBlockNodes = new List<CodeBlockNodeModel>();
//UndoRedo Action Group----------------------------------------------
NodeToCodeUndoHelper undoHelper = new NodeToCodeUndoHelper();
// using (UndoRecorder.BeginActionGroup())
{
foreach (var nodeList in cliques)
{
//Create two dictionarys to store the details of the external connections that have to
//be recreated after the conversion
var externalInputConnections = new Dictionary<ConnectorModel, string>();
var externalOutputConnections = new Dictionary<ConnectorModel, string>();
//Also collect the average X and Y co-ordinates of the different nodes
int nodeCount = nodeList.Count;
var nodeToCodeResult = engineController.ConvertNodesToCode(this.nodes, nodeList, namingProvider);
#region Step I. Delete all nodes and their connections
double totalX = 0, totalY = 0;
foreach (var node in nodeList)
{
#region Step I.A. Delete the connections for the node
foreach (var connector in node.AllConnectors.ToList())
{
if (!IsInternalNodeToCodeConnection(nodeList, connector))
{
//If the connector is an external connector, the save its details
//for recreation later
var startNode = connector.Start.Owner;
int index = startNode.OutPorts.IndexOf(connector.Start);
//We use the varibleName as the connection between the port of the old Node
//to the port of the new node.
var variableName = startNode.GetAstIdentifierForOutputIndex(index).Value;
//Store the data in the corresponding dictionary
if (startNode == node)
{
if (nodeToCodeResult.OutputMap.ContainsKey(variableName))
variableName = nodeToCodeResult.OutputMap[variableName];
externalOutputConnections.Add(connector, variableName);
}
else
{
if (nodeToCodeResult.InputMap.ContainsKey(variableName))
variableName = nodeToCodeResult.InputMap[variableName];
externalInputConnections.Add(connector, variableName);
}
}
//Delete the connector
undoHelper.RecordDeletion(connector);
connector.Delete();
}
#endregion
#region Step I.B. Delete the node
totalX += node.X;
totalY += node.Y;
undoHelper.RecordDeletion(node);
RemoveAndDisposeNode(node);
#endregion
}
#endregion
#region Step II. Create the new code block node
var outputVariables = externalOutputConnections.Values;
var newResult = NodeToCodeCompiler.ConstantPropagationForTemp(nodeToCodeResult, outputVariables);
// Rewrite the AST using the shortest unique name in case of namespace conflicts
NodeToCodeCompiler.ReplaceWithShortestQualifiedName(
engineController.LibraryServices.LibraryManagementCore.ClassTable, newResult.AstNodes, ElementResolver);
var codegen = new ProtoCore.CodeGenDS(newResult.AstNodes);
var code = codegen.GenerateCode();
var codeBlockNode = new CodeBlockNodeModel(
code,
System.Guid.NewGuid(),
totalX / nodeCount,
totalY / nodeCount, engineController.LibraryServices, ElementResolver);
undoHelper.RecordCreation(codeBlockNode);
AddAndRegisterNode(codeBlockNode, false);
codeBlockNodes.Add(codeBlockNode);
#endregion
#region Step III. Recreate the necessary connections
var newInputConnectors = ReConnectInputConnections(externalInputConnections, codeBlockNode);
foreach (var connector in newInputConnectors)
{
undoHelper.RecordCreation(connector);
}
var newOutputConnectors = ReConnectOutputConnections(externalOutputConnections, codeBlockNode);
foreach (var connector in newOutputConnectors)
{
undoHelper.RecordCreation(connector);
}
#endregion
}
}
undoHelper.ApplyActions(UndoRecorder);
DynamoSelection.Instance.ClearSelection();
DynamoSelection.Instance.Selection.AddRange(codeBlockNodes);
RequestRun();
}