void RemoveLineSeparatorElements(NormalizedSnapshotSpanCollection spans) { if (adornmentLayer == null) return; for (int i = lineSeparatorElements.Count - 1; i >= 0; i--) { var lineSeparatorElement = lineSeparatorElements[i]; if (spans.IntersectsWith(lineSeparatorElement.Span)) adornmentLayer.RemoveAdornment(lineSeparatorElement); } }
// Produces tags on the snapshot that this tagger is current with. private IEnumerable <TagSpan <IntraTextAdornmentTag> > GetAdornmentTagsOnSnapshot(NormalizedSnapshotSpanCollection spans) { if (spans.Count == 0) { yield break; } var snapshot = spans[0].Snapshot; System.Diagnostics.Debug.Assert(snapshot == this.snapshot); // Since WPF UI objects have state (like mouse hover or animation) and are relatively expensive to create and lay out, // this code tries to reuse controls as much as possible. // The controls are stored in this.adornmentCache between the calls. // Mark which adornments fall inside the requested spans with Keep=false // so that they can be removed from the cache if they no longer correspond to data tags. var toRemove = new HashSet <SnapshotSpan>(); foreach (var ar in adornmentCache) { if (spans.IntersectsWith(new NormalizedSnapshotSpanCollection(ar.Key))) { toRemove.Add(ar.Key); } } foreach (var spanDataPair in GetAdornmentData(spans).Distinct(new Comparer())) { // Look up the corresponding adornment or create one if it's new. TAdornment adornment; var snapshotSpan = spanDataPair.Item1; var affinity = spanDataPair.Item2; var adornmentData = spanDataPair.Item3; if (adornmentCache.TryGetValue(snapshotSpan, out adornment)) { if (UpdateAdornment(adornment, adornmentData)) { toRemove.Remove(snapshotSpan); } } else { adornment = CreateAdornment(adornmentData, snapshotSpan); if (adornment == null) { continue; } // Get the adornment to measure itself. Its DesiredSize property is used to determine // how much space to leave between text for this adornment. // Note: If the size of the adornment changes, the line will be reformatted to accommodate it. // Note: Some adornments may change size when added to the view's visual tree due to inherited // dependency properties that affect layout. Such options can include SnapsToDevicePixels, // UseLayoutRounding, TextRenderingMode, TextHintingMode, and TextFormattingMode. Making sure // that these properties on the adornment match the view's values before calling Measure here // can help avoid the size change and the resulting unnecessary re-format. adornment.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); adornmentCache.Add(snapshotSpan, adornment); } yield return(new TagSpan <IntraTextAdornmentTag>(snapshotSpan, new IntraTextAdornmentTag(adornment, null, affinity))); } foreach (var snapshotSpan in toRemove) { adornmentCache.Remove(snapshotSpan); } }
public IEnumerable <ITagSpan <IntraTextAdornmentTag> > GetTags( NormalizedSnapshotSpanCollection spans ) { if (spans.Count == 0) { return(Array.Empty <ITagSpan <IntraTextAdornmentTag> >()); } var snapshot = spans[0].Snapshot; if (_cache.Count == 0 || snapshot != _cacheSnapshot) { // Calculate UI elements _cache.Clear(); _cacheSnapshot = snapshot; var document = snapshot.GetOpenDocumentInCurrentContextWithChanges(); var classify = document?.Project.Solution.Workspace.Options.GetOption( InlineHintsOptions.ColorHints, document?.Project.Language ) ?? false; // Calling into the InlineParameterNameHintsDataTaggerProvider which only responds with the current // active view and disregards and requests for tags not in that view var fullSpan = new SnapshotSpan(snapshot, 0, snapshot.Length); var tags = _tagAggregator.GetTags(new NormalizedSnapshotSpanCollection(fullSpan)); foreach (var tag in tags) { // Gets the associated span from the snapshot span and creates the IntraTextAdornmentTag from the data // tags. Only dealing with the dataTagSpans if the count is 1 because we do not see a multi-buffer case // occuring var dataTagSpans = tag.Span.GetSpans(snapshot); if (dataTagSpans.Count == 1) { var dataTagSpan = dataTagSpans[0]; var parameterHintUITag = InlineHintsTag.Create( tag.Tag.Hint, Format, _textView, dataTagSpan, _taggerProvider, _formatMap, classify ); _cache.Add( new TagSpan <IntraTextAdornmentTag>(dataTagSpan, parameterHintUITag) ); } } } var selectedSpans = new List <ITagSpan <IntraTextAdornmentTag> >(); foreach (var tagSpan in _cache) { if (spans.IntersectsWith(tagSpan.Span)) { selectedSpans.Add(tagSpan); } } return(selectedSpans); }
private IEnumerable <IMappingTagSpan <T> > GetTagsForBuffer(KeyValuePair <ITextBuffer, IList <ITagger <T> > > bufferAndTaggers, NormalizedSnapshotSpanCollection snapshotSpans, ITextSnapshot root, CancellationToken?cancel) { ITextSnapshot snapshot = snapshotSpans[0].Snapshot; for (int t = 0; t < bufferAndTaggers.Value.Count; ++t) { ITagger <T> tagger = bufferAndTaggers.Value[t]; IEnumerator <ITagSpan <T> > tags = null; try { IEnumerable <ITagSpan <T> > tagEnumerable; if (cancel.HasValue) { cancel.Value.ThrowIfCancellationRequested(); var tagger2 = tagger as IAccurateTagger <T>; if (tagger2 != null) { tagEnumerable = tagger2.GetAllTags(snapshotSpans, cancel.Value); } else { tagEnumerable = tagger.GetTags(snapshotSpans); } } else { tagEnumerable = tagger.GetTags(snapshotSpans); } if (tagEnumerable != null) { tags = tagEnumerable.GetEnumerator(); } } catch (OperationCanceledException) { // Rethrow cancellation exceptions since we expect our callers to deal with it. throw; } catch (Exception e) { this.TagAggregatorFactoryService.GuardedOperations.HandleException(tagger, e); } if (tags != null) { try { while (true) { ITagSpan <T> tagSpan = null; try { if (tags.MoveNext()) { tagSpan = tags.Current; } } catch (Exception e) { this.TagAggregatorFactoryService.GuardedOperations.HandleException(tagger, e); } if (tagSpan == null) { break; } var snapshotSpan = tagSpan.Span; if (snapshotSpans.IntersectsWith(snapshotSpan.TranslateTo(snapshot, SpanTrackingMode.EdgeExclusive))) { yield return(new MappingTagSpan <T>( (root == null) ? this.BufferGraph.CreateMappingSpan(snapshotSpan, SpanTrackingMode.EdgeExclusive) : MappingSpanSnapshot.Create(root, snapshotSpan, SpanTrackingMode.EdgeExclusive, this.BufferGraph), tagSpan.Tag)); } else { #if DEBUG Debug.WriteLine("tagger provided an extra (non-intersecting) tag at " + snapshotSpan + " when queried for tags over " + snapshotSpans); #endif } } } finally { try { tags.Dispose(); } catch (Exception e) { this.TagAggregatorFactoryService.GuardedOperations.HandleException(tagger, e); } } } } }
private bool IsSuppressed(NormalizedSnapshotSpanCollection suppressedSpans, SnapshotSpan span) { return(suppressedSpans != null && suppressedSpans.IntersectsWith(span)); }
void RemoveMarkerElements(NormalizedSnapshotSpanCollection spans) { for (int i = markerElements.Count - 1; i >= 0; i--) { var markerElement = markerElements[i]; if (spans.IntersectsWith(markerElement.Span)) markerLayer.RemoveAdornment(markerElement); } }
public bool ExecuteCommand(InsertAllMatchingCaretsCommandArgs args, CommandExecutionContext executionContext) { var broker = args.TextView.GetMultiSelectionBroker(); if (broker.PrimarySelection.IsEmpty) { broker.TryPerformActionOnSelection(broker.PrimarySelection, PredefinedSelectionTransformations.SelectCurrentWord, out _); } var navigator = TextSearchNavigatorFactoryService.CreateSearchNavigator(args.TextView.TextViewModel.EditBuffer); var primaryRegion = broker.PrimarySelection; string searchString = primaryRegion.Extent.GetText(); // Intentionally look at all whitespace here if (!string.IsNullOrEmpty(searchString)) { var snapshot = args.TextView.TextViewModel.EditBuffer.CurrentSnapshot; var documentSpan = snapshot.CreateTrackingSpan(0, snapshot.Length, SpanTrackingMode.EdgeInclusive); navigator.SearchSpan = documentSpan; navigator.SearchTerm = searchString; navigator.StartPoint = broker.PrimarySelection.Start.Position; navigator.SearchOptions = FindOptions.MatchCase | FindOptions.Multiline | FindOptions.Wrap; navigator.Find(); // Get and ignore the primary region var newlySelectedSpans = new List <SnapshotSpan>(); var oldSelectedSpans = broker.SelectedSpans; while (navigator.Find()) { var found = navigator.CurrentResult.Value; // If we have found the primary region again, we've gone the whole way around the document. if (found.OverlapsWith(primaryRegion.Extent.SnapshotSpan)) { break; } if (!oldSelectedSpans.OverlapsWith(found)) { newlySelectedSpans.Add(found); } } // Make sure that none of the newly selected spans overlap for (int i = 0; i < (newlySelectedSpans.Count - 1); i++) { if (newlySelectedSpans[i].OverlapsWith(newlySelectedSpans[i + 1])) { newlySelectedSpans.RemoveAt(i + 1); // decrement 1 so we can compare i and what used to be i+2 next time i--; } } var newlySelectedSpanCollection = new NormalizedSnapshotSpanCollection(newlySelectedSpans); // Ok, we've figured out what selections we want to add. Now we need to expand any outlining regions before finally adding the selections var outliningManager = OutliningManagerService.GetOutliningManager(args.TextView); if (outliningManager != null) { var extent = new SnapshotSpan( newlySelectedSpanCollection[0].Start, newlySelectedSpanCollection[newlySelectedSpanCollection.Count - 1].End); outliningManager.ExpandAll(extent, collapsible => { return(newlySelectedSpanCollection.IntersectsWith(collapsible.Extent.GetSpan(broker.CurrentSnapshot))); }); } // Yay, we can finally actually add the selections for (int i = 0; i < newlySelectedSpans.Count; i++) { broker.AddSelectionRange(newlySelectedSpans.Select(span => new Selection(span, broker.PrimarySelection.IsReversed))); } return(true); } return(false); }
/// <summary> /// Determines whether the specified a has intersection. /// </summary> public static bool HasIntersection(NormalizedSnapshotSpanCollection a, NormalizedSnapshotSpanCollection b) { return(SafeExecute(() => a.IntersectsWith(b))); }