Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / 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
- Int64.cs
- DesignerSerializerAttribute.cs
- ZeroOpNode.cs
- Point.cs
- CallTemplateAction.cs
- ErrorWebPart.cs
- HttpStreams.cs
- CryptoConfig.cs
- PropertyItemInternal.cs
- SharedUtils.cs
- ResourceReader.cs
- ExpressionBinding.cs
- DependencyStoreSurrogate.cs
- InstanceCompleteException.cs
- GPPOINT.cs
- EntityWithChangeTrackerStrategy.cs
- QuaternionAnimationBase.cs
- ColumnMapProcessor.cs
- DataBindingHandlerAttribute.cs
- xmlglyphRunInfo.cs
- RawStylusInputCustomDataList.cs
- CodeIndexerExpression.cs
- StopStoryboard.cs
- ItemsControl.cs
- DataStreamFromComStream.cs
- CheckableControlBaseAdapter.cs
- XmlElementAttributes.cs
- ObservableDictionary.cs
- DataGridViewMethods.cs
- DataControlHelper.cs
- WaitHandleCannotBeOpenedException.cs
- PreviewKeyDownEventArgs.cs
- ObjectDisposedException.cs
- X509CertificateCollection.cs
- ConfigDefinitionUpdates.cs
- EntityCommandDefinition.cs
- ImportContext.cs
- Parser.cs
- IFlowDocumentViewer.cs
- CounterSampleCalculator.cs
- ViewManager.cs
- SoapSchemaExporter.cs
- MultiAsyncResult.cs
- IconHelper.cs
- SafeSystemMetrics.cs
- RecordConverter.cs
- Control.cs
- EFAssociationProvider.cs
- FileChangesMonitor.cs
- CodeTypeParameterCollection.cs
- RegexGroup.cs
- TrustLevelCollection.cs
- HwndStylusInputProvider.cs
- CultureMapper.cs
- DataGridViewBindingCompleteEventArgs.cs
- TextServicesCompartmentContext.cs
- Label.cs
- FilterableData.cs
- TextBoxAutomationPeer.cs
- SqlIdentifier.cs
- ProgressBarRenderer.cs
- LoadedOrUnloadedOperation.cs
- BuildProviderCollection.cs
- NameTable.cs
- SurrogateEncoder.cs
- TextWriterTraceListener.cs
- BStrWrapper.cs
- WindowsScrollBar.cs
- ChangeTracker.cs
- BaseCodePageEncoding.cs
- ExpressionBuilderContext.cs
- XmlEntity.cs
- WebPartMenuStyle.cs
- MsmqEncryptionAlgorithm.cs
- GZipStream.cs
- SuppressIldasmAttribute.cs
- XmlName.cs
- ByteKeyFrameCollection.cs
- SessionStateItemCollection.cs
- AccessKeyManager.cs
- ParameterInfo.cs
- Transform.cs
- BeginStoryboard.cs
- Image.cs
- ShaderEffect.cs
- HttpApplicationFactory.cs
- LexicalChunk.cs
- SQLByte.cs
- AttachedPropertyMethodSelector.cs
- BindValidationContext.cs
- StateBag.cs
- TransactionManager.cs
- QueryException.cs
- KeyBinding.cs
- QuaternionAnimation.cs
- RectIndependentAnimationStorage.cs
- ZipIOCentralDirectoryDigitalSignature.cs
- PagerSettings.cs
- IsolatedStorage.cs
- CompiledRegexRunnerFactory.cs