예제 #1
0
        public void AddUndoItem(IUndoItem undoEvent)
        {
            if (Working)
            {
                return;
            }

            bool emptyBefore = (_batch?.Count ?? 0) == 0 && !_undoEvents.Any();

            if (_batch != null)
            {
                _batch.Add(undoEvent);
            }
            else
            {
                ClearRedoHistory();
                _undoEvents.Push(undoEvent);
                if (_undoEvents.Count > MAX_UNDO_ITEMS)
                {
                    // XXX: we throw away the current item? this should be a Dequeue so we can pop the front
                    _undoEvents.Pop();
                }
            }

            if (emptyBefore)
            {
                // no longer empty
                NonEmpty?.Invoke(this, EventArgs.Empty);
            }
        }
예제 #2
0
 private IEnumerable <IUndoItem> PopUntil(FixedStack <IUndoItem> stack, IUndoItem sentinel)
 {
     while (stack.HasItems && stack.Peek() != sentinel)
     {
         yield return(stack.Pop());
     }
 }
예제 #3
0
 public void ExternalTypeChanged(IUndoItem item)
 {
     if (recording && !paused && !undoing)
     {
         undoItems.Add(item);
     }
 }
예제 #4
0
        public void Commit(int transactionID)
        {
            if (paused)
            {
                throw new Exception("Transaction handling is currently paused, can't commit!");
            }
#if LOG_TRANSACTION_HANDLING
            writer.WriteLine(new String(' ', transactionLevel) + "Commit to " + transactionID);
            writer.Flush();
            --transactionLevel;
#endif
#if CHECK_RINGLISTS
            procEnv.graph.CheckTypeRinglistsBroken();
#endif
            if (procEnv.Recorder != null)
            {
                procEnv.Recorder.TransactionCommit(transactionID);
            }

            // removes rollback information only if the transaction is outermost
            // otherwise we might need to undo it because a transaction enclosing this transaction failed
            if (transactionID == 0)
            {
                if (wasVisitedFreeRecorded && undoItems.Count > 0)
                {
                    if (wasGraphChanged)
                    {
                        undoing = true;
                        procEnv.SwitchToSubgraph(procEnv.Graph);
                    }

                    for (int i = undoItems.Count - 1; i >= 0; --i)
                    {
                        IUndoItem curItem = undoItems[i];
                        if (curItem is LGSPUndoVisitedFree)
                        {
                            procEnv.graph.UnreserveVisitedFlag(((LGSPUndoVisitedFree)curItem)._visitorID);
                        }
                        else if (curItem is LGSPUndoGraphChange)
                        {
                            curItem.DoUndo(procEnv);
                        }
                    }

                    if (wasGraphChanged)
                    {
                        procEnv.ReturnFromSubgraph();
                        undoing = false;
                    }
                }

                undoItems.Clear();
                UnsubscribeEvents();
                wasVisitedFreeRecorded = false;
                wasGraphChanged        = false;
            }
        }
예제 #5
0
 /// <summary>
 /// Rollback the last undone command.
 /// </summary>
 public void Redo()
 {
     if (CanRedo)
     {
         _working = true;
         IUndoItem redo = _redoEvents.Pop();
         redo.Do();
         _undoEvents.Push(redo);
         _working = false;
     }
 }
예제 #6
0
 /// <summary>
 /// Rollback the last command.
 /// </summary>
 public void Undo()
 {
     if (CanUndo)
     {
         _working = true;
         IUndoItem undo = _undoEvents.Pop();
         undo.Undo();
         _redoEvents.Push(undo);
         _working = false;
     }
 }
예제 #7
0
        public static void Record( IUndoItem item )
        {
            Node node = new Node( item ) {Previous = currentNode};
            if ( currentNode != null )
            {
                currentNode.Next = node;
            }

            currentNode = node;
            if ( firstNode != null )
                firstNode = node;
        }
예제 #8
0
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < undoItems.Count; ++i)
            {
                IUndoItem item = undoItems[i];
                sb.Append(item.ToString());
                sb.Append(" @");
                sb.Append(i.ToString());
                sb.Append("\n");
            }
            return(sb.ToString());
        }
예제 #9
0
        public static void Record(IUndoItem item)
        {
            Node node = new Node(item)
            {
                Previous = currentNode
            };

            if (currentNode != null)
            {
                currentNode.Next = node;
            }

            currentNode = node;
            if (firstNode != null)
            {
                firstNode = node;
            }
        }
예제 #10
0
 public void AddUndoItem(IUndoItem undoEvent)
 {
     if (!_working)
     {
         if (_batch != null)
         {
             _batch.Add(undoEvent);
         }
         else
         {
             ClearRedoHistory();
             _undoEvents.Push(undoEvent);
             if (_undoEvents.Count > MAX_UNDO_ITEMS)
             {
                 _undoEvents.Pop();
             }
         }
     }
 }
예제 #11
0
        /// <summary>
        /// Rollback the last command.
        /// </summary>
        public void Undo()
        {
            if (!CanUndo)
            {
                return;
            }

            Working = true;
            IUndoItem undo     = _undoEvents.Pop();
            bool      nowEmpty = !_undoEvents.Any();

            undo.Undo();
            _redoEvents.Push(undo);
            Working = false;

            if (nowEmpty)
            {
                Empty?.Invoke(this, EventArgs.Empty);
            }
        }
예제 #12
0
        /// <summary>
        /// Rollback the last undone command.
        /// </summary>
        public void Redo()
        {
            if (!CanRedo)
            {
                return;
            }

            Working = true;
            IUndoItem redo = _redoEvents.Pop();

            redo.Do();
            bool emptyBefore = !_undoEvents.Any();

            _undoEvents.Push(redo);
            Working = false;
            if (emptyBefore)
            {
                NonEmpty?.Invoke(this, EventArgs.Empty);
            }
        }
예제 #13
0
 public Node( IUndoItem item )
 {
     this.UndoItem = item;
 }
예제 #14
0
 public void ExternalTypeChanged(IUndoItem item)
 {
     if(recording && !paused && !undoing)
     {
         undoItems.Add(item);
     }
 }
예제 #15
0
 public void Save(IUndoItem item)
 {
     undo.Push(item);
     redo.Clear();
 }
예제 #16
0
 public Node(IUndoItem item)
 {
     this.UndoItem = item;
 }
예제 #17
0
        public void Rollback(int transactionID)
        {
            if (paused)
            {
                throw new Exception("Transaction handling is currently paused, can't roll back!");
            }
#if LOG_TRANSACTION_HANDLING
            writer.WriteLine(new String(' ', transactionLevel) + "Rollback to " + transactionID);
            writer.Flush();
#endif
            if (procEnv.Recorder != null)
            {
                procEnv.Recorder.TransactionRollback(transactionID, true);
            }

            undoing = true;
            if (wasGraphChanged)
            {
                procEnv.SwitchToSubgraph(procEnv.Graph);
            }

            while (undoItems.Count > transactionID)
            {
                IUndoItem lastItem = undoItems[undoItems.Count - 1];
#if LOG_TRANSACTION_HANDLING
                writer.Write(new String(' ', transactionLevel) + "rolling back " + undoItems.Count + " - ");
                if (lastItem is LGSPUndoTransactionStarted)
                {
                    writer.WriteLine("TransactionStarted");
                }
                else if (lastItem is LGSPUndoElemAdded)
                {
                    LGSPUndoElemAdded item = (LGSPUndoElemAdded)lastItem;
                    if (item._elem is INode)
                    {
                        INode node = (INode)item._elem;
                        writer.WriteLine("ElementAdded: " + ((LGSPNamedGraph)procEnv.graph).GetElementName(node) + ":" + node.Type.Name);
                    }
                    else if (item._elem is IEdge)
                    {
                        IEdge edge = (IEdge)item._elem;
                        writer.WriteLine("ElementAdded: " + ((LGSPNamedGraph)procEnv.graph).GetElementName(edge.Source) + " -" + ((LGSPNamedGraph)procEnv.graph).GetElementName(edge) + ":" + edge.Type.Name + " ->" + ((LGSPNamedGraph)procEnv.graph).GetElementName(edge.Target));
                    }
                    else
                    {
                        IObject obj = (IObject)item._elem;
                        writer.WriteLine("ElementAdded: hash" + obj.GetHashCode() + ":" + obj.Type.Name);
                    }
                }
                else if (lastItem is LGSPUndoElemRemoved)
                {
                    LGSPUndoElemRemoved item = (LGSPUndoElemRemoved)lastItem;
                    if (item._elem is INode)
                    {
                        INode node = (INode)item._elem;
                        writer.WriteLine("RemovingElement: " + ((LGSPNamedGraph)procEnv.graph).GetElementName(node) + ":" + node.Type.Name);
                    }
                    else if (item._elem is IEdge)
                    {
                        IEdge edge = (IEdge)item._elem;
                        writer.WriteLine("RemovingElement: " + ((LGSPNamedGraph)procEnv.graph).GetElementName(edge.Source) + " -" + ((LGSPNamedGraph)procEnv.graph).GetElementName(edge) + ":" + edge.Type.Name + "-> " + ((LGSPNamedGraph)procEnv.graph).GetElementName(edge.Target));
                    }
                    else
                    {
                        IObject obj = (IObject)item._elem;
                        writer.WriteLine("RemovingElement: hash" + obj.GetHashCode() + ":" + obj.Type.Name);
                    }
                }
                else if (lastItem is LGSPUndoAttributeChanged)
                {
                    LGSPUndoAttributeChanged item = (LGSPUndoAttributeChanged)lastItem;
                    if (item._elem is IGraphElement)
                    {
                        writer.WriteLine("ChangingElementAttribute: " + ((LGSPNamedGraph)procEnv.graph).GetElementName((IGraphElement)item._elem) + ":" + item._elem.Type.Name + "." + item._attrType.Name);
                    }
                    else
                    {
                        writer.WriteLine("ChangingElementAttribute: hash" + ((IObject)item._elem).GetHashCode() + ":" + item._elem.Type.Name + "." + item._attrType.Name);
                    }
                }
                else if (lastItem is LGSPUndoElemRetyped)
                {
                    LGSPUndoElemRetyped item = (LGSPUndoElemRetyped)lastItem;
                    writer.WriteLine("RetypingElement: " + ((LGSPNamedGraph)procEnv.graph).GetElementName(item._newElem) + ":" + item._newElem.Type.Name + "<" + ((LGSPNamedGraph)procEnv.graph).GetElementName(item._oldElem) + ":" + item._oldElem.Type.Name + ">");
                }
                else if (lastItem is LGSPUndoElemRedirecting)
                {
                    LGSPUndoElemRedirecting item = (LGSPUndoElemRedirecting)lastItem;
                    writer.WriteLine("RedirectingEdge: " + ((LGSPNamedGraph)procEnv.graph).GetElementName(item._edge) + " before undoing removal");
                }
                else if (lastItem is LGSPUndoVisitedAlloc)
                {
                    LGSPUndoVisitedAlloc item = (LGSPUndoVisitedAlloc)lastItem;
                    writer.WriteLine("VisitedAlloc: " + item._visitorID);
                }
                else if (lastItem is LGSPUndoVisitedFree)
                {
                    LGSPUndoVisitedFree item = (LGSPUndoVisitedFree)lastItem;
                    writer.WriteLine("VisitedFree: " + item._visitorID);
                }
                else if (lastItem is LGSPUndoSettingVisited)
                {
                    LGSPUndoSettingVisited item = (LGSPUndoSettingVisited)lastItem;
                    writer.WriteLine("SettingVisited: " + ((LGSPNamedGraph)procEnv.graph).GetElementName(item._elem) + ".visited[" + item._visitorID + "]");
                }
                else if (lastItem is LGSPUndoGraphChange)
                {
                    LGSPUndoGraphChange item = (LGSPUndoGraphChange)lastItem;
                    writer.WriteLine("GraphChange: to previous " + item._oldGraph.Name);
                }
#endif
                if (wasGraphChanged)
                {
                    if (lastItem is LGSPUndoGraphChange)
                    {
                        if (undoItems.Count - 2 >= 0 && undoItems[undoItems.Count - 2] is LGSPUndoGraphChange)
                        {
                            undoItems.RemoveAt(undoItems.Count - 1);
                            continue; // skip graph change without effect to preceeding graph change
                        }
                    }
                }

                lastItem.DoUndo(procEnv);
                undoItems.RemoveAt(undoItems.Count - 1);
            }

            if (wasGraphChanged)
            {
                procEnv.ReturnFromSubgraph();
            }
            undoing = false;

            if (transactionID == 0)
            {
                UnsubscribeEvents();
                wasVisitedFreeRecorded = false;
                wasGraphChanged        = false;
            }

            if (procEnv.Recorder != null)
            {
                procEnv.Recorder.TransactionRollback(transactionID, false);
            }

#if LOG_TRANSACTION_HANDLING
            --transactionLevel;
            writer.Flush();
#endif
#if CHECK_RINGLISTS
            procEnv.graph.CheckTypeRinglistsBroken();
#endif
        }
예제 #18
0
 public void AddUndoItem(IUndoItem undoEvent)
 {
     if (!_working)
     {
         if (_batch != null)
         {
             _batch.Add(undoEvent);
         }
         else
         {
             ClearRedoHistory();
             _undoEvents.Push(undoEvent);
             if (_undoEvents.Count > MAX_UNDO_ITEMS)
             {
                 _undoEvents.Pop();
             }
         }
     }
 }