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
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);
// 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)
{
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 : 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
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);
// 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)
{
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
- SetStateDesigner.cs
- Renderer.cs
- DesignerDataParameter.cs
- ZipIOLocalFileDataDescriptor.cs
- EventTrigger.cs
- ReaderWriterLock.cs
- CommandManager.cs
- Inline.cs
- WebContext.cs
- ThicknessAnimationBase.cs
- SetterTriggerConditionValueConverter.cs
- AxHost.cs
- WebPartHeaderCloseVerb.cs
- PtsPage.cs
- SrgsElementList.cs
- LinkTarget.cs
- UserControlParser.cs
- ImageAnimator.cs
- TypeElement.cs
- ResourceAttributes.cs
- XmlNullResolver.cs
- ServerTooBusyException.cs
- ItemsPanelTemplate.cs
- MasterPageCodeDomTreeGenerator.cs
- input.cs
- ClickablePoint.cs
- ObjectDataSourceView.cs
- WindowsClientElement.cs
- ByeOperation11AsyncResult.cs
- ZipIOExtraFieldElement.cs
- VisualStyleInformation.cs
- CachedBitmap.cs
- basenumberconverter.cs
- Int16Converter.cs
- _NestedSingleAsyncResult.cs
- WindowManager.cs
- ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs
- GeneralTransform3DTo2DTo3D.cs
- PrinterUnitConvert.cs
- TablePattern.cs
- CodeArgumentReferenceExpression.cs
- TrimSurroundingWhitespaceAttribute.cs
- WebPartMenuStyle.cs
- RefreshEventArgs.cs
- KeyBinding.cs
- BlobPersonalizationState.cs
- ErrorFormatter.cs
- MonitoringDescriptionAttribute.cs
- PropertyBuilder.cs
- ThreadExceptionEvent.cs
- IdentityHolder.cs
- DebugController.cs
- securestring.cs
- XmlSchemaGroupRef.cs
- MaterialCollection.cs
- TransactionProxy.cs
- NullExtension.cs
- DataViewSetting.cs
- PropertyEmitter.cs
- InstanceNormalEvent.cs
- XmlTextAttribute.cs
- DataBindingHandlerAttribute.cs
- PriorityChain.cs
- mongolianshape.cs
- DataPager.cs
- Cursors.cs
- peersecurityelement.cs
- ExceptionHandlers.cs
- DocumentViewerBase.cs
- AutoGeneratedField.cs
- UIntPtr.cs
- AncillaryOps.cs
- PeerEndPoint.cs
- SelectionHighlightInfo.cs
- DataSourceCache.cs
- SerializationObjectManager.cs
- ServiceOperationDetailViewControl.cs
- ListManagerBindingsCollection.cs
- _HTTPDateParse.cs
- ParamArrayAttribute.cs
- ToolStripPanel.cs
- FlowDocumentPaginator.cs
- DrawingGroupDrawingContext.cs
- XmlTextAttribute.cs
- InternalTypeHelper.cs
- TextPointer.cs
- WorkflowDesignerMessageFilter.cs
- RequestTimeoutManager.cs
- ClaimTypes.cs
- PocoEntityKeyStrategy.cs
- PlatformCulture.cs
- TrackBar.cs
- DbTransaction.cs
- ListenerSingletonConnectionReader.cs
- COM2TypeInfoProcessor.cs
- SourceSwitch.cs
- UriTemplateHelpers.cs
- SoapProtocolImporter.cs
- BitmapScalingModeValidation.cs
- UrlPath.cs