IFlowDocumentViewer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

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

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using System;                       // Object, IServiceProvider 
using System.Windows;               // Rect, Point 
using System.Windows.Documents;     // ITextSelection
using System.Windows.Controls;      // FlowDocumentScrollViewer 
using System.Windows.Controls.Primitives;   // IScrollInfo
using System.Windows.Input;         // UICommand
using System.Windows.Threading;     // Dispatcher
using MS.Internal.KnownBoxes;       // BooleanBoxes 

namespace MS.Internal.Documents 
{ 
    /// 
    /// An IFlowDocumentViewer is used for FlowDocumentReader in order to simplify its 
    /// view switching logic.
    /// 
    internal interface IFlowDocumentViewer
    { 
        /// 
        /// Navigate to the previous page. 
        ///  
        void PreviousPage();
 
        /// 
        /// Navigate to the next page.
        /// 
        void NextPage(); 

        ///  
        /// Navigate to the first page. 
        /// 
        void FirstPage(); 

        /// 
        /// Navigate to the last page.
        ///  
        void LastPage();
 
        ///  
        /// Print the document.
        ///  
        void Print();

        /// 
        /// Cancel printing of the document. 
        /// 
        void CancelPrint(); 
 
        /// 
        /// Show find result. 
        /// 
        void ShowFindResult(ITextRange findResult);

        ///  
        /// Whether can navigate to specific page number.
        ///  
        /// Requested page number. 
        /// Whether navigation is possible or not.
        bool CanGoToPage(int pageNumber); 

        /// 
        /// Navigate to requested page number.
        ///  
        /// Requested page number.
        void GoToPage(int pageNumber); 
 
        /// 
        /// Associate the viewer with new document. 
        /// 
        /// New document.
        void SetDocument(FlowDocument document);
 
        /// 
        /// The content position of the document showed in the control. 
        ///  
        ContentPosition ContentPosition { get; set; }
 
        /// 
        /// The Selection of TextEditor
        /// 
        ITextSelection TextSelection { get; set; } 

        ///  
        /// Whether can navigate to the previous page. 
        /// 
        bool CanGoToPreviousPage { get; } 

        /// 
        /// Whether can navigate to the next page.
        ///  
        bool CanGoToNextPage { get; }
 
        ///  
        /// The one-based page number of the page being displayed.
        /// If there is no content, this value will be 0. 
        /// 
        int PageNumber { get; }

        ///  
        /// The number of pages currently available for viewing.
        ///  
        int PageCount { get; } 

        ///  
        /// Fired when the current page number has been changed.
        /// 
        event EventHandler PageNumberChanged;
 
        /// 
        /// Fired when the page count has been changed. 
        ///  
        event EventHandler PageCountChanged;
 
        /// 
        /// Fired when the print has been started.
        /// 
        event EventHandler PrintStarted; 

        ///  
        /// Fired when the print has been completed. 
        /// 
        event EventHandler PrintCompleted; 
    }

    /// 
    /// This class is an internal subclass of the FlowDocumentScrollViewer that provides 
    /// IFlowDocumentViewer interface used by FlowDocumentReader.
    ///  
    internal class ReaderScrollViewer : FlowDocumentScrollViewer, IFlowDocumentViewer 
    {
        //------------------------------------------------------------------- 
        //
        //  Protected Methods
        //
        //------------------------------------------------------------------- 

        #region Protected Methods 
 
        /// 
        /// Called when print has been completed. 
        /// 
        protected override void OnPrintCompleted()
        {
            base.OnPrintCompleted(); 

            if (_printCompleted != null) 
            { 
                _printCompleted(this, EventArgs.Empty);
            } 
        }

        /// 
        /// Handler for the Print command. 
        /// 
        protected override void OnPrintCommand() 
        { 
            base.OnPrintCommand();
 
            if (_printStarted != null && IsPrinting)
            {
                _printStarted(this, EventArgs.Empty);
            } 
        }
 
        ///  
        /// Notification that a specified property has been changed.
        ///  
        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
 
            // PageCount and PageNumber are dependent on Document property value.
            // Hence need to raise changed events when Document property is changing. 
            if (e.Property == DocumentProperty) 
            {
                if (_pageNumberChanged != null) 
                {
                    _pageNumberChanged(this, EventArgs.Empty);
                }
                if (_pageCountChanged != null) 
                {
                    _pageCountChanged(this, EventArgs.Empty); 
                } 
            }
        } 

        #endregion Protected Methods

        //-------------------------------------------------------------------- 
        //
        //  Private Methods 
        // 
        //-------------------------------------------------------------------
 
        #region Private Methods

        /// 
        /// Returns whether TextSelection is valid for document - As this is flow document, we require the text containers to be equal 
        /// to allow it as a valid selection.
        ///  
        private bool IsValidTextSelectionForDocument(ITextSelection textSelection, FlowDocument flowDocument) 
        {
            if(textSelection.Start != null && textSelection.Start.TextContainer == flowDocument.StructuralCache.TextContainer) 
            {
                return true;
            }
 
            return false;
        } 
 
        /// 
        /// Set TextSelection. 
        /// 
        private object SetTextSelection(object arg)
        {
            ITextSelection newTextSelection = arg as ITextSelection; 
            if (newTextSelection != null && Document != null && IsValidTextSelectionForDocument(newTextSelection, Document))
            { 
                ITextSelection textSelection = Document.StructuralCache.TextContainer.TextSelection; 
                if (textSelection != null)
                { 
                    textSelection.SetCaretToPosition(newTextSelection.AnchorPosition, newTextSelection.MovingPosition.LogicalDirection, true, true);
                    textSelection.ExtendToPosition(newTextSelection.MovingPosition);
                }
            } 
            return null;
        } 
 
        #endregion Private Methods
 
        //--------------------------------------------------------------------
        //
        //  Private Fields
        // 
        //--------------------------------------------------------------------
 
        #region Private Fields 

        private EventHandler _pageNumberChanged; 
        private EventHandler _pageCountChanged;
        private EventHandler _printCompleted;
        private EventHandler _printStarted;
 
        #endregion Private Fields
 
        //------------------------------------------------------------------- 
        //
        //  IFlowDocumentViewer Members 
        //
        //--------------------------------------------------------------------

        #region IFlowDocumentViewer Members 

        ///  
        ///  
        /// 
        void IFlowDocumentViewer.PreviousPage() 
        {
            if (ScrollViewer != null)
            {
                ScrollViewer.PageUp(); 
            }
        } 
 
        /// 
        ///  
        /// 
        void IFlowDocumentViewer.NextPage()
        {
            if (ScrollViewer != null) 
            {
                ScrollViewer.PageDown(); 
            } 
        }
 
        /// 
        /// 
        /// 
        void IFlowDocumentViewer.FirstPage() 
        {
            if (ScrollViewer != null) 
            { 
                ScrollViewer.ScrollToHome();
            } 
        }

        /// 
        ///  
        /// 
        void IFlowDocumentViewer.LastPage() 
        { 
            if (ScrollViewer != null)
            { 
                ScrollViewer.ScrollToEnd();
            }
        }
 
        /// 
        ///  
        ///  
        void IFlowDocumentViewer.Print()
        { 
            OnPrintCommand();
        }

        ///  
        /// 
        ///  
        void IFlowDocumentViewer.CancelPrint() 
        {
            OnCancelPrintCommand(); 
        }

        /// 
        ///  
        /// 
        void IFlowDocumentViewer.ShowFindResult(ITextRange findResult) 
        { 
            // If we found something, TextEditor will bring the selection into view.
            // It is possible, because RenderScope is inside ScrollViewer. 
        }

        /// 
        ///  
        /// 
        bool IFlowDocumentViewer.CanGoToPage(int pageNumber) 
        { 
            // FlowDocumentScrollViewer is always a 1 page document, so its page number will always be 1
            return (pageNumber == 1); 
        }

        /// 
        ///  
        /// 
        void IFlowDocumentViewer.GoToPage(int pageNumber) 
        { 
            if (pageNumber == 1 && ScrollViewer != null)
            { 
                ScrollViewer.ScrollToHome();
            }
        }
 
        /// 
        ///  
        ///  
        void IFlowDocumentViewer.SetDocument(FlowDocument document)
        { 
            Document = document;
        }

        ///  
        /// 
        ///  
        ContentPosition IFlowDocumentViewer.ContentPosition 
        {
            get 
            {
                return this.ContentPosition;
            }
            set 
            {
                if (value != null && Document != null) 
                { 
                    // This need be called because the UI may not be ready when Contentposition is set.
                    Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(BringContentPositionIntoView), value); 
                }
            }
        }
 
        /// 
        ///  
        ///  
        ITextSelection IFlowDocumentViewer.TextSelection
        { 
            get
            {
                return this.Selection;
            } 
            set
            { 
                if (value != null && Document != null) 
                {
                    // This need be called because the UI may not be ready when Contentposition is set. 
                    Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(SetTextSelection), value);
                }
            }
        } 

        ///  
        ///  
        /// 
        bool IFlowDocumentViewer.CanGoToPreviousPage 
        {
            get { return false; }
        }
 
        /// 
        ///  
        ///  
        bool IFlowDocumentViewer.CanGoToNextPage
        { 
            get { return false; }
        }

        ///  
        /// 
        ///  
        int IFlowDocumentViewer.PageNumber 
        {
            get { return (Document != null) ? 1 : 0; } 
        }

        /// 
        ///  
        /// 
        int IFlowDocumentViewer.PageCount 
        { 
            get { return (Document != null) ? 1 : 0; }
        } 

        /// 
        /// 
        ///  
        event EventHandler IFlowDocumentViewer.PageNumberChanged
        { 
            add { _pageNumberChanged += value; } 
            remove { _pageNumberChanged -= value; }
        } 

        /// 
        /// 
        ///  
        event EventHandler IFlowDocumentViewer.PageCountChanged
        { 
            add { _pageCountChanged += value; } 
            remove { _pageCountChanged -= value; }
        } 

        /// 
        /// 
        ///  
        event EventHandler IFlowDocumentViewer.PrintStarted
        { 
            add { _printStarted += value; } 
            remove { _printStarted -= value; }
        } 

        /// 
        /// 
        ///  
        event EventHandler IFlowDocumentViewer.PrintCompleted
        { 
            add { _printCompleted += value; } 
            remove { _printCompleted -= value; }
        } 

        #endregion IFlowDocumentViewer Members
    }
 
    /// 
    /// This class is an internal subclass of the FlowDocumentPageViewer that provides 
    /// IFlowDocumentViewer interface used by FlowDocumentReader. 
    /// 
    internal class ReaderPageViewer : FlowDocumentPageViewer, IFlowDocumentViewer 
    {
        //-------------------------------------------------------------------
        //
        //  Protected Methods 
        //
        //------------------------------------------------------------------- 
 
        #region Protected Methods
 
        /// 
        /// Called when print has been completed.
        /// 
        protected override void OnPrintCompleted() 
        {
            base.OnPrintCompleted(); 
 
            if (_printCompleted != null)
            { 
                _printCompleted(this, EventArgs.Empty);
            }
        }
 
        /// 
        /// Handler for the Print command. 
        ///  
        protected override void OnPrintCommand()
        { 
            base.OnPrintCommand();

            if (_printStarted != null && IsPrinting)
            { 
                _printStarted(this, EventArgs.Empty);
            } 
        } 

        ///  
        /// Notification that a specified property has been changed.
        /// 
        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        { 
            base.OnPropertyChanged(e);
 
            // Reader control depends on the actual value of PageCount, PageNumber 
            // CanGoToPreviousPage and CanGoToNextPage. So when values of those
            // properties are changing, schedule async update of the viewer. 
            if (e.Property == PageCountProperty || e.Property == MasterPageNumberProperty ||
                e.Property == CanGoToPreviousPageProperty || e.Property == CanGoToNextPageProperty)
            {
                // If there is already pending update request, do nothng. Otherwise schedule a dispatcher task. 
                if (!_raisePageNumberChanged && !_raisePageCountChanged)
                { 
                    Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(RaisePropertyChangedAsync), null); 
                }
                // Treat CanGoToPage properties as PageNumber. Becasuse PageNumber change affects 
                // those properties, the reader control will update them.
                if (e.Property == PageCountProperty)
                {
                    _raisePageCountChanged = true; 
                    CoerceValue(CanGoToNextPageProperty);
                } 
                else if (e.Property == MasterPageNumberProperty) 
                {
                    _raisePageNumberChanged = true; 
                    CoerceValue(CanGoToNextPageProperty);
                }
                else
                { 
                    _raisePageNumberChanged = true;
                } 
            } 
        }
 
        #endregion Protected Methods

        //-------------------------------------------------------------------
        // 
        //  Private Methods
        // 
        //-------------------------------------------------------------------- 

        #region Private Methods 

        /// 
        /// Set TextSelection.
        ///  
        private object SetTextSelection(object arg)
        { 
            ITextSelection newTextSelection = arg as ITextSelection; 
            FlowDocument flowDocument = Document as FlowDocument;
            if (newTextSelection != null && flowDocument != null && 
                newTextSelection.AnchorPosition != null &&
                newTextSelection.AnchorPosition.TextContainer == flowDocument.StructuralCache.TextContainer)
            {
                ITextSelection textSelection = flowDocument.StructuralCache.TextContainer.TextSelection; 
                if (textSelection != null)
                { 
                    textSelection.SetCaretToPosition(newTextSelection.AnchorPosition, newTextSelection.MovingPosition.LogicalDirection, true, true); 
                    textSelection.ExtendToPosition(newTextSelection.MovingPosition);
                } 
            }
            return null;
        }
 
        /// 
        /// Asynchronously notify about property changes. 
        ///  
        private object RaisePropertyChangedAsync(object arg)
        { 
            // PageCount and PageNumber are dependent on associated DP values.
            // Hence need to raise changed events when those DPs are changing.
            if (_raisePageCountChanged)
            { 
                if (_pageCountChanged != null)
                { 
                    _pageCountChanged(this, EventArgs.Empty); 
                }
                _raisePageCountChanged = false; 
            }
            if (_raisePageNumberChanged)
            {
                if (_pageNumberChanged != null) 
                {
                    _pageNumberChanged(this, EventArgs.Empty); 
                } 
                _raisePageNumberChanged = false;
            } 
            return null;
        }

        #endregion Private Methods 

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

        #region Private Fields
 
        private EventHandler _pageNumberChanged;
        private EventHandler _pageCountChanged; 
        private EventHandler _printCompleted; 
        private EventHandler _printStarted;
        private bool _raisePageNumberChanged; 
        private bool _raisePageCountChanged;

        #endregion Private Fields
 
        //--------------------------------------------------------------------
        // 
        //  IFlowDocumentViewer Members 
        //
        //------------------------------------------------------------------- 

        #region IFlowDocumentViewer Members

        ///  
        /// 
        ///  
        void IFlowDocumentViewer.PreviousPage() 
        {
            OnPreviousPageCommand(); 
        }

        /// 
        ///  
        /// 
        void IFlowDocumentViewer.NextPage() 
        { 
            OnNextPageCommand();
        } 

        /// 
        /// 
        ///  
        void IFlowDocumentViewer.FirstPage()
        { 
            OnFirstPageCommand(); 
        }
 
        /// 
        /// 
        /// 
        void IFlowDocumentViewer.LastPage() 
        {
            OnLastPageCommand(); 
        } 

        ///  
        /// 
        /// 
        void IFlowDocumentViewer.Print()
        { 
            OnPrintCommand();
        } 
 
        /// 
        ///  
        /// 
        void IFlowDocumentViewer.CancelPrint()
        {
            OnCancelPrintCommand(); 
        }
 
        ///  
        /// 
        ///  
        void IFlowDocumentViewer.ShowFindResult(ITextRange findResult)
        {
            if (findResult.Start is ContentPosition)
            { 
                BringContentPositionIntoView((ContentPosition)findResult.Start);
            } 
        } 

        ///  
        /// 
        /// 
        bool IFlowDocumentViewer.CanGoToPage(int pageNumber)
        { 
            return CanGoToPage(pageNumber);
        } 
 
        /// 
        ///  
        /// 
        void IFlowDocumentViewer.GoToPage(int pageNumber)
        {
            OnGoToPageCommand(pageNumber); 
        }
 
        ///  
        /// 
        ///  
        void IFlowDocumentViewer.SetDocument(FlowDocument document)
        {
            Document = document;
        } 

        ///  
        ///  
        /// 
        ContentPosition IFlowDocumentViewer.ContentPosition 
        {
            get { return ContentPosition; }
            set
            { 
                if (value != null && Document != null)
                { 
                    // This need be called because the UI may not be ready when Contentposition is set. 
                    Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(BringContentPositionIntoView), value);
                } 
            }
        }

        ///  
        /// 
        ///  
        ITextSelection IFlowDocumentViewer.TextSelection 
        {
            get 
            {
                return this.Selection;
            }
            set 
            {
                if (value != null && Document != null) 
                { 
                    // This need be called because the UI may not be ready when Contentposition is set.
                    Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(SetTextSelection), value); 
                }
            }
        }
 
        /// 
        ///  
        ///  
        bool IFlowDocumentViewer.CanGoToPreviousPage
        { 
            get { return CanGoToPreviousPage; }
        }

        ///  
        /// 
        ///  
        bool IFlowDocumentViewer.CanGoToNextPage 
        {
            get { return CanGoToNextPage; } 
        }

        /// 
        ///  
        /// 
        int IFlowDocumentViewer.PageNumber 
        { 
            get { return MasterPageNumber; }
        } 

        /// 
        /// 
        ///  
        int IFlowDocumentViewer.PageCount
        { 
            get { return PageCount; } 
        }
 
        /// 
        /// 
        /// 
        event EventHandler IFlowDocumentViewer.PageNumberChanged 
        {
            add { _pageNumberChanged += value; } 
            remove { _pageNumberChanged -= value; } 
        }
 
        /// 
        /// 
        /// 
        event EventHandler IFlowDocumentViewer.PageCountChanged 
        {
            add { _pageCountChanged += value; } 
            remove { _pageCountChanged -= value; } 
        }
 
        /// 
        /// 
        /// 
        event EventHandler IFlowDocumentViewer.PrintStarted 
        {
            add { _printStarted += value; } 
            remove { _printStarted -= value; } 
        }
 
        /// 
        /// 
        /// 
        event EventHandler IFlowDocumentViewer.PrintCompleted 
        {
            add { _printCompleted += value; } 
            remove { _printCompleted -= value; } 
        }
 
        #endregion IFlowDocumentViewer Members
    }

    ///  
    /// This class is an internal subclass of the FlowDocumentPageViewer that provides
    /// IFlowDocumentViewer interface used by FlowDocumentReader. 
    /// In addition to that it also provides support for TwoPage view. 
    /// 
    internal class ReaderTwoPageViewer : ReaderPageViewer 
    {
        //--------------------------------------------------------------------
        //
        //  Protected Methods 
        //
        //------------------------------------------------------------------- 
 
        #region Protected Methods
 
        /// 
        /// Handler for the PreviousPage command.
        /// 
        protected override void OnPreviousPageCommand() 
        {
            GoToPage(Math.Max(1, MasterPageNumber - 2)); 
        } 

        ///  
        /// Handler for the NextPage command.
        /// 
        protected override void OnNextPageCommand()
        { 
            GoToPage(Math.Min(PageCount, MasterPageNumber + 2));
        } 
 
        /// 
        /// Handler for the LastPage command. 
        /// 
        protected override void OnLastPageCommand()
        {
            // Always navigate to odd PageNumber 
            GoToPage(PageCount);
        } 
 
        /// 
        /// Handler for the GoToPage command. 
        /// 
        /// 
        protected override void OnGoToPageCommand(int pageNumber)
        { 
            // Go to only odd page numbers.
            base.OnGoToPageCommand((((pageNumber - 1) / 2) * 2) + 1); 
        } 

        ///  
        /// Notification that a specified property has been changed.
        /// 
        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        { 
            base.OnPropertyChanged(e);
 
            if (e.Property == MasterPageNumberProperty) 
            {
                // Only odd page numbers are allowed. 
                int pageNumber = (int)e.NewValue;
                pageNumber = (((pageNumber - 1) / 2) * 2) + 1;
                if (pageNumber != (int)e.NewValue)
                { 
                    GoToPage(pageNumber);
                } 
            } 
        }
 
        #endregion Protected Methods

        //-------------------------------------------------------------------
        // 
        //  Private Methods
        // 
        //------------------------------------------------------------------- 

        #region Private Methods 

        static ReaderTwoPageViewer()
        {
            CanGoToNextPagePropertyKey.OverrideMetadata(typeof(ReaderTwoPageViewer), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox, null, new CoerceValueCallback(CoerceCanGoToNextPage))); 
        }
 
        ///  
        /// Coerce the value for CanGoToNextPage property.
        ///  
        private static object CoerceCanGoToNextPage(DependencyObject d, object value)
        {
            Invariant.Assert(d != null && d is ReaderTwoPageViewer);
 
            ReaderTwoPageViewer viewer = (ReaderTwoPageViewer)d;
            return (viewer.MasterPageNumber < viewer.PageCount - 1); 
        } 

        #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