Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Framework / System / Windows / Documents / TextSelectionHighlightLayer.cs / 1 / TextSelectionHighlightLayer.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: Highlight rendering for the TextSelection. // // History: // 07/01/2004 : benwest - 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 ListtextSegments = _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: 012 345 678 // New selection: 0123456 78 // // 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); // text container and password text container are utilizing the new selection // that does not rely on text selection event. this is a performance optimization. object textContainer = _selection.Start.TextContainer; if ( textContainer is TextContainer || textContainer is System.Windows.Controls.PasswordTextContainer ) { return; } 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) { ListrangeArray; 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 : benwest - 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 ListtextSegments = _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: 012 345 678 // New selection: 0123456 78 // // 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); // text container and password text container are utilizing the new selection // that does not rely on text selection event. this is a performance optimization. object textContainer = _selection.Start.TextContainer; if ( textContainer is TextContainer || textContainer is System.Windows.Controls.PasswordTextContainer ) { return; } 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) { ListrangeArray; 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
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- AbsoluteQuery.cs
- DataGridViewCellParsingEventArgs.cs
- TextSegment.cs
- AssociationTypeEmitter.cs
- StyleSelector.cs
- XmlAnyElementAttributes.cs
- TableLayout.cs
- RowType.cs
- Configuration.cs
- Thread.cs
- UrlMappingsSection.cs
- IfElseDesigner.xaml.cs
- QueueProcessor.cs
- WindowsFormsHost.cs
- OutputCacheProfileCollection.cs
- EntitySqlQueryCacheEntry.cs
- CacheChildrenQuery.cs
- ContextMenu.cs
- HttpRequestWrapper.cs
- ExpressionLink.cs
- UrlPath.cs
- MergeFilterQuery.cs
- HtmlHead.cs
- JsonStringDataContract.cs
- PrintPageEvent.cs
- DuplicateWaitObjectException.cs
- Point.cs
- Pts.cs
- DesignerCommandSet.cs
- DefaultBindingPropertyAttribute.cs
- ToolStripArrowRenderEventArgs.cs
- ArrangedElement.cs
- DbConvert.cs
- Int16Converter.cs
- SerialErrors.cs
- BevelBitmapEffect.cs
- MDIClient.cs
- ContextInformation.cs
- ViewGenResults.cs
- TypeUnloadedException.cs
- _CommandStream.cs
- Translator.cs
- GradientBrush.cs
- TextTreeFixupNode.cs
- IFlowDocumentViewer.cs
- SendingRequestEventArgs.cs
- XmlSchemaSimpleContentExtension.cs
- PasswordRecovery.cs
- SqlCacheDependencySection.cs
- IndexedSelectQueryOperator.cs
- MarkupCompilePass1.cs
- DetailsViewPageEventArgs.cs
- TypeValidationEventArgs.cs
- ClientUrlResolverWrapper.cs
- TextCharacters.cs
- GeneralTransform3D.cs
- XPathSelectionIterator.cs
- ItemCollection.cs
- DataTableMappingCollection.cs
- CharacterBufferReference.cs
- TextRunTypographyProperties.cs
- Stackframe.cs
- NavigationCommands.cs
- TypefaceCollection.cs
- RectangleF.cs
- XamlReaderHelper.cs
- LinkedResource.cs
- ListViewCancelEventArgs.cs
- PeerNameRecord.cs
- SpellerHighlightLayer.cs
- StringKeyFrameCollection.cs
- ApplicationBuildProvider.cs
- TextProviderWrapper.cs
- DocumentScope.cs
- PersistChildrenAttribute.cs
- StaticSiteMapProvider.cs
- DbConnectionPoolIdentity.cs
- GeneratedContractType.cs
- BrowserDefinition.cs
- IsolatedStorageException.cs
- RadioButtonFlatAdapter.cs
- PropertyDescriptors.cs
- WebPartCatalogAddVerb.cs
- httpapplicationstate.cs
- Internal.cs
- XmlUrlResolver.cs
- ObjectConverter.cs
- TdsEnums.cs
- InternalTypeHelper.cs
- XmlSchemaGroupRef.cs
- TextTreeTextBlock.cs
- unitconverter.cs
- ErrorWebPart.cs
- AssociationSetMetadata.cs
- Listbox.cs
- ResourceSet.cs
- Lasso.cs
- DelegateSerializationHolder.cs
- Camera.cs
- NegationPusher.cs