TextSelectionHelper.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / MS / Internal / Annotations / Anchoring / TextSelectionHelper.cs / 1 / TextSelectionHelper.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//     TextSelectionHelper is a helper class used by TextSelectionProvcrssor 
//     and DynamicSelectionProcessor
// 
// History:
//  03/28/2004: ssimova: Created based on TextSelectionProcessor code
//
//----------------------------------------------------------------------------- 
using System;
using System.Collections; 
using System.Collections.Generic; 
using System.Diagnostics;
using System.Globalization; 
using System.Windows;
using System.Windows.Annotations;
using System.Windows.Annotations.Storage;
using MS.Internal.Annotations.Component; 
using System.Windows.Controls;
using System.Windows.Controls.Primitives; 
using System.Windows.Documents; 
using System.Windows.Media;
using System.Xml; 
using MS.Internal.Documents;
using MS.Utility;

 
namespace MS.Internal.Annotations.Anchoring
{ 
 
    /// 
    ///     TextSelectionHelper uses TextAnchors to represent portions 
    ///     of text that are anchors.  It produces locator parts that
    ///     represent these TextAnchors and can generate TextAnchors from
    ///     the locator parts.
    ///  
    internal class TextSelectionHelper
    { 
        //----------------------------------------------------- 
        //
        //  Constructors 
        //
        //-----------------------------------------------------

        #region Constructors 

        ///  
        /// This ctor is added to prevent the compiler from 
        /// generating a public default ctor. This class
        /// should not be instantiated 
        /// 
        private TextSelectionHelper() { }

        #endregion Constructors 

        //------------------------------------------------------ 
        // 
        //  Public Methods
        // 
        //-----------------------------------------------------

        #region Public Methods
 
        /// 
        ///     Merges the two anchors into one, if possible. 
        ///  
        /// anchor to merge 
        /// other anchor to merge  
        /// new anchor that contains the data from both
        /// anchor1 and anchor2
        /// true if the anchors were merged, false otherwise
        ///  
        /// anchor1 or anchor2 are null
        public static bool MergeSelections(Object anchor1, Object anchor2, out Object newAnchor) 
        { 
            TextAnchor firstAnchor = anchor1 as TextAnchor;
            TextAnchor secondAnchor = anchor2 as TextAnchor; 

            if ((anchor1 != null) && (firstAnchor == null))
                throw new ArgumentException(SR.Get(SRID.WrongSelectionType), "anchor1: type = " + anchor1.GetType().ToString());
 
            if ((anchor2 != null) && (secondAnchor == null))
                throw new ArgumentException(SR.Get(SRID.WrongSelectionType), "Anchor2: type = " + anchor2.GetType().ToString()); 
 
            if (firstAnchor == null)
            { 
                newAnchor = secondAnchor;
                return newAnchor != null;
            }
 
            if (secondAnchor == null)
            { 
                newAnchor = firstAnchor; 
                return newAnchor != null;
            } 

            newAnchor = TextAnchor.ExclusiveUnion(firstAnchor, secondAnchor);

            return true; 
        }
 
 
        /// 
        ///     Gets the tree elements spanned by the selection. 
        /// 
        /// the selection to examine
        /// a list of elements spanned by the selection; never returns
        /// null 
        /// selection is null
        /// selection is of wrong type 
        public static IList GetSelectedNodes(Object selection) 
        {
            if (selection == null) 
                throw new ArgumentNullException("selection");

            IList segments;
            ITextPointer start = null; 
            ITextPointer end = null;
 
            CheckSelection(selection, out start, out end, out segments); 

            IList list = new List(); 

            // If the selection is of length 0, then we simply add the parent of the
            // text container and return.
            if (start.CompareTo(end) == 0) 
            {
                list.Add(((TextPointer)start).Parent); 
 
                return list;
            } 

            TextPointer current = (TextPointer)start.CreatePointer();
            while (((ITextPointer)current).CompareTo(end) < 0)
            { 
                DependencyObject node = current.Parent;
 
                if (!list.Contains(node)) 
                {
                    list.Add(node); 
                }

                current.MoveToNextContextPosition(LogicalDirection.Forward);
            } 

            return list; 
        } 

        ///  
        ///     Gets the parent element of this selection.
        /// 
        /// the selection to examine
        /// the parent element of the selection; can be null 
        /// selection is null
        /// selection is of wrong type 
        public static UIElement GetParent(Object selection) 
        {
            if (selection == null) 
                throw new ArgumentNullException("selection");

            ITextPointer start = null;
            ITextPointer end = null; 
            IList segments;
 
            CheckSelection(selection, out start, out end, out segments); 

            return GetParent(start); 
        }


        ///  
        ///     Gets the parent element of ITextPointer.
        ///  
        /// the pointer to examine 
        /// the parent element of this pointer; can be null
        /// pointer is null 
        public static UIElement GetParent(ITextPointer pointer)
        {
            if (pointer == null)
                throw new ArgumentNullException("pointer"); 

            DependencyObject document = pointer.TextContainer.Parent; 
            DependencyObject parent = PathNode.GetParent(document); 

            FlowDocumentScrollViewer scrollViewer = parent as FlowDocumentScrollViewer; 
            if (scrollViewer != null)
            {
                return (UIElement)scrollViewer.ScrollViewer.Content;
            } 

            // Special case - for paginated content we want the DocumentPageHost for the 
            // specific page instead of the viewer. 
            DocumentViewerBase documentViewerBase = parent as DocumentViewerBase;
            if (documentViewerBase != null) 
            {
                int pageNumber;

                // We get the content again here GetPointerPage handles 
                // special cases like FixedDocumentSequences
                IDocumentPaginatorSource content = GetPointerPage(pointer.CreatePointer(LogicalDirection.Forward), out pageNumber); 
 
                if (pageNumber >= 0)
                { 
                    foreach (DocumentPageView dpv in documentViewerBase.PageViews)
                    {
                        if (dpv.PageNumber == pageNumber)
                        { 
                            // DPVs always have one child - the DocumentPageHost
                            int count = VisualTreeHelper.GetChildrenCount(dpv); 
                            Invariant.Assert(count == 1); 
                            return VisualTreeHelper.GetChild(dpv, 0) as DocumentPageHost;
                        } 
                    }
                    // Page must not be visible.
                    return null;
                } 
            }
 
            return parent as UIElement; 
        }
 
        /// 
        ///  Gets the anchor point for the selection
        /// 
        /// the anchor to examine 
        /// 
        /// The anchor point of the selection; 
        /// If there is no valid AnchorPoint returns Point(Double.NaN, Double.NaN). 
        /// 
        /// anchor is null 
        /// anchor is of wrong type
        public static Point GetAnchorPoint(Object selection)
        {
            if (selection == null) 
                throw new ArgumentNullException("selection");
 
            TextAnchor anchor = selection as TextAnchor; 

            if (anchor == null) 
                throw new ArgumentException(SR.Get(SRID.WrongSelectionType), "selection");

            return GetAnchorPointForPointer(anchor.Start.CreatePointer(LogicalDirection.Forward));
        } 

        ///  
        ///  Gets the anchor point for the text pointer 
        /// 
        /// the pointer to examine 
        /// 
        /// The anchor point of the text pointer
        /// 
        /// pointer is null 
        public static Point GetAnchorPointForPointer(ITextPointer pointer)
        { 
            if (pointer == null) 
                throw new ArgumentNullException("pointer");
 
            Rect rect = GetAnchorRectangle(pointer);

            if (rect != Rect.Empty)
            { 
                return new Point(rect.Left, rect.Top + rect.Height);
            } 
 
            return new Point(0, 0);
        } 


        /// 
        ///  Gets a point for the text pointer that can be turned back into 
        ///  the TextPointer at a later time.
        ///  
        /// the pointer to examine 
        /// 
        /// A point that can be turned back into the TextPointer at a later time 
        /// 
        /// pointer is null
        public static Point GetPointForPointer(ITextPointer pointer)
        { 
            if (pointer == null)
                throw new ArgumentNullException("pointer"); 
 
            Rect rect = GetAnchorRectangle(pointer);
 
            if (rect != Rect.Empty)
            {
                return new Point(rect.Left, rect.Top + rect.Height / 2);
            } 

            return new Point(0, 0); 
        } 

        ///  
        ///  Gets the rectangle for this ITextPointer
        /// 
        /// the pointer to examine
        ///  
        /// The anchor point of the selection;
        /// If there is no valid AnchorPoint returns Point(Double.NaN, Double.NaN). 
        ///  
        /// pointer is null
        public static Rect GetAnchorRectangle(ITextPointer pointer) 
        {
            if (pointer == null)
                throw new ArgumentNullException("pointer");
            bool extension = false; 

            ITextView textView = GetDocumentPageTextView(pointer); 
            if (pointer.CompareTo(pointer.TextContainer.End) == 0) 
            {
                //we can not get rectangle for the end of the TextContainer 
                //so get the last symbol
                Point endPoint = new Point(Double.MaxValue, Double.MaxValue);
                pointer = textView.GetTextPositionFromPoint(endPoint, true);
                //we need to move the resulting rectangle at half space because 
                //the geometry calculating function does the same
                extension = true; 
            } 
            if (textView != null && textView.IsValid && TextDocumentView.Contains(pointer, textView.TextSegments))
            { 
                Rect rect = textView.GetRectangleFromTextPosition(pointer);
                if (extension && rect != Rect.Empty)
                {
                    rect.X += rect.Height / 2.0; 
                }
                return rect; 
            } 

            return Rect.Empty; 
        }

        /// 
        /// Gets DocumentViewerBase and a page number for specified TextPointer 
        /// 
        /// a TP from the container 
        /// the page number 
        /// DocumentViewerBase
        public static IDocumentPaginatorSource GetPointerPage(ITextPointer pointer, out int pageNumber) 
        {
            Invariant.Assert(pointer != null, "unknown pointer");

            IDocumentPaginatorSource idp = pointer.TextContainer.Parent as IDocumentPaginatorSource; 
            FixedDocument fixedDoc = idp as FixedDocument;
            if (fixedDoc != null) 
            { 
                FixedDocumentSequence sequence = fixedDoc.Parent as FixedDocumentSequence;
                if (sequence != null) 
                    idp = sequence;
            }

            Invariant.Assert(idp != null); 
            DynamicDocumentPaginator ddp = idp.DocumentPaginator as DynamicDocumentPaginator;
            pageNumber = ddp != null ? ddp.GetPageNumber((ContentPosition)pointer) : -1; 
 
            return idp;
        } 

        #endregion Public Methods

        //------------------------------------------------------ 
        //
        //  Internal Methods 
        // 
        //------------------------------------------------------
        #region Internal Methods 

        /// 
        /// Gets the start, end and text segments of the selection.  Throws an exception if the
        /// selection is of the wrong type. 
        /// 
        internal static void CheckSelection(object selection, out ITextPointer start, out ITextPointer end, out IList segments) 
        { 
            ITextRange textRange = selection as ITextRange;
 
            if (textRange != null)
            {
                start = textRange.Start;
                end = textRange.End; 
                segments = textRange.TextSegments;
            } 
            else 
            {
                TextAnchor textAnchor = selection as TextAnchor; 
                if (textAnchor == null)
                    throw new ArgumentException(SR.Get(SRID.WrongSelectionType), "selection");

                start = textAnchor.Start; 
                end = textAnchor.End;
                segments = textAnchor.TextSegments; 
            } 
        }
 
        /// 
        /// Gets the TextView exposed by the page where this pointer lives
        /// 
        /// the pointer 
        /// the TextView
        internal static ITextView GetDocumentPageTextView(ITextPointer pointer) 
        { 
            int pageNumber;
 
            DependencyObject content = pointer.TextContainer.Parent as DependencyObject;
            if (content != null)
            {
                FlowDocumentScrollViewer scrollViewer = PathNode.GetParent(content) as FlowDocumentScrollViewer; 
                if (scrollViewer != null)
                { 
                    IServiceProvider provider = scrollViewer.ScrollViewer.Content as IServiceProvider; 
                    Invariant.Assert(provider != null, "FlowDocumentScrollViewer should be an IServiceProvider.");
                    return provider.GetService(typeof(ITextView)) as ITextView; 
                }
            }

            IDocumentPaginatorSource idp = GetPointerPage(pointer, out pageNumber); 
            if (idp != null && pageNumber >= 0)
            { 
                DocumentPage docPage = idp.DocumentPaginator.GetPage(pageNumber); 
                IServiceProvider isp = docPage as IServiceProvider;
                if (isp != null) 
                    return isp.GetService(typeof(ITextView)) as ITextView;
            }

            return null; 
        }
 
        ///  
        /// Gets a list of ITextViews spanned by this text segment
        ///  
        /// the text segment
        /// the TextViews list
        internal static List GetDocumentPageTextViews(TextSegment segment)
        { 
            List res = null;
            int startPageNumber, endPageNumber; 
 
            //revert the logical direction of the pointers
            ITextPointer start = segment.Start.CreatePointer(LogicalDirection.Forward); 
            ITextPointer end = segment.End.CreatePointer(LogicalDirection.Backward);

            DependencyObject content = start.TextContainer.Parent as DependencyObject;
            if (content != null) 
            {
                FlowDocumentScrollViewer scrollViewer = PathNode.GetParent(content) as FlowDocumentScrollViewer; 
                if (scrollViewer != null) 
                {
                    IServiceProvider provider = scrollViewer.ScrollViewer.Content as IServiceProvider; 
                    Invariant.Assert(provider != null, "FlowDocumentScrollViewer should be an IServiceProvider.");
                    res = new List(1);
                    res.Add(provider.GetService(typeof(ITextView)) as ITextView);
                    return res; 
                }
            } 
 
            IDocumentPaginatorSource idp = GetPointerPage(start, out startPageNumber);
            DynamicDocumentPaginator ddp = idp.DocumentPaginator as DynamicDocumentPaginator; 
            endPageNumber = ddp != null ? ddp.GetPageNumber((ContentPosition)end) : -1;

            if (startPageNumber == -1 || endPageNumber == -1)
            { 
                // If either page couldn't be found, we return an empty list.  This
                // could be caused by a failure in paginating the document. 
                res = new List(0); 
            }
            else if (startPageNumber == endPageNumber) 
            {
                res = ProcessSinglePage(idp, startPageNumber);
            }
            else 
            {
                res = ProcessMultiplePages(idp, startPageNumber, endPageNumber); 
            } 

            return res; 
        }

        #endregion Internal Methods
 
        //-----------------------------------------------------
        // 
        //  Private Methods 
        //
        //------------------------------------------------------ 
        #region Private Methods

        /// 
        /// Gets a single page TextView throug the idp.GetPage. cALL this API only when 
        /// it is sure that the page is loaded
        ///  
        /// IDocumentPaginatorSource 
        /// page number
        /// returns a list of one view 
        private static List ProcessSinglePage(IDocumentPaginatorSource idp, int pageNumber)
        {
            Invariant.Assert(idp != null, "IDocumentPaginatorSource is null");
 
            DocumentPage docPage = idp.DocumentPaginator.GetPage(pageNumber);
            IServiceProvider isp = docPage as IServiceProvider; 
            List res = null; 
            if (isp != null)
            { 
                res = new List(1);
                ITextView view = isp.GetService(typeof(ITextView)) as ITextView;
                if (view != null)
                    res.Add(view); 
            }
 
            return res; 
        }
 
        /// 
        /// Gets existing views for pages from start to end. Scans only existing view to
        /// avoid loading of unloaded pages.
        ///  
        /// IDocumentPaginatorSource
        /// start page number 
        /// end page number 
        /// returns a list of text views
        private static List ProcessMultiplePages(IDocumentPaginatorSource idp, int startPageNumber, int endPageNumber) 
        {
            Invariant.Assert(idp != null, "IDocumentPaginatorSource is null");

            //now get available views 
            DocumentViewerBase viewer = PathNode.GetParent(idp as DependencyObject) as DocumentViewerBase;
            Invariant.Assert(viewer != null, "DocumentViewer not found"); 
 
            // If the pages for the text segment are reversed (possibly a floater where the floater
            // reflow on to a page that comes after its anchor) we just swap them 
            if (endPageNumber < startPageNumber)
            {
                int temp = endPageNumber;
                endPageNumber = startPageNumber; 
                startPageNumber = temp;
            } 
 
            List res = null;
            if (idp != null && startPageNumber >= 0 && endPageNumber >= startPageNumber) 
            {
                res = new List(endPageNumber - startPageNumber + 1);
                for (int pageNb = startPageNumber; pageNb <= endPageNumber; pageNb++)
                { 
                    DocumentPageView view = AnnotationHelper.FindView(viewer, pageNb);
                    if (view != null) 
                    { 
                        IServiceProvider serviceProvider = view.DocumentPage as IServiceProvider;
                        if (serviceProvider != null) 
                        {
                            ITextView textView = serviceProvider.GetService(typeof(ITextView)) as ITextView;
                            if (textView != null)
                                res.Add(textView); 
                        }
                    } 
                } 
            }
 
            return res;
        }

        #endregion Private Methods 

    } 
} 


// 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.
//  
//
// Description: 
//     TextSelectionHelper is a helper class used by TextSelectionProvcrssor 
//     and DynamicSelectionProcessor
// 
// History:
//  03/28/2004: ssimova: Created based on TextSelectionProcessor code
//
//----------------------------------------------------------------------------- 
using System;
using System.Collections; 
using System.Collections.Generic; 
using System.Diagnostics;
using System.Globalization; 
using System.Windows;
using System.Windows.Annotations;
using System.Windows.Annotations.Storage;
using MS.Internal.Annotations.Component; 
using System.Windows.Controls;
using System.Windows.Controls.Primitives; 
using System.Windows.Documents; 
using System.Windows.Media;
using System.Xml; 
using MS.Internal.Documents;
using MS.Utility;

 
namespace MS.Internal.Annotations.Anchoring
{ 
 
    /// 
    ///     TextSelectionHelper uses TextAnchors to represent portions 
    ///     of text that are anchors.  It produces locator parts that
    ///     represent these TextAnchors and can generate TextAnchors from
    ///     the locator parts.
    ///  
    internal class TextSelectionHelper
    { 
        //----------------------------------------------------- 
        //
        //  Constructors 
        //
        //-----------------------------------------------------

        #region Constructors 

        ///  
        /// This ctor is added to prevent the compiler from 
        /// generating a public default ctor. This class
        /// should not be instantiated 
        /// 
        private TextSelectionHelper() { }

        #endregion Constructors 

        //------------------------------------------------------ 
        // 
        //  Public Methods
        // 
        //-----------------------------------------------------

        #region Public Methods
 
        /// 
        ///     Merges the two anchors into one, if possible. 
        ///  
        /// anchor to merge 
        /// other anchor to merge  
        /// new anchor that contains the data from both
        /// anchor1 and anchor2
        /// true if the anchors were merged, false otherwise
        ///  
        /// anchor1 or anchor2 are null
        public static bool MergeSelections(Object anchor1, Object anchor2, out Object newAnchor) 
        { 
            TextAnchor firstAnchor = anchor1 as TextAnchor;
            TextAnchor secondAnchor = anchor2 as TextAnchor; 

            if ((anchor1 != null) && (firstAnchor == null))
                throw new ArgumentException(SR.Get(SRID.WrongSelectionType), "anchor1: type = " + anchor1.GetType().ToString());
 
            if ((anchor2 != null) && (secondAnchor == null))
                throw new ArgumentException(SR.Get(SRID.WrongSelectionType), "Anchor2: type = " + anchor2.GetType().ToString()); 
 
            if (firstAnchor == null)
            { 
                newAnchor = secondAnchor;
                return newAnchor != null;
            }
 
            if (secondAnchor == null)
            { 
                newAnchor = firstAnchor; 
                return newAnchor != null;
            } 

            newAnchor = TextAnchor.ExclusiveUnion(firstAnchor, secondAnchor);

            return true; 
        }
 
 
        /// 
        ///     Gets the tree elements spanned by the selection. 
        /// 
        /// the selection to examine
        /// a list of elements spanned by the selection; never returns
        /// null 
        /// selection is null
        /// selection is of wrong type 
        public static IList GetSelectedNodes(Object selection) 
        {
            if (selection == null) 
                throw new ArgumentNullException("selection");

            IList segments;
            ITextPointer start = null; 
            ITextPointer end = null;
 
            CheckSelection(selection, out start, out end, out segments); 

            IList list = new List(); 

            // If the selection is of length 0, then we simply add the parent of the
            // text container and return.
            if (start.CompareTo(end) == 0) 
            {
                list.Add(((TextPointer)start).Parent); 
 
                return list;
            } 

            TextPointer current = (TextPointer)start.CreatePointer();
            while (((ITextPointer)current).CompareTo(end) < 0)
            { 
                DependencyObject node = current.Parent;
 
                if (!list.Contains(node)) 
                {
                    list.Add(node); 
                }

                current.MoveToNextContextPosition(LogicalDirection.Forward);
            } 

            return list; 
        } 

        ///  
        ///     Gets the parent element of this selection.
        /// 
        /// the selection to examine
        /// the parent element of the selection; can be null 
        /// selection is null
        /// selection is of wrong type 
        public static UIElement GetParent(Object selection) 
        {
            if (selection == null) 
                throw new ArgumentNullException("selection");

            ITextPointer start = null;
            ITextPointer end = null; 
            IList segments;
 
            CheckSelection(selection, out start, out end, out segments); 

            return GetParent(start); 
        }


        ///  
        ///     Gets the parent element of ITextPointer.
        ///  
        /// the pointer to examine 
        /// the parent element of this pointer; can be null
        /// pointer is null 
        public static UIElement GetParent(ITextPointer pointer)
        {
            if (pointer == null)
                throw new ArgumentNullException("pointer"); 

            DependencyObject document = pointer.TextContainer.Parent; 
            DependencyObject parent = PathNode.GetParent(document); 

            FlowDocumentScrollViewer scrollViewer = parent as FlowDocumentScrollViewer; 
            if (scrollViewer != null)
            {
                return (UIElement)scrollViewer.ScrollViewer.Content;
            } 

            // Special case - for paginated content we want the DocumentPageHost for the 
            // specific page instead of the viewer. 
            DocumentViewerBase documentViewerBase = parent as DocumentViewerBase;
            if (documentViewerBase != null) 
            {
                int pageNumber;

                // We get the content again here GetPointerPage handles 
                // special cases like FixedDocumentSequences
                IDocumentPaginatorSource content = GetPointerPage(pointer.CreatePointer(LogicalDirection.Forward), out pageNumber); 
 
                if (pageNumber >= 0)
                { 
                    foreach (DocumentPageView dpv in documentViewerBase.PageViews)
                    {
                        if (dpv.PageNumber == pageNumber)
                        { 
                            // DPVs always have one child - the DocumentPageHost
                            int count = VisualTreeHelper.GetChildrenCount(dpv); 
                            Invariant.Assert(count == 1); 
                            return VisualTreeHelper.GetChild(dpv, 0) as DocumentPageHost;
                        } 
                    }
                    // Page must not be visible.
                    return null;
                } 
            }
 
            return parent as UIElement; 
        }
 
        /// 
        ///  Gets the anchor point for the selection
        /// 
        /// the anchor to examine 
        /// 
        /// The anchor point of the selection; 
        /// If there is no valid AnchorPoint returns Point(Double.NaN, Double.NaN). 
        /// 
        /// anchor is null 
        /// anchor is of wrong type
        public static Point GetAnchorPoint(Object selection)
        {
            if (selection == null) 
                throw new ArgumentNullException("selection");
 
            TextAnchor anchor = selection as TextAnchor; 

            if (anchor == null) 
                throw new ArgumentException(SR.Get(SRID.WrongSelectionType), "selection");

            return GetAnchorPointForPointer(anchor.Start.CreatePointer(LogicalDirection.Forward));
        } 

        ///  
        ///  Gets the anchor point for the text pointer 
        /// 
        /// the pointer to examine 
        /// 
        /// The anchor point of the text pointer
        /// 
        /// pointer is null 
        public static Point GetAnchorPointForPointer(ITextPointer pointer)
        { 
            if (pointer == null) 
                throw new ArgumentNullException("pointer");
 
            Rect rect = GetAnchorRectangle(pointer);

            if (rect != Rect.Empty)
            { 
                return new Point(rect.Left, rect.Top + rect.Height);
            } 
 
            return new Point(0, 0);
        } 


        /// 
        ///  Gets a point for the text pointer that can be turned back into 
        ///  the TextPointer at a later time.
        ///  
        /// the pointer to examine 
        /// 
        /// A point that can be turned back into the TextPointer at a later time 
        /// 
        /// pointer is null
        public static Point GetPointForPointer(ITextPointer pointer)
        { 
            if (pointer == null)
                throw new ArgumentNullException("pointer"); 
 
            Rect rect = GetAnchorRectangle(pointer);
 
            if (rect != Rect.Empty)
            {
                return new Point(rect.Left, rect.Top + rect.Height / 2);
            } 

            return new Point(0, 0); 
        } 

        ///  
        ///  Gets the rectangle for this ITextPointer
        /// 
        /// the pointer to examine
        ///  
        /// The anchor point of the selection;
        /// If there is no valid AnchorPoint returns Point(Double.NaN, Double.NaN). 
        ///  
        /// pointer is null
        public static Rect GetAnchorRectangle(ITextPointer pointer) 
        {
            if (pointer == null)
                throw new ArgumentNullException("pointer");
            bool extension = false; 

            ITextView textView = GetDocumentPageTextView(pointer); 
            if (pointer.CompareTo(pointer.TextContainer.End) == 0) 
            {
                //we can not get rectangle for the end of the TextContainer 
                //so get the last symbol
                Point endPoint = new Point(Double.MaxValue, Double.MaxValue);
                pointer = textView.GetTextPositionFromPoint(endPoint, true);
                //we need to move the resulting rectangle at half space because 
                //the geometry calculating function does the same
                extension = true; 
            } 
            if (textView != null && textView.IsValid && TextDocumentView.Contains(pointer, textView.TextSegments))
            { 
                Rect rect = textView.GetRectangleFromTextPosition(pointer);
                if (extension && rect != Rect.Empty)
                {
                    rect.X += rect.Height / 2.0; 
                }
                return rect; 
            } 

            return Rect.Empty; 
        }

        /// 
        /// Gets DocumentViewerBase and a page number for specified TextPointer 
        /// 
        /// a TP from the container 
        /// the page number 
        /// DocumentViewerBase
        public static IDocumentPaginatorSource GetPointerPage(ITextPointer pointer, out int pageNumber) 
        {
            Invariant.Assert(pointer != null, "unknown pointer");

            IDocumentPaginatorSource idp = pointer.TextContainer.Parent as IDocumentPaginatorSource; 
            FixedDocument fixedDoc = idp as FixedDocument;
            if (fixedDoc != null) 
            { 
                FixedDocumentSequence sequence = fixedDoc.Parent as FixedDocumentSequence;
                if (sequence != null) 
                    idp = sequence;
            }

            Invariant.Assert(idp != null); 
            DynamicDocumentPaginator ddp = idp.DocumentPaginator as DynamicDocumentPaginator;
            pageNumber = ddp != null ? ddp.GetPageNumber((ContentPosition)pointer) : -1; 
 
            return idp;
        } 

        #endregion Public Methods

        //------------------------------------------------------ 
        //
        //  Internal Methods 
        // 
        //------------------------------------------------------
        #region Internal Methods 

        /// 
        /// Gets the start, end and text segments of the selection.  Throws an exception if the
        /// selection is of the wrong type. 
        /// 
        internal static void CheckSelection(object selection, out ITextPointer start, out ITextPointer end, out IList segments) 
        { 
            ITextRange textRange = selection as ITextRange;
 
            if (textRange != null)
            {
                start = textRange.Start;
                end = textRange.End; 
                segments = textRange.TextSegments;
            } 
            else 
            {
                TextAnchor textAnchor = selection as TextAnchor; 
                if (textAnchor == null)
                    throw new ArgumentException(SR.Get(SRID.WrongSelectionType), "selection");

                start = textAnchor.Start; 
                end = textAnchor.End;
                segments = textAnchor.TextSegments; 
            } 
        }
 
        /// 
        /// Gets the TextView exposed by the page where this pointer lives
        /// 
        /// the pointer 
        /// the TextView
        internal static ITextView GetDocumentPageTextView(ITextPointer pointer) 
        { 
            int pageNumber;
 
            DependencyObject content = pointer.TextContainer.Parent as DependencyObject;
            if (content != null)
            {
                FlowDocumentScrollViewer scrollViewer = PathNode.GetParent(content) as FlowDocumentScrollViewer; 
                if (scrollViewer != null)
                { 
                    IServiceProvider provider = scrollViewer.ScrollViewer.Content as IServiceProvider; 
                    Invariant.Assert(provider != null, "FlowDocumentScrollViewer should be an IServiceProvider.");
                    return provider.GetService(typeof(ITextView)) as ITextView; 
                }
            }

            IDocumentPaginatorSource idp = GetPointerPage(pointer, out pageNumber); 
            if (idp != null && pageNumber >= 0)
            { 
                DocumentPage docPage = idp.DocumentPaginator.GetPage(pageNumber); 
                IServiceProvider isp = docPage as IServiceProvider;
                if (isp != null) 
                    return isp.GetService(typeof(ITextView)) as ITextView;
            }

            return null; 
        }
 
        ///  
        /// Gets a list of ITextViews spanned by this text segment
        ///  
        /// the text segment
        /// the TextViews list
        internal static List GetDocumentPageTextViews(TextSegment segment)
        { 
            List res = null;
            int startPageNumber, endPageNumber; 
 
            //revert the logical direction of the pointers
            ITextPointer start = segment.Start.CreatePointer(LogicalDirection.Forward); 
            ITextPointer end = segment.End.CreatePointer(LogicalDirection.Backward);

            DependencyObject content = start.TextContainer.Parent as DependencyObject;
            if (content != null) 
            {
                FlowDocumentScrollViewer scrollViewer = PathNode.GetParent(content) as FlowDocumentScrollViewer; 
                if (scrollViewer != null) 
                {
                    IServiceProvider provider = scrollViewer.ScrollViewer.Content as IServiceProvider; 
                    Invariant.Assert(provider != null, "FlowDocumentScrollViewer should be an IServiceProvider.");
                    res = new List(1);
                    res.Add(provider.GetService(typeof(ITextView)) as ITextView);
                    return res; 
                }
            } 
 
            IDocumentPaginatorSource idp = GetPointerPage(start, out startPageNumber);
            DynamicDocumentPaginator ddp = idp.DocumentPaginator as DynamicDocumentPaginator; 
            endPageNumber = ddp != null ? ddp.GetPageNumber((ContentPosition)end) : -1;

            if (startPageNumber == -1 || endPageNumber == -1)
            { 
                // If either page couldn't be found, we return an empty list.  This
                // could be caused by a failure in paginating the document. 
                res = new List(0); 
            }
            else if (startPageNumber == endPageNumber) 
            {
                res = ProcessSinglePage(idp, startPageNumber);
            }
            else 
            {
                res = ProcessMultiplePages(idp, startPageNumber, endPageNumber); 
            } 

            return res; 
        }

        #endregion Internal Methods
 
        //-----------------------------------------------------
        // 
        //  Private Methods 
        //
        //------------------------------------------------------ 
        #region Private Methods

        /// 
        /// Gets a single page TextView throug the idp.GetPage. cALL this API only when 
        /// it is sure that the page is loaded
        ///  
        /// IDocumentPaginatorSource 
        /// page number
        /// returns a list of one view 
        private static List ProcessSinglePage(IDocumentPaginatorSource idp, int pageNumber)
        {
            Invariant.Assert(idp != null, "IDocumentPaginatorSource is null");
 
            DocumentPage docPage = idp.DocumentPaginator.GetPage(pageNumber);
            IServiceProvider isp = docPage as IServiceProvider; 
            List res = null; 
            if (isp != null)
            { 
                res = new List(1);
                ITextView view = isp.GetService(typeof(ITextView)) as ITextView;
                if (view != null)
                    res.Add(view); 
            }
 
            return res; 
        }
 
        /// 
        /// Gets existing views for pages from start to end. Scans only existing view to
        /// avoid loading of unloaded pages.
        ///  
        /// IDocumentPaginatorSource
        /// start page number 
        /// end page number 
        /// returns a list of text views
        private static List ProcessMultiplePages(IDocumentPaginatorSource idp, int startPageNumber, int endPageNumber) 
        {
            Invariant.Assert(idp != null, "IDocumentPaginatorSource is null");

            //now get available views 
            DocumentViewerBase viewer = PathNode.GetParent(idp as DependencyObject) as DocumentViewerBase;
            Invariant.Assert(viewer != null, "DocumentViewer not found"); 
 
            // If the pages for the text segment are reversed (possibly a floater where the floater
            // reflow on to a page that comes after its anchor) we just swap them 
            if (endPageNumber < startPageNumber)
            {
                int temp = endPageNumber;
                endPageNumber = startPageNumber; 
                startPageNumber = temp;
            } 
 
            List res = null;
            if (idp != null && startPageNumber >= 0 && endPageNumber >= startPageNumber) 
            {
                res = new List(endPageNumber - startPageNumber + 1);
                for (int pageNb = startPageNumber; pageNb <= endPageNumber; pageNb++)
                { 
                    DocumentPageView view = AnnotationHelper.FindView(viewer, pageNb);
                    if (view != null) 
                    { 
                        IServiceProvider serviceProvider = view.DocumentPage as IServiceProvider;
                        if (serviceProvider != null) 
                        {
                            ITextView textView = serviceProvider.GetService(typeof(ITextView)) as ITextView;
                            if (textView != null)
                                res.Add(textView); 
                        }
                    } 
                } 
            }
 
            return res;
        }

        #endregion Private Methods 

    } 
} 


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