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
- IsolatedStorage.cs
- ParameterCollectionEditor.cs
- CollectionType.cs
- AmbientProperties.cs
- _ListenerResponseStream.cs
- HtmlFormWrapper.cs
- IItemContainerGenerator.cs
- DesignTimeParseData.cs
- SignatureDescription.cs
- SymbolMethod.cs
- DropShadowEffect.cs
- NullReferenceException.cs
- MessageEnumerator.cs
- PassportAuthenticationEventArgs.cs
- CachedFontFace.cs
- ToolStripProgressBar.cs
- BatchParser.cs
- Asn1IntegerConverter.cs
- XPathNavigatorReader.cs
- FileDialogCustomPlacesCollection.cs
- SqlCachedBuffer.cs
- DataGridViewComboBoxColumn.cs
- ToolStripContextMenu.cs
- TrackingConditionCollection.cs
- RtfNavigator.cs
- PeerResolverElement.cs
- SpeechRecognizer.cs
- Image.cs
- WindowsFormsDesignerOptionService.cs
- TraceProvider.cs
- WindowVisualStateTracker.cs
- XmlBaseWriter.cs
- Repeater.cs
- MobileControlDesigner.cs
- FormClosingEvent.cs
- XPathBinder.cs
- CodeMethodInvokeExpression.cs
- XmlArrayItemAttributes.cs
- ProxyFragment.cs
- MatcherBuilder.cs
- WebBrowserEvent.cs
- ObservableCollection.cs
- Pointer.cs
- TextParentUndoUnit.cs
- TimeSpanStorage.cs
- SiteOfOriginContainer.cs
- StatusBar.cs
- StringConverter.cs
- DictationGrammar.cs
- ServiceDescriptionReflector.cs
- PreviewPageInfo.cs
- ValueTypeFixupInfo.cs
- DataGridItemEventArgs.cs
- SimpleWorkerRequest.cs
- CodeMemberMethod.cs
- RoutedEventHandlerInfo.cs
- MenuItemBinding.cs
- LogLogRecordEnumerator.cs
- connectionpool.cs
- SQLInt32Storage.cs
- ZoneMembershipCondition.cs
- FixedSOMTableRow.cs
- ConfigXmlReader.cs
- _SslState.cs
- TableLayoutPanelCellPosition.cs
- RuleSettingsCollection.cs
- MeasureItemEvent.cs
- TokenDescriptor.cs
- ElementNotAvailableException.cs
- Lasso.cs
- UnionExpr.cs
- ServiceEndpointAssociationProvider.cs
- Parameter.cs
- DoubleStorage.cs
- EncoderParameter.cs
- SqlColumnizer.cs
- GridPattern.cs
- Crc32.cs
- ObjectStateEntryDbDataRecord.cs
- RuntimeWrappedException.cs
- iisPickupDirectory.cs
- Fault.cs
- BaseTemplateParser.cs
- RtfToken.cs
- Substitution.cs
- FontUnit.cs
- ScriptingAuthenticationServiceSection.cs
- MultipleFilterMatchesException.cs
- WorkflowViewElement.cs
- HatchBrush.cs
- UnionCqlBlock.cs
- X509SecurityTokenParameters.cs
- GregorianCalendarHelper.cs
- RenamedEventArgs.cs
- PartialArray.cs
- KeyConstraint.cs
- VirtualDirectoryMapping.cs
- BamlRecords.cs
- ConfigurationException.cs
- ViewGenResults.cs