StructuralCache.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 / PtsHost / StructuralCache.cs / 1 / StructuralCache.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: PTS structural cache related data. 
//
// History: 
//  06/03/2003 : [....] - 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.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; 
            _ptsContext = new PtsContext(true); 
            _textFormatterHost = new TextFormatterHost(_ptsContext.TextFormatter);
            _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 nukeStructure) 
        {
            _section.InvalidateFormatCache(); 
            _nukeStructure = _nukeStructure || nukeStructure;
            // 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 nukeStructureCache)
        {
            _dtrs = null;
            _forceReformat = false; 
            _nukeStructure = false;
            if (nukeStructureCache) 
            { 
                _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
            {
                return _section; 
            }
            set 
            { 
                _section = value;
            } 
        }

        /// 
        /// Hyphenator 
        /// 
        internal NaturalLanguageHyphenator Hyphenator 
        { 
            get
            { 
                EnsureHyphenator();
                return _hyphenator;
            }
        } 

        ///  
        /// Context used to communicate with PTS component. 
        /// 
        internal PtsContext PtsContext 
        {
            get
            {
                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
            { 
                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;
            } 
        }
 
        ///  
        /// Nuke name table on reformatting?
        ///  
        internal bool NukeStructure
        {
            get
            { 
                return _nukeStructure;
            } 
        } 

        ///  
        /// 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();
            } 
        }

        /// 
        /// 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 readonly 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 readonly 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 nuked before reformatting.
        ///  
        private bool _nukeStructure; 

        ///  
        /// 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(); 
            } 

            ///  
            /// 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() 
            {
                _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() { 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