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: 012345 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);
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: 012345 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);
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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- WaitHandleCannotBeOpenedException.cs
- UrlPath.cs
- ShapingWorkspace.cs
- Blend.cs
- ColumnResult.cs
- CodeDOMUtility.cs
- StatusBarPanel.cs
- DetailsViewRow.cs
- InvalidCommandTreeException.cs
- WindowAutomationPeer.cs
- AttributeQuery.cs
- PageWrapper.cs
- DoubleAnimationUsingKeyFrames.cs
- Resources.Designer.cs
- NamespaceTable.cs
- BamlLocalizabilityResolver.cs
- JsonWriter.cs
- EntityDataSourceColumn.cs
- CorruptingExceptionCommon.cs
- RegexMatch.cs
- NavigatingCancelEventArgs.cs
- LookupTables.cs
- VirtualPathProvider.cs
- PolyQuadraticBezierSegmentFigureLogic.cs
- returneventsaver.cs
- PeerServiceMessageContracts.cs
- QuadraticBezierSegment.cs
- ContentHostHelper.cs
- VersionedStream.cs
- SqlBooleanizer.cs
- WebConfigurationManager.cs
- DecimalAnimation.cs
- ADConnectionHelper.cs
- EventsTab.cs
- PropertyRef.cs
- ExtensionQuery.cs
- WebServicesSection.cs
- LinearGradientBrush.cs
- DynamicMetaObjectBinder.cs
- HttpStreams.cs
- StrongBox.cs
- PerfProviderCollection.cs
- WebPartChrome.cs
- SoapAttributeOverrides.cs
- FormatVersion.cs
- Typeface.cs
- DependencyPropertyKey.cs
- ListDictionary.cs
- AppDomainProtocolHandler.cs
- _SecureChannel.cs
- AutomationPatternInfo.cs
- ComponentEditorForm.cs
- AdvancedBindingEditor.cs
- GridItem.cs
- StrokeDescriptor.cs
- CharacterHit.cs
- XsltInput.cs
- IriParsingElement.cs
- SchemaImporterExtensionElement.cs
- DynamicDocumentPaginator.cs
- QuaternionIndependentAnimationStorage.cs
- HtmlDocument.cs
- XmlNamedNodeMap.cs
- DataBindingHandlerAttribute.cs
- ParameterBuilder.cs
- ExpressionVisitor.cs
- WindowsFormsHostPropertyMap.cs
- GiveFeedbackEvent.cs
- IteratorDescriptor.cs
- SqlCommand.cs
- WpfKnownTypeInvoker.cs
- EditorPartChrome.cs
- NetMsmqSecurityMode.cs
- WebReferencesBuildProvider.cs
- Error.cs
- SplitterPanel.cs
- EpmTargetPathSegment.cs
- XmlNodeChangedEventArgs.cs
- WebBrowserPermission.cs
- SymLanguageType.cs
- PtsHost.cs
- SessionStateContainer.cs
- XmlnsDictionary.cs
- CurrentTimeZone.cs
- ColumnResult.cs
- DataTransferEventArgs.cs
- ConvertTextFrag.cs
- PreloadedPackages.cs
- MouseWheelEventArgs.cs
- DataGridPreparingCellForEditEventArgs.cs
- Canvas.cs
- ContentPresenter.cs
- Splitter.cs
- SoapCodeExporter.cs
- IItemProperties.cs
- PriorityItem.cs
- RecordConverter.cs
- SelfIssuedSamlTokenFactory.cs
- TransformerConfigurationWizardBase.cs
- TraceUtils.cs