private bool HandleSetReplicationGuideText(GraphCommand command) { uint nodeId = (uint)command.GetArgument(0); int replicationIndex = (int)command.GetArgument(1); string text = ((string)command.GetArgument(2)); VisualNode node = GetVisualNode(nodeId); if (node.VisualType != NodeType.Function) { throw new InvalidOperationException("Node must be FunctionNode"); } DeltaNodes deltaNodes = new DeltaNodes(); IVisualNode iNode = this.GetVisualNode(nodeId); deltaNodes.AppendToModifiedNodes(iNode); FunctionNode fNode = node as FunctionNode; undoRedoRecorder.BeginGroup(); undoRedoRecorder.RecordNodeModificationForUndo(deltaNodes.ModifiedNodes); undoRedoRecorder.EndGroup(); fNode.SetReplicationText(replicationIndex, text); //if(!fNode.SetReplicationText(replicationIndex,text)) // undoRedoRecorder.PopRecordFromUndoStorage(); node.DisableEdit(); node.Dirty = true; node.Compose(); this.SynchronizeToLiveRunner(deltaNodes); return(true); }
private bool HandleUndoOperation(GraphCommand command) { DeltaNodes deltaNodes = new DeltaNodes(); // Start tracking variables being undefined in this process. { RuntimeStates runtimeStates = this.GetRuntimeStates(); runtimeStates.BeginDefinitionMonitor(); this.undoRedoRecorder.Undo(deltaNodes); Dictionary <uint, List <string> > undefinedVariables = null; runtimeStates.EndDefinitionMonitor(out undefinedVariables); deltaNodes.AppendUndefinedVariables(undefinedVariables); } this.ValidateNodesSyntax(this.nodeCollection.Values.ToList <IVisualNode>()); this.ValidateDefinedAndReferencedVariables(); if (false == deltaNodes.IsEmpty) { this.SynchronizeToLiveRunner(deltaNodes); } this.UpdateDirtyNodes(); this.edgeController.UpdateDirtyEdges(deltaNodes.ModifiedNodes); selectionBox.UpdateSelectionBox(GetSelectedNodes()); return(true); }
internal void SynchronizeToLiveRunner(DeltaNodes deltaNodes) { if (false != deltaNodes.IsEmpty) { throw new InvalidOperationException("Nothing to send to 'lifeRunner'"); } // If there is something that we would like to query // the value for, add it into the modified node list. if (false == scheduledDeltaNodes.IsEmpty) { deltaNodes.AppendToRemovedNodes(scheduledDeltaNodes.RemovedNodes); deltaNodes.AppendToAddedNodes(scheduledDeltaNodes.AddedNodes); deltaNodes.AppendToModifiedNodes(scheduledDeltaNodes.ModifiedNodes); scheduledDeltaNodes.Reset(); } // Compact the DeltaNodes so that there is no duplicate and no node // exists in more than one list (e.g. addedNodes and modifiedNodes). deltaNodes.Compact(); SynchronizeData sd = new SynchronizeData(); if (null != deltaNodes.RemovedNodes && (deltaNodes.RemovedNodes.Count > 0)) { foreach (IVisualNode node in deltaNodes.RemovedNodes) { sd.RemovedNodes.Add(node.NodeId); } } if (null != deltaNodes.AddedNodes && (deltaNodes.AddedNodes.Count > 0)) { sd.AddedNodes = this.CreateSnapshotNodesFromVisualNodes(deltaNodes.AddedNodes); } if (null != deltaNodes.ModifiedNodes && (deltaNodes.ModifiedNodes.Count > 0)) { sd.ModifiedNodes = this.CreateSnapshotNodesFromVisualNodes(deltaNodes.ModifiedNodes); } // Tell the graph compiler that some variables are undefined. MergeUndefinedVariablesIntoData(deltaNodes.Undefinitions, sd); this.sdc.sdList.Add(sd); if (Configurations.EnableLiveExection) { try { this.CurrentSynchronizer.PushUpdate(sd); } catch (Exception e) { Debug.WriteLine(e); } } }
public void TestSynchronizeToLifeRunnerOperationException() { GraphController graphController = new GraphController(null); Assert.Throws <InvalidOperationException>(() => { DeltaNodes deltaNodes = new DeltaNodes(); graphController.SynchronizeToLiveRunner(deltaNodes); }); }
public void TestRedo() { GraphController graphController = new GraphController(null); UndoRedoRecorder urr = new UndoRedoRecorder(graphController); DeltaNodes deltaNodes = new DeltaNodes(); bool result = urr.Redo(deltaNodes); Assert.AreEqual(false, result); }
public bool ProcessNodesToCodeConversion(List <uint> originalNodeIds, List <SnapshotNode> snapshotNodes) { if (originalNodeIds == null || originalNodeIds.Count == 0 || snapshotNodes == null || snapshotNodes.Count == 0) { return(false); } undoRedoRecorder.BeginGroup(); undoRedoRecorder.RecordRuntimeStatesForUndo(graphProperties.RuntimeStates); List <IVisualNode> originalNodes = GetNodesByIds(originalNodeIds); List <IVisualNode> modifiedNodes = new List <IVisualNode>(); DeleteNodesWithRecord(originalNodes, out modifiedNodes); List <Connection> inputConnections = null; Dictionary <string, string> identifierTempVariableMap = null; List <VisualNode> identifierNodes = CreateIntermediateIdentifierNodes(snapshotNodes, out inputConnections, out identifierTempVariableMap); ReplaceVariableNamesInSnapshotNodes(identifierTempVariableMap, snapshotNodes); List <VisualNode> codeBlockNodes = CreateVisualNodesFromSnapshotNodes(snapshotNodes); List <IVisualNode> createdNodes = new List <IVisualNode>(); createdNodes.AddRange(identifierNodes); createdNodes.AddRange(codeBlockNodes); SetNodesPosition(createdNodes, originalNodes[0].X, originalNodes[0].Y); Dictionary <VisualNode, List <Connection> > outputNodeConnectionMap = GetNodeOutputConnectionMapFromSnapshotNodes(snapshotNodes, codeBlockNodes); Dictionary <VisualNode, List <Connection> > inputNodeConnectionMap = GetNodeInputConnectionMapFromSnapshotNodes(identifierNodes, inputConnections); EstablishExplicitConnections(inputNodeConnectionMap, outputNodeConnectionMap, modifiedNodes); EstablishImplicitConnections(modifiedNodes); undoRedoRecorder.EndGroup(); ValidateDefinedAndReferencedVariables(); BeautifyCode(codeBlockNodes); UpdateSlotsVisiblity(); selectionBox.UpdateSelectionBox(GetSelectedNodes()); UpdateDirtyNodes(); edgeController.UpdateDirtyEdges(createdNodes); //update delta nodes send to liveRunner DeltaNodes deltaNodes = new DeltaNodes(); deltaNodes.AppendToAddedNodes(createdNodes); deltaNodes.AppendToModifiedNodes(modifiedNodes.Distinct().ToList()); deltaNodes.AppendToRemovedNodes(originalNodes); SynchronizeToLiveRunner(deltaNodes); return(true); }
public bool UpdateNodeTextHighFrequency(string text) { if (null == nodeSelectedForHighFrequencyUpdate) { throw new InvalidOperationException("No node selected for high frequency update (CAADF8564FE9)"); } nodeSelectedForHighFrequencyUpdate.Edit(text, true); edgeController.UpdateEdgeConnectTo(nodeSelectedForHighFrequencyUpdate); // These calls cause the LiveRunner to update. DeltaNodes deltaNodes = new DeltaNodes(); deltaNodes.AppendToModifiedNodes(nodeSelectedForHighFrequencyUpdate); SynchronizeToLiveRunner(deltaNodes); return(true); }
internal GraphController(IGraphVisualHost visualHost, string filePath) { if (!File.Exists(filePath)) { throw new ArgumentException("'filePath' is not a valid path"); } this.FileLoadInProgress = true; this.InitializeInternal(visualHost); this.LoadFileInternal(filePath); this.filePath = filePath; try { // Attempt to see if we are creating the graph controller from recovery file. int index = -1; uint graphId = uint.MaxValue; Utilities.GetBackupFileIndex(this.filePath, ref graphId, ref index); // If we reach here without exception, then "filePath" is a backup file // name. In which case we should not assign a name to "this.filePath" so // that the user will be prompted to supply an alternative file name. // this.filePath = string.Empty; } catch (Exception) { } DeltaNodes deltaNodes = new DeltaNodes(); deltaNodes.AppendToAddedNodes(this.nodeCollection.Values.ToList <IVisualNode>()); this.ValidateNodesSyntax(deltaNodes.AddedNodes); this.ValidateDefinedAndReferencedVariables(); this.UpdateDirtyNodes(); edgeController.AuditEdges(); this.edgeController.UpdateDirtyEdges(null); if (this.nodeCollection.Count > 0) { this.SynchronizeToLiveRunner(deltaNodes); } this.FileLoadInProgress = false; }
private bool HandleSelectedMenuItem(GraphCommand command) { int menuItemId = (int)command.GetArgument(0); double mouseX = ((double)command.GetArgument(1)); double mouseY = ((double)command.GetArgument(2)); uint nodeId = (uint)command.GetArgument(3); NodePart part = ((NodePart)command.GetArgument(4)); LibraryItem selectedItem = new LibraryItem(); VisualNode node = this.GetVisualNode(nodeId); if (itemsProvider != null) { selectedItem = this.itemsProvider.GetItem(menuItemId); } if (selectedItem == null) //No match in the library { if (part == NodePart.NorthWest) { this.HandleTopLeftSelectedItem(menuItemId, nodeId); } else if (menuItemId == Configurations.ConvertNodeToCode) { HandleConvertSelectionToCode(); return(true); } else if (menuItemId < Configurations.PropertyBase) { // @TODO(Joy): Use switch-case for "menuItemId". ProcessPreviewMenuItems(menuItemId, nodeId); UpdateDirtyNodes(); return(true); } } else //Item found in library { if (selectedItem.Children != null && selectedItem.Children.Count > 0) { selectedItem = selectedItem.Children[0]; } LibraryItem.MemberType itemType = this.GetItemType(menuItemId); DeltaNodes deltaNodes = new DeltaNodes(); VisualNode newNode = null; if (part == NodePart.NorthEast) { if (selectedItem.Type == LibraryItem.MemberType.InstanceProperty) { if (selectedItem.ItemType == NodeType.Function) { newNode = this.CreateMethodNode(mouseX, mouseY, selectedItem.Assembly, selectedItem.QualifiedName, selectedItem.ArgumentTypes); } else { newNode = this.CreatePropertyNode(mouseX, mouseY, selectedItem.Assembly, selectedItem.QualifiedName, selectedItem.ArgumentTypes); } deltaNodes.AppendToAddedNodes(newNode); } else if (selectedItem.Type == LibraryItem.MemberType.InstanceMethod) { newNode = this.CreateMethodNode(mouseX, mouseY, selectedItem.Assembly, selectedItem.QualifiedName, selectedItem.ArgumentTypes); deltaNodes.AppendToAddedNodes(newNode); } if (newNode != null && (null != deltaNodes.AddedNodes) && deltaNodes.AddedNodes.Count > 0) { // @keyu: If we are acessing its member function or // property, there is no reason to mark this node as // dirty. Comment it out to avoid to recreate object. // // deltaNodes.AppendToModifiedNodes(node); Slot inputSlot = this.GetSlot(newNode.GetInputSlot(0)) as Slot; Slot outputSlot = this.GetSlot(node.GetOutputSlot(0)) as Slot; this.undoRedoRecorder.BeginGroup(); this.undoRedoRecorder.RecordRuntimeStatesForUndo(this.graphProperties.RuntimeStates); this.undoRedoRecorder.RecordNodeModificationForUndo(deltaNodes.ModifiedNodes); this.graphProperties.RuntimeStates.AddVariablesDefinedInNode(newNode, false); this.edgeController.CreateLinkingEdge(outputSlot, inputSlot); this.undoRedoRecorder.RecordNodeCreationForUndo(deltaNodes.AddedNodes); this.undoRedoRecorder.EndGroup(); //After EstablishLinkingConnection() is executed, the nodes in the nodeToModify would already be modified this.SynchronizeToLiveRunner(deltaNodes); } } else if (part == NodePart.North) { if (itemType == LibraryItem.MemberType.Constructor) { deltaNodes.AppendToModifiedNodes(node); deltaNodes.AppendToModifiedNodes(FindAssociatedNodesFromNodes(deltaNodes.ModifiedNodes)); this.undoRedoRecorder.BeginGroup(); this.undoRedoRecorder.RecordNodeModificationForUndo(deltaNodes.ModifiedNodes); //this.undoRedoRecorder.RecordEdgeModificationForUndo(edgeController.FindEdgeConnectTo(node)); ((FunctionNode)node).ChangeConstructor(selectedItem.QualifiedName, selectedItem.ArgumentTypes, selectedItem.ArgumentNames); this.undoRedoRecorder.EndGroup(); //After ChangeConstructor() is executed, the nodes in the nodeToModify would already be modified this.SynchronizeToLiveRunner(deltaNodes); } else if (itemType == LibraryItem.MemberType.InstanceProperty) { deltaNodes.AppendToRemovedNodes(node); deltaNodes.AppendToModifiedNodes(this.FindAssociatedNodesFromNodes(deltaNodes.RemovedNodes)); newNode = this.CreatePropertyNode(mouseX, mouseY, selectedItem.Assembly, selectedItem.QualifiedName, selectedItem.ArgumentTypes); deltaNodes.AppendToAddedNodes(newNode); this.undoRedoRecorder.BeginGroup(); this.undoRedoRecorder.RecordRuntimeStatesForUndo(this.graphProperties.RuntimeStates); this.undoRedoRecorder.RecordNodeDeletionForUndo(deltaNodes.RemovedNodes); this.undoRedoRecorder.RecordNodeModificationForUndo(deltaNodes.ModifiedNodes); this.TransferInformationFromMethodToProperty(node, newNode); this.undoRedoRecorder.RecordNodeCreationForUndo(deltaNodes.AddedNodes); this.DeleteNodes(deltaNodes.RemovedNodes); this.undoRedoRecorder.EndGroup(); //After DeleteNodes() is executed, the nodes in the nodeToModify would already be modified this.SynchronizeToLiveRunner(deltaNodes); } else if (itemType == LibraryItem.MemberType.InstanceMethod) { deltaNodes.AppendToModifiedNodes(node); deltaNodes.AppendToModifiedNodes(FindAssociatedNodesFromNodes(deltaNodes.ModifiedNodes)); this.undoRedoRecorder.BeginGroup(); this.undoRedoRecorder.RecordNodeModificationForUndo(deltaNodes.ModifiedNodes); ((FunctionNode)node).ChangeMethod(selectedItem.QualifiedName, selectedItem.ArgumentTypes); this.undoRedoRecorder.EndGroup(); //After ChangeConstructor() is executed, the nodes in the nodeToModify would already be modified this.SynchronizeToLiveRunner(deltaNodes); } } } this.UpdateDirtyNodes(); edgeController.UpdateEdgeConnectTo(node); return(true); }
private bool HandleDeleteComponents(GraphCommand command) { if (currentDragState != DragState.None) { currentDragState = DragState.None; edgeController.ResetParameters(); } DeltaNodes deltaNodes = new DeltaNodes(); foreach (VisualNode node in nodeCollection.Values) { if (node.Selected) { deltaNodes.AppendToRemovedNodes(node); } } if ((null == deltaNodes.RemovedNodes) && edgeController.SelectedEdgeCount() == 0) { return(true); } if (null != deltaNodes.RemovedNodes && (deltaNodes.RemovedNodes.Count > 0)) { deltaNodes.AppendToModifiedNodes(FindAssociatedNodesFromNodes(deltaNodes.RemovedNodes)); } List <IVisualNode> nodesConnectToEdge = edgeController.GetNodesFromSelectedEdges(); foreach (IVisualNode node in nodesConnectToEdge) { bool inDeleteList = (null != deltaNodes.RemovedNodes && (deltaNodes.RemovedNodes.Contains(node))); bool inModifyList = (null != deltaNodes.ModifiedNodes && (deltaNodes.ModifiedNodes.Contains(node))); if (!inDeleteList && !inModifyList) { deltaNodes.AppendToModifiedNodes(node); } } // Begin tracking variables being undefined in this process. { RuntimeStates runtimeStates = this.GetRuntimeStates(); runtimeStates.BeginDefinitionMonitor(); this.undoRedoRecorder.BeginGroup(); this.undoRedoRecorder.RecordRuntimeStatesForUndo(this.graphProperties.RuntimeStates); this.undoRedoRecorder.RecordNodeDeletionForUndo(deltaNodes.RemovedNodes); this.undoRedoRecorder.RecordNodeModificationForUndo(deltaNodes.ModifiedNodes); this.edgeController.DeleteSelectedEdges(); this.DeleteNodes(deltaNodes.RemovedNodes); this.ValidateDefinedAndReferencedVariables(); this.UpdateSlotsVisiblity(); EstablishImplicitConnections(this.nodeCollection.Values.ToList()); this.undoRedoRecorder.EndGroup(); // Gather the data of variables being undefined. Dictionary <uint, List <string> > undefinedVariables = null; runtimeStates.EndDefinitionMonitor(out undefinedVariables); deltaNodes.AppendUndefinedVariables(undefinedVariables); } //After DeleteSelectedEdges() and DeleteNodes() are executed, the nodes in the nodeToModify would already be modified if (false == deltaNodes.IsEmpty) { this.SynchronizeToLiveRunner(deltaNodes); } this.UpdateDirtyNodes(); //If the node is selected for deletion by clicking on the preview, the lastHoveredNode should be reset lastHoveredNodeId = uint.MaxValue; selectionBox.UpdateSelectionBox(GetSelectedNodes()); return(true); }
private bool HandleEndNodeEdit(GraphCommand command) { uint nodeId = (uint)command.GetArgument(0); string text = command.GetArgument(1) as string; bool commit = (bool)command.GetArgument(2); VisualNode node = this.GetVisualNode(nodeId); bool setToPreviousValue = false; bool setToDefaultValue = false; bool recordAsCreation = false; bool recordAndDelete = false; bool validate = false; bool delete = false; text = node.PreprocessInputString(text); bool committingEmptyContent = text == string.Empty; bool committingSameContent = text == this.previousText; bool startedOffDefaultValueDriver = this.previousText == Configurations.DriverInitialTextValue; bool committingEmptyCodeBlock = text == string.Empty || text == Configurations.CodeBlockInitialMessage; bool startedOffEmptyCodeBlock = this.previousText == string.Empty || this.previousText == Configurations.CodeBlockInitialMessage; //Flow logic if (node.VisualType == NodeType.CodeBlock) { if (commit) { if (committingEmptyCodeBlock) { if (startedOffEmptyCodeBlock) { delete = true; } else { recordAndDelete = true; } } else //Not Empty { if (!committingSameContent) { validate = true; } if (startedOffEmptyCodeBlock) { recordAsCreation = true; } } } else //Not committing { if (startedOffEmptyCodeBlock) { delete = true; } } } else if (node.VisualType == NodeType.Driver) { if (commit) { if (committingEmptyContent) { if (node.IsEditingText) { setToDefaultValue = true; } else if (node.IsEditingCaption) { setToPreviousValue = true; } } else //Not Empty { if (!committingSameContent) { validate = true; } } } } else //Other nodes { if (commit) { if (committingEmptyContent) { setToPreviousValue = true; } else //Not empty { if (!committingSameContent) { validate = true; } } } } //Execution node.Edit(this.previousText, false); if (delete) { if (null != visualHost) { this.visualHost.RemoveDrawingVisual(node.NodeId); this.visualHost.RemoveDrawingVisual(node.GetErrorBubbleId()); this.visualHost.RemoveDrawingVisual(node.GetPreviewBubbleId()); this.visualHost.RemoveExtendedBubble(node.GetPreviewBubbleId()); } uint[] outputSlots = node.GetOutputSlots(); uint[] inputSlots = node.GetInputSlots(); if (inputSlots != null) { foreach (uint inputSlot in inputSlots) { this.slotCollection.Remove(inputSlot); } } if (outputSlots != null) { foreach (uint outputSlot in outputSlots) { this.slotCollection.Remove(outputSlot); } } this.nodeCollection.Remove(node.NodeId); this.bubbleCollection.Remove(node.GetErrorBubbleId()); this.bubbleCollection.Remove(node.GetPreviewBubbleId()); } if (recordAndDelete) { DeltaNodes deltaNodes = new DeltaNodes(); deltaNodes.AppendToRemovedNodes(node); deltaNodes.AppendToModifiedNodes(FindAssociatedNodesFromNodes(deltaNodes.RemovedNodes)); this.undoRedoRecorder.BeginGroup(); this.undoRedoRecorder.RecordRuntimeStatesForUndo(this.graphProperties.RuntimeStates); this.undoRedoRecorder.RecordNodeDeletionForUndo(deltaNodes.RemovedNodes); this.undoRedoRecorder.RecordNodeModificationForUndo(deltaNodes.ModifiedNodes); this.DeleteNodes(deltaNodes.RemovedNodes); this.undoRedoRecorder.EndGroup(); this.ValidateDefinedAndReferencedVariables(); this.UpdateSlotsVisiblity(); this.SynchronizeToLiveRunner(deltaNodes); } if (setToDefaultValue) { if (!startedOffDefaultValueDriver) { DeltaNodes deltaNodes = new DeltaNodes(); deltaNodes.AppendToModifiedNodes(node); this.undoRedoRecorder.BeginGroup(); this.undoRedoRecorder.RecordNodeModificationForUndo(deltaNodes.ModifiedNodes); this.undoRedoRecorder.EndGroup(); node.Edit(Configurations.DriverInitialTextValue, false); this.SynchronizeToLiveRunner(deltaNodes); } string warningMessage = "Field cannot be empty. Value will be set to 0."; node.SetErrorValue((object)warningMessage, ErrorType.Warning); } if (setToPreviousValue) { string warningMessage = "Field cannot be empty. Value will be reverted to previous state."; node.SetErrorValue((object)warningMessage, ErrorType.Warning); } if (validate) { DeltaNodes deltaNodes = new DeltaNodes(); List <IVisualNode> addedNodes = new List <IVisualNode>(); List <IVisualNode> modifiedNodes = new List <IVisualNode>(); addedNodes.Add(node); // deltaNodes.AppendToAddedNodes(node); // Start monitoring if we are going to undefine any variables. this.graphProperties.RuntimeStates.BeginDefinitionMonitor(); this.undoRedoRecorder.BeginGroup(); this.undoRedoRecorder.RecordRuntimeStatesForUndo(this.graphProperties.RuntimeStates); if (recordAsCreation) { this.undoRedoRecorder.RecordNodeCreationForUndo(addedNodes); } else //record edited node as modification { deltaNodes.AppendToModifiedNodes(node); deltaNodes.AppendToModifiedNodes(FindAssociatedNodesFromNodes(addedNodes)); this.undoRedoRecorder.RecordNodeModificationForUndo(deltaNodes.ModifiedNodes); } // These methods (especially the first two and last two) must be // called in this particular order (due to their dependencies). // // GC.ValidateNodesSyntax // RS.UpdateVariableDefinitionMap // GC.ValidateDefinedAndReferencedVariables // GC.UpdateSlotsVisiblity // GC.EstablishImplicitConnections // node.SetErrorValue(null, ErrorType.None); node.Edit(text, false); this.ValidateNodesSyntax(addedNodes); this.graphProperties.RuntimeStates.UpdateVariablesDefinedInNode(node, false); this.ValidateDefinedAndReferencedVariables(); this.UpdateSlotsVisiblity(); this.EstablishImplicitConnections(modifiedNodes); this.edgeController.DeleteUnnecessaryEdges(); this.undoRedoRecorder.EndGroup(); // Now all the modifications are over, see what we have undefined. Dictionary <uint, List <string> > undefinedVariables = null; this.graphProperties.RuntimeStates.EndDefinitionMonitor(out undefinedVariables); deltaNodes.AppendUndefinedVariables(undefinedVariables); if (recordAsCreation) { deltaNodes.AppendToAddedNodes(addedNodes); } deltaNodes.AppendToModifiedNodes(modifiedNodes); this.SynchronizeToLiveRunner(deltaNodes); } this.UpdateDirtyNodes(); this.edgeController.UpdateEdgeConnectTo(node); node.DisableEdit(); if (validate && visualHost != null) { visualHost.ScrollToVisual(visualHost.GetDrawingVisualForNode(node.NodeId)); } return(true); }
private bool HandleEndDrag(GraphCommand command) { MouseButton button = ((MouseButton)command.GetArgument(0)); uint compId = ((uint)command.GetArgument(1)); NodePart nodePart = ((NodePart)command.GetArgument(2)); int slotIndex = ((int)command.GetArgument(3)); ModifierKeys modifiers = ((ModifierKeys)command.GetArgument(4)); double mouseX = ((double)command.GetArgument(5)); double mouseY = ((double)command.GetArgument(6)); switch (currentDragState) { case DragState.NodeRepositioning: foreach (DraggedNode draggedNode in dragSet) { ((VisualNode)draggedNode.node).X = mouseX - draggedNode.DeltaX; ((VisualNode)draggedNode.node).Y = mouseY - draggedNode.DeltaY; } // both node that the edge is connected to should be bring to back // foreach (VisualNode connectingNode in edgeController.GetNodesFromSelectedEdges()) { if (!connectingNode.Selected) { RearrangeNodeAndBubbleVisual(connectingNode, false); } } dragSet.Clear(); edgeController.ResetAllEdges(); break; case DragState.CurveDrawing: case DragState.EdgeReconnection: edgeConnection = EdgeConnectionFlag.None; VisualNode node = GetVisualNode(edgeController.GetConnectNodeId()); if (null != node) { node.PreviewSelected = node.Selected; node.Compose(); // Optionally redraw the node. } node = GetVisualNode(edgeController.GetCurrentlySelectedNodeId()); if (null != node) { node.Selected = false; node.Compose(); // reset highlighted node } node = GetVisualNode(compId); List <IVisualNode> modifiedNodes = null; edgeConnection = edgeController.AttemptConnectEdge(node, nodePart, slotIndex, out modifiedNodes); DeltaNodes deltaNodes = new DeltaNodes(); deltaNodes.AppendToModifiedNodes(modifiedNodes.Distinct().ToList()); //reset highlighted node foreach (IVisualNode visualNode in deltaNodes.ModifiedNodes) { ((VisualNode)visualNode).Selected = false; } // Start tracking variables being undefined in this process. { RuntimeStates runtimeStates = graphProperties.RuntimeStates; runtimeStates.BeginDefinitionMonitor(); undoRedoRecorder.BeginGroup(); undoRedoRecorder.RecordRuntimeStatesForUndo(runtimeStates); undoRedoRecorder.RecordNodeModificationForUndo(deltaNodes.ModifiedNodes); edgeController.CreateEdge(); modifiedNodes.Clear(); this.EstablishImplicitConnections(modifiedNodes); undoRedoRecorder.EndGroup(); Dictionary <uint, List <string> > undefinedVariables = null; runtimeStates.EndDefinitionMonitor(out undefinedVariables); deltaNodes.AppendUndefinedVariables(undefinedVariables); } deltaNodes.AppendToModifiedNodes(modifiedNodes); if (deltaNodes.ModifiedNodes.Count > 0) //modification have been done { SynchronizeToLiveRunner(deltaNodes); } else { undoRedoRecorder.PopRecordFromUndoStorage(); } edgeController.ResetParameters(); edgeController.ResetAllEdges(); currentDragState = DragState.None; edgeConnection = EdgeConnectionFlag.None; break; case DragState.RegionSelection: if (visualHost != null) { visualHost.EndDragSelection(); } break; } //currentDragState = DragState.None; selectionBox.UpdateSelectionBox(GetSelectedNodes()); return(true); }
internal bool Undo(DeltaNodes deltaNodes) { if (this.ActionCount != -1) throw new InvalidOperationException("EndGroup() function was not called"); //Check if undoStorage is empty if (this.undoStorage.GetPosition() <= 0) return false; //Retrieve number of UserActions in the group this.undoStorage.Seek(-12, SeekOrigin.Current); int numOfActions = this.undoStorage.ReadInteger(FieldCode.ActionCount); this.undoStorage.Seek(-12, SeekOrigin.Current); //Loop according to the number of UserAction for (int i = 1; i <= numOfActions; i++) { //Retrieve the start point of the data and UserAction type this.undoStorage.Seek(-28, SeekOrigin.Current); long shift = this.undoStorage.ReadLong(FieldCode.Shift); UserAction userAction = (UserAction)this.undoStorage.ReadInteger(FieldCode.UserAction); this.undoStorage.Seek(-(shift + 28), SeekOrigin.Current); //Undo previous task accordingly switch (userAction) { case UserAction.RuntimeStates: //1. Retrieve the current runtimeStates and store the current runtimeStates in the redoStorage //2. Update the runtimeStates through deserialization from the undoStorage this.RecordRuntimeStates(this.redoStorage, this.graphController.GetRuntimeStates(), UserAction.RuntimeStates); this.UpdateRuntimeStates(this.undoStorage, this.graphController.GetRuntimeStates()); break; case UserAction.EdgeCreation: //1. Retrieve edgeId from undoStorage and find the corresponding edge from the dictionary //2. Store the corresponding edge in the redoStorage //3. Delete corresponding edge in dictionary List<IVisualEdge> edgeListForCreation = this.RetrieveEdgesFromIdsInStorage(this.undoStorage); this.RecordEdges(this.redoStorage, edgeListForCreation, UserAction.EdgeCreation); this.DeleteEdges(edgeListForCreation); break; case UserAction.EdgeDeletion: //1. Retrieve the edge from undoStorage //2. Store the corresponding edgeId in the redoStorage //3. Add the corresponding edge to the dictionary List<IVisualEdge> edgeListForDeletion = this.RetrieveEdgesFromStorage(this.undoStorage); this.RecordEdgeIds(this.redoStorage, edgeListForDeletion, UserAction.EdgeDeletion); this.AddEdges(edgeListForDeletion); break; case UserAction.EdgeModification: //1. Retrieve the edgeId from undoStorage without creating the entire edge //2. Retrieve the corresponding edge in the dictionary //3. Store the corresponding edge in the redoStorage //4. Reset cursor position in stream to start of first header, ie. -shift value //5. Update the corresponding edge in the dictionary through deserialization from // from the undoStorage List<uint> edgeIdList = this.RetrieveEdgeIdsFromStorage(this.undoStorage); List<IVisualEdge> edgeList = this.RetrieveEdgesFromDictionary(edgeIdList); this.RecordEdges(this.redoStorage, edgeList, UserAction.EdgeModification); this.undoStorage.Seek(-shift, SeekOrigin.Current); this.UpdateEdges(this.undoStorage, edgeList); break; case UserAction.NodeCreation: //1. Retrieve nodeId from undoStorage and find the corresponding node from the dictionary //2. Store the corresponding node and slot in the redoStorage //3. Delete corresponding node and slot in dictionary //4. Record the deleted node for LifeRunner List<IVisualNode> nodeListForCreation = this.RetrieveNodesFromIdsInStorage(this.undoStorage); this.RecordNodesAndSlots(this.redoStorage, nodeListForCreation, UserAction.NodeCreation); this.DeleteNodesAndSlots(nodeListForCreation); deltaNodes.AppendToRemovedNodes(nodeListForCreation); break; case UserAction.NodeDeletion: //1. Retrieve the slot from undoStorage //2. Retrieve the node from undoStorage //3. Store the corresponding nodeId in the redoStorage //4. Add the corresponding node and slot to the dictionary //5. Record the added node for LifeRunner List<ISlot> slotListForDeletion = this.RetrieveSlotsFromStorage(this.undoStorage); List<IVisualNode> nodeListForDeletion = this.RetrieveNodesFromStorage(this.undoStorage); this.RecordNodeIds(this.redoStorage, nodeListForDeletion, UserAction.NodeDeletion); this.AddNodesAndSlots(nodeListForDeletion, slotListForDeletion); deltaNodes.AppendToAddedNodes(nodeListForDeletion); break; case UserAction.NodeModification: //1. Retrieve the slotId from undoStorage without creating the entire slot //2. Retrieve the nodeId from undoStorage without creating the entire node //3. Retrieve the corresponding node in the dictionary //4. Store the corresponding node and slot in the redoStorage //5. Resolve, if any, the extra number of slot after undo //6. Reset cursor position in stream to start of first header, ie, -shift value //7. Update the corresponding node and slot in the dictionary through deserialization // from the undoStorage and resolve, if any, the missing slot after undo //8. Record the modified node for LifeRunner List<uint> slotIdList = this.RetrieveSlotIdsFromStorage(this.undoStorage); List<uint> nodeIdList = this.RetrieveNodeIdsFromStorage(this.undoStorage); List<IVisualNode> nodeList = this.RetrieveNodesFromDictionary(nodeIdList); this.RecordNodesAndSlots(this.redoStorage, nodeList, UserAction.NodeModification); this.ResolveExtraNumberOfSlotsAfterAction(nodeList, slotIdList); this.undoStorage.Seek(-shift, SeekOrigin.Current); this.UpdateNodesAndSlostWithResolveMissingSlotAfterAction(this.undoStorage, nodeList, slotIdList); deltaNodes.AppendToModifiedNodes(nodeList); break; default: throw new InvalidOperationException("Unknown UserAction"); } //Set cursor for next undo this.undoStorage.Seek(-shift, SeekOrigin.Current); } //Upon Success this.redoStorage.WriteInteger(FieldCode.ActionCount, numOfActions); return true; }