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); } }
private IEnumerable <IUndoItem> PopUntil(FixedStack <IUndoItem> stack, IUndoItem sentinel) { while (stack.HasItems && stack.Peek() != sentinel) { yield return(stack.Pop()); } }
public void ExternalTypeChanged(IUndoItem item) { if (recording && !paused && !undoing) { undoItems.Add(item); } }
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; } }
/// <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; } }
/// <summary> /// Rollback the last command. /// </summary> public void Undo() { if (CanUndo) { _working = true; IUndoItem undo = _undoEvents.Pop(); undo.Undo(); _redoEvents.Push(undo); _working = false; } }
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; }
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()); }
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; } }
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(); } } } }
/// <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); } }
/// <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); } }
public Node( IUndoItem item ) { this.UndoItem = item; }
public void ExternalTypeChanged(IUndoItem item) { if(recording && !paused && !undoing) { undoItems.Add(item); } }
public void Save(IUndoItem item) { undo.Push(item); redo.Clear(); }
public Node(IUndoItem item) { this.UndoItem = item; }
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 }