コード例 #1
0
        /// <summary>
        /// Menu-command handler, undo the last occurrence
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        internal override void OnCommandInvoked(object sender, EventArgs e)
        {
            if (!View.HasAggregateFocus)
            {
                return;
            }

            if (AdornmentLayer.Selector.Selections.Count > 1)
            {
                AdornmentLayer.Selector.Selections.RemoveAt(AdornmentLayer.Selector.Selections.Count - 1);

                if (AdornmentLayer.Selector.Selections.Count == 1)
                {
                    AdornmentLayer.Selector.HasWrappedDocument = false;
                }
            }

            if (AdornmentLayer.Selector.Selections.Any())
            {
                AdornmentLayer.DrawAdornments();

                View.Caret.MoveTo(AdornmentLayer.Selector.Selections.Last().Caret.GetPoint(AdornmentLayer.Snapshot));
                View.ViewScroller.EnsureSpanVisible(
                    new SnapshotSpan(View.Caret.Position.BufferPosition, 0)
                    );
            }
        }
コード例 #2
0
        /// <summary>
        /// Need to remove the tags if they intersect with the editor view, but only if the option
        /// to place the tags at the end of the editor is selected.
        /// </summary>
        private void TextView_ViewportWidthChanged(object sender, EventArgs e)
        {
            // this method should only run on UI thread as we do WPF here.
            Contract.ThrowIfFalse(TextView.VisualElement.Dispatcher.CheckAccess());

            if (AdornmentLayer is null)
            {
                return;
            }

            var document = TextView.TextBuffer.AsTextContainer()?.GetOpenDocumentInCurrentContext();

            if (document is null)
            {
                AdornmentLayer.RemoveAllAdornments();
                return;
            }

            var option = _globalOptions.GetOption(InlineDiagnosticsOptions.Location, document.Project.Language);

            if (option == InlineDiagnosticsLocations.PlacedAtEndOfEditor)
            {
                var normalizedCollectionSpan = new NormalizedSnapshotSpanCollection(TextView.TextViewLines.FormattedSpan);
                UpdateSpans_CallOnlyOnUIThread(normalizedCollectionSpan, removeOldTags: true);
            }
        }
コード例 #3
0
 public void CleanUp()
 {
     if (Image != null)
     {
         AdornmentLayer.RemoveAdornment(Image);
         Image = null;
     }
 }
コード例 #4
0
        protected override void AddAdornment(ITextViewLine viewLine, TagSnapshotRange <LinkTag> tagRange, TextBounds bounds)
        {
            // Create the adornment
            var element  = CreateDecorator(bounds.Width);
            var location = new Point(Math.Round(bounds.Left), bounds.Bottom - 2);

            // Add the adornment to the layer
            AdornmentLayer.AddAdornment(element, location, viewLine, tagRange.SnapshotRange, TextRangeTrackingModes.ExpandBothEdges, null);
        }
コード例 #5
0
        private void CreateVisuals()
        {
            Image = CreateImage();

            Canvas.SetTop(Image, TextView.ViewportTop);
            Canvas.SetLeft(Image, CalcLeft());

            AdornmentLayer.AddAdornment(null, Image);
        }
コード例 #6
0
        private void SetCommonProperties(AdornmentLayer layer)
        {
            layer.Name           = Name;
            layer.Width          = width;
            layer.Height         = Height;
            layer.Location       = Location;
            layer.XOffsetInPixel = offsetX;
            layer.YOffsetInPixel = offsetY;

            layer.BackgroundMask = BackMask;
        }
コード例 #7
0
        private void CreateVisuals()
        {
            var geo = new LineGeometry(new Point(0, 0), new Point(0, TextView.ViewportHeight)).FreezeAnd();
            var img = geo.ToImage(null, Pen);

            Top  = TextView.ViewportTop;
            Left = TextView.Caret.Left;
            Canvas.SetTop(img, Top);
            Canvas.SetLeft(img, Left);
            Panel.SetZIndex(img, 101);
            Image = img;
            AdornmentLayer.AddAdornment(typeof(LineIndicatorAdornment), Image);
        }
コード例 #8
0
        /// <summary>
        /// Menu-command handler, puts cursors at a selections line-ends
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        internal override void OnCommandInvoked(object sender, EventArgs e)
        {
            if (!View.HasAggregateFocus || View.Selection.IsEmpty)
            {
                return;
            }

            AdornmentLayer.Selector.ConvertSelectionToMultipleCursors();

            if (AdornmentLayer.Selector.Selections.Any())
            {
                AdornmentLayer.DrawAdornments();
            }
        }
コード例 #9
0
        /// <summary>
        /// Menu-command handler, aka Ctrl+D
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        internal override void OnCommandInvoked(object sender, EventArgs e)
        {
            if (!View.HasAggregateFocus)
            {
                return;
            }

            AdornmentLayer.Selector.SelectAllOccurrences();

            if (AdornmentLayer.Selector.Selections.Any())
            {
                AdornmentLayer.DrawAdornments();
            }
        }
コード例 #10
0
        /// <summary>
        /// Menu-command handler, selects previous exact occurrence
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        internal override void OnCommandInvoked(object sender, EventArgs e)
        {
            if (!View.HasAggregateFocus)
            {
                return;
            }

            AdornmentLayer.Selector.SelectNextOccurrence(reverseDirection: true, exactMatch: true);

            if (AdornmentLayer.Selector.Selections.Any())
            {
                AdornmentLayer.DrawAdornments();
            }
        }
コード例 #11
0
        /// <summary>
        /// Menu-command handler, adds a new caret one line above the active caret
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        internal override void OnCommandInvoked(object sender, EventArgs e)
        {
            if (!View.HasAggregateFocus)
            {
                return;
            }

            if (!AdornmentLayer.Selector.Selections.Any())
            {
                // Add current caret
                AdornmentLayer.Selector.AddCurrentCaretToSelections();
            }

            AdornmentLayer.Selector.AddCaretAbove();
            AdornmentLayer.DrawAdornments();
        }
コード例 #12
0
        protected override void AddAdornmentsToAdornmentLayer_CallOnlyOnUIThread(NormalizedSnapshotSpanCollection changedSpanCollection)
        {
            // this method should only run on UI thread as we do WPF here.
            Contract.ThrowIfFalse(TextView.VisualElement.Dispatcher.CheckAccess());

            var viewSnapshot = TextView.TextSnapshot;
            var viewLines    = TextView.TextViewLines;

            foreach (var changedSpan in changedSpanCollection)
            {
                // is there any effect on the view?
                if (!viewLines.IntersectsBufferSpan(changedSpan))
                {
                    continue;
                }

                var tagSpans = TagAggregator.GetTags(changedSpan);
                foreach (var tagMappingSpan in tagSpans)
                {
                    if (!ShouldDrawTag(changedSpan, tagMappingSpan, out _))
                    {
                        continue;
                    }

                    if (!TryMapToSingleSnapshotSpan(tagMappingSpan.Span, TextView.TextSnapshot, out var span))
                    {
                        continue;
                    }

                    // add the visual to the adornment layer.
                    var geometry = viewLines.GetMarkerGeometry(span);
                    if (geometry != null)
                    {
                        var tag            = tagMappingSpan.Tag;
                        var graphicsResult = tag.GetGraphics(TextView, geometry, format: null);
                        AdornmentLayer.AddAdornment(
                            behavior: AdornmentPositioningBehavior.TextRelative,
                            visualSpan: span,
                            tag: tag,
                            adornment: graphicsResult.VisualElement,
                            removedCallback: delegate { graphicsResult.Dispose(); });
                    }
                }
            }
        }
コード例 #13
0
        /// <summary>
        /// Iterates through the mapping of line number to span and draws the diagnostic in the appropriate position on the screen,
        /// as well as adding the tag to the adornment layer.
        /// </summary>
        protected override void AddAdornmentsToAdornmentLayer_CallOnlyOnUIThread(NormalizedSnapshotSpanCollection changedSpanCollection)
        {
            // this method should only run on UI thread as we do WPF here.
            Contract.ThrowIfFalse(TextView.VisualElement.Dispatcher.CheckAccess());
            if (changedSpanCollection.IsEmpty())
            {
                return;
            }

            var viewLines = TextView.TextViewLines;

            using var _ = PooledDictionary <int, IMappingTagSpan <InlineDiagnosticsTag> > .GetInstance(out var map);

            AddSpansOnEachLine(changedSpanCollection, map);
            foreach (var(lineNum, tagMappingSpan) in map)
            {
                // Mapping the IMappingTagSpan back up to the TextView's visual snapshot to ensure there will
                // be no adornments drawn on disjoint spans.
                if (!TryMapToSingleSnapshotSpan(tagMappingSpan.Span, TextView.TextSnapshot, out var span))
                {
                    continue;
                }

                var geometry = viewLines.GetMarkerGeometry(span);
                if (geometry is null)
                {
                    continue;
                }

                // Need to get the SnapshotPoint to be able to get the IWpfTextViewLine
                var point = tagMappingSpan.Span.Start.GetPoint(TextView.TextSnapshot, PositionAffinity.Predecessor);
                if (point == null)
                {
                    continue;
                }

                var lineView = viewLines.GetTextViewLineContainingBufferPosition(point.Value);

                if (lineView is null)
                {
                    continue;
                }

                // Looking for IEndOfLineTags and seeing if they exist on the same line as where the
                // diagnostic would be drawn. If they are the same, then we do not want to draw
                // the diagnostic.

                var obstructingTags = _endLineTagAggregator.GetTags(lineView.Extent);
                if (obstructingTags.Where(tag => tag.Tag.Type is not "Inline Diagnostics").Any())
                {
                    continue;
                }

                var tag = tagMappingSpan.Tag;
                var classificationType = _classificationRegistryService.GetClassificationType(InlineDiagnosticsTag.GetClassificationId(tag.ErrorType));
                var graphicsResult     = tag.GetGraphics(TextView, geometry, GetFormat(classificationType));

                var visualElement = graphicsResult.VisualElement;
                // Only place the diagnostics if the diagnostic would not intersect with the editor window
                if (lineView.Right >= TextView.ViewportWidth - visualElement.DesiredSize.Width)
                {
                    continue;
                }

                Canvas.SetLeft(visualElement,
                               tag.Location == InlineDiagnosticsLocations.PlacedAtEndOfCode ? lineView.Right :
                               tag.Location == InlineDiagnosticsLocations.PlacedAtEndOfEditor ? TextView.ViewportRight - visualElement.DesiredSize.Width :
                               throw ExceptionUtilities.UnexpectedValue(tag.Location));

                Canvas.SetTop(visualElement, geometry.Bounds.Bottom - visualElement.DesiredSize.Height);

                AdornmentLayer.AddAdornment(
                    behavior: AdornmentPositioningBehavior.TextRelative,
                    visualSpan: lineView.Extent,
                    tag: tag,
                    adornment: visualElement,
                    removedCallback: delegate { graphicsResult.Dispose(); });
            }
        }
コード例 #14
0
        /// <summary>
        /// Iterates through the mapping of line number to span and draws the diagnostic in the appropriate position on the screen,
        /// as well as adding the tag to the adornment layer.
        /// </summary>
        protected override void AddAdornmentsToAdornmentLayer_CallOnlyOnUIThread(NormalizedSnapshotSpanCollection changedSpanCollection)
        {
            // this method should only run on UI thread as we do WPF here.
            Contract.ThrowIfFalse(TextView.VisualElement.Dispatcher.CheckAccess());
            if (changedSpanCollection.IsEmpty())
            {
                return;
            }

            var viewLines = TextView.TextViewLines;

            using var _ = PooledDictionary <IWpfTextViewLine, IMappingTagSpan <InlineDiagnosticsTag> > .GetInstance(out var map);

            // First loop iterates through the snap collection and determines if an inline diagnostic can be drawn.
            // Creates a mapping of the view line to the IMappingTagSpan with getting the first error that appears
            // on the line if there are multiple.
            foreach (var changedSpan in changedSpanCollection)
            {
                if (!viewLines.IntersectsBufferSpan(changedSpan))
                {
                    continue;
                }

                var tagSpans = TagAggregator.GetTags(changedSpan);
                foreach (var tagMappingSpan in tagSpans)
                {
                    if (!ShouldDrawTag(changedSpan, tagMappingSpan, out var mappedPoint))
                    {
                        continue;
                    }

                    var viewLine = viewLines.GetTextViewLineContainingBufferPosition(mappedPoint);

                    // If the line does not have an associated tagMappingSpan and changedSpan, then add the first one.
                    if (!map.TryGetValue(viewLine, out var value))
                    {
                        map.Add(viewLine, tagMappingSpan);
                    }
                    else if (value.Tag.ErrorType is not PredefinedErrorTypeNames.SyntaxError && tagMappingSpan.Tag.ErrorType is PredefinedErrorTypeNames.SyntaxError)
                    {
                        // Draw the first instance of an error, if what is stored in the map at a specific line is
                        // not an error, then replace it. Otherwise, just get the first warning on the line.
                        map[viewLine] = tagMappingSpan;
                    }
                }
            }

            // Second loop iterates through the map to go through and create the graphics that is being drawn
            // on the canvas as well adding the tag to the Inline Diagnostics adornment layer.
            foreach (var(lineView, tagMappingSpan) in map)
            {
                // Looking for IEndOfLineTags and seeing if they exist on the same line as where the
                // diagnostic would be drawn. If they are the same, then we do not want to draw
                // the diagnostic.
                var obstructingTags = _endLineTagAggregator.GetTags(lineView.Extent);
                if (obstructingTags.Where(tag => tag.Tag.Type is not "Inline Diagnostics").Any())
                {
                    continue;
                }

                var tag = tagMappingSpan.Tag;
                var classificationType = _classificationRegistryService.GetClassificationType(InlineDiagnosticsTag.GetClassificationId(tag.ErrorType));

                // Pass in null! because the geometry is unused for drawing anything for Inline Diagnostics
                var graphicsResult = tag.GetGraphics(TextView, unused: null !, GetFormat(classificationType));

                var visualElement = graphicsResult.VisualElement;

                // Only place the diagnostics if the diagnostic would not intersect with the editor window
                if (lineView.Right >= TextView.ViewportWidth - visualElement.DesiredSize.Width)
                {
                    graphicsResult.Dispose();
                    continue;
                }

                Canvas.SetLeft(visualElement,
                               tag.Location == InlineDiagnosticsLocations.PlacedAtEndOfCode ? lineView.Right :
                               tag.Location == InlineDiagnosticsLocations.PlacedAtEndOfEditor ? TextView.ViewportRight - visualElement.DesiredSize.Width :
                               throw ExceptionUtilities.UnexpectedValue(tag.Location));

                Canvas.SetTop(visualElement, lineView.Bottom - visualElement.DesiredSize.Height);

                AdornmentLayer.AddAdornment(
                    behavior: AdornmentPositioningBehavior.TextRelative,
                    visualSpan: lineView.Extent,
                    tag: tag,
                    adornment: visualElement,
                    removedCallback: delegate { graphicsResult.Dispose(); });
            }
        }
コード例 #15
0
 public CommandTarget(IWpfTextView view)
 {
     this.view           = view;
     this.adornmentLayer = view.Properties
                           .GetProperty <AdornmentLayer>(typeof(AdornmentLayer));
 }
コード例 #16
0
        protected override void AddAdornmentsToAdornmentLayer_CallOnlyOnUIThread(NormalizedSnapshotSpanCollection changedSpanCollection)
        {
            // this method should only run on UI thread as we do WPF here.
            Contract.ThrowIfFalse(TextView.VisualElement.Dispatcher.CheckAccess());

            var viewSnapshot = TextView.TextSnapshot;
            var viewLines    = TextView.TextViewLines;

            foreach (var changedSpan in changedSpanCollection)
            {
                if (!viewLines.IntersectsBufferSpan(changedSpan))
                {
                    continue;
                }

                var tagSpans = TagAggregator.GetTags(changedSpan);
                foreach (var tagMappingSpan in tagSpans)
                {
                    if (!ShouldDrawTag(changedSpan, tagMappingSpan, out _))
                    {
                        continue;
                    }

                    if (!TryMapToSingleSnapshotSpan(tagMappingSpan.Span, TextView.TextSnapshot, out var span))
                    {
                        continue;
                    }

                    if (!TryMapHoleSpans(tagMappingSpan.Tag.OrderedHoleSpans, out var orderedHoleSpans))
                    {
                        continue;
                    }

                    if (VisibleBlock.CreateVisibleBlock(span, orderedHoleSpans, TextView) is not VisibleBlock block)
                    {
                        continue;
                    }

                    var tag   = tagMappingSpan.Tag;
                    var brush = tag.GetBrush(TextView);

                    foreach (var(start, end) in block.YSegments)
                    {
                        var line = new Line
                        {
                            SnapsToDevicePixels = true,
                            StrokeThickness     = 1.0,
                            X1     = block.X,
                            X2     = block.X,
                            Y1     = start,
                            Y2     = end,
                            Stroke = brush,
                        };

                        AdornmentLayer.AddAdornment(
                            behavior: AdornmentPositioningBehavior.TextRelative,
                            visualSpan: span,
                            tag: block,
                            adornment: line,
                            removedCallback: delegate { });
                    }
                }
            }
        }
コード例 #17
0
        public static ScaleLineOrBarAdornmentLayerViewModel CreateInstance(AdornmentLayer scaleLayer)
        {
            ScaleLineOrBarAdornmentLayerViewModel newLayer = new ScaleLineOrBarAdornmentLayerViewModel();

            if (scaleLayer is ScaleBarAdornmentLayer)
            {
                newLayer.ScaleType         = ScaleType.ScaleBar;
                newLayer.NumericFormatType = ScaleNumericFormatType.None;
                string formatString = ((ScaleBarAdornmentLayer)scaleLayer).TextStyle.NumericFormat.ToUpperInvariant();
                switch (formatString)
                {
                case "C": newLayer.NumericFormatType = ScaleNumericFormatType.Currency; break;

                case "D": newLayer.NumericFormatType = ScaleNumericFormatType.Decimal; break;

                case "E": newLayer.NumericFormatType = ScaleNumericFormatType.Scientific; break;

                case "F": newLayer.NumericFormatType = ScaleNumericFormatType.FixedPoint; break;

                case "G": newLayer.NumericFormatType = ScaleNumericFormatType.General; break;

                case "N": newLayer.NumericFormatType = ScaleNumericFormatType.Number; break;

                case "P": newLayer.NumericFormatType = ScaleNumericFormatType.Percent; break;

                case "R": newLayer.NumericFormatType = ScaleNumericFormatType.RoundTrip; break;

                case "X": newLayer.NumericFormatType = ScaleNumericFormatType.Hexadecimal; break;

                default:
                    break;
                }
                newLayer.selectedScaleBarUnitSystem = ((ScaleBarAdornmentLayer)scaleLayer).UnitFamily;
            }
            else
            {
                newLayer.ScaleType = ScaleType.ScaleLine;
                newLayer.selectedScaleLineUnitSystem = ((ScaleLineAdornmentLayer)scaleLayer).UnitSystem;
            }

            newLayer.Name     = scaleLayer.Name;
            newLayer.Width    = (int)scaleLayer.Width;
            newLayer.Location = scaleLayer.Location;
            newLayer.OffsetX  = (int)scaleLayer.XOffsetInPixel;
            newLayer.OffsetY  = (int)scaleLayer.YOffsetInPixel;

            newLayer.BackMask = scaleLayer.BackgroundMask;
            newLayer.Height   = (int)scaleLayer.Height;

            if (scaleLayer is ScaleBarAdornmentLayer)
            {
                ScaleBarAdornmentLayer scaleBarLayer = (ScaleBarAdornmentLayer)scaleLayer;
                newLayer.MaximumWidth = scaleBarLayer.MaxWidth;
                newLayer.Thickness    = scaleBarLayer.Thickness;
                newLayer.ForeColor    = scaleBarLayer.BarBrush;
                newLayer.AlteColor    = scaleBarLayer.AlternateBarBrush;
                newLayer.SelectedScaleBarUnitSystem = scaleBarLayer.UnitFamily;
            }

            return(newLayer);
        }
コード例 #18
0
 protected CmdBase(IWpfTextView view)
 {
     this.view           = view;
     this.adornmentLayer = view.Properties
                           .GetProperty <AdornmentLayer>(typeof(AdornmentLayer));
 }