FlowDocument.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Documents / FlowDocument.cs / 1305600 / 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.ComponentModel;
using System.Windows.Automation.Peers;        // AutomationPeer 
using System.Windows.Controls; 
using System.Windows.Markup;
using System.Windows.Media; 
using System.Windows.Threading;
using MS.Internal;                            // DoubleUtil
using MS.Internal.Documents;
using MS.Internal.PtsHost; 
using MS.Internal.PtsHost.UnsafeNativeMethods; // PTS restrictions
using MS.Internal.Text; 
 
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 
    {
        static private readonly Type _typeofThis = typeof(FlowDocument); 
 
        //-------------------------------------------------------------------
        // 
        //  Constructors
        //
        //-------------------------------------------------------------------
 
        #region Constructors
 
        ///  
        /// Static constructor. Registers metadata for its properties.
        ///  
        static FlowDocument()
        {
            PropertyChangedCallback typographyChanged = new PropertyChangedCallback(OnTypographyChanged);
 
            // Registering typography properties metadata
            DependencyProperty[] typographyProperties = Typography.TypographyPropertiesList; 
            for (int i = 0; i < typographyProperties.Length; i++) 
            {
                typographyProperties[i].OverrideMetadata(_typeofThis, new FrameworkPropertyMetadata(typographyChanged)); 
            }

            DefaultStyleKeyProperty.OverrideMetadata(_typeofThis, new FrameworkPropertyMetadata(_typeofThis));
            FocusableProperty.OverrideMetadata(_typeofThis, 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(_typeofThis); 
 
        /// 
        /// 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(_typeofThis); 

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

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

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

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

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

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

            // 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:*/_typeofThis, /*childType:*/value.GetType()))
            {
                throw new ArgumentException(SR.Get(SRID.TextSchema_ChildTypeIsInvalid, _typeofThis.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.
//---------------------------------------------------------------------------- 
//
// 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.ComponentModel;
using System.Windows.Automation.Peers;        // AutomationPeer 
using System.Windows.Controls; 
using System.Windows.Markup;
using System.Windows.Media; 
using System.Windows.Threading;
using MS.Internal;                            // DoubleUtil
using MS.Internal.Documents;
using MS.Internal.PtsHost; 
using MS.Internal.PtsHost.UnsafeNativeMethods; // PTS restrictions
using MS.Internal.Text; 
 
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 
    {
        static private readonly Type _typeofThis = typeof(FlowDocument); 
 
        //-------------------------------------------------------------------
        // 
        //  Constructors
        //
        //-------------------------------------------------------------------
 
        #region Constructors
 
        ///  
        /// Static constructor. Registers metadata for its properties.
        ///  
        static FlowDocument()
        {
            PropertyChangedCallback typographyChanged = new PropertyChangedCallback(OnTypographyChanged);
 
            // Registering typography properties metadata
            DependencyProperty[] typographyProperties = Typography.TypographyPropertiesList; 
            for (int i = 0; i < typographyProperties.Length; i++) 
            {
                typographyProperties[i].OverrideMetadata(_typeofThis, new FrameworkPropertyMetadata(typographyChanged)); 
            }

            DefaultStyleKeyProperty.OverrideMetadata(_typeofThis, new FrameworkPropertyMetadata(_typeofThis));
            FocusableProperty.OverrideMetadata(_typeofThis, 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(_typeofThis); 
 
        /// 
        /// 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(_typeofThis); 

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

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

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

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

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

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

            // 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:*/_typeofThis, /*childType:*/value.GetType()))
            {
                throw new ArgumentException(SR.Get(SRID.TextSchema_ChildTypeIsInvalid, _typeofThis.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