FlowDocument.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Documents / FlowDocument.cs / 3 / FlowDocument.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
// File: FlowDocument.cs 
//
// Description: Hosts and formats text with advanced document features. 
// 
// History:
//  17/08/2004 : [....] - created. 
//
//---------------------------------------------------------------------------

using System.Collections; 
using System.Collections.Generic;
using System.ComponentModel; 
using System.Diagnostics; 
using System.Windows.Automation.Peers;        // AutomationPeer
using System.Windows.Threading; 
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Markup;
using MS.Utility; 
using MS.Internal;                            // DoubleUtil
using MS.Internal.PtsHost; 
using MS.Internal.Text; 
using MS.Internal.Documents;
using MS.Internal.PtsHost.UnsafeNativeMethods; // PTS restrictions 

namespace System.Windows.Documents
{
    ///  
    /// FlowDocument is the paginating container for text content.
    ///  
    ///  
    /// 
    /// FlowDocument does not derive from Visual, and therefore cannot 
    /// be added as a direct child of UIElements such as Grid.
    /// In order to be displayed, FlowDocument must be viewed within a FlowDocumentPageViewer,
    /// DocumentViewerBase-derived class, or a custom paginated viewer that utilizes the
    /// IDocumentPaginatorSource API. 
    /// It also can be viewed and edited within RichTextBox control,
    /// available as it child in xaml markup or via Document property in api. 
    ///  
    /// 
    /// FlowDocument's content allows elements in some particular hierarchical structure 
    /// specified by Flow Content Schema. The Flow Cotent Schema includes a variety
    /// of element classes that you can use to create rich formatted and structured text content.
    /// 
    ///  
    /// Classes in Flow Content Schema belong to several categories: "Block content",
    /// "Inline Content", "Embedded UIElements". 
    ///  
    /// 
    /// Top-level children of Flow Document must be one of -derived classes: 
    /// , , , .
    /// - Block-level of flow content schema.
    /// 
    ///  
    /// Each of block elements has specific schema, only  allowing
    /// inline content - elements deived from  class: 
    /// , , , , . 
    /// 
    ///  
    /// Only  element can contain text directly. All other elements can only contain
    /// elements specified by Flow Schema.
    /// 
    ///  
    [Localizability(LocalizationCategory.Inherit, Readability = Readability.Unreadable)]
    [ContentProperty("Blocks")] 
    public class FlowDocument : FrameworkContentElement, IDocumentPaginatorSource, IServiceProvider, IAddChild 
    {
        //------------------------------------------------------------------- 
        //
        //  Constructors
        //
        //------------------------------------------------------------------- 

        #region Constructors 
 
        /// 
        /// Static constructor. Registers metadata for its properties. 
        /// 
        static FlowDocument()
        {
            PropertyChangedCallback typographyChanged = new PropertyChangedCallback(OnTypographyChanged); 

            // Registering typography properties metadata 
            Typography.StandardLigaturesProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.ContextualLigaturesProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.DiscretionaryLigaturesProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.HistoricalLigaturesProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.AnnotationAlternatesProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.ContextualAlternatesProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.HistoricalFormsProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.KerningProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.CapitalSpacingProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.CaseSensitiveFormsProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.StylisticSet1Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.StylisticSet2Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.StylisticSet3Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.StylisticSet4Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.StylisticSet5Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.StylisticSet6Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.StylisticSet7Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.StylisticSet8Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.StylisticSet9Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.StylisticSet10Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.StylisticSet11Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.StylisticSet12Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.StylisticSet13Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.StylisticSet14Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.StylisticSet15Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.StylisticSet16Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.StylisticSet17Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.StylisticSet18Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.StylisticSet19Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.StylisticSet20Property.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.FractionProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.SlashedZeroProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.MathematicalGreekProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.EastAsianExpertFormsProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.VariantsProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.CapitalsProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.NumeralStyleProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.NumeralAlignmentProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.EastAsianWidthsProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 
            Typography.EastAsianLanguageProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.StandardSwashesProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.ContextualSwashesProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged));
            Typography.StylisticAlternatesProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typographyChanged)); 

            DefaultStyleKeyProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(typeof(FlowDocument))); 
            FocusableProperty.OverrideMetadata(typeof(FlowDocument), new FrameworkPropertyMetadata(true)); 
        }
 
        /// 
        /// FlowDocument constructor.
        /// 
        public FlowDocument() 
            : base()
        { 
            Initialize(null); // null means to create its own TextContainer 
        }
 
        /// 
        /// Initialized the new instance of a FlowDocument specifying a Block added
        /// as its first child.
        ///  
        /// 
        /// Block added as a first initial child of the FlowDocument. 
        ///  
        public FlowDocument(Block block)
            : base() 
        {
            Initialize(null); // null means to create its own TextContainer

            if (block == null) 
            {
                throw new ArgumentNullException("block"); 
            } 

            this.Blocks.Add(block); 
        }

        /// 
        /// FlowDocument constructor with TextContainer. 
        /// 
        internal FlowDocument(TextContainer textContainer) 
            : base() 
        {
            Initialize(textContainer); 
        }

        #endregion Constructors
 
        //--------------------------------------------------------------------
        // 
        //  Public Properties 
        //
        //------------------------------------------------------------------- 

        #region Public Properties

        ///  
        /// Collection of Blocks contained in this element
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
        public BlockCollection Blocks
        { 
            get
            {
                return new BlockCollection(this, /*isOwnerParent*/true);
            } 
        }
 
        ///  
        /// A TextRange spanning the content of this element.
        ///  
        internal TextRange TextRange
        {
            get
            { 
                return new TextRange(this.ContentStart, this.ContentEnd);
            } 
        } 

        ///  
        /// TextPointer preceding all content.
        /// 
        /// 
        /// The TextPointer returned always has its IsFrozen property set true 
        /// and LogicalDirection property set to LogicalDirection.Backward.
        ///  
        public TextPointer ContentStart 
        {
            get 
            {
                return _structuralCache.TextContainer.Start;
            }
        } 

        ///  
        /// TextPointer following all content. 
        /// 
        ///  
        /// The TextPointer returned always has its IsFrozen property set true
        /// and LogicalDirection property set to LogicalDirection.Forward.
        /// 
        public TextPointer ContentEnd 
        {
            get 
            { 
                return _structuralCache.TextContainer.End;
            } 
        }

        #region Public Dynamic Properties
 
        /// 
        /// DependencyProperty for  property. 
        ///  
        public static readonly DependencyProperty FontFamilyProperty =
                TextElement.FontFamilyProperty.AddOwner(typeof(FlowDocument)); 

        /// 
        /// The FontFamily property specifies the font family.
        ///  
        [Localizability(
            LocalizationCategory.Font, 
            Modifiability = Modifiability.Unmodifiable 
        )]
        public FontFamily FontFamily 
        {
            get { return (FontFamily) GetValue(FontFamilyProperty); }
            set { SetValue(FontFamilyProperty, value); }
        } 

        ///  
        /// DependencyProperty for  property. 
        /// 
        public static readonly DependencyProperty FontStyleProperty = 
                TextElement.FontStyleProperty.AddOwner(typeof(FlowDocument));

        /// 
        /// The FontStyle property requests normal, italic, and oblique faces within a font family. 
        /// 
        public FontStyle FontStyle 
        { 
            get { return (FontStyle) GetValue(FontStyleProperty); }
            set { SetValue(FontStyleProperty, value); } 
        }

        /// 
        /// DependencyProperty for  property. 
        /// 
        public static readonly DependencyProperty FontWeightProperty = 
                TextElement.FontWeightProperty.AddOwner(typeof(FlowDocument)); 

        ///  
        /// The FontWeight property specifies the weight of the font.
        /// 
        public FontWeight FontWeight
        { 
            get { return (FontWeight) GetValue(FontWeightProperty); }
            set { SetValue(FontWeightProperty, value); } 
        } 

        ///  
        /// DependencyProperty for  property.
        /// 
        public static readonly DependencyProperty FontStretchProperty =
                TextElement.FontStretchProperty.AddOwner(typeof(FlowDocument)); 

        ///  
        /// The FontStretch property selects a normal, condensed, or extended face from a font family. 
        /// 
        public FontStretch FontStretch 
        {
            get { return (FontStretch) GetValue(FontStretchProperty); }
            set { SetValue(FontStretchProperty, value); }
        } 

        ///  
        /// DependencyProperty for  property. 
        /// 
        public static readonly DependencyProperty FontSizeProperty = 
                TextElement.FontSizeProperty.AddOwner(
                        typeof(FlowDocument));

        ///  
        /// The FontSize property specifies the size of the font.
        ///  
        [TypeConverter(typeof(FontSizeConverter))] 
        [Localizability(LocalizationCategory.None)]
        public double FontSize 
        {
            get { return (double) GetValue(FontSizeProperty); }
            set { SetValue(FontSizeProperty, value); }
        } 

        ///  
        /// DependencyProperty for  property. 
        /// 
        public static readonly DependencyProperty ForegroundProperty = 
                TextElement.ForegroundProperty.AddOwner(
                        typeof(FlowDocument));

        ///  
        /// The Foreground property specifies the foreground brush of an element's text content.
        ///  
        public Brush Foreground 
        {
            get { return (Brush) GetValue(ForegroundProperty); } 
            set { SetValue(ForegroundProperty, value); }
        }

        ///  
        /// DependencyProperty for  property.
        ///  
        public static readonly DependencyProperty BackgroundProperty = 
                TextElement.BackgroundProperty.AddOwner(
                        typeof(FlowDocument), 
                        new FrameworkPropertyMetadata(
                                null,
                                FrameworkPropertyMetadataOptions.AffectsRender));
 
        /// 
        /// The Background property defines the brush used to fill the content area. 
        ///  
        public Brush Background
        { 
            get { return (Brush) GetValue(BackgroundProperty); }
            set { SetValue(BackgroundProperty, value); }
        }
 
        /// 
        /// DependencyProperty for  property. 
        ///  
        public static readonly DependencyProperty TextEffectsProperty =
                TextElement.TextEffectsProperty.AddOwner( 
                        typeof(FlowDocument),
                        new FrameworkPropertyMetadata(
                                new FreezableDefaultValueFactory(TextEffectCollection.Empty),
                                FrameworkPropertyMetadataOptions.AffectsRender)); 

        ///  
        /// The TextEffects property specifies effects that are added to the text of an element. 
        /// 
        public TextEffectCollection TextEffects 
        {
            get { return (TextEffectCollection) GetValue(TextEffectsProperty); }
            set { SetValue(TextEffectsProperty, value); }
        } 

        ///  
        /// DependencyProperty for  property. 
        /// 
        public static readonly DependencyProperty TextAlignmentProperty = 
                Block.TextAlignmentProperty.AddOwner(typeof(FlowDocument));

        /// 
        /// The TextAlignment property specifies the alignmnet of the element. 
        /// 
        public TextAlignment TextAlignment 
        { 
            get { return (TextAlignment)GetValue(TextAlignmentProperty); }
            set { SetValue(TextAlignmentProperty, value); } 
        }

        /// 
        /// DependencyProperty for  property. 
        /// 
        public static readonly DependencyProperty FlowDirectionProperty = 
                Block.FlowDirectionProperty.AddOwner(typeof(FlowDocument)); 

        ///  
        /// The FlowDirection property specifies the flow direction of the element.
        /// 
        public FlowDirection FlowDirection
        { 
            get { return (FlowDirection)GetValue(FlowDirectionProperty); }
            set { SetValue(FlowDirectionProperty, value); } 
        } 

        ///  
        /// DependencyProperty for  property.
        /// 
        public static readonly DependencyProperty LineHeightProperty =
                Block.LineHeightProperty.AddOwner(typeof(FlowDocument)); 

        ///  
        /// The LineHeight property specifies the height of each generated line box. 
        /// 
        [TypeConverter(typeof(LengthConverter))] 
        public double LineHeight
        {
            get { return (double)GetValue(LineHeightProperty); }
            set { SetValue(LineHeightProperty, value); } 
        }
 
        ///  
        /// DependencyProperty for  property.
        ///  
        public static readonly DependencyProperty LineStackingStrategyProperty =
                Block.LineStackingStrategyProperty.AddOwner(typeof(FlowDocument));

        ///  
        /// The LineStackingStrategy property specifies how lines are placed
        ///  
        public LineStackingStrategy LineStackingStrategy 
        {
            get { return (LineStackingStrategy)GetValue(LineStackingStrategyProperty); } 
            set { SetValue(LineStackingStrategyProperty, value); }
        }

        ///  
        /// DependencyProperty for  property.
        ///  
        public static readonly DependencyProperty ColumnWidthProperty = 
                DependencyProperty.Register(
                        "ColumnWidth", 
                        typeof(double),
                        typeof(FlowDocument),
                        new FrameworkPropertyMetadata(
                                double.NaN, 
                                FrameworkPropertyMetadataOptions.AffectsMeasure));
 
        ///  
        /// The minimum width of each column.  If IsColumnWidthIsFlexible is True, then this
        /// value is clamped to be no larger than the width of the page (specified by 
        /// PageWidth or PageSize) minus the PagePadding.
        /// 
        [TypeConverter(typeof(LengthConverter))]
        [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)] 
        public double ColumnWidth
        { 
            get { return (double)GetValue(ColumnWidthProperty); } 
            set { SetValue(ColumnWidthProperty, value); }
        } 

        /// 
        /// DependencyProperty for  property.
        ///  
        public static readonly DependencyProperty ColumnGapProperty =
                DependencyProperty.Register( 
                        "ColumnGap", 
                        typeof(double),
                        typeof(FlowDocument), 
                        new FrameworkPropertyMetadata(
                                double.NaN,
                                FrameworkPropertyMetadataOptions.AffectsMeasure),
                                new ValidateValueCallback(IsValidColumnGap)); 

        ///  
        /// The distance between each column. This value is clamped to be no larger than 
        /// the width of the page (specified by PageWidth or PageSize) minus the PagePadding.
        ///  
        [TypeConverter(typeof(LengthConverter))]
        [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)]
        public double ColumnGap
        { 
            get { return (double) GetValue(ColumnGapProperty); }
            set { SetValue(ColumnGapProperty, value); } 
        } 

        ///  
        /// DependencyProperty for  property.
        /// 
        public static readonly DependencyProperty IsColumnWidthFlexibleProperty =
                DependencyProperty.Register( 
                        "IsColumnWidthFlexible",
                        typeof(bool), 
                        typeof(FlowDocument), 
                        new FrameworkPropertyMetadata(
                                true, 
                                FrameworkPropertyMetadataOptions.AffectsMeasure));

        /// 
        /// Whether the width of columns is flexible. If this property is true, then columns 
        /// will frequently be wider than ColumnWidth. If false, columns will always be exactly
        /// ColumnWidth (as long as the value is smaller than the width of the page minus padding). 
        ///  
        public bool IsColumnWidthFlexible
        { 
            get { return (bool)GetValue(IsColumnWidthFlexibleProperty); }
            set { SetValue(IsColumnWidthFlexibleProperty, value); }
        }
 
        /// 
        /// DependencyProperty for  property. 
        ///  
        public static readonly DependencyProperty ColumnRuleWidthProperty =
                DependencyProperty.Register( 
                        "ColumnRuleWidth",
                        typeof(double),
                        typeof(FlowDocument),
                        new FrameworkPropertyMetadata( 
                                0.0,
                                FrameworkPropertyMetadataOptions.AffectsMeasure), 
                        new ValidateValueCallback(IsValidColumnRuleWidth)); 

        ///  
        /// The width of the line drawn in between columns. This value is clamped
        /// to be no larger than the ColumnGap.
        /// 
        [TypeConverter(typeof(LengthConverter))] 
        [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)]
        public double ColumnRuleWidth 
        { 
            get { return (double)GetValue(ColumnRuleWidthProperty); }
            set { SetValue(ColumnRuleWidthProperty, value); } 
        }

        /// 
        /// DependencyProperty for  property. 
        /// 
        public static readonly DependencyProperty ColumnRuleBrushProperty = 
                DependencyProperty.Register( 
                        "ColumnRuleBrush",
                        typeof(Brush), 
                        typeof(FlowDocument),
                        new FrameworkPropertyMetadata(
                                null,
                                FrameworkPropertyMetadataOptions.AffectsRender)); 

        ///  
        /// The brush used to draw the line between columns. 
        /// 
        public Brush ColumnRuleBrush 
        {
            get { return (Brush)GetValue(ColumnRuleBrushProperty); }
            set { SetValue(ColumnRuleBrushProperty, value); }
        } 

        ///  
        /// DependencyProperty for  property. 
        /// 
        public static readonly DependencyProperty IsOptimalParagraphEnabledProperty = 
                DependencyProperty.Register(
                        "IsOptimalParagraphEnabled",
                        typeof(bool),
                        typeof(FlowDocument), 
                        new FrameworkPropertyMetadata(
                                false, 
                                FrameworkPropertyMetadataOptions.AffectsMeasure)); 

        ///  
        /// Whether FlowDocument should attempt to construct optimal text paragraphs.
        /// 
        public bool IsOptimalParagraphEnabled
        { 
            get { return (bool)GetValue(IsOptimalParagraphEnabledProperty); }
            set { SetValue(IsOptimalParagraphEnabledProperty, value); } 
        } 

        ///  
        /// DependencyProperty for  property.
        /// 
        public static readonly DependencyProperty PageWidthProperty =
                DependencyProperty.Register( 
                        "PageWidth",
                        typeof(double), 
                        typeof(FlowDocument), 
                        new FrameworkPropertyMetadata(
                                double.NaN, 
                                FrameworkPropertyMetadataOptions.AffectsMeasure,
                                new PropertyChangedCallback(OnPageMetricsChanged),
                                new CoerceValueCallback(CoercePageWidth)),
                        new ValidateValueCallback(IsValidPageSize)); 

        ///  
        /// The width of pages returned by GetPage. This value takes precedence over 
        /// PageSize.Width, MinPageWidth, and MaxPageWidth.
        ///  
        [TypeConverter(typeof(LengthConverter))]
        public double PageWidth
        {
            get { return (double) GetValue(PageWidthProperty); } 
            set { SetValue(PageWidthProperty, value); }
        } 
 
        /// 
        /// DependencyProperty for  property. 
        /// 
        public static readonly DependencyProperty MinPageWidthProperty =
                DependencyProperty.Register(
                        "MinPageWidth", 
                        typeof(double),
                        typeof(FlowDocument), 
                        new FrameworkPropertyMetadata( 
                                0.0,
                                FrameworkPropertyMetadataOptions.AffectsMeasure, 
                                new PropertyChangedCallback(OnMinPageWidthChanged)),
                        new ValidateValueCallback(IsValidMinPageSize));

        ///  
        /// The minimum width of pages returned by GetPage. This value takes
        /// precedence over PageSize.Width, but not PageWidth. 
        ///  
        [TypeConverter(typeof(LengthConverter))]
        public double MinPageWidth 
        {
            get { return (double) GetValue(MinPageWidthProperty); }
            set { SetValue(MinPageWidthProperty, value); }
        } 

        ///  
        /// DependencyProperty for  property. 
        /// 
        public static readonly DependencyProperty MaxPageWidthProperty = 
                DependencyProperty.Register(
                        "MaxPageWidth",
                        typeof(double),
                        typeof(FlowDocument), 
                        new FrameworkPropertyMetadata(
                                double.PositiveInfinity, 
                                FrameworkPropertyMetadataOptions.AffectsMeasure, 
                                new PropertyChangedCallback(OnMaxPageWidthChanged),
                                new CoerceValueCallback(CoerceMaxPageWidth)), 
                        new ValidateValueCallback(IsValidMaxPageSize));

        /// 
        /// The maximum width of pages returned by GetPage. This value takes 
        /// precedence over PageSize.Width, but not PageWidth.
        ///  
        [TypeConverter(typeof(LengthConverter))] 
        public double MaxPageWidth
        { 
            get { return (double) GetValue(MaxPageWidthProperty); }
            set { SetValue(MaxPageWidthProperty, value); }
        }
 
        /// 
        /// DependencyProperty for  property. 
        ///  
        public static readonly DependencyProperty PageHeightProperty =
                DependencyProperty.Register( 
                        "PageHeight",
                        typeof(double),
                        typeof(FlowDocument),
                        new FrameworkPropertyMetadata( 
                                double.NaN,
                                FrameworkPropertyMetadataOptions.AffectsMeasure, 
                                new PropertyChangedCallback(OnPageMetricsChanged), 
                                new CoerceValueCallback(CoercePageHeight)),
                        new ValidateValueCallback(IsValidPageSize)); 

        /// 
        /// The height of pages returned by GetPage. This value takes precedence
        /// over PageSize.Height, MinPageHeight, and MaxPageHeight. 
        /// 
        [TypeConverter(typeof(LengthConverter))] 
        public double PageHeight 
        {
            get { return (double) GetValue(PageHeightProperty); } 
            set { SetValue(PageHeightProperty, value); }
        }

        ///  
        /// DependencyProperty for  property.
        ///  
        public static readonly DependencyProperty MinPageHeightProperty = 
                DependencyProperty.Register(
                        "MinPageHeight", 
                        typeof(double),
                        typeof(FlowDocument),
                        new FrameworkPropertyMetadata(
                                0.0, 
                                FrameworkPropertyMetadataOptions.AffectsMeasure,
                                new PropertyChangedCallback(OnMinPageHeightChanged)), 
                        new ValidateValueCallback(IsValidMinPageSize)); 

        ///  
        /// The minimum height of pages returned by GetPage. This value takes
        /// precedence over PageSize.Height, but not PageHeight.
        /// 
        [TypeConverter(typeof(LengthConverter))] 
        public double MinPageHeight
        { 
            get { return (double) GetValue(MinPageHeightProperty); } 
            set { SetValue(MinPageHeightProperty, value); }
        } 

        /// 
        /// DependencyProperty for  property.
        ///  
        public static readonly DependencyProperty MaxPageHeightProperty =
                DependencyProperty.Register( 
                        "MaxPageHeight", 
                        typeof(double),
                        typeof(FlowDocument), 
                        new FrameworkPropertyMetadata(
                                double.PositiveInfinity,
                                FrameworkPropertyMetadataOptions.AffectsMeasure,
                                new PropertyChangedCallback(OnMaxPageHeightChanged), 
                                new CoerceValueCallback(CoerceMaxPageHeight)),
                        new ValidateValueCallback(IsValidMaxPageSize)); 
 
        /// 
        /// The maximum height of pages returned by GetPage. This value takes 
        /// precedence over PageSize.Height, but not PageHeight.
        /// 
        [TypeConverter(typeof(LengthConverter))]
        public double MaxPageHeight 
        {
            get { return (double) GetValue(MaxPageHeightProperty); } 
            set { SetValue(MaxPageHeightProperty, value); } 
        }
 
        /// 
        /// DependencyProperty for  property.
        /// 
        public static readonly DependencyProperty PagePaddingProperty = 
                DependencyProperty.Register(
                        "PagePadding", 
                        typeof(Thickness), 
                        typeof(FlowDocument),
                        new FrameworkPropertyMetadata( 
                                new Thickness(Double.NaN),
                                FrameworkPropertyMetadataOptions.AffectsMeasure,
                                new PropertyChangedCallback(OnPageMetricsChanged)),
                        new ValidateValueCallback(IsValidPagePadding)); 

        ///  
        /// Padding applied between the page boundaries and the content of the page. 
        /// If the sum of the specified padding in a dimension is greater than the
        /// corresponding page dimension, then the padding values in that dimension 
        /// will be proportionally reduced such that the sum of the padding in that
        /// dimension is equal to the page dimension.
        /// For example, if the PageSize is (100, 100) and PagePadding is (0, 120, 0, 80),
        /// then the page will be formatted as if the PagePadding were actually (0, 60, 0, 40). 
        /// 
        public Thickness PagePadding 
        { 
            get { return (Thickness) GetValue(PagePaddingProperty); }
            set { SetValue(PagePaddingProperty, value); } 
        }

        /// 
        /// Class providing access to all text typography properties 
        /// 
        public Typography Typography 
        { 
            get
            { 
                return new Typography(this);
            }
        }
 
        /// 
        /// DependencyProperty for hyphenation property. 
        ///  
        public static readonly DependencyProperty IsHyphenationEnabledProperty =
                Block.IsHyphenationEnabledProperty.AddOwner(typeof(FlowDocument)); 

        /// 
        /// CLR property for hyphenation
        ///  
        public bool IsHyphenationEnabled
        { 
            get { return (bool)GetValue(IsHyphenationEnabledProperty); } 
            set { SetValue(IsHyphenationEnabledProperty, value); }
        } 

        #endregion Public Dynamic Properties

        #endregion Public Properties 

        //-------------------------------------------------------------------- 
        // 
        //  Protected Methods
        // 
        //--------------------------------------------------------------------

        #region Protected Methods
 
        /// 
        /// Notification that a specified property has been invalidated 
        ///  
        /// EventArgs that contains the property, metadata, old value, and new value for this change
        protected sealed override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) 
        {
            // Always call base.OnPropertyChanged, otherwise Property Engine will not work.
            base.OnPropertyChanged(e);
 
            if (e.IsAValueChange || e.IsASubPropertyChange)
            { 
                // Skip caches invalidation if content has not been formatted yet - non of caches are valid, 
                // so they will be aquired during first formatting (full format).
                if (_structuralCache != null && _structuralCache.IsFormattedOnce) 
                {
                    FrameworkPropertyMetadata fmetadata = e.Metadata as FrameworkPropertyMetadata;
                    if (fmetadata != null)
                    { 
                        bool affectsRender = (fmetadata.AffectsRender &&
                            (e.IsAValueChange || !fmetadata.SubPropertiesDoNotAffectRender)); 
                        if (fmetadata.AffectsMeasure || fmetadata.AffectsArrange || affectsRender || fmetadata.AffectsParentMeasure || fmetadata.AffectsParentArrange) 
                        {
                            // Detect invalid content change operations. 
                            if (_structuralCache.IsFormattingInProgress)
                            {
                                _structuralCache.OnInvalidOperationDetected();
                                throw new InvalidOperationException(SR.Get(SRID.FlowDocumentInvalidContnetChange)); 
                            }
 
                            // None of FlowDocument properties can invalidate structural caches (the NameTable), 
                            // but most likely it invalidates format caches. Invalidate all format caches
                            // accumulated in the NameTable. 
                            _structuralCache.InvalidateFormatCache(!affectsRender);

                            // Notify formatter about content invalidation.
                            if (_formatter != null) 
                            {
                                _formatter.OnContentInvalidated(!affectsRender); 
                            } 
                        }
                    } 
                }
            }
        }
 
        /// 
        /// Creates AutomationPeer () 
        ///  
        protected override AutomationPeer OnCreateAutomationPeer()
        { 
            return new DocumentAutomationPeer(this);
        }

        #endregion Protected Methods 

        //------------------------------------------------------------------- 
        // 
        //  Protected Properties
        // 
        //--------------------------------------------------------------------

        #region Protected Properties
 
        /// 
        /// Returns enumerator to logical children. 
        ///  
        protected internal override IEnumerator LogicalChildren
        { 
            get
            {
                return new RangeContentEnumerator(_structuralCache.TextContainer.Start, _structuralCache.TextContainer.End);
            } 
        }
 
        ///  
        ///     Fetches the value of the IsEnabled property
        ///  
        /// 
        ///     We want to coerce ContentElements and UIElement children of FlowDocument to be disabled in _editable_ content (ie, RichTextBox).
        ///     In read-only mode, in say the FlowDocumentReader, we don't want any coercing.
        ///  
        protected override bool IsEnabledCore
        { 
            get 
            {
                if (!base.IsEnabledCore) 
                {
                    return false;
                }
 
                RichTextBox parentRichTextBox = this.Parent as RichTextBox;
 
                return (parentRichTextBox == null) ? true : parentRichTextBox.IsDocumentEnabled; 
            }
        } 

        #endregion Protected Properties

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

        /// 
        /// Returns a ContentPosition for an object. 
        /// 
        /// Object within this element's tree. 
        /// Returns a ContentPosition for an object. 
        internal ContentPosition GetObjectPosition(Object element)
        { 
            TextPointer flowContentPosition;
            ITextPointer textPointer = null;
            DependencyObject parentOfEmbeddedElement;
 
            // If element is 'this', return ContentPosition representing ContentStart.
            if (element == this) 
            { 
                textPointer = this.ContentStart;
            } 
            // If element is a TextElement, return its ContentStart.
            else if (element is TextElement)
            {
                textPointer = ((TextElement)element).ContentStart; 
            }
            // Otherwise we are dealing with embedded element. Find its position in the 
            // TextContainer and return it. 
            // It is possible that somebody asks for FrameworkElement that is not an immediate
            // child of FlowDocument's content. In such case walk up the parent chain and 
            // get FrameworkElement that is directly embedded within FlowDocument's content.
            else if (element is FrameworkElement)
            {
                parentOfEmbeddedElement = null; 
                while (element is FrameworkElement)
                { 
                    parentOfEmbeddedElement = LogicalTreeHelper.GetParent((DependencyObject)element); 
                    if (parentOfEmbeddedElement == null)
                    { 
                        parentOfEmbeddedElement = VisualTreeHelper.GetParent((Visual)element);
                    }
                    if (!(parentOfEmbeddedElement is FrameworkElement))
                    { 
                        break;
                    } 
                    element = parentOfEmbeddedElement; 
                }
                if (parentOfEmbeddedElement is BlockUIContainer || parentOfEmbeddedElement is InlineUIContainer) 
                {
                    textPointer = TextContainerHelper.GetTextPointerForEmbeddedObject((FrameworkElement)element);
                }
            } 
            // Check if the TextPointer belongs to our tree.
            if (textPointer != null && textPointer.TextContainer != _structuralCache.TextContainer) 
            { 
                textPointer = null;
            } 
            flowContentPosition = textPointer as TextPointer;
            return (flowContentPosition != null) ? flowContentPosition : ContentPosition.Missing;
        }
 
        /// 
        /// OnChildDesiredSizeChanged 
        /// Called from FlowDocumentPage for IContentHost implementation 
        ///
 


        internal void OnChildDesiredSizeChanged(UIElement child)
        { 
            if (_structuralCache != null && _structuralCache.IsFormattedOnce && !_structuralCache.ForceReformat)
            { 
                // If executed during formatting process, delay invalidation. 
                // This may happen during formatting when text host notifies its about
                // baseline changes. 
                if (_structuralCache.IsFormattingInProgress)
                {
                    Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                        new DispatcherOperationCallback(OnChildDesiredSizeChangedAsync), child); 
                    return;
                } 
 
                // Get start and end positions
                int childStartIndex = TextContainerHelper.GetCPFromEmbeddedObject(child, ElementEdge.BeforeStart); 
                if (childStartIndex < 0)
                {
                    return;
                } 

                TextPointer childStart = new TextPointer(_structuralCache.TextContainer.Start); 
                childStart.MoveByOffset(childStartIndex); 
                TextPointer childEnd = new TextPointer(childStart);
                childEnd.MoveByOffset(TextContainerHelper.EmbeddedObjectLength); 

                // Create new DTR for changing UIElement and add it to DRTList.
                DirtyTextRange dtr = new DirtyTextRange(childStartIndex, TextContainerHelper.EmbeddedObjectLength, TextContainerHelper.EmbeddedObjectLength);
                _structuralCache.AddDirtyTextRange(dtr); 

                // Notify formatter about content invalidation. 
                if (_formatter != null) 
                {
                    _formatter.OnContentInvalidated(true, childStart, childEnd); 
                }
            }
        }
 
        /// 
        /// Do delayed initialization before first formatting. 
        ///  
        internal void InitializeForFirstFormatting()
        { 
            _structuralCache.TextContainer.Changing += new EventHandler(OnTextContainerChanging);
            _structuralCache.TextContainer.Change += new TextContainerChangeEventHandler(OnTextContainerChange);
            _structuralCache.TextContainer.Highlights.Changed += new HighlightChangedEventHandler(OnHighlightChanged);
        } 

        ///  
        /// Clear the TextContainer and unregister events.  Called by TextBox on style change. 
        /// 
        internal void Uninitialize() 
        {
            _structuralCache.TextContainer.Changing -= new EventHandler(OnTextContainerChanging);
            _structuralCache.TextContainer.Change -= new TextContainerChangeEventHandler(OnTextContainerChange);
            _structuralCache.TextContainer.Highlights.Changed -= new HighlightChangedEventHandler(OnHighlightChanged); 
            _structuralCache.IsFormattedOnce = false;
        } 
 
        /// 
        /// Compute margin for a page. 
        /// 
        internal Thickness ComputePageMargin()
        {
            double lineHeight = DynamicPropertyReader.GetLineHeightValue(this); 
            Thickness pageMargin = this.PagePadding;
 
            // If Padding value is 'Auto', treat it as 1*LineHeight. 
            if (DoubleUtil.IsNaN(pageMargin.Left))
            { 
                pageMargin.Left = lineHeight;
            }
            if (DoubleUtil.IsNaN(pageMargin.Top))
            { 
                pageMargin.Top = lineHeight;
            } 
            if (DoubleUtil.IsNaN(pageMargin.Right)) 
            {
                pageMargin.Right = lineHeight; 
            }
            if (DoubleUtil.IsNaN(pageMargin.Bottom))
            {
                pageMargin.Bottom = lineHeight; 
            }
            return pageMargin; 
        } 

        ///  
        /// Called before the parent is changed to the new value.
        /// We listen to parent change notifications to enforce coercing FlowDocument's IsEnabled property to false
        /// (when it is parented by RichTextBox).
        /// This property coersion is done in 2 parts. 
        ///     1. Implement IsEnabledCore for property coersion
        ///     2. Listen to changes to parent 
        /// (2) needs to be done, since property system does not coerce default values. 
        /// Listening to parent changes guarantees that every time FlowDocument is removed or connected to a RichTextBox parent,
        /// we explicitly coerce IsEnabled for the new tree. 
        /// 
        /// 
        internal override void OnNewParent(DependencyObject newParent)
        { 
            DependencyObject oldParent = this.Parent;
            base.OnNewParent(newParent); 
 
            if (newParent is RichTextBox || oldParent is RichTextBox)
            { 
                CoerceValue(IsEnabledProperty);
            }
        }
 
        #endregion Internal Methods
 
        //------------------------------------------------------------------- 
        //
        //  Internal Properties 
        //
        //--------------------------------------------------------------------

        #region Internal Properties 

        ///  
        /// An object which formats botomless content. 
        /// 
        internal FlowDocumentFormatter BottomlessFormatter 
        {
            get
            {
                if (_formatter != null && !(_formatter is FlowDocumentFormatter)) 
                {
                    _formatter.Suspend(); 
                    _formatter = null; 
                }
                if (_formatter == null) 
                {
                    _formatter = new FlowDocumentFormatter(this);
                }
                return (FlowDocumentFormatter)_formatter; 
            }
        } 
 
        /// 
        /// StructuralCache. 
        /// 
        internal StructuralCache StructuralCache
        {
            get 
            {
                return _structuralCache; 
            } 
        }
 
        /// 
        /// Typography properties group.
        /// 
        internal TypographyProperties TypographyPropertiesGroup 
        {
            get 
            { 
                if (_typographyPropertiesGroup == null)
                { 
                    _typographyPropertiesGroup = TextElement.GetTypographyProperties(this);
                }
                return _typographyPropertiesGroup;
            } 
        }
 
        ///  
        /// TextWrapping property value (set by TextBox/RichTextBox)
        ///  
        internal TextWrapping TextWrapping
        {
            get
            { 
                return _textWrapping;
            } 
            set 
            {
                _textWrapping = value; 
            }
        }

        ///  
        /// Formatter value
        ///  
        internal IFlowDocumentFormatter Formatter 
        {
            get 
            {
                return _formatter;
            }
        } 

        //------------------------------------------------------------------- 
        // Is layout data is in a valid state. 
        //--------------------------------------------------------------------
        internal bool IsLayoutDataValid 
        {
            get
            {
                if(_formatter != null) 
                {
                    return _formatter.IsLayoutDataValid; 
                } 

                return false; 
            }
        }

        //-------------------------------------------------------------------- 
        // TextContainer associated with this FlowDocument.
        //------------------------------------------------------------------- 
        internal TextContainer TextContainer 
        {
            get 
            {
                return _structuralCache.TextContainer;
            }
        } 

        #endregion Internal Properties 
 
        //--------------------------------------------------------------------
        // 
        //  Internal Events
        //
        //-------------------------------------------------------------------
 
        #region Internal Events
 
        ///  
        /// Fired when a PageSize property is changed
        ///  
        internal event EventHandler PageSizeChanged;

        #endregion Internal Events
 
        //-------------------------------------------------------------------
        // 
        //  Private Methods 
        //
        //------------------------------------------------------------------- 

        #region Private Methods

        ///  
        /// One of the properties which comprises TypographyProperties has changed -- reset cache.
        ///  
        private static void OnTypographyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            ((FlowDocument)d)._typographyPropertiesGroup = null; 
        }

        /// 
        /// OnChildDesiredSizeChanged delayed to avoid changes during page 
        /// formatting.
        ///  
        ///  
        /// 
        private object OnChildDesiredSizeChangedAsync(object arg) 
        {
            OnChildDesiredSizeChanged(arg as UIElement);
            return null;
        } 

        ///  
        /// Initialize FlowDocument. 
        /// 
        ///  
        private void Initialize(TextContainer textContainer)
        {
            if (textContainer == null)
            { 
                // Create text tree that contains content of the element.
                textContainer = new TextContainer(this, false /* plainTextOnly */); 
            } 

            // Create structural cache object 
            _structuralCache = new StructuralCache(this, textContainer);
            _structuralCache.Section = new MS.Internal.PtsHost.Section(_structuralCache);

            // Get rid of the current formatter. 
            if (_formatter != null)
            { 
                _formatter.Suspend(); 
                _formatter = null;
            } 
        }

        /// 
        /// Respond to page metrics changes. 
        /// 
        private static void OnPageMetricsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        { 
            FlowDocument fd = (FlowDocument)d;
            if (fd._structuralCache != null && fd._structuralCache.IsFormattedOnce) 
            {
                // Notify formatter about content invalidation.
                if (fd._formatter != null)
                { 
                    // Any change of page metrics invalidates the layout.
                    // Hence page metrics change is treated in the same way as ContentChanged 
                    // spanning entire content. 
                    fd._formatter.OnContentInvalidated(true);
                } 

                // Fire notification about the PageSize change - needed in RichTextBox
                if (fd.PageSizeChanged != null)
                { 
                    // NOTE: May execute external code, so it is possible to get
                    //       an exception here. 
                    fd.PageSizeChanged(fd, EventArgs.Empty); 
                }
            } 
        }

        /// 
        /// Respond to MinPageWidth change. 
        /// 
        private static void OnMinPageWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        { 
            d.CoerceValue(MaxPageWidthProperty);
            d.CoerceValue(PageWidthProperty); 
        }

        /// 
        /// Respond to MinPageHeight change. 
        /// 
        private static void OnMinPageHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        { 
            d.CoerceValue(MaxPageHeightProperty);
            d.CoerceValue(PageHeightProperty); 
        }

        /// 
        /// Respond to MaxPageWidth change. 
        /// 
        private static void OnMaxPageWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        { 
            d.CoerceValue(PageWidthProperty);
        } 

        /// 
        /// Respond to MaxPageHeight change.
        ///  
        private static void OnMaxPageHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            d.CoerceValue(PageHeightProperty); 
        }
 
        /// 
        /// Coerce MaxPageWidth value.
        /// 
        private static object CoerceMaxPageWidth(DependencyObject d, object value) 
        {
            FlowDocument fd = (FlowDocument) d; 
            double max = (double) value; 
            double min = fd.MinPageWidth;
            if (max < min) 
            {
                return min;
            }
            return value; 
        }
 
        ///  
        /// Coerce MaxPageHeight value.
        ///  
        private static object CoerceMaxPageHeight(DependencyObject d, object value)
        {
            FlowDocument fd = (FlowDocument) d;
            double max = (double) value; 
            double min = fd.MinPageHeight;
            if (max < min) 
            { 
                return min;
            } 
            return value;
        }

        ///  
        /// Coerce PageWidth value.
        ///  
        private static object CoercePageWidth(DependencyObject d, object value) 
        {
            FlowDocument fd = (FlowDocument) d; 
            double width = (double) value;

            if (!DoubleUtil.IsNaN(width))
            { 
                double max = fd.MaxPageWidth;
                if (width > max) 
                { 
                    width = max;
                } 

                double min = fd.MinPageWidth;
                if (width < min)
                { 
                    width = min;
                } 
            } 

            return value; 
        }

        /// 
        /// Coerce PageHeight value. 
        /// 
        private static object CoercePageHeight(DependencyObject d, object value) 
        { 
            FlowDocument fd = (FlowDocument) d;
            double height = (double) value; 

            if (!DoubleUtil.IsNaN(height))
            {
                double max = fd.MaxPageHeight; 
                if (height > max)
                { 
                    height = max; 
                }
 
                double min = fd.MinPageHeight;
                if (height < min)
                {
                    height = min; 
                }
            } 
 
            return value;
        } 

        /// 
        /// Invalidates a portion of text affected by a highlight change.
        ///  
        /// 
        ///  
        private void OnHighlightChanged(object sender, HighlightChangedEventArgs args) 
        {
            TextSegment textSegment; 
            int i;

            Invariant.Assert(args != null);
            Invariant.Assert(args.Ranges != null); 
            Invariant.Assert(_structuralCache != null && _structuralCache.IsFormattedOnce, "Unexpected Highlights.Changed callback before first format!");
 
            // Detect invalid content change operations. 
            if (_structuralCache.IsFormattingInProgress)
            { 
                _structuralCache.OnInvalidOperationDetected();
                throw new InvalidOperationException(SR.Get(SRID.FlowDocumentInvalidContnetChange));
            }
 
            // The only supported highlight type for FlowDocument is SpellerHightlight.
            // TextSelection and HighlightComponent are ignored, because they are handled by 
            // separate layer. 
            if (args.OwnerType != typeof(SpellerHighlightLayer))
            { 
                return;
            }

            if (args.Ranges.Count > 0) 
            {
 
                // Invalidate affected pages and break records. 
                // We DTR invalidate if we're using a formatter as well for incremental update.
                if (_formatter == null || !(_formatter is FlowDocumentFormatter)) 
                {
                    _structuralCache.InvalidateFormatCache(/*Clear structure*/ false);
                }
 
                // Notify formatter about content invalidation.
                if (_formatter != null) 
                { 
                    for (i = 0; i < args.Ranges.Count; i++)
                    { 
                        textSegment = (TextSegment)args.Ranges[i];
                        _formatter.OnContentInvalidated(false, textSegment.Start, textSegment.End);

                        if (_formatter is FlowDocumentFormatter) 
                        {
                            DirtyTextRange dtr = new DirtyTextRange(textSegment.Start.Offset, 
                                                                    textSegment.Start.GetOffsetToPosition(textSegment.End), 
                                                                    textSegment.Start.GetOffsetToPosition(textSegment.End)
                                                                    ); 
                            _structuralCache.AddDirtyTextRange(dtr);
                        }
                    }
                } 
            }
        } 
 
        /// 
        /// Handler for TextContainer changing notifications. 
        /// 
        private void OnTextContainerChanging(object sender, EventArgs args)
        {
            Invariant.Assert(sender == _structuralCache.TextContainer, "Received text change for foreign TextContainer."); 
            Invariant.Assert(_structuralCache != null && _structuralCache.IsFormattedOnce, "Unexpected TextContainer.Changing callback before first format!");
 
            // Detect invalid content change operations. 
            if (_structuralCache.IsFormattingInProgress)
            { 
                _structuralCache.OnInvalidOperationDetected();
                throw new InvalidOperationException(SR.Get(SRID.FlowDocumentInvalidContnetChange));
            }
 
            // Remember the fact that content is changing.
            // OnTextContainerChange has to be received after this event. 
            _structuralCache.IsContentChangeInProgress = true; 
        }
 
        /// 
        /// Handler for TextContainer change notifications.
        /// 
        ///  
        /// 
        private void OnTextContainerChange(object sender, TextContainerChangeEventArgs args) 
        { 
            DirtyTextRange dtr;
            ITextPointer segmentEnd; 

            Invariant.Assert(args != null);
            Invariant.Assert(sender == _structuralCache.TextContainer);
            Invariant.Assert(_structuralCache != null && _structuralCache.IsFormattedOnce, "Unexpected TextContainer.Change callback before first format!"); 

            if (args.Count == 0) 
            { 
                // A no-op for this control.  Happens when IMECharCount updates happen
                // without corresponding SymbolCount changes. 
                return;
            }

            try 
            {
                // Detect invalid content change operations. 
                if (_structuralCache.IsFormattingInProgress) 
                {
                    _structuralCache.OnInvalidOperationDetected(); 
                    throw new InvalidOperationException(SR.Get(SRID.FlowDocumentInvalidContnetChange));
                }

                // Since content is changeing, do partial invalidation of BreakRecordTable. 
                if (args.TextChange != TextChangeType.ContentRemoved)
                { 
                    segmentEnd = args.ITextPosition.CreatePointer(args.Count, LogicalDirection.Forward); 
                }
                else 
                {
                    segmentEnd = args.ITextPosition;
                }
 
                // Invalidate affected pages and break records.
                // We DTR invalidate if we're using a formatter as well for incremental update. 
                if (!args.AffectsRenderOnly || (_formatter != null && _formatter is FlowDocumentFormatter)) 
                {
                    // Create new DTR for changing range and add it to DRTList. 
                    dtr = new DirtyTextRange(args);
                    _structuralCache.AddDirtyTextRange(dtr);
                }
                else 
                {
                    // Clear format caches. 
                    _structuralCache.InvalidateFormatCache(/*Clear structure*/ false); 
                }
 
                // Notify formatter about content invalidation.
                if (_formatter != null)
                {
                    _formatter.OnContentInvalidated(!args.AffectsRenderOnly, args.ITextPosition, segmentEnd); 
                }
            } 
            finally 
            {
                // Content has been changed, so reset appropriate flag. 
                _structuralCache.IsContentChangeInProgress = false;
            }
        }
 

        private static bool IsValidPageSize(object o) 
        { 
            double value = (double)o;
            double maxSize = Math.Min(1000000, PTS.MaxPageSize); 
            if (Double.IsNaN(value))
            {
                return true;
            } 
            if (value < 0 || value > maxSize)
            { 
                return false; 
            }
            return true; 
        }

        private static bool IsValidMinPageSize(object o)
        { 
            double value = (double)o;
            double maxSize = Math.Min(1000000, PTS.MaxPageSize); 
            if (Double.IsNaN(value)) 
            {
                return false; 
            }
            if (!Double.IsNegativeInfinity(value) && (value < 0 || value > maxSize))
            {
                return false; 
            }
            return true; 
        } 

        private static bool IsValidMaxPageSize(object o) 
        {
            double value = (double)o;
            double maxSize = Math.Min(1000000, PTS.MaxPageSize);
            if (Double.IsNaN(value)) 
            {
                return false; 
            } 
            if (!Double.IsPositiveInfinity(value) && (value < 0 || value > maxSize))
            { 
                return false;
            }
            return true;
        } 

        private static bool IsValidPagePadding(object o) 
        { 
            Thickness value = (Thickness)o;
            return Block.IsValidThickness(value, /*allow NaN*/true); 
        }

        private static bool IsValidColumnRuleWidth(object o)
        { 
            double ruleWidth = (double)o;
            double maxRuleWidth = Math.Min(1000000, PTS.MaxPageSize); 
            if (Double.IsNaN(ruleWidth) || ruleWidth < 0 || ruleWidth > maxRuleWidth) 
            {
                return false; 
            }
            return true;
        }
 
        private static bool IsValidColumnGap(object o)
        { 
            double gap = (double)o; 
            double maxGap = Math.Min(1000000, PTS.MaxPageSize);
            if (Double.IsNaN(gap)) 
            {
                // Default value.
                return true;
            } 
            if (gap < 0 || gap > maxGap)
            { 
                return false; 
            }
            return true; 
        }

        #endregion Private methods
 
        //--------------------------------------------------------------------
        // 
        //  Private Fields 
        //
        //------------------------------------------------------------------- 

        #region Private Fields

        private StructuralCache _structuralCache;                   // Structural cache for the content. 
        private TypographyProperties _typographyPropertiesGroup;    // Cache for typography properties.
        private IFlowDocumentFormatter _formatter;                  // Current formatter asociated with FlowDocument. 
        private TextWrapping _textWrapping = TextWrapping.Wrap;     // internal cache for TextBox/RichTextBox 

        #endregion Private Fields 

        //--------------------------------------------------------------------
        //
        //  IAddChild Members 
        //
        //-------------------------------------------------------------------- 
 
        #region IAddChild Members
 
        ///
        /// Called to Add the object as a Child.
        ///
        /// 
        /// Object to add as a child
        /// 
        void IAddChild.AddChild(Object value) 
        {
            if (value == null) 
            {
                throw new ArgumentNullException("value");
            }
 
            if (!TextSchema.IsValidChildOfContainer(/*parentType:*/typeof(FlowDocument), /*childType:*/value.GetType()))
            { 
                throw new ArgumentException(SR.Get(SRID.TextSchema_ChildTypeIsInvalid, typeof(FlowDocument).Name, value.GetType().Name)); 
            }
 
            // Checking that the element inserted does not have a parent
            if (value is TextElement && ((TextElement)value).Parent != null)
            {
                throw new ArgumentException(SR.Get(SRID.TextSchema_TheChildElementBelongsToAnotherTreeAlready, value.GetType().Name)); 
            }
 
            if (value is Block) 
            {
                TextContainer textContainer = _structuralCache.TextContainer; 
                ((Block)value).RepositionWithContent(textContainer.End);
            }
            else
            { 
                Invariant.Assert(false); // We do not expect anything except Blocks on top level of a FlowDocument
            } 
        } 

        /// 
        /// Called when text appears under the tag in markup
        ///
        ///
        /// Text to Add to the Object 
        ///
        void IAddChild.AddText(string text) 
        { 
            XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this);
        } 

        #endregion IAddChild Members

        //------------------------------------------------------------------- 
        //
        //  IServiceProvider Members 
        // 
        //--------------------------------------------------------------------
 
        #region IServiceProvider Members

        /// 
        /// Gets the service object of the specified type. 
        /// 
        ///  
        /// FlowDocument supports only TextContainer. 
        /// 
        ///  
        /// An object that specifies the type of service object to get.
        /// 
        /// 
        /// A service object of type serviceType. A null reference if there is no 
        /// service object of type serviceType.
        ///  
        object IServiceProvider.GetService(Type serviceType) 
        {
            if (serviceType == null) 
            {
                throw new ArgumentNullException("serviceType");
            }
            if (serviceType == typeof(ITextContainer)) 
            {
                return _structuralCache.TextContainer; 
            } 
            else if (serviceType == typeof(TextContainer))
            { 
                return _structuralCache.TextContainer as TextContainer;
            }
            return null;
        } 

        #endregion IServiceProvider Members 
 
        //-------------------------------------------------------------------
        // 
        //  IDocumentPaginatorSource Members
        //
        //-------------------------------------------------------------------
 
        #region IDocumentPaginatorSource Members
 
        ///  
        /// An object which paginates content.
        ///  
        DocumentPaginator IDocumentPaginatorSource.DocumentPaginator
        {
            get
            { 
                if (_formatter != null && !(_formatter is FlowDocumentPaginator))
                { 
                    _formatter.Suspend(); 
                    _formatter = null;
                } 
                if (_formatter == null)
                {
                    _formatter = new FlowDocumentPaginator(this);
                } 
                return (FlowDocumentPaginator)_formatter;
            } 
        } 

        #endregion IDocumentPaginatorSource Members 
    }
}


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