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

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: Highlight rendering for the TextSelection. 
// 
// History:
//  07/01/2004 : [....] - Created 
//
//---------------------------------------------------------------------------

using System; 
using MS.Internal;
using System.Collections; 
using System.Collections.Generic; 
using System.Collections.ObjectModel;
 
namespace System.Windows.Documents
{
    // Highlight rendering for the TextSelection.
    internal class TextSelectionHighlightLayer : HighlightLayer 
    {
        //----------------------------------------------------- 
        // 
        //  Constructors
        // 
        //-----------------------------------------------------

        #region Constructors
 
        // Static constructor.
        static TextSelectionHighlightLayer() 
        { 
            _selectedValue = new object();
        } 

        // Constructor.
        internal TextSelectionHighlightLayer(ITextSelection selection)
        { 
            _selection = selection;
            _selection.Changed += new EventHandler(OnSelectionChanged); 
 
            _oldStart = _selection.Start;
            _oldEnd = _selection.End; 
        }

        #endregion Constructors
 
        //------------------------------------------------------
        // 
        //  Internal Methods 
        //
        //----------------------------------------------------- 

        #region Internal Methods

        // Returns the value of a property stored on scoping highlight, if any. 
        //
        // If no property value is set, returns DependencyProperty.UnsetValue. 
        internal override object GetHighlightValue(StaticTextPointer textPosition, LogicalDirection direction) 
        {
            object value; 

            if (IsContentHighlighted(textPosition, direction))
            {
                value = _selectedValue; 
            }
            else 
            { 
                value = DependencyProperty.UnsetValue;
            } 

            return value;
        }
 
        // Returns true iff the indicated content has scoping highlights.
        internal override bool IsContentHighlighted(StaticTextPointer textPosition, LogicalDirection direction) 
        { 
            int segmentCount;
            TextSegment textSegment; 

            // No highlight when the selection is for interim character.
            if (_selection.IsInterimSelection)
            { 
                return false;
            } 
 
            // Check all segments of selection
            List textSegments = _selection.TextSegments; 
            segmentCount = textSegments.Count;
            for (int segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++)
            {
                textSegment = textSegments[segmentIndex]; 

                if ((direction == LogicalDirection.Forward && textSegment.Start.CompareTo(textPosition) <= 0 && textPosition.CompareTo(textSegment.End) < 0) || // 
                    (direction == LogicalDirection.Backward && textSegment.Start.CompareTo(textPosition) < 0 && textPosition.CompareTo(textSegment.End) <= 0)) 
                {
                    return true; 
                }

            }
            return false; 
        }
 
        // Returns the position of the next highlight start or end in an 
        // indicated direction, or null if there is no such position.
        internal override StaticTextPointer GetNextChangePosition(StaticTextPointer textPosition, LogicalDirection direction) 
        {
            StaticTextPointer transitionPosition;

            transitionPosition = StaticTextPointer.Null; 

            if (!IsTextRangeEmpty(_selection) && !_selection.IsInterimSelection) 
            { 
                int segmentCount;
                List textSegments = _selection.TextSegments; 
                TextSegment textSegment;

                segmentCount = textSegments.Count;
 
                if (direction == LogicalDirection.Forward)
                { 
                    for (int segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++) 
                    {
                        textSegment = textSegments[segmentIndex]; 

                        // Ignore empty segments.
                        //
 

 
 

 



 

 
                        if (textSegment.Start.CompareTo(textSegment.End) != 0) 
                        {
                            if (textPosition.CompareTo(textSegment.Start) < 0) 
                            {
                                transitionPosition = textSegment.Start.CreateStaticPointer();
                                break;
                            } 
                            else if (textPosition.CompareTo(textSegment.End) < 0)
                            { 
                                transitionPosition = textSegment.End.CreateStaticPointer(); 
                                break;
                            } 
                        }
                    }
                }
                else 
                {
                    for (int segmentIndex = segmentCount - 1; segmentIndex >= 0; segmentIndex--) 
                    { 
                        textSegment = textSegments[segmentIndex];
 
                        if (textSegment.Start.CompareTo(textSegment.End) != 0)
                        {
                            if (textPosition.CompareTo(textSegment.End) > 0)
                            { 
                                transitionPosition = textSegment.End.CreateStaticPointer();
                                break; 
                            } 
                            else if (textPosition.CompareTo(textSegment.Start) > 0)
                            { 
                                transitionPosition = textSegment.Start.CreateStaticPointer();
                                break;
                            }
                        } 
                    }
                } 
            } 

            return transitionPosition; 
        }

        // This is actual implementation to make highlight change notification.
        // This is called when highlight needs to be changed without public TextSelection change event. 
        internal void InternalOnSelectionChanged()
        { 
            ITextPointer newStart; 
            ITextPointer newEnd;
            ITextPointer invalidRangeLeftStart; 
            ITextPointer invalidRangeLeftEnd;
            ITextPointer invalidRangeRightStart;
            ITextPointer invalidRangeRightEnd;
            TextSelectionHighlightChangedEventArgs args; 

            // If the current seleciton is interim selection, we do not highlight it 
            // and we make newStart == newEnd. 
            if (!_selection.IsInterimSelection)
            { 
                newStart = _selection.Start;
            }
            else
            { 
                newStart = _selection.End;
            } 
 
            newEnd = _selection.End;
 
            // We want to raise an event that tracks the change tightly --
            // only identifying content where the selection status actually changed.
            // This is important for render performance.
            // 
            // Ex:
            // Old selection: 012345678 
            // New selection: 012345678 
            //
            // Should raise (3-3), (6-6) as deltas, not (3-6). 
            //

            // Get the left side invalid range.
            if (_oldStart.CompareTo(newStart) < 0) 
            {
                invalidRangeLeftStart = _oldStart; 
                invalidRangeLeftEnd = TextPointerBase.Min(newStart, _oldEnd); 
            }
            else 
            {
                invalidRangeLeftStart = newStart;
                invalidRangeLeftEnd = TextPointerBase.Min(newEnd, _oldStart);
            } 

            // Get the right side invalid range. 
            if (_oldEnd.CompareTo(newEnd) < 0) 
            {
                invalidRangeRightStart = TextPointerBase.Max(newStart, _oldEnd); 
                invalidRangeRightEnd = newEnd;
            }
            else
            { 
                invalidRangeRightStart = TextPointerBase.Max(newEnd, _oldStart);
                invalidRangeRightEnd = _oldEnd; 
            } 

            _oldStart = newStart; 
            _oldEnd = newEnd;

            if (this.Changed != null)
            { 
                if (invalidRangeLeftStart.CompareTo(invalidRangeLeftEnd) != 0 || invalidRangeRightStart.CompareTo(invalidRangeRightEnd) != 0)
                { 
                    args = new TextSelectionHighlightChangedEventArgs(invalidRangeLeftStart, invalidRangeLeftEnd, invalidRangeRightStart, invalidRangeRightEnd); 

                    this.Changed(this, args); 
                }
            }
        }
 
        #endregion Internal Methods
 
        //------------------------------------------------------ 
        //
        //  Internal Properties 
        //
        //------------------------------------------------------

        #region Internal Properties 

        ///  
        /// Type identifying this layer for Highlights.GetHighlightValue calls. 
        /// 
        internal override Type OwnerType 
        {
            get
            {
                return typeof(TextSelection); 
            }
        } 
 
        #endregion Internal Properties
 
        //-----------------------------------------------------
        //
        //  Internal Events
        // 
        //------------------------------------------------------
 
        #region Internal Events 

        // Event raised when a highlight range is inserted, removed, moved, or 
        // has a local property value change.
        internal override event HighlightChangedEventHandler Changed;

        #endregion Internal Events 

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

        #region Private Methods
 
        // Callback for TextSelection.Moved event.
        // We use this event to trigger highlight change notifications. 
        private void OnSelectionChanged(object sender, EventArgs e) 
        {
            Invariant.Assert(_selection == (ITextSelection)sender); 
            InternalOnSelectionChanged();
        }

        // Check the text range whether it is empty or not without normalization. 
        private bool IsTextRangeEmpty(ITextRange textRange)
        { 
            // We assume that TextRange.TextSegments property getter does not normalize a range, 
            // thus we can avoid re-entrancy.
            Invariant.Assert(textRange._TextSegments.Count > 0); 
            return textRange._TextSegments[0].Start.CompareTo(textRange._TextSegments[textRange._TextSegments.Count - 1].End) == 0;
        }

        #endregion Private Methods 

        //----------------------------------------------------- 
        // 
        //  Private Types
        // 
        //------------------------------------------------------

        #region Private Types
 
        // Argument for the Changed event, encapsulates a highlight change.
        private class TextSelectionHighlightChangedEventArgs : HighlightChangedEventArgs 
        { 
            // Constructor.
            internal TextSelectionHighlightChangedEventArgs(ITextPointer invalidRangeLeftStart, ITextPointer invalidRangeLeftEnd, 
                                                            ITextPointer invalidRangeRightStart, ITextPointer invalidRangeRightEnd)
            {
                List rangeArray;
 
                Invariant.Assert(invalidRangeLeftStart != invalidRangeLeftEnd || invalidRangeRightStart != invalidRangeRightEnd, "Unexpected empty range!");
 
                if (invalidRangeLeftStart.CompareTo(invalidRangeLeftEnd) == 0) 
                {
                    rangeArray = new List(1); 
                    rangeArray.Add(new TextSegment(invalidRangeRightStart, invalidRangeRightEnd));
                }
                else if (invalidRangeRightStart.CompareTo(invalidRangeRightEnd) == 0)
                { 
                    rangeArray = new List(1);
                    rangeArray.Add(new TextSegment(invalidRangeLeftStart, invalidRangeLeftEnd)); 
                } 
                else
                { 
                    rangeArray = new List(2);
                    rangeArray.Add(new TextSegment(invalidRangeLeftStart, invalidRangeLeftEnd));
                    rangeArray.Add(new TextSegment(invalidRangeRightStart, invalidRangeRightEnd));
                } 

                _ranges = new ReadOnlyCollection(rangeArray); 
            } 

            // Collection of changed content ranges. 
            internal override IList Ranges
            {
                get
                { 
                    return _ranges;
                } 
            } 

            // Type identifying the owner of the changed layer. 
            internal override Type OwnerType
            {
                get
                { 
                    return typeof(TextSelection);
                } 
            } 

            // Collection of changed content ranges. 
            private readonly ReadOnlyCollection _ranges;
        }

        #endregion Private Types 

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

        #region Private Fields
 
        // TextSelection associated with this layer.
        private readonly ITextSelection _selection; 
 
        // Previous position of the TextSelection, used to calculate deltas
        // on TextSelection.Moved events. 
        private ITextPointer _oldStart;
        private ITextPointer _oldEnd;

        // Sentinel object used to tag highlights. 
        private static readonly object _selectedValue;
 
        #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: Highlight rendering for the TextSelection. 
// 
// History:
//  07/01/2004 : [....] - Created 
//
//---------------------------------------------------------------------------

using System; 
using MS.Internal;
using System.Collections; 
using System.Collections.Generic; 
using System.Collections.ObjectModel;
 
namespace System.Windows.Documents
{
    // Highlight rendering for the TextSelection.
    internal class TextSelectionHighlightLayer : HighlightLayer 
    {
        //----------------------------------------------------- 
        // 
        //  Constructors
        // 
        //-----------------------------------------------------

        #region Constructors
 
        // Static constructor.
        static TextSelectionHighlightLayer() 
        { 
            _selectedValue = new object();
        } 

        // Constructor.
        internal TextSelectionHighlightLayer(ITextSelection selection)
        { 
            _selection = selection;
            _selection.Changed += new EventHandler(OnSelectionChanged); 
 
            _oldStart = _selection.Start;
            _oldEnd = _selection.End; 
        }

        #endregion Constructors
 
        //------------------------------------------------------
        // 
        //  Internal Methods 
        //
        //----------------------------------------------------- 

        #region Internal Methods

        // Returns the value of a property stored on scoping highlight, if any. 
        //
        // If no property value is set, returns DependencyProperty.UnsetValue. 
        internal override object GetHighlightValue(StaticTextPointer textPosition, LogicalDirection direction) 
        {
            object value; 

            if (IsContentHighlighted(textPosition, direction))
            {
                value = _selectedValue; 
            }
            else 
            { 
                value = DependencyProperty.UnsetValue;
            } 

            return value;
        }
 
        // Returns true iff the indicated content has scoping highlights.
        internal override bool IsContentHighlighted(StaticTextPointer textPosition, LogicalDirection direction) 
        { 
            int segmentCount;
            TextSegment textSegment; 

            // No highlight when the selection is for interim character.
            if (_selection.IsInterimSelection)
            { 
                return false;
            } 
 
            // Check all segments of selection
            List textSegments = _selection.TextSegments; 
            segmentCount = textSegments.Count;
            for (int segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++)
            {
                textSegment = textSegments[segmentIndex]; 

                if ((direction == LogicalDirection.Forward && textSegment.Start.CompareTo(textPosition) <= 0 && textPosition.CompareTo(textSegment.End) < 0) || // 
                    (direction == LogicalDirection.Backward && textSegment.Start.CompareTo(textPosition) < 0 && textPosition.CompareTo(textSegment.End) <= 0)) 
                {
                    return true; 
                }

            }
            return false; 
        }
 
        // Returns the position of the next highlight start or end in an 
        // indicated direction, or null if there is no such position.
        internal override StaticTextPointer GetNextChangePosition(StaticTextPointer textPosition, LogicalDirection direction) 
        {
            StaticTextPointer transitionPosition;

            transitionPosition = StaticTextPointer.Null; 

            if (!IsTextRangeEmpty(_selection) && !_selection.IsInterimSelection) 
            { 
                int segmentCount;
                List textSegments = _selection.TextSegments; 
                TextSegment textSegment;

                segmentCount = textSegments.Count;
 
                if (direction == LogicalDirection.Forward)
                { 
                    for (int segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++) 
                    {
                        textSegment = textSegments[segmentIndex]; 

                        // Ignore empty segments.
                        //
 

 
 

 



 

 
                        if (textSegment.Start.CompareTo(textSegment.End) != 0) 
                        {
                            if (textPosition.CompareTo(textSegment.Start) < 0) 
                            {
                                transitionPosition = textSegment.Start.CreateStaticPointer();
                                break;
                            } 
                            else if (textPosition.CompareTo(textSegment.End) < 0)
                            { 
                                transitionPosition = textSegment.End.CreateStaticPointer(); 
                                break;
                            } 
                        }
                    }
                }
                else 
                {
                    for (int segmentIndex = segmentCount - 1; segmentIndex >= 0; segmentIndex--) 
                    { 
                        textSegment = textSegments[segmentIndex];
 
                        if (textSegment.Start.CompareTo(textSegment.End) != 0)
                        {
                            if (textPosition.CompareTo(textSegment.End) > 0)
                            { 
                                transitionPosition = textSegment.End.CreateStaticPointer();
                                break; 
                            } 
                            else if (textPosition.CompareTo(textSegment.Start) > 0)
                            { 
                                transitionPosition = textSegment.Start.CreateStaticPointer();
                                break;
                            }
                        } 
                    }
                } 
            } 

            return transitionPosition; 
        }

        // This is actual implementation to make highlight change notification.
        // This is called when highlight needs to be changed without public TextSelection change event. 
        internal void InternalOnSelectionChanged()
        { 
            ITextPointer newStart; 
            ITextPointer newEnd;
            ITextPointer invalidRangeLeftStart; 
            ITextPointer invalidRangeLeftEnd;
            ITextPointer invalidRangeRightStart;
            ITextPointer invalidRangeRightEnd;
            TextSelectionHighlightChangedEventArgs args; 

            // If the current seleciton is interim selection, we do not highlight it 
            // and we make newStart == newEnd. 
            if (!_selection.IsInterimSelection)
            { 
                newStart = _selection.Start;
            }
            else
            { 
                newStart = _selection.End;
            } 
 
            newEnd = _selection.End;
 
            // We want to raise an event that tracks the change tightly --
            // only identifying content where the selection status actually changed.
            // This is important for render performance.
            // 
            // Ex:
            // Old selection: 012345678 
            // New selection: 012345678 
            //
            // Should raise (3-3), (6-6) as deltas, not (3-6). 
            //

            // Get the left side invalid range.
            if (_oldStart.CompareTo(newStart) < 0) 
            {
                invalidRangeLeftStart = _oldStart; 
                invalidRangeLeftEnd = TextPointerBase.Min(newStart, _oldEnd); 
            }
            else 
            {
                invalidRangeLeftStart = newStart;
                invalidRangeLeftEnd = TextPointerBase.Min(newEnd, _oldStart);
            } 

            // Get the right side invalid range. 
            if (_oldEnd.CompareTo(newEnd) < 0) 
            {
                invalidRangeRightStart = TextPointerBase.Max(newStart, _oldEnd); 
                invalidRangeRightEnd = newEnd;
            }
            else
            { 
                invalidRangeRightStart = TextPointerBase.Max(newEnd, _oldStart);
                invalidRangeRightEnd = _oldEnd; 
            } 

            _oldStart = newStart; 
            _oldEnd = newEnd;

            if (this.Changed != null)
            { 
                if (invalidRangeLeftStart.CompareTo(invalidRangeLeftEnd) != 0 || invalidRangeRightStart.CompareTo(invalidRangeRightEnd) != 0)
                { 
                    args = new TextSelectionHighlightChangedEventArgs(invalidRangeLeftStart, invalidRangeLeftEnd, invalidRangeRightStart, invalidRangeRightEnd); 

                    this.Changed(this, args); 
                }
            }
        }
 
        #endregion Internal Methods
 
        //------------------------------------------------------ 
        //
        //  Internal Properties 
        //
        //------------------------------------------------------

        #region Internal Properties 

        ///  
        /// Type identifying this layer for Highlights.GetHighlightValue calls. 
        /// 
        internal override Type OwnerType 
        {
            get
            {
                return typeof(TextSelection); 
            }
        } 
 
        #endregion Internal Properties
 
        //-----------------------------------------------------
        //
        //  Internal Events
        // 
        //------------------------------------------------------
 
        #region Internal Events 

        // Event raised when a highlight range is inserted, removed, moved, or 
        // has a local property value change.
        internal override event HighlightChangedEventHandler Changed;

        #endregion Internal Events 

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

        #region Private Methods
 
        // Callback for TextSelection.Moved event.
        // We use this event to trigger highlight change notifications. 
        private void OnSelectionChanged(object sender, EventArgs e) 
        {
            Invariant.Assert(_selection == (ITextSelection)sender); 
            InternalOnSelectionChanged();
        }

        // Check the text range whether it is empty or not without normalization. 
        private bool IsTextRangeEmpty(ITextRange textRange)
        { 
            // We assume that TextRange.TextSegments property getter does not normalize a range, 
            // thus we can avoid re-entrancy.
            Invariant.Assert(textRange._TextSegments.Count > 0); 
            return textRange._TextSegments[0].Start.CompareTo(textRange._TextSegments[textRange._TextSegments.Count - 1].End) == 0;
        }

        #endregion Private Methods 

        //----------------------------------------------------- 
        // 
        //  Private Types
        // 
        //------------------------------------------------------

        #region Private Types
 
        // Argument for the Changed event, encapsulates a highlight change.
        private class TextSelectionHighlightChangedEventArgs : HighlightChangedEventArgs 
        { 
            // Constructor.
            internal TextSelectionHighlightChangedEventArgs(ITextPointer invalidRangeLeftStart, ITextPointer invalidRangeLeftEnd, 
                                                            ITextPointer invalidRangeRightStart, ITextPointer invalidRangeRightEnd)
            {
                List rangeArray;
 
                Invariant.Assert(invalidRangeLeftStart != invalidRangeLeftEnd || invalidRangeRightStart != invalidRangeRightEnd, "Unexpected empty range!");
 
                if (invalidRangeLeftStart.CompareTo(invalidRangeLeftEnd) == 0) 
                {
                    rangeArray = new List(1); 
                    rangeArray.Add(new TextSegment(invalidRangeRightStart, invalidRangeRightEnd));
                }
                else if (invalidRangeRightStart.CompareTo(invalidRangeRightEnd) == 0)
                { 
                    rangeArray = new List(1);
                    rangeArray.Add(new TextSegment(invalidRangeLeftStart, invalidRangeLeftEnd)); 
                } 
                else
                { 
                    rangeArray = new List(2);
                    rangeArray.Add(new TextSegment(invalidRangeLeftStart, invalidRangeLeftEnd));
                    rangeArray.Add(new TextSegment(invalidRangeRightStart, invalidRangeRightEnd));
                } 

                _ranges = new ReadOnlyCollection(rangeArray); 
            } 

            // Collection of changed content ranges. 
            internal override IList Ranges
            {
                get
                { 
                    return _ranges;
                } 
            } 

            // Type identifying the owner of the changed layer. 
            internal override Type OwnerType
            {
                get
                { 
                    return typeof(TextSelection);
                } 
            } 

            // Collection of changed content ranges. 
            private readonly ReadOnlyCollection _ranges;
        }

        #endregion Private Types 

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

        #region Private Fields
 
        // TextSelection associated with this layer.
        private readonly ITextSelection _selection; 
 
        // Previous position of the TextSelection, used to calculate deltas
        // on TextSelection.Moved events. 
        private ITextPointer _oldStart;
        private ITextPointer _oldEnd;

        // Sentinel object used to tag highlights. 
        private static readonly object _selectedValue;
 
        #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