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
- SingleStorage.cs
- UrlMapping.cs
- ScriptServiceAttribute.cs
- MultiSelectRootGridEntry.cs
- DbParameterHelper.cs
- LogLogRecordHeader.cs
- ServiceEndpointElement.cs
- StrokeCollection2.cs
- HttpResponseHeader.cs
- EntityRecordInfo.cs
- TaskSchedulerException.cs
- SocketPermission.cs
- SoapDocumentMethodAttribute.cs
- Socket.cs
- UnsafeNativeMethods.cs
- DataSourceControlBuilder.cs
- StateDesignerConnector.cs
- TryCatch.cs
- PeerCollaborationPermission.cs
- ListViewEditEventArgs.cs
- StringExpressionSet.cs
- MULTI_QI.cs
- DataObject.cs
- ValueExpressions.cs
- XPathArrayIterator.cs
- SoapSchemaExporter.cs
- UntrustedRecipientException.cs
- WindowsEditBoxRange.cs
- XsltArgumentList.cs
- ChildDocumentBlock.cs
- DiagnosticTrace.cs
- ComboBox.cs
- SignedXml.cs
- SourceLocation.cs
- ComplusTypeValidator.cs
- AnimationStorage.cs
- UpdatePanelControlTrigger.cs
- SqlFunctionAttribute.cs
- ObjectParameterCollection.cs
- Pkcs7Recipient.cs
- DummyDataSource.cs
- XamlPointCollectionSerializer.cs
- TypeSchema.cs
- TableRow.cs
- TypeSemantics.cs
- ResourceDictionary.cs
- BezierSegment.cs
- StreamDocument.cs
- TextProperties.cs
- FullTrustAssemblyCollection.cs
- ObjectIDGenerator.cs
- StandardBindingElement.cs
- ThicknessKeyFrameCollection.cs
- RegexEditorDialog.cs
- TableDetailsRow.cs
- util.cs
- Rectangle.cs
- ProgramNode.cs
- Int16KeyFrameCollection.cs
- XmlWriterSettings.cs
- State.cs
- TdsEnums.cs
- ScrollViewerAutomationPeer.cs
- FixedSOMPage.cs
- Funcletizer.cs
- ComponentEditorPage.cs
- RoutedPropertyChangedEventArgs.cs
- FunctionImportMapping.ReturnTypeRenameMapping.cs
- SerializationEventsCache.cs
- DeclarativeExpressionConditionDeclaration.cs
- SkipQueryOptionExpression.cs
- XmlToDatasetMap.cs
- SessionEndedEventArgs.cs
- FixedHyperLink.cs
- CompositeFontInfo.cs
- ParserHooks.cs
- ThemeInfoAttribute.cs
- ContactManager.cs
- BezierSegment.cs
- DeflateInput.cs
- ExtenderControl.cs
- Graph.cs
- TraceListener.cs
- ChildTable.cs
- MessageAction.cs
- SourceLocationProvider.cs
- HtmlTextArea.cs
- UpDownBase.cs
- WCFServiceClientProxyGenerator.cs
- XmlCDATASection.cs
- RequestResizeEvent.cs
- EditorPart.cs
- Peer.cs
- QueryGenerator.cs
- RenderingEventArgs.cs
- DataSourceNameHandler.cs
- NamespaceCollection.cs
- InfoCardRSAOAEPKeyExchangeDeformatter.cs
- ReturnValue.cs
- HelpProvider.cs