Run.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 / Run.cs / 1305600 / Run.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
// Description: Run class - Text node in Flow content (text run) 
//
//--------------------------------------------------------------------------- 
 
using MS.Internal;                  // Invariant.Assert
using System.Windows.Markup; // ContentProperty 
using System.Windows.Controls;
using MS.Internal.Documents;

namespace System.Windows.Documents 
{
    ///  
    /// A terminal element in text flow hierarchy - contains a uniformatted run of unicode characters 
    /// 
    [ContentProperty("Text")] 
    public class Run : Inline
    {
        //-------------------------------------------------------------------
        // 
        // Constructors
        // 
        //------------------------------------------------------------------- 

        #region Constructors 

        /// 
        /// Initializes an instance of Run class.
        ///  
        public Run()
        { 
        } 

        ///  
        /// Initializes an instance of Run class specifying its text content.
        /// 
        /// 
        /// Text content assigned to the Run. 
        /// 
        public Run(string text) : this(text, null) 
        { 
        }
 
        /// 
        /// Creates a new Run instance.
        /// 
        ///  
        /// Optional text content.  May be null.
        ///  
        ///  
        /// Optional position at which to insert the new Run. May
        /// be null. 
        /// 
        public Run(string text, TextPointer insertionPosition)
        {
            if (insertionPosition != null) 
            {
                insertionPosition.TextContainer.BeginChange(); 
            } 
            try
            { 
                if (insertionPosition != null)
                {
                    // This will throw InvalidOperationException if schema validity is violated.
                    insertionPosition.InsertInline(this); 
                }
 
                if (text != null) 
                {
                    // No need to duplicate the string data in TextProperty here. TextContainer will 
                    // set the property to a deferred reference.
                    this.ContentStart.InsertTextInRun(text);
                }
            } 
            finally
            { 
                if (insertionPosition != null) 
                {
                    insertionPosition.TextContainer.EndChange(); 
                }
            }
        }
 
        #endregion Constructors
 
        //-------------------------------------------------------------------- 
        //
        // Public Properties 
        //
        //-------------------------------------------------------------------

        #region Public Properties 

        ///  
        /// Dependency property backing Text. 
        /// 
        ///  
        /// Note that when a TextRange that intersects with this Run gets modified (e.g. by editing
        /// a selection in RichTextBox), we will get two changes to this property since we delete
        /// and then insert when setting the content of a TextRange.
        ///  
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(Run),
            new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 
                new PropertyChangedCallback(OnTextPropertyChanged), new CoerceValueCallback(CoerceText))); 

        ///  
        /// The content spanned by this TextElement.
        /// 
        public string Text
        { 
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); } 
        } 

        #endregion Public Properties 

        //--------------------------------------------------------------------
        //
        // Internal Methods 
        //
        //-------------------------------------------------------------------- 
 
        #region Internal Methods
 
        /// 
        /// Updates TextProperty when it is no longer in [....] with the backing store. Called by
        /// TextContainer when a change affects the text contained by this Run.
        ///  
        /// 
        /// If a public TextChanged event is added, we need to raise the event only when the 
        /// outermost call to this function exits. 
        /// 
        internal override void OnTextUpdated() 
        {
            // If the value of Run.Text comes from a local value without a binding expression, we purposely allow the
            // redundant roundtrip property set here. (SetValue on Run.TextProperty causes a TextContainer change,
            // which causes this notification, and we set the property again.) We want to avoid keeping duplicate string 
            // data (both in the property system and in the backing store) when Run.Text is set, so we replace the
            // original string property value with a deferred reference. This causes an extra property changed 
            // notification, but this is better than duplicating the data. 

            ValueSource textPropertySource = DependencyPropertyHelper.GetValueSource(this, TextProperty); 
            if (!_isInsideDeferredSet && (_changeEventNestingCount == 0 || (textPropertySource.BaseValueSource == BaseValueSource.Local
                && !textPropertySource.IsExpression)))
            {
                _changeEventNestingCount++; 
                _isInsideDeferredSet = true;
                try 
                { 
                    // Use a deferred reference as a performance optimization. Most of the time, no
                    // one will even be watching this property. 
                    SetCurrentDeferredValue(TextProperty, new DeferredRunTextReference(this));
                }
                finally
                { 
                    _isInsideDeferredSet = false;
                    _changeEventNestingCount--; 
                } 
            }
        } 

        /// 
        /// Increments the reference count that prevents reentrancy during TextContainer changes.
        ///  
        /// 
        /// Adding/removing elements from the logical tree will cause bindings on Run.Text to get 
        /// invalidated. We don't want to indirectly cause a TextContainer change when that happens. 
        /// 
        internal override void BeforeLogicalTreeChange() 
        {
            _changeEventNestingCount++;
        }
 
        /// 
        /// Decrements the reference count that prevents reentrancy during TextContainer changes. 
        ///  
        /// 
        /// Adding/removing elements from the logical tree will cause bindings on Run.Text to get 
        /// invalidated. We don't want to indirectly cause a TextContainer change when that happens.
        /// 
        internal override void AfterLogicalTreeChange()
        { 
            _changeEventNestingCount--;
        } 
 
        //
        //  This property 
        //  1. Finds the correct initial size for the _effectiveValues store on the current DependencyObject
        //  2. This is a performance optimization
        //
        internal override int EffectiveValuesInitialSize 
        {
            get { return 13; } 
        } 

        ///  
        /// This method is used by TypeDescriptor to determine if this property should
        /// be serialized.
        /// 
        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] 
        public bool ShouldSerializeText(XamlDesignerSerializationManager manager)
        { 
            return manager != null && manager.XmlWriter == null; 
        }
 
        #endregion Internal Methods


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

        /// 
        /// Changed handler for the Text property. 
        /// 
        /// The source of the event. 
        /// A PropertyChangedEventArgs that contains the event data. 
        /// 
        /// We can't assume the value is a string here -- it may be a DeferredRunTextReference. 
        /// 
        private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Run run = (Run)d; 

            // Return if this update was caused by a TextContainer change or a reentrant change. 
            if (run._changeEventNestingCount > 0) 
            {
                return; 
            }

            Invariant.Assert(!e.NewEntry.IsDeferredReference);
 
            // CoerceText will have already converted null -> String.Empty, but our default
            // CoerceValueCallback could be overridden by a derived class.  So check again here. 
            string newText = (string)e.NewValue; 
            if (newText == null)
            { 
                newText = String.Empty;
            }

            // Run.TextProperty has changed. Update the backing store. 
            run._changeEventNestingCount++;
            try 
            { 
                TextContainer textContainer = run.TextContainer;
                textContainer.BeginChange(); 

                try
                {
                    TextPointer contentStart = run.ContentStart; 
                    if (!run.IsEmpty)
                    { 
                        textContainer.DeleteContentInternal(contentStart, run.ContentEnd); 
                    }
                    contentStart.InsertTextInRun(newText); 
                }
                finally
                {
                    textContainer.EndChange(); 
                }
            } 
            finally 
            {
                run._changeEventNestingCount--; 
            }

            // We need to clear undo stack if we are in a RichTextBox and the value comes from
            // data binding or some other expression. 
            FlowDocument document = run.TextContainer.Parent as FlowDocument;
            if (document != null) 
            { 
                RichTextBox rtb = document.Parent as RichTextBox;
                if (rtb != null && run.HasExpression(run.LookupEntry(Run.TextProperty.GlobalIndex), Run.TextProperty)) 
                {
                    UndoManager undoManager = rtb.TextEditor._GetUndoManager();
                    if (undoManager != null && undoManager.IsEnabled)
                    { 
                        undoManager.Clear();
                    } 
                } 
            }
        } 

        /// 
        /// Coercion callback for the Text property.
        ///  
        /// The object that the property exists on.
        /// The new value of the property, prior to any coercion attempt. 
        /// The coerced value. 
        /// 
        /// We can't assume the value is a string here -- it may be a DeferredRunTextReference. 
        /// 
        private static object CoerceText(DependencyObject d, object baseValue)
        {
            if (baseValue == null) 
            {
                baseValue = string.Empty; 
            } 

            return baseValue; 
        }

        #endregion Private Methods
 
        //-----------------------------------------------------
        // 
        //  Private Fields 
        //
        //----------------------------------------------------- 

        #region Private Fields

        // Number of nested TextContainer change notifications. 
        private int _changeEventNestingCount;
 
        // If we are inside a property set caused by a backing store change. 
        private bool _isInsideDeferredSet;
 
        #endregion Private Fields
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
// Description: Run class - Text node in Flow content (text run) 
//
//--------------------------------------------------------------------------- 
 
using MS.Internal;                  // Invariant.Assert
using System.Windows.Markup; // ContentProperty 
using System.Windows.Controls;
using MS.Internal.Documents;

namespace System.Windows.Documents 
{
    ///  
    /// A terminal element in text flow hierarchy - contains a uniformatted run of unicode characters 
    /// 
    [ContentProperty("Text")] 
    public class Run : Inline
    {
        //-------------------------------------------------------------------
        // 
        // Constructors
        // 
        //------------------------------------------------------------------- 

        #region Constructors 

        /// 
        /// Initializes an instance of Run class.
        ///  
        public Run()
        { 
        } 

        ///  
        /// Initializes an instance of Run class specifying its text content.
        /// 
        /// 
        /// Text content assigned to the Run. 
        /// 
        public Run(string text) : this(text, null) 
        { 
        }
 
        /// 
        /// Creates a new Run instance.
        /// 
        ///  
        /// Optional text content.  May be null.
        ///  
        ///  
        /// Optional position at which to insert the new Run. May
        /// be null. 
        /// 
        public Run(string text, TextPointer insertionPosition)
        {
            if (insertionPosition != null) 
            {
                insertionPosition.TextContainer.BeginChange(); 
            } 
            try
            { 
                if (insertionPosition != null)
                {
                    // This will throw InvalidOperationException if schema validity is violated.
                    insertionPosition.InsertInline(this); 
                }
 
                if (text != null) 
                {
                    // No need to duplicate the string data in TextProperty here. TextContainer will 
                    // set the property to a deferred reference.
                    this.ContentStart.InsertTextInRun(text);
                }
            } 
            finally
            { 
                if (insertionPosition != null) 
                {
                    insertionPosition.TextContainer.EndChange(); 
                }
            }
        }
 
        #endregion Constructors
 
        //-------------------------------------------------------------------- 
        //
        // Public Properties 
        //
        //-------------------------------------------------------------------

        #region Public Properties 

        ///  
        /// Dependency property backing Text. 
        /// 
        ///  
        /// Note that when a TextRange that intersects with this Run gets modified (e.g. by editing
        /// a selection in RichTextBox), we will get two changes to this property since we delete
        /// and then insert when setting the content of a TextRange.
        ///  
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(Run),
            new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 
                new PropertyChangedCallback(OnTextPropertyChanged), new CoerceValueCallback(CoerceText))); 

        ///  
        /// The content spanned by this TextElement.
        /// 
        public string Text
        { 
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); } 
        } 

        #endregion Public Properties 

        //--------------------------------------------------------------------
        //
        // Internal Methods 
        //
        //-------------------------------------------------------------------- 
 
        #region Internal Methods
 
        /// 
        /// Updates TextProperty when it is no longer in [....] with the backing store. Called by
        /// TextContainer when a change affects the text contained by this Run.
        ///  
        /// 
        /// If a public TextChanged event is added, we need to raise the event only when the 
        /// outermost call to this function exits. 
        /// 
        internal override void OnTextUpdated() 
        {
            // If the value of Run.Text comes from a local value without a binding expression, we purposely allow the
            // redundant roundtrip property set here. (SetValue on Run.TextProperty causes a TextContainer change,
            // which causes this notification, and we set the property again.) We want to avoid keeping duplicate string 
            // data (both in the property system and in the backing store) when Run.Text is set, so we replace the
            // original string property value with a deferred reference. This causes an extra property changed 
            // notification, but this is better than duplicating the data. 

            ValueSource textPropertySource = DependencyPropertyHelper.GetValueSource(this, TextProperty); 
            if (!_isInsideDeferredSet && (_changeEventNestingCount == 0 || (textPropertySource.BaseValueSource == BaseValueSource.Local
                && !textPropertySource.IsExpression)))
            {
                _changeEventNestingCount++; 
                _isInsideDeferredSet = true;
                try 
                { 
                    // Use a deferred reference as a performance optimization. Most of the time, no
                    // one will even be watching this property. 
                    SetCurrentDeferredValue(TextProperty, new DeferredRunTextReference(this));
                }
                finally
                { 
                    _isInsideDeferredSet = false;
                    _changeEventNestingCount--; 
                } 
            }
        } 

        /// 
        /// Increments the reference count that prevents reentrancy during TextContainer changes.
        ///  
        /// 
        /// Adding/removing elements from the logical tree will cause bindings on Run.Text to get 
        /// invalidated. We don't want to indirectly cause a TextContainer change when that happens. 
        /// 
        internal override void BeforeLogicalTreeChange() 
        {
            _changeEventNestingCount++;
        }
 
        /// 
        /// Decrements the reference count that prevents reentrancy during TextContainer changes. 
        ///  
        /// 
        /// Adding/removing elements from the logical tree will cause bindings on Run.Text to get 
        /// invalidated. We don't want to indirectly cause a TextContainer change when that happens.
        /// 
        internal override void AfterLogicalTreeChange()
        { 
            _changeEventNestingCount--;
        } 
 
        //
        //  This property 
        //  1. Finds the correct initial size for the _effectiveValues store on the current DependencyObject
        //  2. This is a performance optimization
        //
        internal override int EffectiveValuesInitialSize 
        {
            get { return 13; } 
        } 

        ///  
        /// This method is used by TypeDescriptor to determine if this property should
        /// be serialized.
        /// 
        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] 
        public bool ShouldSerializeText(XamlDesignerSerializationManager manager)
        { 
            return manager != null && manager.XmlWriter == null; 
        }
 
        #endregion Internal Methods


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

        /// 
        /// Changed handler for the Text property. 
        /// 
        /// The source of the event. 
        /// A PropertyChangedEventArgs that contains the event data. 
        /// 
        /// We can't assume the value is a string here -- it may be a DeferredRunTextReference. 
        /// 
        private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Run run = (Run)d; 

            // Return if this update was caused by a TextContainer change or a reentrant change. 
            if (run._changeEventNestingCount > 0) 
            {
                return; 
            }

            Invariant.Assert(!e.NewEntry.IsDeferredReference);
 
            // CoerceText will have already converted null -> String.Empty, but our default
            // CoerceValueCallback could be overridden by a derived class.  So check again here. 
            string newText = (string)e.NewValue; 
            if (newText == null)
            { 
                newText = String.Empty;
            }

            // Run.TextProperty has changed. Update the backing store. 
            run._changeEventNestingCount++;
            try 
            { 
                TextContainer textContainer = run.TextContainer;
                textContainer.BeginChange(); 

                try
                {
                    TextPointer contentStart = run.ContentStart; 
                    if (!run.IsEmpty)
                    { 
                        textContainer.DeleteContentInternal(contentStart, run.ContentEnd); 
                    }
                    contentStart.InsertTextInRun(newText); 
                }
                finally
                {
                    textContainer.EndChange(); 
                }
            } 
            finally 
            {
                run._changeEventNestingCount--; 
            }

            // We need to clear undo stack if we are in a RichTextBox and the value comes from
            // data binding or some other expression. 
            FlowDocument document = run.TextContainer.Parent as FlowDocument;
            if (document != null) 
            { 
                RichTextBox rtb = document.Parent as RichTextBox;
                if (rtb != null && run.HasExpression(run.LookupEntry(Run.TextProperty.GlobalIndex), Run.TextProperty)) 
                {
                    UndoManager undoManager = rtb.TextEditor._GetUndoManager();
                    if (undoManager != null && undoManager.IsEnabled)
                    { 
                        undoManager.Clear();
                    } 
                } 
            }
        } 

        /// 
        /// Coercion callback for the Text property.
        ///  
        /// The object that the property exists on.
        /// The new value of the property, prior to any coercion attempt. 
        /// The coerced value. 
        /// 
        /// We can't assume the value is a string here -- it may be a DeferredRunTextReference. 
        /// 
        private static object CoerceText(DependencyObject d, object baseValue)
        {
            if (baseValue == null) 
            {
                baseValue = string.Empty; 
            } 

            return baseValue; 
        }

        #endregion Private Methods
 
        //-----------------------------------------------------
        // 
        //  Private Fields 
        //
        //----------------------------------------------------- 

        #region Private Fields

        // Number of nested TextContainer change notifications. 
        private int _changeEventNestingCount;
 
        // If we are inside a property set caused by a backing store change. 
        private bool _isInsideDeferredSet;
 
        #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