ParentUndoUnit.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / MS / Internal / documents / ParentUndoUnit.cs / 2 / ParentUndoUnit.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
// 
//      See spec at [....]/uis/Stock%20Services/Undo%20spec.htm
// 
// History:
//  07/21/2003 : [....]   ported to WCP tree
//  03/21/2004 : [....] - code style cleaned
// 
//---------------------------------------------------------------------------
 
using System; 
using System.Windows;
using System.Collections; 
using MS.Utility;

namespace MS.Internal.Documents
{ 
    /// 
    /// ParentUndoUnit 
    ///  
    internal class ParentUndoUnit : IParentUndoUnit
    { 
        //-----------------------------------------------------
        //
        //  Constructors
        // 
        //-----------------------------------------------------
 
        #region Constructors 

        ///  
        /// Constructor
        /// 
        /// 
        /// Text description of the undo unit 
        /// 
        public ParentUndoUnit(string description) : base() 
        { 
            Init(description);
        } 

        #endregion Constructors

        //------------------------------------------------------ 
        //
        //  Public Methods 
        // 
        //-----------------------------------------------------
 
        #region Public Methods

        /// 
        /// Opens a new parent undo unit. 
        /// 
        ///  
        /// IParentUndoUnit to open 
        /// 
        ///  
        /// Thrown if passed unit is null.
        /// 
        public virtual void Open(IParentUndoUnit newUnit)
        { 
            IParentUndoUnit deepestOpen;
 
            if (newUnit == null) 
            {
                throw new ArgumentNullException("newUnit"); 
            }

            deepestOpen = DeepestOpenUnit;
            if (deepestOpen == null) 
            {
                if (IsInParentUnitChain(newUnit)) 
                { 
                    throw new InvalidOperationException(SR.Get(SRID.UndoUnitCantBeOpenedTwice));
                } 

                _openedUnit = newUnit;
                if (newUnit != null)
                { 
                    newUnit.Container = this;
                } 
            } 
            else
            { 
                if (newUnit != null)
                {
                    newUnit.Container = deepestOpen;
                } 

                deepestOpen.Open(newUnit); 
            } 
        }
 
        /// 
        /// Closes the current open unit, adding it to the containing unit's undo stack if committed.
        /// 
        public virtual void Close(UndoCloseAction closeAction) 
        {
            Close(OpenedUnit, closeAction); 
        } 

 
        /// 
        /// Closes an open child parent unit, adding it to the containing unit's undo stack if committed.
        /// 
        ///  
        /// IParentUndoUnit to close.  If NULL, this unit's OpenedUnit is closed.
        ///  
        ///  
        /// 
        ///  
        /// Thrown if no undo unit is currently open
        /// 
        /// 
        /// Thrown if unit is null 
        /// 
        public virtual void Close(IParentUndoUnit unit, UndoCloseAction closeAction) 
        { 
            UndoManager undoManager;
 
            if (unit == null)
            {
                throw new ArgumentNullException("unit");
            } 

            if (OpenedUnit == null) 
            { 
                throw new InvalidOperationException(SR.Get(SRID.UndoNoOpenUnit));
            } 

            // find the parent of the given unit
            if (OpenedUnit != unit)
            { 
                IParentUndoUnit closeParent;
 
                closeParent = this; 
                while (closeParent.OpenedUnit != null && closeParent.OpenedUnit != unit)
                { 
                    closeParent = closeParent.OpenedUnit;
                }

                if (closeParent.OpenedUnit == null) 
                {
                    throw new ArgumentException(SR.Get(SRID.UndoUnitNotFound), "unit"); 
                } 

                if (closeParent != this) 
                {
                    closeParent.Close(closeAction);
                    return;
                } 
            }
 
            // 
            // Close our open unit
            // 

            // Get the undo manager
            undoManager = TopContainer as UndoManager;
 
            if (closeAction != UndoCloseAction.Commit)
            { 
                // discard unit 
                if (undoManager != null)
                { 
                    undoManager.IsEnabled = false;
                }

                if (OpenedUnit.OpenedUnit != null) 
                {
                    OpenedUnit.Close(closeAction); 
                } 

                if (closeAction == UndoCloseAction.Rollback) 
                {
                    ((IParentUndoUnit)OpenedUnit).Do();
                }
 
                _openedUnit = null;
 
                // unlock previous unit(s) 
                if (TopContainer is UndoManager)
                { 
                    ((UndoManager)TopContainer).OnNextDiscard();
                }
                else
                { 
                    ((IParentUndoUnit)TopContainer).OnNextDiscard();
                } 
 
                if (undoManager != null)
                { 
                    undoManager.IsEnabled = true;
                }
            }
            else 
            {
                // commit unit 
                if (OpenedUnit.OpenedUnit != null) 
                {
                    OpenedUnit.Close(UndoCloseAction.Commit); 
                }

                IParentUndoUnit openedUnit = OpenedUnit;
                _openedUnit = null; 
                Add(openedUnit);
                SetLastUnit(openedUnit); 
            } 
        }
 
        /// 
        /// Adds an undo unit to the deepest open parent unit's collection.
        /// 
        ///  
        /// IUndoUnit to add
        ///  
        ///  
        /// TRUE if unit successfully added, FALSE otherwise
        ///  
        /// 
        /// Thrown if unit is null
        /// 
        ///  
        /// Thrown if:
        ///     unit being added is already open 
        ///     unit being added to is locked 
        /// 
        public virtual void Add(IUndoUnit unit) 
        {
            IParentUndoUnit parentUndoUnit;

            if (unit == null) 
            {
                throw new ArgumentNullException("unit"); 
            } 

            parentUndoUnit = DeepestOpenUnit; 

            // If we have an open unit, call Add on it
            if (parentUndoUnit != null)
            { 
                parentUndoUnit.Add(unit);
                return; 
            } 

            if (IsInParentUnitChain(unit)) 
            {
                throw new InvalidOperationException(SR.Get(SRID.UndoUnitCantBeAddedTwice));
            }
 
            if (Locked)
            { 
                throw new InvalidOperationException(SR.Get(SRID.UndoUnitLocked)); 
            }
 
            if (!Merge(unit))
            {
                _units.Push(unit);
                if (LastUnit is IParentUndoUnit) 
                {
                    ((IParentUndoUnit)LastUnit).OnNextAdd(); 
                } 

                SetLastUnit(unit); 
            }
        }

        ///  
        /// Clear all undo units.
        ///  
        ///  
        /// Thrown if unit is locked
        ///  
        public virtual void Clear()
        {
            if (Locked)
            { 
                throw new InvalidOperationException(SR.Get(SRID.UndoUnitLocked));
            } 
 
            _units.Clear();
            SetOpenedUnit(null); 
            SetLastUnit(null);
        }

        ///  
        /// Notifies the last parent undo unit in the collection that a new unit has been added
        /// to the collection.  The undo manager or containing parent undo unit calls this 
        /// function on its most recently added parent undo unit to notify it that the context 
        /// has changed and no further modifications should be made to it.
        ///  
        public virtual void OnNextAdd()
        {
            _locked = true;
            foreach (IUndoUnit unit in _units) 
            {
                if (unit is IParentUndoUnit) 
                { 
                    ((IParentUndoUnit)unit).OnNextAdd();
                } 
            }
        }

        ///  
        /// Inverse of OnNextAdd().  Called when a unit previously added after this one gets discarded.
        ///  
        public virtual void OnNextDiscard() 
        {
            _locked = false; 
            IParentUndoUnit lastParent = this;
            foreach (IUndoUnit unit in _units)
            {
                if (unit is IParentUndoUnit) 
                {
                    lastParent = unit as IParentUndoUnit; 
                } 
            }
 
            if (lastParent != this)
            {
                lastParent.OnNextDiscard();
            } 
        }
 
        ///  
        /// Implements IUndoUnit::Do().  For IParentUndoUnit, this means iterating through
        /// all contained units and calling their Do(). 
        /// 
        public virtual void Do()
        {
            IParentUndoUnit redo; 
            UndoManager topContainer;
 
            // Create the parent redo unit 
            redo = CreateParentUndoUnitForSelf();
            topContainer = TopContainer as UndoManager; 

            if (topContainer != null)
            {
                if (topContainer.IsEnabled) 
                {
                    topContainer.Open(redo); 
                } 
            }
 
            while (_units.Count > 0)
            {
                IUndoUnit unit;
 
                unit = _units.Pop() as IUndoUnit;
                unit.Do(); 
            } 

            if (topContainer != null) 
            {
                if (topContainer.IsEnabled)
                {
                    topContainer.Close(redo, UndoCloseAction.Commit); 
                }
            } 
        } 

        ///  
        /// Iterates through all child units, attempting to merge the given unit into that unit.
        /// Only simple undo units are merged-- parent undo units are not.
        /// 
        ///  
        /// IUndoUnit to merge
        ///  
        ///  
        /// true if unit was merged, false otherwise
        ///  
        public virtual bool Merge(IUndoUnit unit)
        {
            Invariant.Assert(unit != null);
            return false; 
        }
 
        #endregion Public Methods 

        //------------------------------------------------------ 
        //
        //  Public Properties
        //
        //------------------------------------------------------ 

        #region Public Properties 
 
        /// 
        /// text description of this unit 
        /// 
        public string Description
        {
            get 
            {
                return _description; 
            } 
            set
            { 
                if (value == null)
                {
                    value = String.Empty;
                } 

                _description = value; 
            } 
        }
 
        /// 
        /// Returns the most recent child parent unit
        /// 
        public IParentUndoUnit OpenedUnit 
        {
            get 
            { 
                return _openedUnit;
            } 
        }

        /// 
        /// Readonly access to the last unit added to the IParentUndoUnit 
        /// 
        public IUndoUnit LastUnit 
        { 
            get
            { 
                return _lastUnit;
            }
        }
 
        /// 
        /// Whether or not the unit can accept new changes 
        ///  
        public virtual bool Locked
        { 
            get
            {
                return _locked;
            } 

            protected set 
            { 
                _locked = value;
            } 
        }

        /// 
        /// The IParentUndoUnit or UndoManager this parent unit is contained by. 
        ///
        public object Container 
        { 
            get
            { 
                return _container;
            }
            set
            { 
                if (!(value is IParentUndoUnit || value is UndoManager))
                { 
                    throw new Exception(SR.Get(SRID.UndoContainerTypeMismatch)); 
                }
                _container = value; 
            }
        }

        #endregion Public Properties 

        //----------------------------------------------------- 
        // 
        //  Public Events
        // 
        //------------------------------------------------------

        //-----------------------------------------------------
        // 
        //  Protected Methods
        // 
        //----------------------------------------------------- 

        #region Protected Methods 

        /// 
        /// Initialization common to all constructors
        ///  
        /// 
        /// String describing the undo unit 
        ///  
        protected void Init(string description)
        { 
            if (description == null)
            {
                description = String.Empty;
            } 

            _description = description; 
            _locked = false; 
            _openedUnit = null;
            _units = new Stack(2); 
            _container = null;
        }

        ///  
        /// current opened unit
        ///  
        ///  
        /// IParentUndoUnit to which OpenedUnit is to be set
        ///  
        protected void SetOpenedUnit(IParentUndoUnit value)
        {
            _openedUnit = value;
        } 

        ///  
        /// Set LastUnit 
        /// 
        ///  
        /// IUndoUnit to which LastUnit is to be set
        /// 
        protected void SetLastUnit(IUndoUnit value)
        { 
            _lastUnit = value;
        } 
 
        /// 
        /// Callback from Do method allowing derived subclass to 
        /// provide its own ParentUndoUnit. By default general
        /// ParentUndoUnit is created.
        /// 
        ///  
        protected virtual IParentUndoUnit CreateParentUndoUnitForSelf()
        { 
            return new ParentUndoUnit(Description); 
        }
 

        #endregion Protected Methods

        //----------------------------------------------------- 
        //
        //  Protected Properties 
        // 
        //------------------------------------------------------
 
        #region Protected Properties

        /// 
        /// Returns the deepest open parent undo unit contained within this one. 
        /// 
        protected IParentUndoUnit DeepestOpenUnit 
        { 
            get
            { 
                IParentUndoUnit openedUnit;

                openedUnit = _openedUnit;
                if (openedUnit != null) 
                {
                    while (openedUnit.OpenedUnit != null) 
                    { 
                        openedUnit = openedUnit.OpenedUnit;
                    } 
                }
                return openedUnit;
            }
        } 

        ///  
        /// Returns the outermost container of this unit. 
        /// 
        protected object TopContainer 
        {
            get
            {
                object container; 

                container = this; 
                while (container is IParentUndoUnit && ((IParentUndoUnit)container).Container != null) 
                {
                    container = ((IParentUndoUnit)container).Container; 
                }
                return container;
            }
        } 

        protected Stack Units 
        { 
            get
            { 
                return _units;
            }
        }
 
        #endregion Protected Properties
 
        //----------------------------------------------------- 
        //
        //  Private Methods 
        //
        //------------------------------------------------------

        #region Private Methods 

        ///  
        /// Walk up the parent undo unit chain and make sure none of the parent units 
        /// in that chain are the same as the given unit.
        ///  
        /// 
        /// Unit to search for in the parent chain
        /// 
        ///  
        /// true if the unit is already in the parent chain, false otherwise
        ///  
        bool IsInParentUnitChain(IUndoUnit unit) 
        {
            if (unit is IParentUndoUnit) 
            {
                IParentUndoUnit parent;

                parent = this; 
                do
                { 
                    if (parent == unit) 
                    {
                        return true; 
                    }

                    parent = parent.Container as IParentUndoUnit;
                } while (parent != null); 
            }
            return false; 
        } 

        #endregion Private methods 

        //------------------------------------------------------
        //
        //  Private Properties 
        //
        //----------------------------------------------------- 
 
        //------------------------------------------------------
        // 
        //  Private Fields
        //
        //-----------------------------------------------------
 
        #region Private Fields
 
        private string _description; 
        private bool _locked;
        private IParentUndoUnit _openedUnit; 
        private IUndoUnit _lastUnit;
        private Stack _units;
        private object _container;
 
        #endregion Private Fields
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK