internal static void ConvertNodesToCodeInternal(this WorkspaceModel workspace, 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(); 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(workspace.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); workspace.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, workspace.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, workspace.ElementResolver); undoHelper.RecordCreation(codeBlockNode); workspace.AddAndRegisterNode(codeBlockNode, false); codeBlockNodes.Add(codeBlockNode); #endregion #region Step III. Recreate the necessary connections var newInputConnectors = ReConnectInputConnections(externalInputConnections, codeBlockNode, workspace); foreach (var connector in newInputConnectors) { undoHelper.RecordCreation(connector); } var newOutputConnectors = ReConnectOutputConnections(externalOutputConnections, codeBlockNode); foreach (var connector in newOutputConnectors) { undoHelper.RecordCreation(connector); } #endregion } undoHelper.ApplyActions(workspace.UndoRecorder); DynamoSelection.Instance.ClearSelection(); DynamoSelection.Instance.Selection.AddRange(codeBlockNodes); Debug.WriteLine(string.Format("Workspace has {0} nodes and {1} connectors after N2C operation.", workspace.Nodes.Count(), workspace.Connectors.Count())); workspace.RequestRun(); }
internal void ConvertNodesToCodeInternal(Guid nodeId, EngineController engineController, bool verboseLogging) { IEnumerable <NodeModel> selectedNodes = DynamoSelection.Instance.Selection.OfType <NodeModel>().Where(n => n.IsConvertible); if (!selectedNodes.Any()) { return; } Dictionary <string, string> variableNameMap; string code = engineController.ConvertNodesToCode(selectedNodes, out variableNameMap, verboseLogging); CodeBlockNodeModel codeBlockNode; //UndoRedo Action Group---------------------------------------------- using (UndoRecorder.BeginActionGroup()) { #region Step I. Delete all nodes and their connections //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 var nodeList = selectedNodes.ToList(); int nodeCount = nodeList.Count; 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(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; if (variableNameMap.ContainsKey(variableName)) { variableName = variableNameMap[variableName]; } //Store the data in the corresponding dictionary if (startNode == node) { externalOutputConnections.Add(connector, variableName); } else { externalInputConnections.Add(connector, variableName); } } //Delete the connector UndoRecorder.RecordDeletionForUndo(connector); connector.Delete(); } #endregion #region Step I.B. Delete the node totalX += node.X; totalY += node.Y; UndoRecorder.RecordDeletionForUndo(node); Nodes.Remove(node); #endregion } #endregion #region Step II. Create the new code block node codeBlockNode = new CodeBlockNodeModel( code, nodeId, totalX / nodeCount, totalY / nodeCount, engineController.LibraryServices); UndoRecorder.RecordCreationForUndo(codeBlockNode); Nodes.Add(codeBlockNode); #endregion #region Step III. Recreate the necessary connections ReConnectInputConnections(externalInputConnections, codeBlockNode); ReConnectOutputConnections(externalOutputConnections, codeBlockNode); #endregion } //End UndoRedo Action Group------------------------------------------ // select node DynamoSelection.Instance.ClearSelection(); DynamoSelection.Instance.Selection.Add(codeBlockNode); OnAstUpdated(); }