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
- ContentElement.cs
- CheckedListBox.cs
- ResourceManager.cs
- MultipartContentParser.cs
- unitconverter.cs
- WS2007HttpBindingElement.cs
- BitmapVisualManager.cs
- BuildProvider.cs
- CollectionsUtil.cs
- Rect3DConverter.cs
- ListView.cs
- SoapInteropTypes.cs
- FormsAuthenticationUser.cs
- ToolStripControlHost.cs
- DBSqlParserTableCollection.cs
- WsatEtwTraceListener.cs
- DrawingContextDrawingContextWalker.cs
- CodeDirectiveCollection.cs
- SQLResource.cs
- MetaData.cs
- TabControlEvent.cs
- TextEditorContextMenu.cs
- WebPartConnectVerb.cs
- DataGridViewCellStyleConverter.cs
- WebPartsPersonalizationAuthorization.cs
- UnknownWrapper.cs
- URLBuilder.cs
- SerializationObjectManager.cs
- _SpnDictionary.cs
- SessionState.cs
- Composition.cs
- EventLogTraceListener.cs
- ReservationCollection.cs
- DataServiceQueryOfT.cs
- CriticalExceptions.cs
- DoubleCollection.cs
- MetadataStore.cs
- TabControlAutomationPeer.cs
- MetadataArtifactLoaderCompositeResource.cs
- ToolboxItem.cs
- KnownColorTable.cs
- SqlTransaction.cs
- DesignerDataConnection.cs
- UrlMappingsSection.cs
- EntityContainerEmitter.cs
- UrlPath.cs
- PublisherMembershipCondition.cs
- OutOfMemoryException.cs
- Oid.cs
- ViewCellRelation.cs
- Trace.cs
- TextBlockAutomationPeer.cs
- ValidatorUtils.cs
- StylusPlugInCollection.cs
- DecimalConstantAttribute.cs
- Annotation.cs
- DynamicResourceExtension.cs
- Win32SafeHandles.cs
- Rss20FeedFormatter.cs
- CodeConditionStatement.cs
- XmlAttributeAttribute.cs
- MulticastIPAddressInformationCollection.cs
- AspProxy.cs
- _AcceptOverlappedAsyncResult.cs
- ThreadInterruptedException.cs
- XAMLParseException.cs
- CompilerWrapper.cs
- XhtmlTextWriter.cs
- RequestQueryParser.cs
- XmlNamedNodeMap.cs
- FileUtil.cs
- WebControlsSection.cs
- LinkedResource.cs
- MtomMessageEncoder.cs
- SemanticBasicElement.cs
- ToolboxCategoryItems.cs
- ApplicationServicesHostFactory.cs
- PropertyEmitter.cs
- LoginName.cs
- Odbc32.cs
- BitmapEffectGroup.cs
- PropertyValueChangedEvent.cs
- RequestQueue.cs
- LockRecoveryTask.cs
- TokenizerHelper.cs
- TreeWalkHelper.cs
- ScriptResourceAttribute.cs
- Attributes.cs
- _NestedSingleAsyncResult.cs
- ParagraphVisual.cs
- QilPatternFactory.cs
- FlowPosition.cs
- Annotation.cs
- EntityParameter.cs
- WebPartDisplayMode.cs
- datacache.cs
- StaticTextPointer.cs
- EventMappingSettingsCollection.cs
- FixedTextBuilder.cs
- SiteMap.cs