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);
            });
        }
Exemple #5
0
        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);
        }
Exemple #13
0
        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;
        }