in src/MatchMargin/MatchMarginElement.cs [419:498]
private bool UpdateMatches(bool wereAdornmentsEnabled = true)
{
if (_hasEvents)
{
SnapshotSpan? oldHighlightSpan = _highlightSpan;
string oldHighlight = _highlight;
bool matchWholeWord = _textView.Selection.IsEmpty;
_highlightSpan = matchWholeWord
? BackgroundSearch.GetExtentOfWord(_textView.Caret.Position.BufferPosition)
: this.SelectionToHighlightSpan();
_highlight = (_highlightSpan.HasValue) ? _highlightSpan.Value.GetText() : null;
//Do a new search if the highlight changed, there is no existing search, or the existing search was on the wrong snapshot.
if ((_highlight != oldHighlight) || (_search == null) || (_search.Snapshot != _textView.TextSnapshot))
{
//The text of the highlight changes ... restart the search.
if (_search != null)
{
//Stop and blow away the old search (even if it didn't finish, the results are not interesting anymore).
_search.Abort();
_search = null;
}
if (_highlight != null)
{
//The underlying buffer could be very large, meaning that doing the search for all matches on the UI thread
//is a bad idea. Do the search on the background thread and use a callback to invalidate the visual when
//the entire search has completed.
_search = new BackgroundSearch(_textView.TextSnapshot, _highlight, matchWholeWord,
delegate
{
//Force the invalidate to happen on the UI thread to satisfy WPF
this.Dispatcher.Invoke(DispatcherPriority.Normal,
new DispatcherOperationCallback(delegate
{
//Guard against the view closing before dispatcher executes this.
if (!_isDisposed)
{
this.InvalidateVisual();
this.RedrawAdornments();
}
return null;
}),
null);
});
}
else
{
//no highlight == no adornments or marks.
_layer.RemoveAllAdornments();
this.InvalidateVisual();
}
return true;
}
else if ((oldHighlight != null) && wereAdornmentsEnabled && this.AdornmentsActive)
{
//The highlight didn't change and isn't null ... therefore both old & new highlight spans have values. Update the adornments so we don't highlight the
//match the caret is on.
SnapshotSpan translatedOldHighlightSpan = oldHighlightSpan.Value.TranslateTo(_textView.TextSnapshot, SpanTrackingMode.EdgeInclusive);
if (translatedOldHighlightSpan != _highlightSpan.Value)
{
//The spans moved (e.g. the user moved from this on one line to this on another).
//Remove the adornment from the new highlight.
_layer.RemoveAdornmentsByVisualSpan(_highlightSpan.Value);
//Add an adornment at the old source of the highlight span.
Geometry g = _textView.TextViewLines.GetMarkerGeometry(translatedOldHighlightSpan);
if (g != null)
{
_layer.AddAdornment(translatedOldHighlightSpan, null, new GeometryAdornment(_adornmentMatchBrush, g));
}
}
}
}
return false;
}