DocumentPageTextView.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / documents / DocumentPageTextView.cs / 1305600 / DocumentPageTextView.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
// File: DocumentPageTextView.cs 
//
// Description: TextView implementation for DocumentPageView. 
// 
//---------------------------------------------------------------------------
 
using System;                               // InvalidOperationException, ...
using System.Collections.Generic;           // List
using System.Collections.ObjectModel;       // ReadOnlyCollection
using System.Windows;                       // Point, Rect, ... 
using System.Windows.Controls.Primitives;   // DocumentPageView
using System.Windows.Documents;             // ITextView, ITextContainer 
using System.Windows.Media;                 // VisualTreeHelper 
using MS.Internal.PtsHost;                  // BackgroundFormatInfo
 
namespace MS.Internal.Documents
{
    /// 
    /// TextView implementation for DocumentPageView. 
    /// 
    internal class DocumentPageTextView : TextViewBase 
    { 
        //-------------------------------------------------------------------
        // 
        //  Constructors
        //
        //-------------------------------------------------------------------
 
        #region Constructors
 
        ///  
        /// Constructor.
        ///  
        /// 
        /// Root of layout structure visualizing content of a page.
        /// 
        ///  
        /// TextContainer representing content.
        ///  
        internal DocumentPageTextView(DocumentPageView owner, ITextContainer textContainer) 
        {
            Invariant.Assert(owner != null && textContainer != null); 
            _owner = owner;
            _page = owner.DocumentPageInternal;
            _textContainer = textContainer;
            // Retrive inner TextView 
            if (_page is IServiceProvider)
            { 
                _pageTextView = ((IServiceProvider)_page).GetService(typeof(ITextView)) as ITextView; 
            }
            if (_pageTextView != null) 
            {
                _pageTextView.Updated += new EventHandler(HandlePageTextViewUpdated);
            }
        } 

        ///  
        /// Constructor. 
        /// 
        ///  
        /// Root of layout structure visualizing content of a page.
        /// 
        /// 
        /// TextContainer representing content. 
        /// 
        internal DocumentPageTextView(FlowDocumentView owner, ITextContainer textContainer) 
        { 
            Invariant.Assert(owner != null && textContainer != null);
            _owner = owner; 
            _page = owner.DocumentPage;
            _textContainer = textContainer;
            // Retrive inner TextView
            if (_page is IServiceProvider) 
            {
                _pageTextView = ((IServiceProvider)_page).GetService(typeof(ITextView)) as ITextView; 
            } 
            if (_pageTextView != null)
            { 
                _pageTextView.Updated += new EventHandler(HandlePageTextViewUpdated);
            }
        }
 
        #endregion Constructors
 
        //-------------------------------------------------------------------- 
        //
        //  Internal Methods 
        //
        //-------------------------------------------------------------------

        #region Internal Methods 

        ///  
        ///  
        /// 
        internal override ITextPointer GetTextPositionFromPoint(Point point, bool snapToText) 
        {
            // Verify that layout information is valid. Cannot continue if not valid.
            if (!IsValid)
            { 
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
            } 
            if (IsPageMissing) 
            {
                return null; 
            }
            // Transform to page coordinates.
            point = TransformToDescendant(point);
            return _pageTextView.GetTextPositionFromPoint(point, snapToText); 
        }
 
        ///  
        /// 
        ///  
        internal override Rect GetRawRectangleFromTextPosition(ITextPointer position, out Transform transform)
        {
            Rect rect;
            Transform pageTextViewTransform, ancestorTransform; 

            // Initialize transform to identity 
            transform = Transform.Identity; 

            // Verify that layout information is valid. Cannot continue if not valid. 
            if (!IsValid)
            {
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
            } 
            if (IsPageMissing)
            { 
                return Rect.Empty; 
            }
 
            rect = _pageTextView.GetRawRectangleFromTextPosition(position, out pageTextViewTransform);
            Invariant.Assert(pageTextViewTransform != null);
            ancestorTransform = GetTransformToAncestor();
            transform = GetAggregateTransform(pageTextViewTransform, ancestorTransform); 
            return rect;
        } 
 
        /// 
        ///  
        /// 
        internal override Geometry GetTightBoundingGeometryFromTextPositions(ITextPointer startPosition, ITextPointer endPosition)
        {
            //  verify that layout information is valid. Cannot continue if not valid. 
            if (!IsValid)
            { 
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout)); 
            }
 
            Geometry geometry = null;

            if (!IsPageMissing)
            { 
                geometry = _pageTextView.GetTightBoundingGeometryFromTextPositions(startPosition, endPosition);
                if (geometry != null) 
                { 
                    Transform transform = GetTransformToAncestor().AffineTransform;
                    CaretElement.AddTransformToGeometry(geometry, transform); 
                }
            }

            return (geometry); 
        }
 
        ///  
        /// 
        ///  
        internal override ITextPointer GetPositionAtNextLine(ITextPointer position, double suggestedX, int count, out double newSuggestedX, out int linesMoved)
        {
            ITextPointer positionOut;
            Point offset; 

            // Verify that layout information is valid. Cannot continue if not valid. 
            if (!IsValid) 
            {
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout)); 
            }
            if (IsPageMissing)
            {
                newSuggestedX = suggestedX; 
                linesMoved = 0;
                return position; 
            } 

            offset = TransformToDescendant(new Point(suggestedX, 0)); 
            suggestedX = offset.X;
            positionOut = _pageTextView.GetPositionAtNextLine(position, suggestedX, count, out newSuggestedX, out linesMoved);
            offset = TransformToAncestor(new Point(newSuggestedX, 0));
            newSuggestedX = offset.X; 

            return positionOut; 
        } 

        ///  
        /// 
        /// 
        internal override ITextPointer GetPositionAtNextPage(ITextPointer position, Point suggestedOffset, int count, out Point newSuggestedOffset, out int pagesMoved)
        { 
            ITextPointer positionOut = position;
            newSuggestedOffset = suggestedOffset; 
            Point offset = suggestedOffset; 
            pagesMoved = 0;
 
            if (count == 0)
            {
                return positionOut;
            } 

            // Verify that layout information is valid. Cannot continue if not valid. 
            if (!IsValid) 
            {
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout)); 
            }
            if (IsPageMissing)
            {
                return position; 
            }
 
            // Calculate distance from current position 
            offset.Y = GetYOffsetAtNextPage(offset.Y, count, out pagesMoved);
 
            if (pagesMoved != 0)
            {
                // Transfrom offset to _pageTextView's coordinate position, obtain position from _pageTextView and convert back
                offset = TransformToDescendant(offset); 
                positionOut = _pageTextView.GetTextPositionFromPoint(offset, true);
                Invariant.Assert(positionOut != null); 
                Rect rect = _pageTextView.GetRectangleFromTextPosition(position); 
                newSuggestedOffset = TransformToAncestor(new Point(rect.X, rect.Y));
            } 

            return positionOut;
        }
 
        /// 
        ///  
        ///  
        internal override bool IsAtCaretUnitBoundary(ITextPointer position)
        { 
            // Verify that layout information is valid. Cannot continue if not valid.
            if (!IsValid)
            {
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout)); 
            }
            if (IsPageMissing) 
            { 
                return false;
            } 
            return _pageTextView.IsAtCaretUnitBoundary(position);
        }

        ///  
        /// 
        ///  
        internal override ITextPointer GetNextCaretUnitPosition(ITextPointer position, LogicalDirection direction) 
        {
            // Verify that layout information is valid. Cannot continue if not valid. 
            if (!IsValid)
            {
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
            } 
            if (IsPageMissing)
            { 
                return null; 
            }
            return _pageTextView.GetNextCaretUnitPosition(position, direction); 
        }

        /// 
        ///  
        /// 
        internal override ITextPointer GetBackspaceCaretUnitPosition(ITextPointer position) 
        { 
            // Verify that layout information is valid. Cannot continue if not valid.
            if (!IsValid) 
            {
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
            }
            if (IsPageMissing) 
            {
                return null; 
            } 
            return _pageTextView.GetBackspaceCaretUnitPosition(position);
        } 

        /// 
        /// 
        ///  
        internal override TextSegment GetLineRange(ITextPointer position)
        { 
            // Verify that layout information is valid. Cannot continue if not valid. 
            if (!IsValid)
            { 
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
            }
            if (IsPageMissing)
            { 
                return TextSegment.Null;
            } 
            return _pageTextView.GetLineRange(position); 
        }
 
        /// 
        /// 
        /// 
        internal override ReadOnlyCollection GetGlyphRuns(ITextPointer start, ITextPointer end) 
        {
            // Verify that layout information is valid. Cannot continue if not valid. 
            if (!IsValid) 
            {
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout)); 
            }
            if (IsPageMissing)
            {
                return new ReadOnlyCollection(new List()); 
            }
            return _pageTextView.GetGlyphRuns(start, end); 
        } 

        ///  
        /// 
        /// 
        internal override bool Contains(ITextPointer position)
        { 
            // Verify that layout information is valid. Cannot continue if not valid.
            if (!IsValid) 
            { 
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
            } 
            if (IsPageMissing)
            {
                return false;
            } 
            return _pageTextView.Contains(position);
        } 
 
        /// 
        /// Handler for PageConnected raised by the DocumentPageView. 
        /// 
        internal void OnPageConnected()
        {
            OnPageDisconnected(); 
            if (_owner is DocumentPageView)
            { 
                _page = ((DocumentPageView)_owner).DocumentPageInternal; 
            }
            else if (_owner is FlowDocumentView) 
            {
                _page = ((FlowDocumentView)_owner).DocumentPage;
            }
 
            if (_page is IServiceProvider)
            { 
                _pageTextView = ((IServiceProvider)_page).GetService(typeof(ITextView)) as ITextView; 
            }
            if (_pageTextView != null) 
            {
                _pageTextView.Updated += new EventHandler(HandlePageTextViewUpdated);
            }
            if (IsValid) 
            {
                OnUpdated(EventArgs.Empty); 
            } 
        }
 
        /// 
        /// Handler for PageDisconnected raised by the DocumentPageView.
        /// 
        internal void OnPageDisconnected() 
        {
            if (_pageTextView != null) 
            { 
                _pageTextView.Updated -= new EventHandler(HandlePageTextViewUpdated);
            } 
            _pageTextView = null;
            _page = null;
        }
 
        /// 
        /// Handler for TransformChanged raised by the DocumentPageView. 
        ///  
        internal void OnTransformChanged()
        { 
            if (IsValid)
            {
                OnUpdated(EventArgs.Empty);
            } 
        }
 
        ///  
        /// 
        ///  
        internal override bool Validate()
        {
            if (!_owner.IsMeasureValid || !_owner.IsArrangeValid)
            { 
                _owner.UpdateLayout();
            } 
            return (_pageTextView != null && _pageTextView.Validate()); 
        }
 
        /// 
        /// 
        /// 
        internal override bool Validate(ITextPointer position) 
        {
            FlowDocumentView owner = _owner as FlowDocumentView; 
            bool isValid; 

            if (owner == null || owner.Document == null) 
            {
                isValid = base.Validate(position);
            }
            else 
            {
                if (Validate()) 
                { 
                    BackgroundFormatInfo backgroundFormatInfo = owner.Document.StructuralCache.BackgroundFormatInfo;
                    FlowDocumentFormatter formatter = owner.Document.BottomlessFormatter; 

                    int lastCPInterrupted = -1;

                    while (this.IsValid && !Contains(position)) 
                    {
                        backgroundFormatInfo.BackgroundFormat(formatter, true /* ignoreThrottle */); 
                        _owner.UpdateLayout(); // May invalidate the view. 

                        // Break if background layout is not progressing. 
                        // There are some edge cases where Validate() == true, but background
                        // layout will not progress (such as collapsed text in a tree view).
                        if (backgroundFormatInfo.CPInterrupted <= lastCPInterrupted)
                        { 
                            // CPInterrupted is reset to -1 when background layout finishes, so
                            // check explicitly below to see if the position is valid or not. 
                            break; 
                        }
                        lastCPInterrupted = backgroundFormatInfo.CPInterrupted; 
                    }
                }

                isValid = this.IsValid && Contains(position); 
            }
 
            return isValid; 
        }
 
        /// 
        /// 
        /// 
        internal override void ThrottleBackgroundTasksForUserInput() 
        {
            FlowDocumentView owner = _owner as FlowDocumentView; 
 
            if (owner != null && owner.Document != null)
            { 
                owner.Document.StructuralCache.ThrottleBackgroundFormatting();
            }
        }
 
        #endregion Internal Methods
 
        //-------------------------------------------------------------------- 
        //
        //  Internal Properties 
        //
        //--------------------------------------------------------------------

        #region Internal Properties 

        ///  
        ///  
        /// 
        internal override UIElement RenderScope 
        {
            get { return _owner; }
        }
 
        /// 
        ///  
        ///  
        internal override ITextContainer TextContainer
        { 
            get { return _textContainer; }
        }

        ///  
        /// 
        ///  
        internal override bool IsValid 
        {
            get 
            {
                if (!_owner.IsMeasureValid || !_owner.IsArrangeValid || _page == null)
                {
                    return false; 
                }
                if (IsPageMissing) 
                { 
                    return true;
                } 
                return (_pageTextView != null && _pageTextView.IsValid);
            }
        }
 
        /// 
        ///  
        ///  
        internal override bool RendersOwnSelection
        { 
            get
            {
                if (_pageTextView != null)
                { 
                    return _pageTextView.RendersOwnSelection;
                } 
                return false; 
            }
        } 


        /// 
        ///  
        /// 
        internal override ReadOnlyCollection TextSegments 
        { 
            get
            { 
                if (!IsValid || IsPageMissing)
                {
                    return new ReadOnlyCollection(new List());
                } 
                return _pageTextView.TextSegments;
            } 
        } 

        ///  
        /// DocumentPageView associated with this TextView.
        /// 
        internal DocumentPageView DocumentPageView
        { 
            get { return _owner as DocumentPageView; }
        } 
 
        #endregion Internal Properties
 
        //-------------------------------------------------------------------
        //
        //  Private Methods
        // 
        //--------------------------------------------------------------------
 
        #region Private Methods 

        ///  
        /// Handler for Updated event raised by the inner TextView.
        /// 
        private void HandlePageTextViewUpdated(object sender, EventArgs e)
        { 
            Invariant.Assert(_pageTextView != null);
            if (sender == _pageTextView) 
            { 
                OnUpdated(EventArgs.Empty);
            } 
        }

        /// 
        /// Gets transform to ancestor 
        /// 
        private Transform GetTransformToAncestor() 
        { 
            Invariant.Assert(IsValid && !IsPageMissing);
            // NOTE: TransformToAncestor is safe (will never throw an exception). 
            Transform transform = _page.Visual.TransformToAncestor(_owner) as Transform;
            if (transform == null)
            {
                transform = Transform.Identity; 
            }
            return transform; 
        } 

        ///  
        /// Transforms point from inner scope.
        /// 
        private Point TransformToAncestor(Point point)
        { 
            Invariant.Assert(IsValid && !IsPageMissing);
            // NOTE: TransformToAncestor is safe (will never throw an exception). 
            GeneralTransform transform = _page.Visual.TransformToAncestor(_owner); 
            if (transform != null)
            { 
                point = transform.Transform(point);
            }
            return point;
        } 

        ///  
        /// Transforms rectangle from inner scope 
        /// 
        private Point TransformToDescendant(Point point) 
        {
            Invariant.Assert(IsValid && !IsPageMissing);
            // NOTE: TransformToAncestor is safe (will never throw an exception).
            GeneralTransform transform = _page.Visual.TransformToAncestor(_owner); 
            if (transform != null)
            { 
                transform = transform.Inverse; 
                if (transform != null)
                { 
                    point = transform.Transform(point);
                }
            }
            return point; 
        }
 
        ///  
        /// Gets updated offset at next page
        ///  
        /// 
        /// Current value of offset
        /// 
        /// Number of pages to move 
        /// 
        ///  
        /// Number of pages actually moved 
        /// 
        private double GetYOffsetAtNextPage(double offset, int count, out int pagesMoved) 
        {
            double newOffset = offset;
            pagesMoved = 0;
            if (_owner is IScrollInfo && ((IScrollInfo)_owner).ScrollOwner != null) 
            {
                IScrollInfo scrollInfo = (IScrollInfo)_owner; 
                double viewportHeight = scrollInfo.ViewportHeight; 
                double extentHeight = scrollInfo.ExtentHeight;
                if (count > 0) 
                {
                    while (pagesMoved < count)
                    {
                        if (DoubleUtil.LessThanOrClose(offset + viewportHeight, extentHeight)) 
                        {
                            newOffset += viewportHeight; 
                            pagesMoved++; 
                        }
                        else 
                        {
                            break;
                        }
                    } 
                }
                else 
                { 
                    while (Math.Abs(pagesMoved) < Math.Abs(count))
                    { 
                        if (DoubleUtil.GreaterThanOrClose(offset - viewportHeight, 0))
                        {
                            newOffset -= viewportHeight;
                            pagesMoved--; 
                        }
                        else 
                        { 
                            break;
                        } 
                    }
                }
            }
            return newOffset; 
        }
 
        #endregion Private Methods 

        //------------------------------------------------------------------- 
        //
        //  Private Properties
        //
        //------------------------------------------------------------------- 

        #region Private Properties 
 
        /// 
        /// Whether page is missing. 
        /// 
        private bool IsPageMissing
        {
            get { return (_page == DocumentPage.Missing); } 
        }
 
        #endregion Private Properties 

        //------------------------------------------------------------------- 
        //
        //  Private Fields
        //
        //-------------------------------------------------------------------- 

        #region Private Fields 
 
        /// 
        /// Root of layout structure visualizing content. 
        /// 
        private readonly UIElement _owner;

        ///  
        /// TextContainer representing content.
        ///  
        private readonly ITextContainer _textContainer; 

        ///  
        /// DocumentPage associated with this view.
        /// 
        private DocumentPage _page;
 
        /// 
        /// TextView associated with DocumentPage. 
        ///  
        private ITextView _pageTextView;
 
        #endregion Private Fields
    }
}
 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
// File: DocumentPageTextView.cs 
//
// Description: TextView implementation for DocumentPageView. 
// 
//---------------------------------------------------------------------------
 
using System;                               // InvalidOperationException, ...
using System.Collections.Generic;           // List
using System.Collections.ObjectModel;       // ReadOnlyCollection
using System.Windows;                       // Point, Rect, ... 
using System.Windows.Controls.Primitives;   // DocumentPageView
using System.Windows.Documents;             // ITextView, ITextContainer 
using System.Windows.Media;                 // VisualTreeHelper 
using MS.Internal.PtsHost;                  // BackgroundFormatInfo
 
namespace MS.Internal.Documents
{
    /// 
    /// TextView implementation for DocumentPageView. 
    /// 
    internal class DocumentPageTextView : TextViewBase 
    { 
        //-------------------------------------------------------------------
        // 
        //  Constructors
        //
        //-------------------------------------------------------------------
 
        #region Constructors
 
        ///  
        /// Constructor.
        ///  
        /// 
        /// Root of layout structure visualizing content of a page.
        /// 
        ///  
        /// TextContainer representing content.
        ///  
        internal DocumentPageTextView(DocumentPageView owner, ITextContainer textContainer) 
        {
            Invariant.Assert(owner != null && textContainer != null); 
            _owner = owner;
            _page = owner.DocumentPageInternal;
            _textContainer = textContainer;
            // Retrive inner TextView 
            if (_page is IServiceProvider)
            { 
                _pageTextView = ((IServiceProvider)_page).GetService(typeof(ITextView)) as ITextView; 
            }
            if (_pageTextView != null) 
            {
                _pageTextView.Updated += new EventHandler(HandlePageTextViewUpdated);
            }
        } 

        ///  
        /// Constructor. 
        /// 
        ///  
        /// Root of layout structure visualizing content of a page.
        /// 
        /// 
        /// TextContainer representing content. 
        /// 
        internal DocumentPageTextView(FlowDocumentView owner, ITextContainer textContainer) 
        { 
            Invariant.Assert(owner != null && textContainer != null);
            _owner = owner; 
            _page = owner.DocumentPage;
            _textContainer = textContainer;
            // Retrive inner TextView
            if (_page is IServiceProvider) 
            {
                _pageTextView = ((IServiceProvider)_page).GetService(typeof(ITextView)) as ITextView; 
            } 
            if (_pageTextView != null)
            { 
                _pageTextView.Updated += new EventHandler(HandlePageTextViewUpdated);
            }
        }
 
        #endregion Constructors
 
        //-------------------------------------------------------------------- 
        //
        //  Internal Methods 
        //
        //-------------------------------------------------------------------

        #region Internal Methods 

        ///  
        ///  
        /// 
        internal override ITextPointer GetTextPositionFromPoint(Point point, bool snapToText) 
        {
            // Verify that layout information is valid. Cannot continue if not valid.
            if (!IsValid)
            { 
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
            } 
            if (IsPageMissing) 
            {
                return null; 
            }
            // Transform to page coordinates.
            point = TransformToDescendant(point);
            return _pageTextView.GetTextPositionFromPoint(point, snapToText); 
        }
 
        ///  
        /// 
        ///  
        internal override Rect GetRawRectangleFromTextPosition(ITextPointer position, out Transform transform)
        {
            Rect rect;
            Transform pageTextViewTransform, ancestorTransform; 

            // Initialize transform to identity 
            transform = Transform.Identity; 

            // Verify that layout information is valid. Cannot continue if not valid. 
            if (!IsValid)
            {
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
            } 
            if (IsPageMissing)
            { 
                return Rect.Empty; 
            }
 
            rect = _pageTextView.GetRawRectangleFromTextPosition(position, out pageTextViewTransform);
            Invariant.Assert(pageTextViewTransform != null);
            ancestorTransform = GetTransformToAncestor();
            transform = GetAggregateTransform(pageTextViewTransform, ancestorTransform); 
            return rect;
        } 
 
        /// 
        ///  
        /// 
        internal override Geometry GetTightBoundingGeometryFromTextPositions(ITextPointer startPosition, ITextPointer endPosition)
        {
            //  verify that layout information is valid. Cannot continue if not valid. 
            if (!IsValid)
            { 
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout)); 
            }
 
            Geometry geometry = null;

            if (!IsPageMissing)
            { 
                geometry = _pageTextView.GetTightBoundingGeometryFromTextPositions(startPosition, endPosition);
                if (geometry != null) 
                { 
                    Transform transform = GetTransformToAncestor().AffineTransform;
                    CaretElement.AddTransformToGeometry(geometry, transform); 
                }
            }

            return (geometry); 
        }
 
        ///  
        /// 
        ///  
        internal override ITextPointer GetPositionAtNextLine(ITextPointer position, double suggestedX, int count, out double newSuggestedX, out int linesMoved)
        {
            ITextPointer positionOut;
            Point offset; 

            // Verify that layout information is valid. Cannot continue if not valid. 
            if (!IsValid) 
            {
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout)); 
            }
            if (IsPageMissing)
            {
                newSuggestedX = suggestedX; 
                linesMoved = 0;
                return position; 
            } 

            offset = TransformToDescendant(new Point(suggestedX, 0)); 
            suggestedX = offset.X;
            positionOut = _pageTextView.GetPositionAtNextLine(position, suggestedX, count, out newSuggestedX, out linesMoved);
            offset = TransformToAncestor(new Point(newSuggestedX, 0));
            newSuggestedX = offset.X; 

            return positionOut; 
        } 

        ///  
        /// 
        /// 
        internal override ITextPointer GetPositionAtNextPage(ITextPointer position, Point suggestedOffset, int count, out Point newSuggestedOffset, out int pagesMoved)
        { 
            ITextPointer positionOut = position;
            newSuggestedOffset = suggestedOffset; 
            Point offset = suggestedOffset; 
            pagesMoved = 0;
 
            if (count == 0)
            {
                return positionOut;
            } 

            // Verify that layout information is valid. Cannot continue if not valid. 
            if (!IsValid) 
            {
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout)); 
            }
            if (IsPageMissing)
            {
                return position; 
            }
 
            // Calculate distance from current position 
            offset.Y = GetYOffsetAtNextPage(offset.Y, count, out pagesMoved);
 
            if (pagesMoved != 0)
            {
                // Transfrom offset to _pageTextView's coordinate position, obtain position from _pageTextView and convert back
                offset = TransformToDescendant(offset); 
                positionOut = _pageTextView.GetTextPositionFromPoint(offset, true);
                Invariant.Assert(positionOut != null); 
                Rect rect = _pageTextView.GetRectangleFromTextPosition(position); 
                newSuggestedOffset = TransformToAncestor(new Point(rect.X, rect.Y));
            } 

            return positionOut;
        }
 
        /// 
        ///  
        ///  
        internal override bool IsAtCaretUnitBoundary(ITextPointer position)
        { 
            // Verify that layout information is valid. Cannot continue if not valid.
            if (!IsValid)
            {
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout)); 
            }
            if (IsPageMissing) 
            { 
                return false;
            } 
            return _pageTextView.IsAtCaretUnitBoundary(position);
        }

        ///  
        /// 
        ///  
        internal override ITextPointer GetNextCaretUnitPosition(ITextPointer position, LogicalDirection direction) 
        {
            // Verify that layout information is valid. Cannot continue if not valid. 
            if (!IsValid)
            {
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
            } 
            if (IsPageMissing)
            { 
                return null; 
            }
            return _pageTextView.GetNextCaretUnitPosition(position, direction); 
        }

        /// 
        ///  
        /// 
        internal override ITextPointer GetBackspaceCaretUnitPosition(ITextPointer position) 
        { 
            // Verify that layout information is valid. Cannot continue if not valid.
            if (!IsValid) 
            {
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
            }
            if (IsPageMissing) 
            {
                return null; 
            } 
            return _pageTextView.GetBackspaceCaretUnitPosition(position);
        } 

        /// 
        /// 
        ///  
        internal override TextSegment GetLineRange(ITextPointer position)
        { 
            // Verify that layout information is valid. Cannot continue if not valid. 
            if (!IsValid)
            { 
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
            }
            if (IsPageMissing)
            { 
                return TextSegment.Null;
            } 
            return _pageTextView.GetLineRange(position); 
        }
 
        /// 
        /// 
        /// 
        internal override ReadOnlyCollection GetGlyphRuns(ITextPointer start, ITextPointer end) 
        {
            // Verify that layout information is valid. Cannot continue if not valid. 
            if (!IsValid) 
            {
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout)); 
            }
            if (IsPageMissing)
            {
                return new ReadOnlyCollection(new List()); 
            }
            return _pageTextView.GetGlyphRuns(start, end); 
        } 

        ///  
        /// 
        /// 
        internal override bool Contains(ITextPointer position)
        { 
            // Verify that layout information is valid. Cannot continue if not valid.
            if (!IsValid) 
            { 
                throw new InvalidOperationException(SR.Get(SRID.TextViewInvalidLayout));
            } 
            if (IsPageMissing)
            {
                return false;
            } 
            return _pageTextView.Contains(position);
        } 
 
        /// 
        /// Handler for PageConnected raised by the DocumentPageView. 
        /// 
        internal void OnPageConnected()
        {
            OnPageDisconnected(); 
            if (_owner is DocumentPageView)
            { 
                _page = ((DocumentPageView)_owner).DocumentPageInternal; 
            }
            else if (_owner is FlowDocumentView) 
            {
                _page = ((FlowDocumentView)_owner).DocumentPage;
            }
 
            if (_page is IServiceProvider)
            { 
                _pageTextView = ((IServiceProvider)_page).GetService(typeof(ITextView)) as ITextView; 
            }
            if (_pageTextView != null) 
            {
                _pageTextView.Updated += new EventHandler(HandlePageTextViewUpdated);
            }
            if (IsValid) 
            {
                OnUpdated(EventArgs.Empty); 
            } 
        }
 
        /// 
        /// Handler for PageDisconnected raised by the DocumentPageView.
        /// 
        internal void OnPageDisconnected() 
        {
            if (_pageTextView != null) 
            { 
                _pageTextView.Updated -= new EventHandler(HandlePageTextViewUpdated);
            } 
            _pageTextView = null;
            _page = null;
        }
 
        /// 
        /// Handler for TransformChanged raised by the DocumentPageView. 
        ///  
        internal void OnTransformChanged()
        { 
            if (IsValid)
            {
                OnUpdated(EventArgs.Empty);
            } 
        }
 
        ///  
        /// 
        ///  
        internal override bool Validate()
        {
            if (!_owner.IsMeasureValid || !_owner.IsArrangeValid)
            { 
                _owner.UpdateLayout();
            } 
            return (_pageTextView != null && _pageTextView.Validate()); 
        }
 
        /// 
        /// 
        /// 
        internal override bool Validate(ITextPointer position) 
        {
            FlowDocumentView owner = _owner as FlowDocumentView; 
            bool isValid; 

            if (owner == null || owner.Document == null) 
            {
                isValid = base.Validate(position);
            }
            else 
            {
                if (Validate()) 
                { 
                    BackgroundFormatInfo backgroundFormatInfo = owner.Document.StructuralCache.BackgroundFormatInfo;
                    FlowDocumentFormatter formatter = owner.Document.BottomlessFormatter; 

                    int lastCPInterrupted = -1;

                    while (this.IsValid && !Contains(position)) 
                    {
                        backgroundFormatInfo.BackgroundFormat(formatter, true /* ignoreThrottle */); 
                        _owner.UpdateLayout(); // May invalidate the view. 

                        // Break if background layout is not progressing. 
                        // There are some edge cases where Validate() == true, but background
                        // layout will not progress (such as collapsed text in a tree view).
                        if (backgroundFormatInfo.CPInterrupted <= lastCPInterrupted)
                        { 
                            // CPInterrupted is reset to -1 when background layout finishes, so
                            // check explicitly below to see if the position is valid or not. 
                            break; 
                        }
                        lastCPInterrupted = backgroundFormatInfo.CPInterrupted; 
                    }
                }

                isValid = this.IsValid && Contains(position); 
            }
 
            return isValid; 
        }
 
        /// 
        /// 
        /// 
        internal override void ThrottleBackgroundTasksForUserInput() 
        {
            FlowDocumentView owner = _owner as FlowDocumentView; 
 
            if (owner != null && owner.Document != null)
            { 
                owner.Document.StructuralCache.ThrottleBackgroundFormatting();
            }
        }
 
        #endregion Internal Methods
 
        //-------------------------------------------------------------------- 
        //
        //  Internal Properties 
        //
        //--------------------------------------------------------------------

        #region Internal Properties 

        ///  
        ///  
        /// 
        internal override UIElement RenderScope 
        {
            get { return _owner; }
        }
 
        /// 
        ///  
        ///  
        internal override ITextContainer TextContainer
        { 
            get { return _textContainer; }
        }

        ///  
        /// 
        ///  
        internal override bool IsValid 
        {
            get 
            {
                if (!_owner.IsMeasureValid || !_owner.IsArrangeValid || _page == null)
                {
                    return false; 
                }
                if (IsPageMissing) 
                { 
                    return true;
                } 
                return (_pageTextView != null && _pageTextView.IsValid);
            }
        }
 
        /// 
        ///  
        ///  
        internal override bool RendersOwnSelection
        { 
            get
            {
                if (_pageTextView != null)
                { 
                    return _pageTextView.RendersOwnSelection;
                } 
                return false; 
            }
        } 


        /// 
        ///  
        /// 
        internal override ReadOnlyCollection TextSegments 
        { 
            get
            { 
                if (!IsValid || IsPageMissing)
                {
                    return new ReadOnlyCollection(new List());
                } 
                return _pageTextView.TextSegments;
            } 
        } 

        ///  
        /// DocumentPageView associated with this TextView.
        /// 
        internal DocumentPageView DocumentPageView
        { 
            get { return _owner as DocumentPageView; }
        } 
 
        #endregion Internal Properties
 
        //-------------------------------------------------------------------
        //
        //  Private Methods
        // 
        //--------------------------------------------------------------------
 
        #region Private Methods 

        ///  
        /// Handler for Updated event raised by the inner TextView.
        /// 
        private void HandlePageTextViewUpdated(object sender, EventArgs e)
        { 
            Invariant.Assert(_pageTextView != null);
            if (sender == _pageTextView) 
            { 
                OnUpdated(EventArgs.Empty);
            } 
        }

        /// 
        /// Gets transform to ancestor 
        /// 
        private Transform GetTransformToAncestor() 
        { 
            Invariant.Assert(IsValid && !IsPageMissing);
            // NOTE: TransformToAncestor is safe (will never throw an exception). 
            Transform transform = _page.Visual.TransformToAncestor(_owner) as Transform;
            if (transform == null)
            {
                transform = Transform.Identity; 
            }
            return transform; 
        } 

        ///  
        /// Transforms point from inner scope.
        /// 
        private Point TransformToAncestor(Point point)
        { 
            Invariant.Assert(IsValid && !IsPageMissing);
            // NOTE: TransformToAncestor is safe (will never throw an exception). 
            GeneralTransform transform = _page.Visual.TransformToAncestor(_owner); 
            if (transform != null)
            { 
                point = transform.Transform(point);
            }
            return point;
        } 

        ///  
        /// Transforms rectangle from inner scope 
        /// 
        private Point TransformToDescendant(Point point) 
        {
            Invariant.Assert(IsValid && !IsPageMissing);
            // NOTE: TransformToAncestor is safe (will never throw an exception).
            GeneralTransform transform = _page.Visual.TransformToAncestor(_owner); 
            if (transform != null)
            { 
                transform = transform.Inverse; 
                if (transform != null)
                { 
                    point = transform.Transform(point);
                }
            }
            return point; 
        }
 
        ///  
        /// Gets updated offset at next page
        ///  
        /// 
        /// Current value of offset
        /// 
        /// Number of pages to move 
        /// 
        ///  
        /// Number of pages actually moved 
        /// 
        private double GetYOffsetAtNextPage(double offset, int count, out int pagesMoved) 
        {
            double newOffset = offset;
            pagesMoved = 0;
            if (_owner is IScrollInfo && ((IScrollInfo)_owner).ScrollOwner != null) 
            {
                IScrollInfo scrollInfo = (IScrollInfo)_owner; 
                double viewportHeight = scrollInfo.ViewportHeight; 
                double extentHeight = scrollInfo.ExtentHeight;
                if (count > 0) 
                {
                    while (pagesMoved < count)
                    {
                        if (DoubleUtil.LessThanOrClose(offset + viewportHeight, extentHeight)) 
                        {
                            newOffset += viewportHeight; 
                            pagesMoved++; 
                        }
                        else 
                        {
                            break;
                        }
                    } 
                }
                else 
                { 
                    while (Math.Abs(pagesMoved) < Math.Abs(count))
                    { 
                        if (DoubleUtil.GreaterThanOrClose(offset - viewportHeight, 0))
                        {
                            newOffset -= viewportHeight;
                            pagesMoved--; 
                        }
                        else 
                        { 
                            break;
                        } 
                    }
                }
            }
            return newOffset; 
        }
 
        #endregion Private Methods 

        //------------------------------------------------------------------- 
        //
        //  Private Properties
        //
        //------------------------------------------------------------------- 

        #region Private Properties 
 
        /// 
        /// Whether page is missing. 
        /// 
        private bool IsPageMissing
        {
            get { return (_page == DocumentPage.Missing); } 
        }
 
        #endregion Private Properties 

        //------------------------------------------------------------------- 
        //
        //  Private Fields
        //
        //-------------------------------------------------------------------- 

        #region Private Fields 
 
        /// 
        /// Root of layout structure visualizing content. 
        /// 
        private readonly UIElement _owner;

        ///  
        /// TextContainer representing content.
        ///  
        private readonly ITextContainer _textContainer; 

        ///  
        /// DocumentPage associated with this view.
        /// 
        private DocumentPage _page;
 
        /// 
        /// TextView associated with DocumentPage. 
        ///  
        private ITextView _pageTextView;
 
        #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