StructuralCache.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / PtsHost / StructuralCache.cs / 1305600 / StructuralCache.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: PTS structural cache related data. 
//
// History: 
//  06/03/2003 : olego - Created
//
//---------------------------------------------------------------------------
 
using MS.Internal.Text;
using MS.Internal.PtsHost.UnsafeNativeMethods; 
using MS.Utility; 
using System;
using System.Collections.Generic; 
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using System.Windows.Media; 
using System.Windows.Documents;
 
namespace MS.Internal.PtsHost 
{
    ///  
    /// PTS structural cache related data
    /// 
    internal sealed class StructuralCache
    { 
        //-----------------------------------------------------
        // 
        //  Constructors 
        //
        //----------------------------------------------------- 

        #region Constructors

        ///  
        /// Structural Cache contructor.
        ///  
        /// Owner of the conent 
        /// TextContainer representing content
        internal StructuralCache(FlowDocument owner, TextContainer textContainer) 
        {
            Invariant.Assert(owner != null);
            Invariant.Assert(textContainer != null);
            Invariant.Assert(textContainer.Parent != null); 

            _owner = owner; 
            _textContainer = textContainer; 
            _backgroundFormatInfo = new BackgroundFormatInfo(this);
        } 

        /// 
        /// Finalizer
        ///  
        ~StructuralCache()
        { 
            // Notify the PtsCache about the fact that PtsContext needs to be destroyed. 
            // NOTE: It is safe to access PtsContext, because the PtsContext
            //       does not have a finalizer. 
            if (_ptsContext != null)
            {
                PtsCache.ReleaseContext(_ptsContext);
            } 
        }
 
        #endregion Constructors 

        //------------------------------------------------------ 
        //
        //  Internal Methods
        //
        //----------------------------------------------------- 

        #region Internal Methods 
 
        /// 
        /// Sets current page context to be used in the cache's queries 
        /// 
        /// Document page to become current in the context
        /// Reference to object compatible with IDisposable to re-initialize page context
        internal IDisposable SetDocumentFormatContext(FlowDocumentPage currentPage) 
        {
            if (!CheckFlags(Flags.FormattedOnce)) 
            { 
                SetFlags(true, Flags.FormattedOnce);
                _owner.InitializeForFirstFormatting(); 
            }
            return (new DocumentFormatContext(this, currentPage) as IDisposable);
        }
 
        /// 
        /// Sets current page context to be used in the cache's queries 
        ///  
        /// Document page to become current in the context
        /// Reference to object compatible with IDisposable to re-initialize page context 
        internal IDisposable SetDocumentArrangeContext(FlowDocumentPage currentPage)
        {
            return (new DocumentArrangeContext(this, currentPage) as IDisposable);
        } 

        ///  
        /// Sets current page context to be used in the cache's queries 
        /// 
        /// Document page to become current in the context 
        /// Reference to object compatible with IDisposable to re-initialize page context
        internal IDisposable SetDocumentVisualValidationContext(FlowDocumentPage currentPage)
        {
            return (new DocumentVisualValidationContext(this, currentPage) as IDisposable); 
        }
 
        ///  
        /// Detects if illegal tree change operation has been performed, but hidden by external
        /// code through try-catch statement. 
        /// 
        internal void DetectInvalidOperation()
        {
            if (_illegalTreeChangeDetected) 
            {
                throw new InvalidOperationException(SR.Get(SRID.IllegalTreeChangeDetectedPostAction)); 
            } 
        }
 
        /// 
        /// Notes the fact that world has changed while in measure / arrange.
        /// 
        internal void OnInvalidOperationDetected() 
        {
            if (_currentPage != null) 
            { 
                _illegalTreeChangeDetected = true;
            } 
        }

        /// 
        /// Invalidate format caches accumulated in the NameTable. 
        /// 
        internal void InvalidateFormatCache(bool destroyStructure) 
        { 
            if (_section != null)
            { 
                _section.InvalidateFormatCache();
                _destroyStructure = _destroyStructure || destroyStructure;
                // Formatting caches are acquired during page formatting (full or incremental).
                // But since there is no DTR available, need to force reformatting 
                // to reacquire formatting caches.
                _forceReformat = true; 
            } 
        }
 
        /// 
        /// Add new DirtyTextRange.
        /// 
        /// New DTR being added. 
        internal void AddDirtyTextRange(DirtyTextRange dtr)
        { 
            if (_dtrs == null) 
            {
                _dtrs = new DtrList(); 
            }
            _dtrs.Merge(dtr);
        }
 
        /// 
        /// Retrieve list of dtrs from range. 
        /// DTR StartIndex for each dtr returned is scaled to be relative to dcpNew, no other translation required. 
        /// 
        /// Distance from the beginning of textContainer after all tree changes 
        /// Number of characters in the range, but before any  tree changes
        /// List of DRTs for specified range.
        internal DtrList DtrsFromRange(int dcpNew, int cchOld)
        { 
            return (_dtrs != null) ? _dtrs.DtrsFromRange(dcpNew, cchOld) : null;
        } 
 
        /// 
        /// Clear update info. 
        /// 
        /// Destroy structure cache.
        internal void ClearUpdateInfo(bool destroyStructureCache)
        { 
            _dtrs = null;
            _forceReformat = false; 
            _destroyStructure = false; 

           /* 
            * Have to make sure the ptsContext is not disposed
            * as the resulting call to ReleaseHandle will throw an exception.
            *
            * This is possible when the dispatcher.Shutdown event fires before 
            * the Visibility changed event fires.
            **/ 
            if (_section != null && !_ptsContext.Disposed) 
            {
                if (destroyStructureCache) 
                {
                    _section.DestroyStructure();
                }
                _section.ClearUpdateInfo(); 
            }
        } 
 
        /// 
        /// This method is called after user input. 
        /// Temporarily drop our background layout time slice to cut down on
        /// latency.
        /// 
        internal void ThrottleBackgroundFormatting() 
        {
            _backgroundFormatInfo.ThrottleBackgroundFormatting(); 
        } 

        #endregion Internal Methods 

        // ------------------------------------------------------------------
        //
        //  Internal Properties 
        //
        // ------------------------------------------------------------------ 
 
        #region Internal Properties
 
        /// 
        /// The DependencyObject supplying property values for this cache.
        /// 
        ///  
        /// Typically PropertyOwner == FormattingOwner.  However, when content
        /// is hosted by TextBox or RichTextBox, we want to read property values 
        /// from the control, not FlowDocument. 
        /// 
        internal DependencyObject PropertyOwner 
        {
            get
            {
                return _textContainer.Parent; 
            }
        } 
 
        /// 
        /// The DependencyObject whose structure is represented by this cache. 
        /// 
        internal FlowDocument FormattingOwner
        {
            get 
            {
                return _owner; 
            } 
        }
 
        /// 
        /// PTS section object.
        /// 
        internal Section Section 
        {
            get 
            { 
                EnsurePtsContext();
                return _section; 
            }
        }

        ///  
        /// Hyphenator
        ///  
        internal NaturalLanguageHyphenator Hyphenator 
        {
            get 
            {
                EnsureHyphenator();
                return _hyphenator;
            } 
        }
 
        ///  
        /// Context used to communicate with PTS component.
        ///  
        internal PtsContext PtsContext
        {
            get
            { 
                EnsurePtsContext();
                return _ptsContext; 
            } 
        }
 
        /// 
        /// Context used to communicate with PTS component.
        /// 
        internal DocumentFormatContext CurrentFormatContext { get { return _documentFormatContext; } } 

        ///  
        /// Context used to communicate with PTS component. 
        /// 
        internal DocumentArrangeContext CurrentArrangeContext { get { return _documentArrangeContext; } } 

        /// 
        /// TextFormatter host.
        ///  
        internal TextFormatterHost TextFormatterHost
        { 
            get 
            {
                EnsurePtsContext(); 
                return _textFormatterHost;
            }
        }
 
        /// 
        /// TextContainer exposing access to the content. 
        ///  
        internal TextContainer TextContainer
        { 
            get
            {
                return _textContainer;
            } 
        }
 
        ///  
        /// TextContainer exposing access to the content.
        ///  
        internal FlowDirection PageFlowDirection
        {
            get
            { 
                return _pageFlowDirection;
            } 
            set 
            {
                _pageFlowDirection = value; 
            }
        }

        ///  
        /// Force content reformatting?
        ///  
        internal bool ForceReformat 
        {
            get 
            {
                return _forceReformat;
            }
            set 
            {
                _forceReformat = value; 
            } 
        }
 
        /// 
        /// destroy name table on reformatting?
        /// 
        internal bool DestroyStructure 
        {
            get 
            { 
                return _destroyStructure;
            } 
        }

        /// 
        /// DTRs list. 
        /// 
        internal DtrList DtrList 
        { 
            get
            { 
                return _dtrs;
            }
        }
 
        /// 
        /// Whether deferred visual creation is supported for the given context 
        ///  
        internal bool IsDeferredVisualCreationSupported
        { 
            get { return _currentPage != null && !_currentPage.FinitePage; }
        }

        ///  
        /// Background formatting information
        ///  
        internal BackgroundFormatInfo BackgroundFormatInfo 
        {
            get 
            {
                return _backgroundFormatInfo;
            }
        } 

        ///  
        /// Is Optimal paragraph enabled for this session 
        /// 
        internal bool IsOptimalParagraphEnabled 
        {
            get
            {
                if (PtsContext.IsOptimalParagraphEnabled) 
                {
                    return (bool)this.PropertyOwner.GetValue(FlowDocument.IsOptimalParagraphEnabledProperty); 
                } 
                return false;
            } 
        }

        /// 
        /// Whether formatting is currently in progress. 
        /// 
        internal bool IsFormattingInProgress 
        { 
            get
            { 
                return CheckFlags(Flags.FormattingInProgress);
            }
            set
            { 
                SetFlags(value, Flags.FormattingInProgress);
            } 
        } 

        ///  
        /// Whether content change is currently in progress.
        /// 
        internal bool IsContentChangeInProgress
        { 
            get
            { 
                return CheckFlags(Flags.ContentChangeInProgress); 
            }
            set 
            {
                SetFlags(value, Flags.ContentChangeInProgress);
            }
        } 

        ///  
        /// Whether the first formatting was done. 
        /// 
        internal bool IsFormattedOnce 
        {
            get
            {
                return CheckFlags(Flags.FormattedOnce); 
            }
            set 
            { 
                SetFlags(value, Flags.FormattedOnce);
            } 
        }

        #endregion Internal Properties
 
        // -----------------------------------------------------------------
        // 
        //  Private Methods 
        //
        // ------------------------------------------------------------------ 

        #region Private Methods

        ///  
        /// Ensures the hyphenator exists.
        ///  
        private void EnsureHyphenator() 
        {
            if (_hyphenator == null) 
            {
                _hyphenator = new NaturalLanguageHyphenator();
            }
        } 

        ///  
        /// Ensures the PtsContext exists. 
        /// 
        private void EnsurePtsContext() 
        {
            if (_ptsContext == null)
            {
                TextFormattingMode textFormattingMode = TextOptions.GetTextFormattingMode(this.PropertyOwner); 
                _ptsContext = new PtsContext(true, textFormattingMode);
                _textFormatterHost = new TextFormatterHost(_ptsContext.TextFormatter, textFormattingMode); 
                _section = new MS.Internal.PtsHost.Section(this); 
            }
        } 

        /// 
        /// SetFlags is used to set or unset one or multiple flags.
        ///  
        private void SetFlags(bool value, Flags flags)
        { 
            _flags = value ? (_flags | flags) : (_flags & (~flags)); 
        }
 
        /// 
        /// CheckFlags returns true if all of passed flags in the bitmask are set.
        /// 
        private bool CheckFlags(Flags flags) 
        {
            return ((_flags & flags) == flags); 
        } 

        #endregion Private Methods 

        // -----------------------------------------------------------------
        //
        //  Private Fields 
        //
        // ----------------------------------------------------------------- 
 
        #region Private Fields
 
        /// 
        /// Owner of the content.
        /// 
        private readonly FlowDocument _owner; 

        ///  
        /// Context used to communicate with PTS. 
        /// 
        private PtsContext _ptsContext; 

        /// 
        /// Root of the NameTable for PTS. Encapsulates all content of TextFlow and Cell.
        /// There is always one section. 
        /// 
        private Section _section; 
 
        /// 
        /// TextContainer exposing access to the content. 
        /// 
        private TextContainer _textContainer;

        ///  
        /// TextFormatter host.
        ///  
        private TextFormatterHost _textFormatterHost; 

        ///  
        /// Currently formatted page. Valid only during measure pass.
        /// 
        private FlowDocumentPage _currentPage;
 
        /// 
        /// Document Format Context - All information necessary during document formatting. Null outside of DocumentFormat. 
        ///  
        private DocumentFormatContext _documentFormatContext;
 
        /// 
        /// Document Arrange Context - All information necessary during document arrange. Null outside of Arrange.
        /// 
        private DocumentArrangeContext _documentArrangeContext; 

        ///  
        /// List of dirty text ranges. 
        /// 
        private DtrList _dtrs = null; 

        /// 
        /// Set to true if tree and / or properties were changed during document page context life time
        ///  
        private bool _illegalTreeChangeDetected;
 
        ///  
        /// Set to true if full formatting needs to be done (incremental upate is not possible).
        ///  
        private bool _forceReformat;

        /// 
        /// Set to true if name table should be destroyed before reformatting. 
        /// 
        private bool _destroyStructure; 
 
        /// 
        /// Info class with background format information 
        /// 
        private BackgroundFormatInfo _backgroundFormatInfo;

        ///  
        /// Flow direction for page.
        ///  
        private FlowDirection _pageFlowDirection; 

        ///  
        /// Hyphenator
        /// 
        private NaturalLanguageHyphenator _hyphenator;
 
        /// 
        /// Flags reflecting various aspects of FlowDocumentPaginator's state. 
        ///  
        private Flags _flags;
        [System.Flags] 
        private enum Flags
        {
            FormattedOnce = 0x001,              // Element has been formatted at least once.
            ContentChangeInProgress = 0x002,    // Content change is in progress. 
            FormattingInProgress = 0x008,       // Formatting operation in progress.
        } 
 
        #endregion Private Fields
 
        // -----------------------------------------------------------------
        //
        //  Private Structures and Classes
        // 
        // ------------------------------------------------------------------
 
        #region Private Structures and Classes 

        ///  
        /// Base helper class for setting / resetting structural cache state
        /// 
        internal abstract class DocumentOperationContext
        { 
            /// 
            /// Constructor 
            ///  
            /// Associated structural cache instance
            /// Document page to set 
            internal DocumentOperationContext(StructuralCache owner, FlowDocumentPage page)
            {
                Invariant.Assert(owner != null, "Invalid owner object.");
                Invariant.Assert(page != null, "Invalid page object."); 
                Invariant.Assert(owner._currentPage == null, "Page formatting reentrancy detected. Trying to create second _DocumentPageContext for the same StructuralCache.");
 
                _owner = owner; 
                _owner._currentPage = page;
                _owner._illegalTreeChangeDetected = false; 
                owner.PtsContext.Enter();
            }

            ///  
            /// 
            ///  
            protected void Dispose() 
            {
                Invariant.Assert(_owner._currentPage != null, "DocumentPageContext is already disposed."); 

                try
                {
                    _owner.PtsContext.Leave(); 
                }
                finally 
                { 
                    _owner._currentPage = null;
                } 
            }

            /// 
            /// Size of document 
            /// 
            internal Size DocumentPageSize { get { return _owner._currentPage.Size; } } 
 
            /// 
            /// Thickness of document margin 
            /// 
            internal Thickness DocumentPageMargin { get { return _owner._currentPage.Margin; } }

            ///  
            /// Owner of the _DocumentPageContext.
            ///  
            protected readonly StructuralCache _owner; 
        }
 
        /// 
        /// Document format context - holds any information needed during the formatting of a document.
        /// 
        internal class DocumentFormatContext : DocumentOperationContext, IDisposable 
        {
            ///  
            /// Constructor 
            /// 
            /// Associated structural cache instance 
            /// Document page to set
            internal DocumentFormatContext(StructuralCache owner, FlowDocumentPage page) : base(owner, page)
            {
                _owner._documentFormatContext = this; 
            }
 
            ///  
            /// 
            ///  
            void IDisposable.Dispose()
            {
                _owner._documentFormatContext = null;
 
                base.Dispose();
                GC.SuppressFinalize(this); 
            } 

            ///  
            /// OnFormatLine - Adds to current line format count.
            /// 
            internal void OnFormatLine()
            { 
                _owner._currentPage.OnFormatLine();
            } 
 
            /// 
            /// PushNewPageData - Pushes new page data to the top of the stack. 
            /// 
            /// Size of page
            /// Margin of page
            /// Are we in Incremental Update 
            /// Is the current page a Finite Page
            internal void PushNewPageData(Size pageSize, Thickness pageMargin, bool incrementalUpdate, bool finitePage) 
            { 
                _documentFormatInfoStack.Push(_currentFormatInfo);
 
                _currentFormatInfo.PageSize = pageSize;
                _currentFormatInfo.PageMargin = pageMargin;
                _currentFormatInfo.IncrementalUpdate = incrementalUpdate;
                _currentFormatInfo.FinitePage = finitePage; 
            }
 
            ///  
            /// PopPageData - Pops page data from top of stack.
            ///  
            internal void PopPageData()
            {
                _currentFormatInfo = _documentFormatInfoStack.Pop();
            } 

            ///  
            /// Height of page 
            /// 
            internal double PageHeight { get { return _currentFormatInfo.PageSize.Height; } } 

            /// 
            /// Width of page
            ///  
            internal double PageWidth { get { return _currentFormatInfo.PageSize.Width; } }
 
            ///  
            /// PageSize as a size
            ///  
            internal Size PageSize { get { return _currentFormatInfo.PageSize; } }

            /// 
            /// Margin in page. 
            /// 
            internal Thickness PageMargin { get { return _currentFormatInfo.PageMargin; } } 
 
            /// 
            /// Incremental update mode 
            /// 
            internal bool IncrementalUpdate { get { return _currentFormatInfo.IncrementalUpdate; } }

            ///  
            /// Is Finite or Bottomless Page
            ///  
            internal bool FinitePage { get { return _currentFormatInfo.FinitePage; } } 

            ///  
            /// Rectangle of current page in TextDpi
            /// 
            internal PTS.FSRECT PageRect { get { return new PTS.FSRECT(new Rect(0, 0, PageWidth, PageHeight)); } }
 
            /// 
            /// Rectangle of margin in TextDpi 
            ///  
            internal PTS.FSRECT PageMarginRect { get { return new PTS.FSRECT(new Rect(PageMargin.Left, PageMargin.Top,
                                                                                      PageSize.Width - PageMargin.Left - PageMargin.Right, 
                                                                                      PageSize.Height - PageMargin.Top - PageMargin.Bottom)); } }
            /// 
            /// DependentMax used for invalidation calculations
            ///  
            internal TextPointer DependentMax { set { _owner._currentPage.DependentMax = value; } }
 
 
            private struct DocumentFormatInfo
            { 
                internal Size PageSize;
                internal Thickness PageMargin;
                internal bool IncrementalUpdate;
                internal bool FinitePage; 
            };
 
            private DocumentFormatInfo _currentFormatInfo; 
            private Stack _documentFormatInfoStack = new Stack();
        } 

        /// 
        /// Document arrange context - holds any information needed during the arrange of a document.
        ///  
        internal class DocumentArrangeContext : DocumentOperationContext, IDisposable
        { 
            ///  
            /// Constructor
            ///  
            /// Associated structural cache instance
            /// Document page to set
            internal DocumentArrangeContext(StructuralCache owner, FlowDocumentPage page) : base(owner, page)
            { 
                _owner._documentArrangeContext = this;
            } 
 
            /// 
            /// PushNewPageData - Pushes new page data to the top of the stack. 
            /// 
            /// Page context we were formatted in
            /// Rect of current column
            /// Is the current page a Finite Page 
            internal void PushNewPageData(PageContext pageContext, PTS.FSRECT columnRect, bool finitePage)
            { 
                _documentArrangeInfoStack.Push(_currentArrangeInfo); 

                _currentArrangeInfo.PageContext = pageContext; 
                _currentArrangeInfo.ColumnRect = columnRect;
                _currentArrangeInfo.FinitePage = finitePage;
            }
 
            /// 
            /// PopPageData - Pops page data from top of stack. 
            ///  
            internal void PopPageData()
            { 
                _currentArrangeInfo = _documentArrangeInfoStack.Pop();
            }

            ///  
            /// 
            ///  
            void IDisposable.Dispose() 
            {
                GC.SuppressFinalize(this); 
                _owner._documentArrangeContext = null;

                base.Dispose();
            } 

 
            ///  
            /// Page Context (used to register/unregister floating elements)
            ///  
            internal PageContext PageContext { get { return _currentArrangeInfo.PageContext; } }

            /// 
            /// Rectangle of current column 
            /// 
            internal PTS.FSRECT  ColumnRect  { get { return _currentArrangeInfo.ColumnRect; } } 
 
            /// 
            /// Is current page Finite 
            /// 
            internal bool        FinitePage  { get { return _currentArrangeInfo.FinitePage; } }

 
            private struct DocumentArrangeInfo
            { 
                internal PageContext PageContext; 
                internal PTS.FSRECT ColumnRect;
                internal bool FinitePage; 
            };

            private DocumentArrangeInfo _currentArrangeInfo;
            private Stack _documentArrangeInfoStack = new Stack(); 

        } 
 
        /// 
        /// Document visual validation context - holds any information needed during the visual validation of a document. 
        /// 
        internal class DocumentVisualValidationContext : DocumentOperationContext, IDisposable
        {
            ///  
            /// Constructor
            ///  
            /// Associated structural cache instance 
            /// Document page to set
            internal DocumentVisualValidationContext(StructuralCache owner, FlowDocumentPage page) : base(owner, page) { } 


            /// 
            ///  
            /// 
            void IDisposable.Dispose() 
            { 
                GC.SuppressFinalize(this);
                base.Dispose(); 
            }
        }

        #endregion Private Structures and Classes 
    }
 
 
}

// 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