Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / Tools / System.Activities.Presentation / System / Activities / Presentation / UndoEngine.cs / 1305376 / UndoEngine.cs
//---------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //--------------------------------------------------------------- namespace System.Activities.Presentation { using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Runtime; [Fx.Tag.XamlVisible(false)] public class UndoEngine : IUndoEngineOperations { const int capacity = 100; ListundoBuffer; List redoBuffer; EditingContext context; Bookmark bookmark; //interface which contains actual implementation of AddUndoUnit, Undo and Redo operations IUndoEngineOperations undoEngineImpl = null; public event EventHandler UndoUnitAdded; public event EventHandler UndoUnitDiscarded; internal event EventHandler ExecuteUndo; public event EventHandler UndoRedoBufferChanged; public UndoEngine(EditingContext context) { this.context = context; undoBuffer = new List (capacity); redoBuffer = new List (capacity); this.undoEngineImpl = this; } //CreateBookmark - creates a new UndoUnit which gatters all edits in its //undo unit list. all changes in bookmark appear as a one change and can be //undoned or redoned as a one set. internal Bookmark CreateBookmark(string bookmarkName) { //only one bookmark is supported if (null == this.bookmark) { //create bookmark undo unit, and give it a description BookmarkUndoUnit unit = new BookmarkUndoUnit(this.context) { Description = bookmarkName ?? string.Format(CultureInfo.InvariantCulture, "Bookmark {0}", Guid.NewGuid()), }; //create bookmark, and pass bookmark undo unit to it. this.bookmark = new Bookmark(this, unit); //switch implementation of AddUndoUnit, Undo, Redo to be delegated through bookmark this.undoEngineImpl = bookmark; return this.bookmark; } throw FxTrace.Exception.AsError(new NotSupportedException(SR.UndoEngine_NestedBookmarksException)); } public IEnumerable GetUndoActions() { return this.undoBuffer.Select(p => p.Description); } public IEnumerable GetRedoActions() { return this.redoBuffer.Select(p => p.Description); } void NotifyChange() { if (null != this.UndoRedoBufferChanged) { this.UndoRedoBufferChanged(this, EventArgs.Empty); } } public void AddUndoUnit(UndoUnit unit) { if (unit == null) { throw FxTrace.Exception.ArgumentNull("unit"); } this.undoEngineImpl.AddUndoUnitCore(unit); this.NotifyChange(); } public bool Undo() { this.IsUndoRedoInProgress = true; bool succeeded = this.undoEngineImpl.UndoCore(); this.IsUndoRedoInProgress = false; if (succeeded) { this.NotifyChange(); } return succeeded; } public bool Redo() { this.IsUndoRedoInProgress = true; bool succeeded = this.undoEngineImpl.RedoCore(); this.IsUndoRedoInProgress = false; if (succeeded) { this.NotifyChange(); } return succeeded; } public bool IsUndoRedoInProgress { get; private set; } void IUndoEngineOperations.AddUndoUnitCore(UndoUnit unit) { undoBuffer.Add(unit); RaiseUndoUnitAdded(unit); if (undoBuffer.Count > capacity) { undoBuffer.RemoveAt(0); RaiseUndoUnitDiscarded(); } redoBuffer.Clear(); } bool IUndoEngineOperations.UndoCore() { bool succeeded = false; if (undoBuffer.Count > 0) { UndoUnit unitToUndo = undoBuffer.Last(); undoBuffer.RemoveAt(undoBuffer.Count - 1); unitToUndo.Undo(); redoBuffer.Add(unitToUndo); RaiseExecuteUndo(unitToUndo); succeeded = true; } return succeeded; } bool IUndoEngineOperations.RedoCore() { bool succeeded = false; if (redoBuffer.Count > 0) { UndoUnit unitToRedo = redoBuffer.Last(); redoBuffer.RemoveAt(redoBuffer.Count - 1); unitToRedo.Redo(); undoBuffer.Add(unitToRedo); succeeded = true; } return succeeded; } void RaiseUndoUnitAdded(UndoUnit unit) { if (this.UndoUnitAdded != null) { this.UndoUnitAdded(this, new UndoUnitEventArgs() { UndoUnit = unit }); } } void RaiseUndoUnitDiscarded() { if (this.UndoUnitDiscarded != null) { this.UndoUnitDiscarded(this, null); } } void RaiseExecuteUndo(UndoUnit unitToUndo) { if (this.ExecuteUndo != null) { this.ExecuteUndo(this, new UndoUnitEventArgs() { UndoUnit = unitToUndo }); } } //Bookmark implmeentation - implements core UndoEngine operations + IDisposable - //default bookmark behaviour is to Rollback changes, unless commited explicitly. //usage of IDisposable enables usage of pattern: // using (Bookmark b = new Bookmark()).... internal sealed class Bookmark : IDisposable, IUndoEngineOperations { BookmarkUndoUnit containerUndoUnit; UndoEngine undoEngine; bool isCommited = false; bool isRolledBack = false; bool isDisposed = false; internal Bookmark(UndoEngine undoEngine, BookmarkUndoUnit undoUnit) { this.undoEngine = undoEngine; this.containerUndoUnit = undoUnit; } public void CommitBookmark() { //cannot commit more than once... if (this.isDisposed) { throw FxTrace.Exception.AsError(new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.UndoEngine_OperationNotAllowed, "CommitBookmark"))); } this.isCommited = true; //restore original undo engine implementation this.undoEngine.undoEngineImpl = this.undoEngine; //get rid of the bookmark this.undoEngine.bookmark = null; //check if bookmark has any changes if (this.containerUndoUnit.DoList.Count != 0 || this.containerUndoUnit.RedoList.Count != 0) { //add all changes in bookmark into a undo list as a one element this.undoEngine.AddUndoUnit(this.containerUndoUnit); } //dispose bookmark this.Dispose(); } public void RollbackBookmark() { //cannot rollback more than once if (this.isDisposed) { throw FxTrace.Exception.AsError(new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.UndoEngine_OperationNotAllowed, "RollbackBookmark"))); } this.isRolledBack = true; //get through the list of all accumulated changes and reverse each of them foreach (UndoUnit unit in this.containerUndoUnit.DoList.Reverse ()) { unit.Undo(); } //clear the lists this.containerUndoUnit.DoList.Clear(); this.containerUndoUnit.RedoList.Clear(); //restore original undo engine implementation this.undoEngine.undoEngineImpl = this.undoEngine; //get rid of the bookmark this.undoEngine.bookmark = null; //dispose bookmark this.Dispose(); } public void Dispose() { if (!this.isDisposed) { GC.SuppressFinalize(this); DisposeInternal(); } } void DisposeInternal() { if (!this.isDisposed) { //if not commited or rolled back - rollback by default if (!this.isCommited && !this.isRolledBack) { this.RollbackBookmark(); } this.isDisposed = true; } } void IUndoEngineOperations.AddUndoUnitCore(UndoUnit unit) { //add element to Undo list this.containerUndoUnit.DoList.Add(unit); //clear redo list this.containerUndoUnit.RedoList.Clear(); } bool IUndoEngineOperations.UndoCore() { //if there is anything to undo bool succeeded = false; if (this.containerUndoUnit.DoList.Count > 0) { //get the last element done UndoUnit unitToUndo = this.containerUndoUnit.DoList.Last(); //remove it this.containerUndoUnit.DoList.RemoveAt(this.containerUndoUnit.DoList.Count - 1); //undo it unitToUndo.Undo(); //and insert to the head of redo list this.containerUndoUnit.RedoList.Insert(0, unitToUndo); succeeded = true; } return succeeded; } bool IUndoEngineOperations.RedoCore() { //if there is anything to redo bool succeeded = false; if (this.containerUndoUnit.RedoList.Count > 0) { //get first element to redo UndoUnit unitToRedo = this.containerUndoUnit.RedoList.First(); //remove it this.containerUndoUnit.RedoList.RemoveAt(0); //redo it unitToRedo.Redo(); //add it to the end of undo list this.containerUndoUnit.DoList.Add(unitToRedo); succeeded = true; } return succeeded; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //--------------------------------------------------------------- namespace System.Activities.Presentation { using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Runtime; [Fx.Tag.XamlVisible(false)] public class UndoEngine : IUndoEngineOperations { const int capacity = 100; List undoBuffer; List redoBuffer; EditingContext context; Bookmark bookmark; //interface which contains actual implementation of AddUndoUnit, Undo and Redo operations IUndoEngineOperations undoEngineImpl = null; public event EventHandler UndoUnitAdded; public event EventHandler UndoUnitDiscarded; internal event EventHandler ExecuteUndo; public event EventHandler UndoRedoBufferChanged; public UndoEngine(EditingContext context) { this.context = context; undoBuffer = new List (capacity); redoBuffer = new List (capacity); this.undoEngineImpl = this; } //CreateBookmark - creates a new UndoUnit which gatters all edits in its //undo unit list. all changes in bookmark appear as a one change and can be //undoned or redoned as a one set. internal Bookmark CreateBookmark(string bookmarkName) { //only one bookmark is supported if (null == this.bookmark) { //create bookmark undo unit, and give it a description BookmarkUndoUnit unit = new BookmarkUndoUnit(this.context) { Description = bookmarkName ?? string.Format(CultureInfo.InvariantCulture, "Bookmark {0}", Guid.NewGuid()), }; //create bookmark, and pass bookmark undo unit to it. this.bookmark = new Bookmark(this, unit); //switch implementation of AddUndoUnit, Undo, Redo to be delegated through bookmark this.undoEngineImpl = bookmark; return this.bookmark; } throw FxTrace.Exception.AsError(new NotSupportedException(SR.UndoEngine_NestedBookmarksException)); } public IEnumerable GetUndoActions() { return this.undoBuffer.Select(p => p.Description); } public IEnumerable GetRedoActions() { return this.redoBuffer.Select(p => p.Description); } void NotifyChange() { if (null != this.UndoRedoBufferChanged) { this.UndoRedoBufferChanged(this, EventArgs.Empty); } } public void AddUndoUnit(UndoUnit unit) { if (unit == null) { throw FxTrace.Exception.ArgumentNull("unit"); } this.undoEngineImpl.AddUndoUnitCore(unit); this.NotifyChange(); } public bool Undo() { this.IsUndoRedoInProgress = true; bool succeeded = this.undoEngineImpl.UndoCore(); this.IsUndoRedoInProgress = false; if (succeeded) { this.NotifyChange(); } return succeeded; } public bool Redo() { this.IsUndoRedoInProgress = true; bool succeeded = this.undoEngineImpl.RedoCore(); this.IsUndoRedoInProgress = false; if (succeeded) { this.NotifyChange(); } return succeeded; } public bool IsUndoRedoInProgress { get; private set; } void IUndoEngineOperations.AddUndoUnitCore(UndoUnit unit) { undoBuffer.Add(unit); RaiseUndoUnitAdded(unit); if (undoBuffer.Count > capacity) { undoBuffer.RemoveAt(0); RaiseUndoUnitDiscarded(); } redoBuffer.Clear(); } bool IUndoEngineOperations.UndoCore() { bool succeeded = false; if (undoBuffer.Count > 0) { UndoUnit unitToUndo = undoBuffer.Last(); undoBuffer.RemoveAt(undoBuffer.Count - 1); unitToUndo.Undo(); redoBuffer.Add(unitToUndo); RaiseExecuteUndo(unitToUndo); succeeded = true; } return succeeded; } bool IUndoEngineOperations.RedoCore() { bool succeeded = false; if (redoBuffer.Count > 0) { UndoUnit unitToRedo = redoBuffer.Last(); redoBuffer.RemoveAt(redoBuffer.Count - 1); unitToRedo.Redo(); undoBuffer.Add(unitToRedo); succeeded = true; } return succeeded; } void RaiseUndoUnitAdded(UndoUnit unit) { if (this.UndoUnitAdded != null) { this.UndoUnitAdded(this, new UndoUnitEventArgs() { UndoUnit = unit }); } } void RaiseUndoUnitDiscarded() { if (this.UndoUnitDiscarded != null) { this.UndoUnitDiscarded(this, null); } } void RaiseExecuteUndo(UndoUnit unitToUndo) { if (this.ExecuteUndo != null) { this.ExecuteUndo(this, new UndoUnitEventArgs() { UndoUnit = unitToUndo }); } } //Bookmark implmeentation - implements core UndoEngine operations + IDisposable - //default bookmark behaviour is to Rollback changes, unless commited explicitly. //usage of IDisposable enables usage of pattern: // using (Bookmark b = new Bookmark()).... internal sealed class Bookmark : IDisposable, IUndoEngineOperations { BookmarkUndoUnit containerUndoUnit; UndoEngine undoEngine; bool isCommited = false; bool isRolledBack = false; bool isDisposed = false; internal Bookmark(UndoEngine undoEngine, BookmarkUndoUnit undoUnit) { this.undoEngine = undoEngine; this.containerUndoUnit = undoUnit; } public void CommitBookmark() { //cannot commit more than once... if (this.isDisposed) { throw FxTrace.Exception.AsError(new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.UndoEngine_OperationNotAllowed, "CommitBookmark"))); } this.isCommited = true; //restore original undo engine implementation this.undoEngine.undoEngineImpl = this.undoEngine; //get rid of the bookmark this.undoEngine.bookmark = null; //check if bookmark has any changes if (this.containerUndoUnit.DoList.Count != 0 || this.containerUndoUnit.RedoList.Count != 0) { //add all changes in bookmark into a undo list as a one element this.undoEngine.AddUndoUnit(this.containerUndoUnit); } //dispose bookmark this.Dispose(); } public void RollbackBookmark() { //cannot rollback more than once if (this.isDisposed) { throw FxTrace.Exception.AsError(new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.UndoEngine_OperationNotAllowed, "RollbackBookmark"))); } this.isRolledBack = true; //get through the list of all accumulated changes and reverse each of them foreach (UndoUnit unit in this.containerUndoUnit.DoList.Reverse ()) { unit.Undo(); } //clear the lists this.containerUndoUnit.DoList.Clear(); this.containerUndoUnit.RedoList.Clear(); //restore original undo engine implementation this.undoEngine.undoEngineImpl = this.undoEngine; //get rid of the bookmark this.undoEngine.bookmark = null; //dispose bookmark this.Dispose(); } public void Dispose() { if (!this.isDisposed) { GC.SuppressFinalize(this); DisposeInternal(); } } void DisposeInternal() { if (!this.isDisposed) { //if not commited or rolled back - rollback by default if (!this.isCommited && !this.isRolledBack) { this.RollbackBookmark(); } this.isDisposed = true; } } void IUndoEngineOperations.AddUndoUnitCore(UndoUnit unit) { //add element to Undo list this.containerUndoUnit.DoList.Add(unit); //clear redo list this.containerUndoUnit.RedoList.Clear(); } bool IUndoEngineOperations.UndoCore() { //if there is anything to undo bool succeeded = false; if (this.containerUndoUnit.DoList.Count > 0) { //get the last element done UndoUnit unitToUndo = this.containerUndoUnit.DoList.Last(); //remove it this.containerUndoUnit.DoList.RemoveAt(this.containerUndoUnit.DoList.Count - 1); //undo it unitToUndo.Undo(); //and insert to the head of redo list this.containerUndoUnit.RedoList.Insert(0, unitToUndo); succeeded = true; } return succeeded; } bool IUndoEngineOperations.RedoCore() { //if there is anything to redo bool succeeded = false; if (this.containerUndoUnit.RedoList.Count > 0) { //get first element to redo UndoUnit unitToRedo = this.containerUndoUnit.RedoList.First(); //remove it this.containerUndoUnit.RedoList.RemoveAt(0); //redo it unitToRedo.Redo(); //add it to the end of undo list this.containerUndoUnit.DoList.Add(unitToRedo); succeeded = true; } return succeeded; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- BuilderPropertyEntry.cs
- SendReply.cs
- Menu.cs
- HotCommands.cs
- FrameworkPropertyMetadata.cs
- PathParser.cs
- DefaultHttpHandler.cs
- ScrollBar.cs
- UpdateException.cs
- TextBlock.cs
- KeyboardDevice.cs
- WorkBatch.cs
- SqlConnectionHelper.cs
- TextServicesLoader.cs
- QilXmlReader.cs
- ClientBuildManager.cs
- XamlWriterExtensions.cs
- ListDataHelper.cs
- AudienceUriMode.cs
- CompiledQuery.cs
- ClientTargetCollection.cs
- ContainerActivationHelper.cs
- PerformanceCounterScope.cs
- Attributes.cs
- MethodBuilder.cs
- IteratorFilter.cs
- SystemResourceHost.cs
- OrderPreservingPipeliningSpoolingTask.cs
- PbrsForward.cs
- ProfileInfo.cs
- TemplatedWizardStep.cs
- FastEncoderWindow.cs
- SafeTokenHandle.cs
- DrawingCollection.cs
- NamedPipeAppDomainProtocolHandler.cs
- Facet.cs
- TableRowCollection.cs
- MouseButtonEventArgs.cs
- AppDomain.cs
- ping.cs
- AnimationException.cs
- HMACSHA1.cs
- ElementHostPropertyMap.cs
- TransformerInfoCollection.cs
- HMACSHA256.cs
- DataGridColumnStyleMappingNameEditor.cs
- ParameterToken.cs
- RelationshipWrapper.cs
- LongValidator.cs
- DataContractSerializerOperationBehavior.cs
- Style.cs
- InstanceHandleConflictException.cs
- QueryCacheEntry.cs
- CellTreeSimplifier.cs
- TextTreeNode.cs
- IEnumerable.cs
- PasswordTextNavigator.cs
- SafeArrayTypeMismatchException.cs
- SelectorItemAutomationPeer.cs
- VariantWrapper.cs
- TriggerActionCollection.cs
- DynamicRenderer.cs
- TimeSpanConverter.cs
- Expression.cs
- SiteIdentityPermission.cs
- RightsManagementProvider.cs
- Italic.cs
- Rotation3D.cs
- MenuAdapter.cs
- MetadataCacheItem.cs
- Int32Converter.cs
- TraceHandler.cs
- KoreanCalendar.cs
- CustomErrorsSectionWrapper.cs
- SessionEndedEventArgs.cs
- WebBrowserNavigatedEventHandler.cs
- CacheMode.cs
- Validator.cs
- PageAdapter.cs
- HtmlShim.cs
- RangeValuePattern.cs
- HttpWrapper.cs
- DataRow.cs
- RectangleConverter.cs
- DES.cs
- RuntimeHelpers.cs
- FunctionCommandText.cs
- PrinterResolution.cs
- SoapTypeAttribute.cs
- HtmlForm.cs
- DrawingDrawingContext.cs
- ValidationError.cs
- DataServiceHost.cs
- ContentPlaceHolder.cs
- DockPattern.cs
- DiffuseMaterial.cs
- AuthorizationRuleCollection.cs
- Rect3DConverter.cs
- ReferencedType.cs
- AssemblyResourceLoader.cs