Esempio n. 1
0
        private void AsyncUpdate()
        {
            // Store the snapshot that we're now current with and send an event
            // for the text that has changed.
            if (Snapshot != TextView.TextBuffer.CurrentSnapshot)
            {
                Snapshot = TextView.TextBuffer.CurrentSnapshot;

                var translatedAdornmentCache = adormentDictionariesPool.Get();
                Debug.Assert(translatedAdornmentCache.Count == 0);
                lock (adornmentsCache)
                {
                    foreach (var keyValuePair in adornmentsCache)
                    {
                        var newKey = new AdornmentCacheKey(keyValuePair.Key.Span.TranslateTo(Snapshot, SpanTrackingMode.EdgeExclusive));
                        if (!translatedAdornmentCache.ContainsKey(newKey))
                        {
                            translatedAdornmentCache.Add(newKey, keyValuePair.Value);
                        }
                    }

                    adornmentsCache.Clear();
                    adormentDictionariesPool.Put(adornmentsCache);
                    adornmentsCache = translatedAdornmentCache;
                }
            }

            int minSpan = int.MaxValue, maxSpan = int.MinValue;

            lock (invalidatedSpans)
            {
                if (invalidatedSpans.Count == 0)
                {
                    return;
                }

                for (int i = 0; i < invalidatedSpans.Count; i++)
                {
                    var translatedSpan = invalidatedSpans[i].TranslateTo(Snapshot, SpanTrackingMode.EdgeInclusive);
                    if (translatedSpan.Start < minSpan)
                    {
                        minSpan = translatedSpan.Start;
                    }
                    if (translatedSpan.End > maxSpan)
                    {
                        maxSpan = translatedSpan.End;
                    }
                }

                invalidatedSpans.Clear();
            }

            RaiseTagsChanged(new SnapshotSpan(Snapshot, minSpan, maxSpan - minSpan));
        }
Esempio n. 2
0
        private PooledStructEnumerable <ITagSpan <IntraTextAdornmentTag> > GetAdornmentTagsOnSnapshot(ITextSnapshot 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.

            var results = tagSpanListsPool.Get();

            Debug.Assert(results.Count == 0);

            var toRemove = adornmentCacheKeyHashsetsPool.Get();

            Debug.Assert(toRemove.Count == 0);

            lock (adornmentsCache)
            {
                // 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.
                foreach (var kv in adornmentsCache)
                {
                    toRemove.Add(kv.Key);
                }

                foreach (var tagData in GetAdornmentData(new NormalizedSnapshotSpanCollection(snapshot, new Span(0, snapshot.Length))))
                {
                    // Look up the corresponding adornment or create one if it's new.
                    AdornmentInfo adornmentInfo;
                    var           key = new AdornmentCacheKey(tagData.Span);
                    if (adornmentsCache.TryGetValue(key, out TAdornment adornment))
                    {
                        adornmentInfo = tagData.GetAdornmentInfo(adornment.DisplayMode);
                        UpdateAdornment(adornment, tagData.Tag, snapshot);
                        toRemove.Remove(key);

                        Debug.WriteLine($"Updating adornment {adornment.Index}");
                    }
                    else
                    {
                        adornmentInfo = tagData.GetAdornmentInfo(Mode);

                        if (adornmentsPool.Count > 0)
                        {
                            adornment = adornmentsPool[adornmentsPool.Count - 1];
                            adornmentsPool.RemoveAt(adornmentsPool.Count - 1);
                            UpdateAdornment(adornment, tagData.Tag, snapshot);
                            adornment.CurrentState = TeXCommentAdornmentState.EditingAndRenderingPreview;
                            Debug.WriteLine($"Reusing adornment {adornment.Index} from pool");
                        }
                        else
                        {
                            adornment = CreateAdornment(tagData.Tag, snapshot);
                            adornment.DisplayModeChanged += (s, e) => perSnapshotResults.UpdateValue(Snapshot); //will be deattached on  dispose
                            Debug.WriteLine($"Creating adornment {adornment.Index}");
                        }

                        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));

                        adornmentsCache.Add(key, adornment);
                    }

                    Debug.WriteLine($"Yielding adornment {adornment.Index} with span {adornmentInfo.Span}");
                    results.Add(new TagSpan <IntraTextAdornmentTag>(adornmentInfo.Span, new IntraTextAdornmentTag(adornment, null, adornmentInfo.Affinity)));
                }

                foreach (var adornmentKey in toRemove)
                {
                    if (adornmentsPool.Count < MaxAdornmentPoolSize)
                    {
                        adornmentsPool.Add(adornmentsCache[adornmentKey]);
                    }
                    adornmentsCache.Remove(adornmentKey);
                }

                toRemove.Clear();
                adornmentCacheKeyHashsetsPool.Put(toRemove);
            }

            return(new PooledStructEnumerable <ITagSpan <IntraTextAdornmentTag> >(results, tagSpanListsPool));
        }