///<summary> /// Revert ByteBuffer to the last saved state ///</summary> public void Revert() { lock (LockObj) { if (!modifyAllowed) { return; } if (this.HasFile) { // reload file string filename = fileBuf.Filename; if (!File.Exists(filename)) { throw new FileNotFoundException(filename); } fileBuf.Close(); undoDeque.Clear(); redoDeque.Clear(); LoadWithFile(filename); SaveCheckpoint = null; changedBeyondUndo = false; // emit bytebuffer changed event EmitChanged(); } } }
///<summary> /// Add an action to the undo deque, taking into /// account maximum undo action restrictions ///</summary> void AddUndoAction(ByteBufferAction action) { if (maxUndoActions != -1) { while (undoDeque.Count >= maxUndoActions) { undoDeque.RemoveEnd(); changedBeyondUndo = true; } } undoDeque.AddFront(action); }
///<summary> /// Called when an asynchronous in-place save operation finishes ///</summary> void SaveInPlaceAsyncCallback(IAsyncResult ar) { lock (LockObj) { SaveInPlaceOperation sipo = (SaveInPlaceOperation)ar.AsyncState; if (sipo.Result == ThreadedAsyncOperation.OperationResult.Finished) // save went ok { LoadWithFile(sipo.SavePath); if (undoDeque.Count > 0) { SaveCheckpoint = undoDeque.PeekFront(); } else { SaveCheckpoint = null; } changedBeyondUndo = false; } else if (sipo.Result == ThreadedAsyncOperation.OperationResult.Cancelled) // save cancelled { } else if (sipo.Result == ThreadedAsyncOperation.OperationResult.CaughtException) { } // re-allow buffer usage this.ReadAllowed = true; this.ModifyAllowed = true; this.FileOperationsAllowed = true; this.EmitEvents = true; fsw.EnableRaisingEvents = true; // notify the world about the changes EmitPermissionsChanged(); EmitChanged(); // if user provided a callback, call it now if (userSaveAsyncCallback != null) { userSaveAsyncCallback(ar); } // notify that Save has finished saveFinishedEvent.Set(); } }
///<summary>Handle actions as a single one</summary> bool HandleChaining(ByteBufferAction action) { if (!actionChaining) { return(false); } // add the multiAction to the undo deque if (actionChainingFirst) { AddUndoAction(multiAction); actionChainingFirst = false; } multiAction.Add(action); return(true); }
///<summary>Redo the last undone action</summary> public void Redo() { lock (LockObj) { if (!modifyAllowed) { return; } // if there is an action to redo if (redoDeque.Count > 0) { ByteBufferAction action = redoDeque.RemoveFront(); action.Do(); AddUndoAction(action); EmitChanged(); } } }
public ByteBuffer() { segCol = new SegmentCollection(); undoDeque = new Deque <ByteBufferAction>(); redoDeque = new Deque <ByteBufferAction>(); size = 0; SaveCheckpoint = null; // name the buffer automatically autoFilename = Catalog.GetString("Untitled") + " " + ByteBuffer.autoNum; ByteBuffer.autoNum++; // set default permissions readAllowed = true; fileOperationsAllowed = true; modifyAllowed = true; saveFinishedEvent = new AutoResetEvent(false); useGLibIdle = false; emitEvents = true; maxUndoActions = -1; // unlimited undo tempDir = Path.GetTempPath(); }
///<summary> /// Called when an asynchronous save operation finishes ///</summary> void SaveAsyncCallback(IAsyncResult ar) { lock (LockObj) { SaveOperation so = (SaveOperation)ar.AsyncState; if (so.Result == SaveOperation.OperationResult.Finished) // save went ok // No need to call CloseFile() MakePrivateCopyOfUndoRedo() // because it has already been called in SaveOperation { LoadWithFile(so.SavePath); if (undoDeque.Count > 0) { SaveCheckpoint = undoDeque.PeekFront(); } else { SaveCheckpoint = null; } changedBeyondUndo = false; } else if (so.Result == SaveOperation.OperationResult.Cancelled) // save cancelled { if (so.StageReached == SaveOperation.SaveStage.BeforeSaveAs) { System.IO.File.Delete(so.TempPath); } else if (so.StageReached == SaveOperation.SaveStage.BeforeDelete) { System.IO.File.Delete(so.TempPath); fileBuf.Load(so.SavePath); } else if (so.StageReached == SaveOperation.SaveStage.BeforeMove) { // cancel has no effect during move. // mark operation as successful so.Result = SaveOperation.OperationResult.Finished; LoadWithFile(so.SavePath); if (undoDeque.Count > 0) { SaveCheckpoint = undoDeque.PeekFront(); } else { SaveCheckpoint = null; } } } else if (so.Result == SaveOperation.OperationResult.CaughtException) { if (so.StageReached == SaveOperation.SaveStage.BeforeSaveAs) { System.IO.File.Delete(so.TempPath); } else if (so.StageReached == SaveOperation.SaveStage.BeforeDelete) { System.IO.File.Delete(so.TempPath); fileBuf.Load(so.SavePath); // make sure FSW is valid (it is probably not // because bb.CloseFile has been called in SaveOperation) SetupFSW(); } else if (so.StageReached == SaveOperation.SaveStage.BeforeMove) { // TO-DO: better handling? fileBuf.Load(so.SavePath); } } // re-allow buffer usage this.ReadAllowed = true; this.ModifyAllowed = true; this.FileOperationsAllowed = true; this.EmitEvents = true; fsw.EnableRaisingEvents = true; // notify the world about the changes EmitPermissionsChanged(); EmitChanged(); // if user provided a callback, call it now if (userSaveAsyncCallback != null) { userSaveAsyncCallback(ar); } // notify that Save has finished saveFinishedEvent.Set(); } }
///<summary> /// Called when an asynchronous Save As operation finishes ///</summary> void SaveAsAsyncCallback(IAsyncResult ar) { lock (LockObj) { SaveAsOperation so = (SaveAsOperation)ar.AsyncState; // re-allow buffer usage this.FileOperationsAllowed = true; // make sure Save As went smoothly before doing anything if (so.Result == SaveAsOperation.OperationResult.Finished) { // make sure data in undo redo are stored safely // because we are going to close the file MakePrivateCopyOfUndoRedo(); CloseFile(); LoadWithFile(so.SavePath); if (undoDeque.Count > 0) { SaveCheckpoint = undoDeque.PeekFront(); } else { SaveCheckpoint = null; } changedBeyondUndo = false; } else { // if cancelled or caught an exception // delete the file only if we have altered it if (so.StageReached != SaveAsOperation.SaveAsStage.BeforeCreate) { try { System.IO.File.Delete(so.SavePath); } catch (Exception e) { System.Console.WriteLine(e.Message); } } } // re-allow buffer usage this.ReadAllowed = true; this.ModifyAllowed = true; this.EmitEvents = true; if (fsw != null) { fsw.EnableRaisingEvents = true; } // notify the world about the changes EmitPermissionsChanged(); EmitChanged(); // if user provided a callback, call it now if (userSaveAsyncCallback != null) { userSaveAsyncCallback(ar); } // notify that Save As has finished saveFinishedEvent.Set(); } }
public void Add(ByteBufferAction action) { list.Add(action); }