TextSchema.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

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

                            //---------------------------------------------------------------------------- 
//
// File TextSchema.cs
//
// Copyright (C) Microsoft Corporation.  All rights reserved. 
//
// Description: A static class providing information about text content schema 
// 
//---------------------------------------------------------------------------
 
namespace System.Windows.Documents
{
    using MS.Internal;
    using System.Collections.Generic; 
    using System.Windows.Controls; // TextBox, TextBlock
    using System.Windows.Media; // Brush 
 
    /// 
    /// Provides an information about text structure schema. 
    /// The schema is used in editing operations for maintaining
    /// content integrity.
    /// 
    ///  
    /// Currently this class is totally private and hard-coded
    /// for some particular text structure. 
    /// The intention is to make this mechanism public - 
    /// as part of Text OM, so that custom backing store implementation
    /// could provide its own schemas. 
    /// But we need to experiment with this approach first to make
    /// sure that it is feasible.
    /// 
    internal static class TextSchema 
    {
        // ............................................................... 
        // 
        // Constructors
        // 
        // ...............................................................

        static TextSchema()
        { 
            // Initialize TextElement inheritable properties
            DependencyProperty[] textElementPropertyList = new DependencyProperty[] 
                { 
                    FrameworkElement.LanguageProperty,
                    FrameworkElement.FlowDirectionProperty, 
                    NumberSubstitution.CultureSourceProperty,
                    NumberSubstitution.SubstitutionProperty,
                    NumberSubstitution.CultureOverrideProperty,
                    TextElement.FontFamilyProperty, 
                    TextElement.FontStyleProperty,
                    TextElement.FontWeightProperty, 
                    TextElement.FontStretchProperty, 
                    TextElement.FontSizeProperty,
                    TextElement.ForegroundProperty, 
                };

            _inheritableTextElementProperties = new DependencyProperty[textElementPropertyList.Length + Typography.TypographyPropertiesList.Length];
            Array.Copy(textElementPropertyList, 0, _inheritableTextElementProperties, 0, textElementPropertyList.Length); 
            Array.Copy(Typography.TypographyPropertiesList, 0, _inheritableTextElementProperties, textElementPropertyList.Length, Typography.TypographyPropertiesList.Length);
 
            // Initialize Block/FlowDocument inheritable properties 
            DependencyProperty[] blockPropertyList = new DependencyProperty[]
                { 
                    Block.TextAlignmentProperty,
                    Block.LineHeightProperty,
                    Block.IsHyphenationEnabledProperty,
                }; 

            _inheritableBlockProperties = new DependencyProperty[blockPropertyList.Length + _inheritableTextElementProperties.Length]; 
            Array.Copy(blockPropertyList, 0, _inheritableBlockProperties, 0, blockPropertyList.Length); 
            Array.Copy(_inheritableTextElementProperties, 0, _inheritableBlockProperties, blockPropertyList.Length, _inheritableTextElementProperties.Length);
        } 

        // ...............................................................
        //
        // Element Content Model 
        //
        // ............................................................... 
 
        internal static bool IsInTextContent(ITextPointer position)
        { 
            return IsValidChild(position, typeof(string));
        }

#if UNUSED 
        internal static bool IsValidChild(TextElement parent, TextElement child)
        { 
            return ValidateChild(parent, child, false /* throwIfIllegalChild */, false /* throwIfIllegalHyperlinkDescendent */); 
        }
#endif 

        internal static bool ValidateChild(TextElement parent, TextElement child, bool throwIfIllegalChild, bool throwIfIllegalHyperlinkDescendent)
        {
            // Disallow nested hyperlink elements. 
            if (TextSchema.HasHyperlinkAncestor(parent) &&
                TextSchema.HasIllegalHyperlinkDescendant(child, throwIfIllegalHyperlinkDescendent)) 
            { 
                return false;
            } 

            bool isValidChild = IsValidChild(parent.GetType(), child.GetType());

            if (!isValidChild && throwIfIllegalChild) 
            {
                throw new InvalidOperationException(SR.Get(SRID.TextSchema_ChildTypeIsInvalid, parent.GetType().Name, child.GetType().Name)); 
            } 

            return isValidChild; 
        }

        internal static bool IsValidChild(TextElement parent, Type childType)
        { 
            return ValidateChild(parent, childType, false /* throwIfIllegalChild */, false /* throwIfIllegalHyperlinkDescendent */);
        } 
 
        internal static bool ValidateChild(TextElement parent, Type childType, bool throwIfIllegalChild, bool throwIfIllegalHyperlinkDescendent)
        { 
            // Disallow nested hyperlink elements.
            if (TextSchema.HasHyperlinkAncestor(parent))
            {
                if (typeof(Hyperlink).IsAssignableFrom(childType) || 
                    typeof(AnchoredBlock).IsAssignableFrom(childType))
                { 
                    if (throwIfIllegalHyperlinkDescendent) 
                    {
                        throw new InvalidOperationException(SR.Get(SRID.TextSchema_IllegalHyperlinkChild, childType)); 
                    }
                    return false;
                }
            } 

            bool isValidChild = IsValidChild(parent.GetType(), childType); 
 
            if (!isValidChild && throwIfIllegalChild)
            { 
                throw new InvalidOperationException(SR.Get(SRID.TextSchema_ChildTypeIsInvalid, parent.GetType().Name, childType.Name));
            }

            return isValidChild; 
        }
 
        internal static bool IsValidChild(TextPointer position, Type childType) 
        {
            return ValidateChild(position, childType, false /* throwIfIllegalChild */, false /* throwIfIllegalHyperlinkDescendent */); 
        }

        internal static bool ValidateChild(TextPointer position, Type childType, bool throwIfIllegalChild, bool throwIfIllegalHyperlinkDescendent)
        { 
            DependencyObject parent = position.Parent;
 
            if (parent is TextElement) 
            {
                return ValidateChild((TextElement)parent, childType, throwIfIllegalChild, throwIfIllegalHyperlinkDescendent); 
            }

            bool isValidChild = IsValidChild(parent.GetType(), childType);
 
            if (!isValidChild && throwIfIllegalChild)
            { 
                throw new InvalidOperationException(SR.Get(SRID.TextSchema_ChildTypeIsInvalid, parent.GetType().Name, childType.Name)); 
            }
 
            return isValidChild;
        }

        internal static bool IsValidChild(ITextPointer position, Type childType) 
        {
            // Disallow nested hyperlink elements. 
            if (typeof(TextElement).IsAssignableFrom(position.ParentType) && 
                TextPointerBase.IsInHyperlinkScope(position))
            { 
                if (typeof(Hyperlink).IsAssignableFrom(childType) ||
                    typeof(AnchoredBlock).IsAssignableFrom(childType))
                {
                    return false; 
                }
            } 
 
            return IsValidChild(position.ParentType, childType);
        } 

        internal static bool IsValidChildOfContainer(Type parentType, Type childType)
        {
            Invariant.Assert(!typeof(TextElement).IsAssignableFrom(parentType)); 
            return IsValidChild(parentType, childType);
        } 
 
        // Walks parents of this TextElement until it finds a hyperlink ancestor.
        internal static bool HasHyperlinkAncestor(TextElement element) 
        {
            Inline ancestor = element as Inline;

            while (ancestor != null && !(ancestor is Hyperlink)) 
            {
                ancestor = ancestor.Parent as Inline; 
            } 

            return ancestor != null; 
        }

        /// 
        /// Returns true indicatinng that a type can be skipped for pointer normalization - 
        /// it is formattinng tag not producing a caret stop position.
        ///  
        ///  
        /// 
        internal static bool IsFormattingType(Type elementType) 
        {
            return
                typeof(Run).IsAssignableFrom(elementType) ||
                typeof(Span).IsAssignableFrom(elementType); 
        }
 
        ///  
        /// Determine if the given type is "known"-- that is, is part of the framework as
        /// opposed to a custom, user-defined type. 
        /// 
        internal static bool IsKnownType(Type elementType)
        {
            return elementType.Module == typeof(System.Windows.Documents.TextElement).Module || // presentationframework 
                elementType.Module == typeof(System.Windows.UIElement).Module; // presentationcore
        } 
 
        internal static bool IsNonFormattingInline(Type elementType)
        { 
            return typeof(Inline).IsAssignableFrom(elementType) && !IsFormattingType(elementType);
        }

        internal static bool IsMergeableInline(Type elementType) 
        {
            return IsFormattingType(elementType) && !IsNonMergeableInline(elementType); 
        } 

        internal static bool IsNonMergeableInline(Type elementType) 
        {
            TextElementEditingBehaviorAttribute att = (TextElementEditingBehaviorAttribute)Attribute.GetCustomAttribute(elementType, typeof(TextElementEditingBehaviorAttribute));
            if (att != null && att.IsMergeable == false)
            { 
                return true;
            } 
            else 
            {
                return false; 
            }
        }

        ///  
        /// Returns true for a type which allows paragraph merging
        /// across its boundary. 
        /// Hard-structured elements like Table, Floater, Figure 
        /// does not allow paragraph merging.
        ///  
        internal static bool AllowsParagraphMerging(Type elementType)
        {
            return
                typeof(Paragraph).IsAssignableFrom(elementType) || 
                typeof(ListItem).IsAssignableFrom(elementType) ||
                typeof(List).IsAssignableFrom(elementType) || 
                typeof(Section).IsAssignableFrom(elementType); 
        }
 
        /// 
        /// Classifies the elementType as a generalized Paragraph -
        /// a block behaving similar to paragraph in regards of
        /// margins, indentations, bullets, and other paragraph properties. 
        /// 
        ///  
        /// Element type to check 
        /// 
        ///  
        /// true if the element can be treated as a paragraph
        /// 
        internal static bool IsParagraphOrBlockUIContainer(Type elementType)
        { 
            return
                typeof(Paragraph).IsAssignableFrom(elementType) || 
                typeof(BlockUIContainer).IsAssignableFrom(elementType); 
        }
 
        // Identifies any block element
        internal static bool IsBlock(Type type)
        {
            return ( // 
                typeof(Block).IsAssignableFrom(type));
        } 
 
        internal static bool IsBreak(Type type)
        { 
            return ( //
                typeof(LineBreak).IsAssignableFrom(type));
        }
 
        // ...............................................................
        // 
        // Formatting Properties 
        //
        // ............................................................... 

        // Helper for defining whether text decoration value is non-empty collection
        internal static bool HasTextDecorations(object value)
        { 
            return (value is TextDecorationCollection) && ((TextDecorationCollection)value).Count > 0;
        } 
 
        // From a given element type returns one of statically known
        // reduceElement parameter: True value of this parameter indicates that 
        // serialization goes into XamlPackage, so all elements
        // can be preserved as is; otherwise some of them must be
        // reduced into simpler representations (such as InlineUIContainer -> Run
        // and BlockUIContainer -> Paragraph). 
        internal static Type GetStandardElementType(Type type, bool reduceElement)
        { 
            // Run-derived elements 
            // --------------------
            if (typeof(Run).IsAssignableFrom(type)) 
            {
                // Must be after all elements derived from Run
                return typeof(Run);
            } 

            // Span-derived elements 
            // --------------------- 
            else if (typeof(Hyperlink).IsAssignableFrom(type))
            { 
                return typeof(Hyperlink);
            }
            else if (typeof(Span).IsAssignableFrom(type))
            { 
                // Must be after all other standard Span-derived elements such as Hyperlink, Bold, etc.
                return typeof(Span); 
            } 

            // Other Inline elements 
            // ---------------------
            else if (typeof(InlineUIContainer).IsAssignableFrom(type))
            {
                return reduceElement ? typeof(Run) : typeof(InlineUIContainer); 
            }
            else if (typeof(LineBreak).IsAssignableFrom(type)) 
            { 
                return typeof(LineBreak);
            } 
            else if (typeof(Floater).IsAssignableFrom(type))
            {
                return typeof(Floater);
            } 
            else if (typeof(Figure).IsAssignableFrom(type))
            { 
                return typeof(Figure); 
            }
 
            // Block-derived elements
            // ----------------------
            else if (typeof(Paragraph).IsAssignableFrom(type))
            { 
                return typeof(Paragraph);
            } 
            else if (typeof(Section).IsAssignableFrom(type)) 
            {
                return typeof(Section); 
            }
            else if (typeof(List).IsAssignableFrom(type))
            {
                return typeof(List); 
            }
            else if (typeof(Table).IsAssignableFrom(type)) 
            { 
                return typeof(Table);
            } 
            else if (typeof(BlockUIContainer).IsAssignableFrom(type))
            {
                return reduceElement ? typeof(Paragraph) : typeof(BlockUIContainer);
            } 

            // Other TextElements 
            // ------------------ 
            else if (typeof(ListItem).IsAssignableFrom(type))
            { 
                return typeof(ListItem);
            }
            else if (typeof(TableColumn).IsAssignableFrom(type))
            { 
                return typeof(TableColumn);
            } 
            else if (typeof(TableRowGroup).IsAssignableFrom(type)) 
            {
                return typeof(TableRowGroup); 
            }
            else if (typeof(TableRow).IsAssignableFrom(type))
            {
                return typeof(TableRow); 
            }
            else if (typeof(TableCell).IsAssignableFrom(type)) 
            { 
                return typeof(TableCell);
            } 

            // To make compiler happy in cases of Invariant.Assert - return something
            Invariant.Assert(false, "We do not expect any unknown elements derived directly from TextElement, Block or Inline. Schema must have been checking for that");
            return null; 
        }
 
        // Returns a list of inheritable properties applicable to a particular type 
        internal static DependencyProperty[] GetInheritableProperties(Type type)
        { 
            if (typeof(Block).IsAssignableFrom(type) || typeof(FlowDocument).IsAssignableFrom(type))
            {
                return _inheritableBlockProperties;
            } 

            Invariant.Assert(typeof(TextElement).IsAssignableFrom(type) || typeof(TableColumn).IsAssignableFrom(type), 
                "type must be one of TextElement, FlowDocument or TableColumn"); 

            return _inheritableTextElementProperties; 
        }

        // Returns a list of noninheritable properties applicable to a particular type
        // They are safe to be transferred from outer scope to inner scope when the outer one 
        // is removed (e.g. TextRangeEdit.RemoveUnnecessarySpans(...)).
        internal static DependencyProperty[] GetNoninheritableProperties(Type type) 
        { 
            // Run-derived elements
            // -------------------- 
            if (typeof(Run).IsAssignableFrom(type))
            {
                // Must be after all elements derived from Run
                return _inlineProperties; 
            }
 
            // Span-derived elements 
            // ---------------------
            else if (typeof(Hyperlink).IsAssignableFrom(type)) 
            {
                return _hyperlinkProperties;
            }
            else if (typeof(Span).IsAssignableFrom(type)) 
            {
                // Must be after all other standard Span-derived elements such as Hyperlink, Bold, etc. 
                return _inlineProperties; 
            }
 
            // Other Inline elements
            // ---------------------
            else if (typeof(InlineUIContainer).IsAssignableFrom(type))
            { 
                return _inlineProperties;
            } 
            else if (typeof(LineBreak).IsAssignableFrom(type)) 
            {
                return _emptyPropertyList; 
            }
            else if (typeof(Floater).IsAssignableFrom(type))
            {
                return _floaterProperties; 
            }
            else if (typeof(Figure).IsAssignableFrom(type)) 
            { 
                return _figureProperties;
            } 

            // Block-derived elements
            // ----------------------
            else if (typeof(Paragraph).IsAssignableFrom(type)) 
            {
                return _paragraphProperties; 
            } 
            else if (typeof(Section).IsAssignableFrom(type))
            { 
                return _blockProperties;
            }
            else if (typeof(List).IsAssignableFrom(type))
            { 
                return _listProperties;
            } 
            else if (typeof(Table).IsAssignableFrom(type)) 
            {
                return _tableProperties; 
            }
            else if (typeof(BlockUIContainer).IsAssignableFrom(type))
            {
                return _blockProperties; 
            }
 
            // Other TextElements 
            // ------------------
            else if (typeof(ListItem).IsAssignableFrom(type)) 
            {
                return _listItemProperties;
            }
            else if (typeof(TableColumn).IsAssignableFrom(type)) 
            {
                return _tableColumnProperties; 
            } 
            else if (typeof(TableRowGroup).IsAssignableFrom(type))
            { 
                return _tableRowGroupProperties;
            }
            else if (typeof(TableRow).IsAssignableFrom(type))
            { 
                return _tableRowProperties;
            } 
            else if (typeof(TableCell).IsAssignableFrom(type)) 
            {
                return _tableCellProperties; 
            }

            Invariant.Assert(false, "We do not expect any unknown elements derived directly from TextElement. Schema must have been checking for that");
            return _emptyPropertyList; // to make compiler happy 
        }
 
        // Compares two values for equality 
        /// 
        /// Property comparison helper. 
        /// Compares property values for equivalence from serialization
        /// standpoint. In editing we consider properties equal
        /// if they have the same serialized representation.
        /// Differences coming from current dynamic state changes 
        /// should not affect comparison if they are not going to be
        /// visible after serialization. 
        /// Instantiation dirrefences are also insignificant. 
        /// 
        ///  
        /// 
        /// 
        /// 
        ///  
        /// True if two values have the same serialized representation
        ///  
        internal static bool ValuesAreEqual(object value1, object value2) 
        {
            if ((object)value1 == (object)value2) // this check includes two nulls 
            {
                return true;
            }
 
            // Comparing null with empty collections
            if (value1 == null) 
            { 
                if (value2 is TextDecorationCollection)
                { 
                    TextDecorationCollection decorations2 = (TextDecorationCollection)value2;
                    return decorations2.Count == 0;
                }
                else if (value2 is TextEffectCollection) 
                {
                    TextEffectCollection effects2 = (TextEffectCollection)value2; 
                    return effects2.Count == 0; 
                }
                return false; 
            }
            else if (value2 == null)
            {
                if (value1 is TextDecorationCollection) 
                {
                    TextDecorationCollection decorations1 = (TextDecorationCollection)value1; 
                    return decorations1.Count == 0; 
                }
                else if (value1 is TextEffectCollection) 
                {
                    TextEffectCollection effects1 = (TextEffectCollection)value1;
                    return effects1.Count == 0;
                } 
                return false;
            } 
 
            // Must be of exactly the same types (really ?)
            // 
            if (value1.GetType() != value2.GetType())
            {
                return false;
            } 

            // Special cases for known types: TextDecorations, FontFamily, Brush 
            if (value1 is TextDecorationCollection) 
            {
                TextDecorationCollection decorations1 = (TextDecorationCollection)value1; 
                TextDecorationCollection decorations2 = (TextDecorationCollection)value2;
                return decorations1.ValueEquals(decorations2);
            }
            else if (value1 is FontFamily) 
            {
                FontFamily fontFamily1 = (FontFamily)value1; 
                FontFamily fontFamily2 = (FontFamily)value2; 
                return fontFamily1.Equals(fontFamily2);
            } 
            else if (value1 is Brush)
            {
                return AreBrushesEqual((Brush)value1, (Brush)value2);
            } 
            else
            { 
                string string1 = value1.ToString(); 
                string string2 = value2.ToString();
                return string1 == string2; 
            }
        }

        ///  
        /// Tests whether it is the paragraph property or not.
        /// Used to decide should the property be applied to character runs or to paragraphs 
        /// in TextRange.ApplyProperty() 
        /// 
        internal static bool IsParagraphProperty(DependencyProperty formattingProperty) 
        {
            // Check inheritable paragraph properties
            for (int i = 0; i < _inheritableBlockProperties.Length; i++)
            { 
                if (formattingProperty == _inheritableBlockProperties[i])
                { 
                    return true; 
                }
            } 

            // Check non-inheritable paragraph properties
            for (int i = 0; i < _paragraphProperties.Length; i++)
            { 
                if (formattingProperty == _paragraphProperties[i])
                { 
                    return true; 
                }
            } 
            return false;
        }

        ///  
        /// Returns true if this property is applicable to inline character formatting element
        ///  
        internal static bool IsCharacterProperty(DependencyProperty formattingProperty) 
        {
            // Check inheritable inline properties 
            for (int i = 0; i < _inheritableTextElementProperties.Length; i++)
            {
                if (formattingProperty == _inheritableTextElementProperties[i])
                { 
                    return true;
                } 
            } 

            // Check non-inheritable Inline properties 
            for (int i = 0; i < _inlineProperties.Length; i++)
            {
                if (formattingProperty == _inlineProperties[i])
                { 
                    return true;
                } 
            } 
            return false;
        } 

        /// 
        /// Returns true if this property is a character property NOT affecting formatting.
        ///  
        internal static bool IsNonFormattingCharacterProperty(DependencyProperty property)
        { 
            for (int i = 0; i < _nonFormattingCharacterProperties.Length; i++) 
            {
                if (property == _nonFormattingCharacterProperties[i]) 
                {
                    return true;
                }
            } 

            return false; 
        } 

        internal static DependencyProperty[] GetNonFormattingCharacterProperties() 
        {
            return _nonFormattingCharacterProperties;
        }
 
        /// 
        /// Returns true if this property is a structural property of inline element. 
        ///  
        /// 
        /// A structural character property is more strict for its scope than other (non-structural) inline properties (such as fontweight). 
        /// While the associativity rule holds true for non-structural properties when there values are equal,
        ///     (FontWeight)A (FontWeight)B == (FontWeight) AB
        /// this does not hold true for structual properties even when there values may be equal,
        ///     (FlowDirection)A (FlowDirection)B != (FlowDirection)A B 
        /// Hence, these properties require special logic in setting, merging, splitting rules for inline elements.
        ///  
        internal static bool IsStructuralCharacterProperty(DependencyProperty formattingProperty) 
        {
            int i; 

            for (i = 0; i < _structuralCharacterProperties.Length; i++)
            {
                if (formattingProperty == _structuralCharacterProperties[i]) 
                    break;
            } 
 
            return (i < _structuralCharacterProperties.Length);
        } 

        // Returns true if a property value can be incremented or decremented
        internal static bool IsPropertyIncremental(DependencyProperty property)
        { 
            if (property == null)
            { 
                return false; 
            }
 
            Type propertyType = property.PropertyType;

            return
                typeof(double).IsAssignableFrom(propertyType) || 
                typeof(long).IsAssignableFrom(propertyType) ||
                typeof(int).IsAssignableFrom(propertyType) || 
                typeof(Thickness).IsAssignableFrom(propertyType); 
        }
 
        // Set of properties affecting editing behavior that must be transferred
        // from hosting UI elements (like RichTextBox) to FlowDocument to ensure appropriate
        // editing behavior.
        // This is especially important for FlowDocuments with FormattingDefaults="Standalone". 
        internal static DependencyProperty[] BehavioralProperties
        { 
            get 
            {
                return _behavioralPropertyList; 
            }
        }

        internal static DependencyProperty[] ImageProperties 
        {
            get 
            { 
                return _imagePropertyList;
            } 
        }

        // List of structural properties.
        internal static DependencyProperty[] StructuralCharacterProperties 
        {
            get 
            { 
                return _structuralCharacterProperties;
            } 
        }

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

        #region Private Methods 

        private static bool IsValidChild(Type parentType, Type childType)
        {
            // Text Content 
            if (parentType == null || //
                typeof(Run).IsAssignableFrom(parentType) || 
                typeof(TextBox).IsAssignableFrom(parentType) || 
                typeof(PasswordBox).IsAssignableFrom(parentType))
            { 
                // NOTE: Even though we use TextBlock or FlowDocumentView for TextBox's render scope,
                // a parent for position will be directly TextBlock or PasswordBox, thus allowing
                // text content. Otherwise neither TextBlock nor FlowDocumentView allow direct text content -
                // only through Run. 
                return childType == typeof(string);
            } 
            // TextBlock allowed children 
            else if (typeof(TextBlock).IsAssignableFrom(parentType))
            { 
                return typeof(Inline).IsAssignableFrom(childType) &&
                    !typeof(AnchoredBlock).IsAssignableFrom(childType);
            }
            // Hyperlink allowed children 
            else if (typeof(Hyperlink).IsAssignableFrom(parentType))
            { 
                return typeof(Inline).IsAssignableFrom(childType) && 
                    !typeof(Hyperlink).IsAssignableFrom(childType) &&
                    !typeof(AnchoredBlock).IsAssignableFrom(childType); 
            }
            // Inline items
            else if (typeof(Span).IsAssignableFrom(parentType) ||
                typeof(Paragraph).IsAssignableFrom(parentType) || 
                typeof(AccessText).IsAssignableFrom(parentType))
            { 
                return typeof(Inline).IsAssignableFrom(childType); 
            }
            // Inline UIElements 
            else if (typeof(InlineUIContainer).IsAssignableFrom(parentType))
            {
                return typeof(UIElement).IsAssignableFrom(childType);
            } 
            // List Content
            else if (typeof(List).IsAssignableFrom(parentType)) 
            { 
                return typeof(ListItem).IsAssignableFrom(childType);
            } 
            // Table Content
            else if (typeof(Table).IsAssignableFrom(parentType))
            {
                return typeof(TableRowGroup).IsAssignableFrom(childType); 
            }
            else if (typeof(TableRowGroup).IsAssignableFrom(parentType)) 
            { 
                return typeof(TableRow).IsAssignableFrom(childType);
            } 
            else if (typeof(TableRow).IsAssignableFrom(parentType))
            {
                return typeof(TableCell).IsAssignableFrom(childType);
            } 
            // Block Content
            // 
            else if ( 
                typeof(Section).IsAssignableFrom(parentType) ||
                typeof(ListItem).IsAssignableFrom(parentType) || 
                typeof(TableCell).IsAssignableFrom(parentType) ||
                typeof(Floater).IsAssignableFrom(parentType) ||
                typeof(Figure).IsAssignableFrom(parentType) ||
                typeof(FlowDocument).IsAssignableFrom(parentType)) 
            {
                return typeof(Block).IsAssignableFrom(childType); 
            } 
            // Block UIElements
            else if (typeof(BlockUIContainer).IsAssignableFrom(parentType)) 
            {
                return typeof(UIElement).IsAssignableFrom(childType);
            }
            else 
            {
                return false; 
            } 
        }
 
        // Returns true if passed textelement has any Hyperlink or AnchoredBlock descendant.
        // It this context, the element or one of its ancestors is a Hyperlink.
        private static bool HasIllegalHyperlinkDescendant(TextElement element, bool throwIfIllegalDescendent)
        { 
            TextPointer start = element.ElementStart;
            TextPointer end = element.ElementEnd; 
 
            while (start.CompareTo(end) < 0)
            { 
                TextPointerContext forwardContext = start.GetPointerContext(LogicalDirection.Forward);
                if (forwardContext == TextPointerContext.ElementStart)
                {
                    TextElement nextElement = (TextElement)start.GetAdjacentElement(LogicalDirection.Forward); 

                    if (nextElement is Hyperlink || 
                        nextElement is AnchoredBlock) 
                    {
                        if (throwIfIllegalDescendent) 
                        {
                            throw new InvalidOperationException(SR.Get(SRID.TextSchema_IllegalHyperlinkChild, nextElement.GetType()));
                        }
                        return true; 
                    }
                } 
 
                start = start.GetNextContextPosition(LogicalDirection.Forward);
            } 
            return false;
        }

        private static bool AreBrushesEqual(Brush brush1, Brush brush2) 
        {
            SolidColorBrush solidBrush1 = brush1 as SolidColorBrush; 
            if (solidBrush1 != null) 
            {
                return solidBrush1.Color.Equals(((SolidColorBrush)brush2).Color); 
            }
            else
            {
                // When the brush is not serializable to string, we consider values equal only is they are equal as objects 
                string string1 = DPTypeDescriptorContext.GetStringValue(TextElement.BackgroundProperty, brush1);
                string string2 = DPTypeDescriptorContext.GetStringValue(TextElement.BackgroundProperty, brush2); 
                return string1 != null && string2 != null ? string1 == string2 : false; 
            }
        } 

        #endregion Private Methods

        //------------------------------------------------------ 
        //
        //  Private Fields 
        // 
        //-----------------------------------------------------
 
        #region Private Fields

        // List of all inheritable properties applicable to TextElement types
        private static readonly DependencyProperty[] _inheritableTextElementProperties; 

        // Block element adds a few inhertiable properties that dont apply to other TextElement types, 
        // this list includes inheritable properties applicable to Block and also root FlowDocument types. 
        private static readonly DependencyProperty[] _inheritableBlockProperties;
 
        // List of all non-inheritable properties applicable to Hyperlink element
        private static readonly DependencyProperty[] _hyperlinkProperties = new DependencyProperty[]
            {
                Hyperlink.NavigateUriProperty, 
                Hyperlink.TargetNameProperty,
                Hyperlink.CommandProperty, 
                Hyperlink.CommandParameterProperty, 
                Hyperlink.CommandTargetProperty,
 
                // Inherits Inline Properties
                Inline.BaselineAlignmentProperty,
                Inline.TextDecorationsProperty,
 
                // Inherits TextElement properties
                TextElement.BackgroundProperty, 
                //TextElement.TextEffectsProperty, -- the property is not supported in text editor 

                // Inherits FrameworkContentElement properties 
                FrameworkContentElement.ToolTipProperty,
            };

        // List of all non-inheritable properties applicable to Inline element 
        private static readonly DependencyProperty[] _inlineProperties = new DependencyProperty[]
            { 
                Inline.BaselineAlignmentProperty, 
                Inline.TextDecorationsProperty,
 
                // Inherits TextElement properties
                TextElement.BackgroundProperty,
                //TextElement.TextEffectsProperty, -- the property is not supported in text editor
            }; 

        // List of all non-inheritable properties applicable to Paragraph element 
        private static readonly DependencyProperty[] _paragraphProperties = new DependencyProperty[] 
            {
                Paragraph.MinWidowLinesProperty, 
                Paragraph.MinOrphanLinesProperty,
                Paragraph.TextIndentProperty,
                Paragraph.KeepWithNextProperty,
                Paragraph.KeepTogetherProperty, 
                Paragraph.TextDecorationsProperty,
 
                // Inherits Block properties 
                Block.MarginProperty,
                Block.PaddingProperty, 
                Block.BorderThicknessProperty,
                Block.BorderBrushProperty,

                // Inherits TextElement properties 
                TextElement.BackgroundProperty,
                //TextElement.TextEffectsProperty, -- the property is not supported in text editor 
            }; 

        // List of all non-inheritable properties applicable to List element 
        private static readonly DependencyProperty[] _listProperties = new DependencyProperty[]
            {
                List.MarkerStyleProperty,
                List.MarkerOffsetProperty, 
                List.StartIndexProperty,
 
                // Inherits Block properties 
                Block.MarginProperty,
                Block.PaddingProperty, 
                Block.BorderThicknessProperty,
                Block.BorderBrushProperty,

                // Inherits TextElement properties 
                TextElement.BackgroundProperty,
                //TextElement.TextEffectsProperty, -- the property is not supported in text editor 
            }; 

        // List of all non-inheritable properties applicable to ListItem element 
        private static readonly DependencyProperty[] _listItemProperties = new DependencyProperty[]
            {
                // Adds owner to Block properties
                ListItem.MarginProperty, 
                ListItem.PaddingProperty,
                ListItem.BorderThicknessProperty, 
                ListItem.BorderBrushProperty, 

                // Inherits TextElement properties 
                TextElement.BackgroundProperty,
                //TextElement.TextEffectsProperty, -- the property is not supported in text editor
            };
 
        // List of all non-inheritable properties applicable to Table element
        private static readonly DependencyProperty[] _tableProperties = new DependencyProperty[] 
            { 
                Table.CellSpacingProperty,
 
                // Inherits Block properties
                Block.MarginProperty,
                Block.PaddingProperty,
                Block.BorderThicknessProperty, 
                Block.BorderBrushProperty,
 
                // Inherits TextElement properties 
                TextElement.BackgroundProperty,
                //TextElement.TextEffectsProperty, -- the property is not supported in text editor 
            };

        // List of all non-inheritable properties applicable to TableColumn element
        private static readonly DependencyProperty[] _tableColumnProperties = new DependencyProperty[] 
            {
                TableColumn.WidthProperty, 
                TableColumn.BackgroundProperty, 
            };
 
        // List of all non-inheritable properties applicable to TableRowGroup element
        private static readonly DependencyProperty[] _tableRowGroupProperties = new DependencyProperty[]
            {
                // Inherits TextElement properties 
                TextElement.BackgroundProperty,
                //TextElement.TextEffectsProperty, -- the property is not supported in text editor 
            }; 

        // List of all non-inheritable properties applicable to TableRow element 
        private static readonly DependencyProperty[] _tableRowProperties = new DependencyProperty[]
            {
                // Inherits TextElement properties
                TextElement.BackgroundProperty, 
                //TextElement.TextEffectsProperty, -- the property is not supported in text editor
            }; 
 
        // List of all non-inheritable properties applicable to TableCell element
        private static readonly DependencyProperty[] _tableCellProperties = new DependencyProperty[] 
            {
                TableCell.ColumnSpanProperty,
                TableCell.RowSpanProperty,
 
                // Adds ownership to Block properties
                TableCell.PaddingProperty, 
                TableCell.BorderThicknessProperty, 
                TableCell.BorderBrushProperty,
 
                // Inherits TextElement properties
                TextElement.BackgroundProperty,
                //TextElement.TextEffectsProperty, -- the property is not supported in text editor
            }; 

        // List of all non-inheritable properties applicable to Floater element 
        private static readonly DependencyProperty[] _floaterProperties = new DependencyProperty[] 
            {
                Floater.HorizontalAlignmentProperty, 
                Floater.WidthProperty,

                // Adds ownership to Block properties
                Floater.MarginProperty, 
                Floater.PaddingProperty,
                Floater.BorderThicknessProperty, 
                Floater.BorderBrushProperty, 

                // Inherits TextElement properties 
                TextElement.BackgroundProperty,
                //TextElement.TextEffectsProperty, -- the property is not supported in text editor
            };
 
        // List of all non-inheritable properties applicable to Figure element
        private static readonly DependencyProperty[] _figureProperties = new DependencyProperty[] 
            { 
                Figure.HorizontalAnchorProperty,
                Figure.VerticalAnchorProperty, 
                Figure.HorizontalOffsetProperty,
                Figure.VerticalOffsetProperty,
                Figure.CanDelayPlacementProperty,
                Figure.WrapDirectionProperty, 
                Figure.WidthProperty,
                Figure.HeightProperty, 
 
                // Adds ownership to Block properties
                Figure.MarginProperty, 
                Figure.PaddingProperty,
                Figure.BorderThicknessProperty,
                Figure.BorderBrushProperty,
 
                // Inherits TextElement properties
                TextElement.BackgroundProperty, 
                //TextElement.TextEffectsProperty, -- the property is not supported in text editor 
            };
 
        // List of all non-inheritable properties applicable to Block element
        private static readonly DependencyProperty[] _blockProperties = new DependencyProperty[]
            {
                Block.MarginProperty, 
                Block.PaddingProperty,
                Block.BorderThicknessProperty, 
                Block.BorderBrushProperty, 
                Block.BreakPageBeforeProperty,
                Block.BreakColumnBeforeProperty, 
                Block.ClearFloatersProperty,
                Block.IsHyphenationEnabledProperty,

                // Inherits TextElement properties 
                TextElement.BackgroundProperty,
                //TextElement.TextEffectsProperty, -- the property is not supported in text editor 
            }; 

        // List of all non-inheritable properties applicable to TextElement element 
        private static readonly DependencyProperty[] _textElementPropertyList = new DependencyProperty[]
            {
                TextElement.BackgroundProperty,
                //TextElement.TextEffectsProperty, -- the property is not supported in text editor 
            };
 
        // List of all non-inheritable properties applicable to TextElement element 
        private static readonly DependencyProperty[] _imagePropertyList = new DependencyProperty[]
            { 
                Image.SourceProperty,
                Image.StretchProperty,
                Image.StretchDirectionProperty,
 
                // Inherits FrameworkElement properties
                //FrameworkElement.StyleProperty, 
                //FrameworkElement.OverridesDefaultStyleProperty, 
                //FrameworkElement.DataContextProperty,
                FrameworkElement.LanguageProperty, 
                //FrameworkElement.NameProperty,
                //FrameworkElement.TagProperty,
                //FrameworkElement.InputScopeProperty,
                FrameworkElement.LayoutTransformProperty, 
                FrameworkElement.WidthProperty,
                FrameworkElement.MinWidthProperty, 
                FrameworkElement.MaxWidthProperty, 
                FrameworkElement.HeightProperty,
                FrameworkElement.MinHeightProperty, 
                FrameworkElement.MaxHeightProperty,
                //FrameworkElement.FlowDirectionProperty,
                FrameworkElement.MarginProperty,
                FrameworkElement.HorizontalAlignmentProperty, 
                FrameworkElement.VerticalAlignmentProperty,
                //FrameworkElement.FocusVisualStyleProperty, 
                FrameworkElement.CursorProperty, 
                FrameworkElement.ForceCursorProperty,
                //FrameworkElement.FocusableProperty, 
                FrameworkElement.ToolTipProperty,
                //FrameworkElement.ContextMenuProperty,

                // Inherits UIElement properties 
                //UIElement.AllowDropProperty,
                UIElement.RenderTransformProperty, 
                UIElement.RenderTransformOriginProperty, 
                UIElement.OpacityProperty,
                UIElement.OpacityMaskProperty, 
                UIElement.BitmapEffectProperty,
                UIElement.BitmapEffectInputProperty,
                UIElement.VisibilityProperty,
                UIElement.ClipToBoundsProperty, 
                UIElement.ClipProperty,
                UIElement.SnapsToDevicePixelsProperty, 
            }; 

        // Behavioral property list 
        private static readonly DependencyProperty[] _behavioralPropertyList = new DependencyProperty[]
            {
                UIElement.AllowDropProperty,
            }; 

        // Empty property list 
        private static readonly DependencyProperty[] _emptyPropertyList = new DependencyProperty[] { }; 

        // Structural property list. 
        // NB: Existing code depends on these being inheritable properties.
        private static readonly DependencyProperty[] _structuralCharacterProperties = new DependencyProperty[]
            {
                Inline.FlowDirectionProperty, 
            };
 
        // List of inline properties (both inheritable or non-inheritable) that are "content" properties, not "formatting" properties. 
        private static readonly DependencyProperty[] _nonFormattingCharacterProperties = new DependencyProperty[]
            { 
                FrameworkElement.FlowDirectionProperty,
                FrameworkElement.LanguageProperty,
            };
 
        #endregion Private Fields
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK