diff options
author | David Karlaš <david.karlas@microsoft.com> | 2019-01-22 12:29:18 +0300 |
---|---|---|
committer | David Karlaš <david.karlas@microsoft.com> | 2019-01-22 20:55:26 +0300 |
commit | 333faaaabe5803030cfe6f8d2476a614b4fd89de (patch) | |
tree | dab464727e0eb99292425000b714fa71e8bf02f7 /main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView | |
parent | 38a30db559e0e4410f6b6b8c041041e5748c348d (diff) |
Initial Debugger support in new editor
Diffstat (limited to 'main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView')
41 files changed, 1850 insertions, 0 deletions
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphFactoryProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphFactoryProvider.cs new file mode 100644 index 0000000000..c5b3b0d856 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphFactoryProvider.cs @@ -0,0 +1,81 @@ +using System.ComponentModel.Composition;
+using Microsoft.Ide.Editor; +using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Utilities;
+using Microsoft.VisualStudio.Core.Imaging;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (IGlyphFactoryProvider))] + [Name (nameof (BreakpointGlyphTag))] + [ContentType ("code")] + [TagType (typeof (BreakpointGlyphTag))] + internal class BreakpointGlyphFactoryProvider : IGlyphFactoryProvider + { + public IGlyphFactory GetGlyphFactory (ICocoaTextView view, ICocoaTextViewMargin margin) + { + return new ImageSourceGlyphFactory<BreakpointGlyphTag> ("md-breakpoint"); + } + }
+
+ [Export (typeof (IGlyphFactoryProvider))]
+ [Name (nameof (BreakpointDisabledGlyphTag))]
+ [ContentType ("code")]
+ [TagType (typeof (BreakpointDisabledGlyphTag))]
+ internal class BreakpointDisabledGlyphFactoryProvider : IGlyphFactoryProvider
+ {
+ public IGlyphFactory GetGlyphFactory (ICocoaTextView view, ICocoaTextViewMargin margin)
+ {
+ return new ImageSourceGlyphFactory<BreakpointDisabledGlyphTag> ("md-breakpoint-disabled");
+ }
+ }
+ + [Export (typeof (IGlyphFactoryProvider))] + [Name (nameof (BreakpointInvalidGlyphTag))] + [ContentType ("code")] + [TagType (typeof (BreakpointInvalidGlyphTag))] + internal class BreakpointInvalidGlyphFactoryProvider : IGlyphFactoryProvider + { + public IGlyphFactory GetGlyphFactory (ICocoaTextView view, ICocoaTextViewMargin margin) + { + return new ImageSourceGlyphFactory<BreakpointInvalidGlyphTag> ("md-breakpoint-invalid"); + } + }
+
+ [Export (typeof (IGlyphFactoryProvider))]
+ [Name (nameof (TracepointGlyphTag))]
+ [ContentType ("code")]
+ [TagType (typeof (TracepointGlyphTag))]
+ internal class TracepointGlyphFactoryProvider : IGlyphFactoryProvider
+ {
+ public IGlyphFactory GetGlyphFactory (ICocoaTextView view, ICocoaTextViewMargin margin)
+ {
+ return new ImageSourceGlyphFactory<TracepointGlyphTag> ("md-gutter-tracepoint");
+ }
+ }
+
+ [Export (typeof (IGlyphFactoryProvider))]
+ [Name (nameof (TracepointDisabledGlyphTag))]
+ [ContentType ("code")]
+ [TagType (typeof (TracepointDisabledGlyphTag))]
+ internal class TracepointDisabledGlyphFactoryProvider : IGlyphFactoryProvider
+ {
+ public IGlyphFactory GetGlyphFactory (ICocoaTextView view, ICocoaTextViewMargin margin)
+ {
+ return new ImageSourceGlyphFactory<TracepointDisabledGlyphTag> ("md-gutter-tracepoint-disabled");
+ }
+ }
+
+ [Export (typeof (IGlyphFactoryProvider))]
+ [Name (nameof (TracepointInvalidGlyphTag))]
+ [ContentType ("code")]
+ [TagType (typeof (TracepointInvalidGlyphTag))]
+ internal class TracepointInvalidGlyphFactoryProvider : IGlyphFactoryProvider
+ {
+ public IGlyphFactory GetGlyphFactory (ICocoaTextView view, ICocoaTextViewMargin margin)
+ {
+ return new ImageSourceGlyphFactory<TracepointInvalidGlyphTag> ("md-gutter-tracepoint-invalid");
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphMouseProcessor.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphMouseProcessor.cs new file mode 100644 index 0000000000..07761fb5f1 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphMouseProcessor.cs @@ -0,0 +1,583 @@ +using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Threading;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Formatting;
+using Microsoft.VisualStudio.Text.Tagging;
+using AppKit;
+using CoreGraphics;
+using MonoDevelop.Debugger;
+using MonoDevelop.Ide.Gui; +using MonoDevelop.Ide; +using MonoDevelop.Ide.Editor; + +namespace MonoDevelop.Debugger
+{ + public class BreakpointGlyphMouseProcessor : CocoaMouseProcessorBase + { + private readonly ICocoaTextViewHost textViewHost; + private ITagAggregator<IGlyphTag> glyphTagAggregator; + private readonly ICocoaTextViewMargin glyphMargin; + private readonly IViewPrimitives viewPrimitives; + private IActiveGlyphDropHandler activeGlyphDropHandler; + + // Tooltip + //private readonly Popup popup; + + // Hover members + private DispatcherTimer mouseHoverTimer = null; + private ITextViewLine lastHoverPosition; + private ITextViewLine currentlyHoveringLine; + + // Drag/drop members + private CGPoint clickLocation; + internal bool LastLeftButtonWasDoubleClick = true; // internal for unit testing + private bool dragOccurred = false; + + // Constants for scrolling tolerance (borrowed from \platform\text\dragdrop\DragDropMouseProcessor.cs). + private const double VerticalScrollTolerance = 15; + private const double HorizontalScrollTolerance = 15; + + // Delay before tooltips display + private const int ToolTipDelayMilliseconds = 150; + + public BreakpointGlyphMouseProcessor ( + ICocoaTextViewHost wpfTextViewHost, + ICocoaTextViewMargin margin, + ITagAggregator<IGlyphTag> tagAggregator, + IViewPrimitives viewPrimitives) + { + this.textViewHost = wpfTextViewHost; + this.glyphMargin = margin; + this.glyphTagAggregator = tagAggregator; + this.viewPrimitives = viewPrimitives; + + // Setup the UI + //TODO:MAC + //popup = new Popup(); + //popup.IsOpen = false; + //popup.Visibility = Visibility.Hidden; + + textViewHost.Closed += delegate { + glyphTagAggregator.Dispose (); + glyphTagAggregator = null; + }; + } + + public override void PreprocessMouseLeftButtonDown (MouseEvent e) + { + // Record click location. + clickLocation = GetMouseLocationInTextView (e); + + // We don't handle double-click, and set the flag so that the mouse + // up handler doesn't try to handle it as a click either. + LastLeftButtonWasDoubleClick = e.Event.ClickCount == 2; + + if (LastLeftButtonWasDoubleClick) { + return; + } + + // Starts a drag if applicable. + HandleDragStart (clickLocation); + } + + public override void PreprocessMouseLeftButtonUp (MouseEvent e) + { + // Did we successfully drag a glyph? + var mouseUpLocation = GetMouseLocationInTextView (e); + if (HandleDragEnd (mouseUpLocation)) { + e.Handled = true; + return; + } + + // We don't handle double-click + if (LastLeftButtonWasDoubleClick) { + return; + } + + if (GetTextViewLine (mouseUpLocation.Y) != GetTextViewLine (clickLocation.Y)) { + // If the user (probably accidentally) click-dragged to a different line, don't treat it as a click. + e.Handled = false; + return; + } + + // Treat this as a marker click + e.Handled = HandleMarkerClick (e); + } + + public override void PostprocessMouseRightButtonUp (MouseEvent e) + { + var mouseUpLocation = GetMouseLocationInTextView (e);
+ var textViewLine = GetTextViewLine (mouseUpLocation.Y);
+ if (!textViewLine.Extent.Contains (textViewHost.TextView.Caret.Position.BufferPosition)) + textViewHost.TextView.Caret.MoveTo (textViewLine.Start); + var view = (ViewContent)textViewHost.TextView.Properties [typeof (ViewContent)]; + var ctx = view.WorkbenchWindow?.ExtensionContext ?? Mono.Addins.AddinManager.AddinEngine;
+ var cset = IdeApp.CommandService.CreateCommandEntrySet (ctx, "/MonoDevelop/SourceEditor2/IconContextMenu/Editor"); + var pt = ((NSEvent)e.Event).LocationInWindow; + pt = textViewHost.TextView.VisualElement.ConvertPointFromView (pt, null); + IdeApp.CommandService.ShowContextMenu (textViewHost.TextView.VisualElement, (int)pt.X, (int)pt.Y, cset, view); + } + + public override void PostprocessMouseEnter (MouseEvent e) + { + EnableToolTips (); + } + + public override void PostprocessMouseLeave (MouseEvent e) + { + DisableToolTips (); + } + + public override void PreprocessMouseMove (MouseEvent e) + { + // If we're dragging a glyph, show proper cursor, scroll the view, etc. + var pt = GetMouseLocationInTextView (e); + if (HandleDragOver (pt)) { + return; + } + + ITextViewLine textLine = GetTextViewLine (pt.Y); + + // If we're hovering, make sure we're still hovering over the same line. + if (mouseHoverTimer != null) { + if (textLine != currentlyHoveringLine) { + currentlyHoveringLine = null; + + HideTooltip (); + } + + mouseHoverTimer.Start (); + } + + // If there's a glyph with a hover mouse cursor, show it. + if (textLine != null) { + foreach (IInteractiveGlyph textMarkerGlyphTag in GetTextMarkerGlyphTagsStartingOnLine (textLine)) { + if (textMarkerGlyphTag.HoverCursor != null) { + //TODO:MAC + //Mouse.SetCursor(textMarkerGlyphTag.HoverCursor); + break; + } + } + } + } + + #region Private Drag/Drop Helpers
+ + // Internal for unit testing. + internal void HandleDragStart (CGPoint viewPoint) + { + Debug.Assert (activeGlyphDropHandler == null); + activeGlyphDropHandler = null; + + // Get the ITextViewLine corresponding to the click point. + ITextViewLine textLine = GetTextViewLine (viewPoint.Y); + if (textLine == null) { + return; + } + + // Is there a draggable glyph here? + IActiveGlyphDropHandler draggableTextMarkerGlyphTag = null; + foreach (IInteractiveGlyph textMarkerGlyphTag in GetTextMarkerGlyphTagsStartingOnLine (textLine)) { + if (textMarkerGlyphTag.DropHandler != null) { + draggableTextMarkerGlyphTag = textMarkerGlyphTag.DropHandler; + break; + } + } + + if (draggableTextMarkerGlyphTag == null) { + return; + } + + // We have a draggable glyph. Start dragging it! + // Store the handler for the glyph being dragged. + activeGlyphDropHandler = draggableTextMarkerGlyphTag; + + HideTooltip (); + + dragOccurred = false; + + // Capture mouse events so we catch mouse moves over the entire screen and the mouse up event. + // Note: This may trigger an immediate OnMouseMove event, so make sure we do it last. + //glyphMargin.VisualElement.CaptureMouse(); + } + + internal bool HandleDragOver (CGPoint viewPoint) + { + if (activeGlyphDropHandler == null) { + return false; // not dragging + } + + if (!dragOccurred) { + // if the mouse moved position is less than the system settings for drag start, don't start the + // drag operation + Vector dragDelta = new Vector (clickLocation.X - viewPoint.X, clickLocation.Y - viewPoint.Y); + if (Math.Abs (dragDelta.X) < SystemParameters.MinimumHorizontalDragDistance && Math.Abs (dragDelta.Y) < SystemParameters.MinimumVerticalDragDistance) { + return false; + } + + // Now that the mouse has moved, this is an actual drag. + dragOccurred = true; + } + + Tuple<int, int> lineAndColumn = GetLineNumberAndColumn (viewPoint); + + // If this line isn't in the data (surface) buffer, we can't use it + if (lineAndColumn.Item1 < 0) { + return false; + } + + // Query if we can drop here and set mouse cursor appropriately. + if (activeGlyphDropHandler.CanDrop (lineAndColumn.Item1, lineAndColumn.Item2)) { + // We can drop here. Use "hand" cursor. + //TODO:MAC + //Mouse.OverrideCursor = Cursors.Hand; + } else { + // Can't drop here; change mouse cursor. + //TODO:MAC + //Mouse.OverrideCursor = Cursors.No; + } + + // if the view does not have any focus, grab it + if (!textViewHost.TextView.HasAggregateFocus) { + textViewHost.TextView.VisualElement.BecomeFirstResponder (); + } + + // Position the drag/drop caret and ensure it's visible. + ITextViewLine textViewLine = GetTextViewLine (viewPoint.Y); + viewPrimitives.Caret.AdvancedCaret.MoveTo (textViewLine, viewPoint.X); + + this.EnsureCaretVisibleWithPadding (); + + return true; + } + + private void EnsureCaretVisibleWithPadding () + { + // ensure caret is visible with a little padding to all sides. + ITextViewLine caretLine = viewPrimitives.Caret.AdvancedCaret.ContainingTextViewLine; + double padding = Math.Max (0.0, (textViewHost.TextView.ViewportHeight - caretLine.Height) * 0.5); + + // Ensure vertical padding. + double topSpace = caretLine.Top - (textViewHost.TextView.ViewportTop + VerticalScrollTolerance); + double bottomSpace = (textViewHost.TextView.ViewportBottom - VerticalScrollTolerance) - caretLine.Bottom; + + if ((topSpace < 0.0) != (bottomSpace < 0.0)) { + if (topSpace < 0.0) { + textViewHost.TextView.DisplayTextLineContainingBufferPosition (caretLine.Start, Math.Min (VerticalScrollTolerance, padding), ViewRelativePosition.Top); + } else { + textViewHost.TextView.DisplayTextLineContainingBufferPosition (caretLine.Start, Math.Min (VerticalScrollTolerance, padding), ViewRelativePosition.Bottom); + } + } + + // Ensure horizontal padding + double leftSpace = viewPrimitives.Caret.AdvancedCaret.Left - (textViewHost.TextView.ViewportLeft + HorizontalScrollTolerance); + double rightSpace = (textViewHost.TextView.ViewportRight - HorizontalScrollTolerance) - viewPrimitives.Caret.AdvancedCaret.Right; + + if ((leftSpace < 0.0) != (rightSpace < 0.0)) { + if (leftSpace < 0.0) { + textViewHost.TextView.ViewportLeft = viewPrimitives.Caret.AdvancedCaret.Left - Math.Min (HorizontalScrollTolerance, rightSpace); + } else { + textViewHost.TextView.ViewportLeft = (viewPrimitives.Caret.AdvancedCaret.Right + Math.Min (HorizontalScrollTolerance, leftSpace)) - textViewHost.TextView.ViewportWidth; + } + } + } + + internal bool HandleDragEnd (CGPoint viewPoint) + { + // Clean up our dragging state. + //glyphMargin.VisualElement.ReleaseMouseCapture(); + //Mouse.OverrideCursor = null; + + IActiveGlyphDropHandler glyphDropHandler = activeGlyphDropHandler; + activeGlyphDropHandler = null; + + // Did we actually do a drag? + if (!dragOccurred) { + return false; + } + + dragOccurred = false; + + if (glyphDropHandler != null) { + Tuple<int, int> lineAndColumn = GetLineNumberAndColumn (viewPoint); + + // If this line isn't in the data (surface) buffer, we can't use it + if (lineAndColumn.Item1 < 0) { + return false; + } + + // Query if we can drop here. + if (glyphDropHandler.CanDrop (lineAndColumn.Item1, lineAndColumn.Item2)) { + glyphDropHandler.DropAtLocation (lineAndColumn.Item1, lineAndColumn.Item2); + } + } + + // Even if we couldn't drop here, we return true to ensure that we don't handle this as a normal click. + return true; + } + + private bool HandleMarkerClick (MouseEvent e) + { + // Raise MarkerCommandValues.mcvGlyphSingleClickCommand + if (ExecuteMarkerCommand (glyphMargin.VisualElement.ConvertPointFromView (e.Event.LocationInWindow, null), + GlyphCommandType.SingleClick)) { + return true; + } + + // Also, make sure that this point in the margin maps to a line/column in the correct buffer. In + // certain projection scenarios, this span may not be in the data buffer. + Tuple<int, int> lineCol = GetLineNumberAndColumn (GetMouseLocationInTextView (e)); + if (lineCol.Item1 < 0) { + return false; + } + + return ToggleBreakpoint (lineCol.Item1, lineCol.Item2); + } + + private bool ToggleBreakpoint (int line, int column) + { + var buffer = textViewHost.TextView.TextBuffer; + var path = buffer.GetFilePathOrNull ();
+ if (path == null)
+ return false; + DebuggingService.Breakpoints.Toggle (path, line + 1, column + 1); + return true; + } + + #endregion
+ + #region Private Helpers
+ + private CGPoint GetMouseLocationInTextView (MouseEvent e) + { + ICocoaTextView textView = textViewHost.TextView; + var pt = textView.VisualElement.ConvertPointFromView (e.Event.LocationInWindow, null); + pt.Y += (nfloat)textView.ViewportTop; + pt.X += (nfloat)textView.ViewportLeft; + + return pt; + } + + private ITextViewLine GetTextViewLine (double y) + { + ICocoaTextView textView = textViewHost.TextView; + + // Establish line for point + ITextViewLine textViewLine = textView.TextViewLines.GetTextViewLineContainingYCoordinate (y); + if (textViewLine == null) { + textViewLine = y <= textView.TextViewLines [0].Top ? + textView.TextViewLines.FirstVisibleLine : + textView.TextViewLines.LastVisibleLine; + } + + return textViewLine; + } + + private static SnapshotPoint GetBufferPosition (ITextViewLine textViewLine, double x) + { + SnapshotPoint? bufferPosition = textViewLine.GetBufferPositionFromXCoordinate (x); + if (!bufferPosition.HasValue) { + bufferPosition = x < textViewLine.TextLeft ? textViewLine.Start : textViewLine.End; + } + + return bufferPosition.Value; + } + + private Tuple<int, int> GetLineNumberAndColumn (CGPoint viewPoint) + { + int line = 0; + int col = 0; + + ITextViewLine textViewLine = GetTextViewLine (viewPoint.Y); + if (textViewLine != null) { + // The line number should be the line number in the data buffer, + // which is the text buffer adapter's surface buffer + var dataSpans = textViewLine.ExtentAsMappingSpan.GetSpans (textViewHost.TextView.TextViewModel.DataBuffer); + + // If this point doesn't map into the data buffer at all, then return line + // number of -1 to indicate failure + if (dataSpans.Count == 0) { + return Tuple.Create (-1, -1); + } + + line = dataSpans [0].Start.GetContainingLine ().LineNumber; + } + + // Establish col for point + int bufferPosition = GetBufferPosition (textViewLine, viewPoint.X); + col = bufferPosition - textViewLine.Start; + + return Tuple.Create (line, col); + } + + // Internal for unit testing + internal bool ExecuteMarkerCommand (CGPoint pt, GlyphCommandType markerCommand) + { + bool commandHandled = false; + + pt.Y += (nfloat)textViewHost.TextView.ViewportTop; + + ITextViewLine textLine = textViewHost.TextView.TextViewLines.GetTextViewLineContainingYCoordinate (pt.Y); + if (textLine == null) { + return commandHandled; + } + + // Tags are sorted from low priority to high priority + IInteractiveGlyph highestPriorityTag = null; + foreach (IInteractiveGlyph textMarkerTag in GetTextMarkerGlyphTagsStartingOnLine (textLine)) { + // only consider visible glyph markers. + if (textMarkerTag.IsEnabled) { + highestPriorityTag = textMarkerTag; + } + } + + if (highestPriorityTag != null && highestPriorityTag.ExecuteCommand (markerCommand)) { + // Only handle the highest priority command + commandHandled = true; + } + + return commandHandled; + } + + private void EnableToolTips () + { + if (mouseHoverTimer == null) { + mouseHoverTimer = new DispatcherTimer ( + TimeSpan.FromMilliseconds (ToolTipDelayMilliseconds), + DispatcherPriority.Normal, + OnHoverTimer, + Dispatcher.CurrentDispatcher); + } + + mouseHoverTimer.Start (); + } + + private void DisableToolTips () + { + if (mouseHoverTimer != null) { + mouseHoverTimer.Stop (); + } + + HideTooltip (); + lastHoverPosition = null; + } + + private void OnHoverTimer (object sender, EventArgs e) + { + // It's possible the view was closed before our timer triggered, in which case + // _glyphMargin is disposed and we can't touch it. + if (textViewHost.IsClosed) { + return; + } + + if ((NSEvent.CurrentPressedMouseButtons & 1) > 0) { + return; // don't show tooltips when button is pressed (e.g. during a drag) + } + //TODO:MAC, convert mouse location + HoverAtPoint (NSEvent.CurrentMouseLocation); + } + + // internal for exposure to unit tests + internal void HoverAtPoint (CGPoint pt) + { + // The HoverAtPoint calls get dispatched to the UI thread and you can imagine rare scenarios where + // either multiple calls get queued up (and, possibly, execute after the view has lost focus and + // the mouse hover has been disabled). Only execute if we still have a running mouse timer. + if ((mouseHoverTimer != null) && mouseHoverTimer.IsEnabled && glyphMargin.Enabled && !dragOccurred) { + ITextViewLine textLine = textViewHost.TextView.TextViewLines.GetTextViewLineContainingYCoordinate (pt.Y + textViewHost.TextView.ViewportTop); + if (textLine != lastHoverPosition) { + lastHoverPosition = textLine; + + // Get textmarkers + if (textLine != null) { + // Tags are returned in lowest to highest priority order + // Keep track of highest priority tip text + string tipText = null; + foreach (IInteractiveGlyph textMarkerGlyphTag in GetTextMarkerGlyphTagsStartingOnLine (textLine)) { + tipText = textMarkerGlyphTag.TooltipText; + } + //TODO:MAC + //if (!string.IsNullOrEmpty(tipText)) + //{ + // popup.Child = null; + + // TextBlock textBlock = new TextBlock(); + // textBlock.Text = tipText; + // textBlock.Name = "GlyphToolTip"; + + // Border border = new Border(); + // border.Padding = new Thickness(1); + // border.BorderThickness = new Thickness(1); + // border.Child = textBlock; + + // // set colors of the tooltip to shell's defined colors + // textBlock.SetResourceReference(TextBlock.ForegroundProperty, "VsBrush.ScreenTipText"); + // border.SetResourceReference(Border.BorderBrushProperty, "VsBrush.ScreenTipBorder"); + // border.SetResourceReference(Border.BackgroundProperty, "VsBrush.ScreenTipBackground"); + + // popup.Child = border; + // popup.Placement = PlacementMode.Relative; + // popup.PlacementTarget = glyphMargin.VisualElement; + // popup.HorizontalOffset = 0.0; + // popup.VerticalOffset = textLine.Bottom - textViewHost.TextView.ViewportTop; + // popup.IsOpen = true; + // popup.Visibility = Visibility.Visible; + + // currentlyHoveringLine = textLine; + //} + } + } + } + } + + private void HideTooltip () + { + //TODO:MAC + //popup.Child = null; + //popup.IsOpen = false; + //popup.Visibility = Visibility.Hidden; + } + + // helper method to get the text marker tags starting on a line. + private IEnumerable<IInteractiveGlyph> GetTextMarkerGlyphTagsStartingOnLine (ITextViewLine textViewLine) + { + var visualBuffer = textViewHost.TextView.TextViewModel.VisualBuffer; + var editBuffer = textViewHost.TextView.TextBuffer; + + // Tags are sorted from low priority to high priority + foreach (var mappingTagSpan in glyphTagAggregator.GetTags (textViewLine.ExtentAsMappingSpan)) { + // Only take tag spans with a visible start point and that map to something + // in the edit buffer, and the markers that *start* on this line + + IInteractiveGlyph textMarkerGlyphTag = mappingTagSpan.Tag as IInteractiveGlyph; + + if (textMarkerGlyphTag == null) { + continue; + } + + SnapshotPoint? pointInVisualBuffer = mappingTagSpan.Span.Start.GetPoint ( + visualBuffer, + PositionAffinity.Predecessor); + SnapshotPoint? pointInEditBuffer = mappingTagSpan.Span.Start.GetPoint ( + editBuffer, + PositionAffinity.Predecessor); + + if (!(pointInVisualBuffer.HasValue && pointInEditBuffer.HasValue)) { + continue; + } + + if (pointInEditBuffer.Value >= textViewLine.Start && + pointInEditBuffer.Value <= textViewLine.End) { + yield return textMarkerGlyphTag; + } + } + } + + #endregion
+ }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphMouseProcessorProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphMouseProcessorProvider.cs new file mode 100644 index 0000000000..29390386e3 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphMouseProcessorProvider.cs @@ -0,0 +1,31 @@ +using System.ComponentModel.Composition;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (IGlyphMouseProcessorProvider))] + [Name ("BreakpointGlyphMouseProcessorProvider")] + [Order] + [ContentType ("any")] + public class BreakpointGlyphMouseProcessorProvider : IGlyphMouseProcessorProvider + { + [Import] + private IViewTagAggregatorFactoryService viewTagAggregatorService = null; + + [Import] + private IEditorPrimitivesFactoryService editorPrimitivesFactoryService = null; + + public ICocoaMouseProcessor GetAssociatedMouseProcessor ( + ICocoaTextViewHost wpfTextViewHost, + ICocoaTextViewMargin margin) + { + return new BreakpointGlyphMouseProcessor ( + wpfTextViewHost, + margin, + viewTagAggregatorService.CreateTagAggregator<IGlyphTag> (wpfTextViewHost.TextView), + editorPrimitivesFactoryService.GetViewPrimitives (wpfTextViewHost.TextView)); + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphTag.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphTag.cs new file mode 100644 index 0000000000..a051d11df3 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphTag.cs @@ -0,0 +1,89 @@ +using System.Windows.Input;
+using AppKit; +using Microsoft.VisualStudio.Text.Editor;
+using Mono.Debugging.Client; +using MonoDevelop.Debugger;
+using MonoDevelop.Ide.Gui;
+ +namespace MonoDevelop.Debugger
+{
+ class BreakpointGlyphTag : BaseBreakpointGlyphTag
+ {
+ public BreakpointGlyphTag (BreakEvent breakpoint) : base (breakpoint)
+ {
+ }
+ }
+ class BreakpointDisabledGlyphTag : BaseBreakpointGlyphTag
+ {
+ public BreakpointDisabledGlyphTag (BreakEvent breakpoint) : base (breakpoint)
+ {
+ }
+ }
+ class BreakpointInvalidGlyphTag : BaseBreakpointGlyphTag
+ {
+ public BreakpointInvalidGlyphTag (BreakEvent breakpoint) : base (breakpoint)
+ {
+ }
+ } + class TracepointGlyphTag : BaseBreakpointGlyphTag
+ {
+ public TracepointGlyphTag (BreakEvent breakpoint) : base (breakpoint)
+ {
+ }
+ }
+ class TracepointDisabledGlyphTag : BaseBreakpointGlyphTag
+ {
+ public TracepointDisabledGlyphTag (BreakEvent breakpoint) : base (breakpoint)
+ {
+ }
+ }
+ class TracepointInvalidGlyphTag : BaseBreakpointGlyphTag
+ {
+ public TracepointInvalidGlyphTag (BreakEvent breakpoint) : base (breakpoint)
+ {
+ }
+ }
+ + abstract class BaseBreakpointGlyphTag : IGlyphTag, IInteractiveGlyph + { + private readonly BreakEvent breakpoint; + + public BaseBreakpointGlyphTag (BreakEvent breakpoint) + {
+ this.breakpoint = breakpoint; + } + + public NSCursor HoverCursor { + get { + return null; + } + } + + public IActiveGlyphDropHandler DropHandler { + get { + return null; + } + } + + public bool IsEnabled { + get { + return true; + } + } + + public bool ExecuteCommand (GlyphCommandType markerCommand) + { + if (markerCommand == GlyphCommandType.SingleClick) {
+ DebuggingService.Breakpoints.Remove (breakpoint); + return true; + } + return false; + } + + public string TooltipText { + get { + return null; + } + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphTagger.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphTagger.cs new file mode 100644 index 0000000000..bab58a6d67 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphTagger.cs @@ -0,0 +1,69 @@ +using System;
+using System.Collections.Generic;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+using Mono.Debugging.Client; +using MonoDevelop.Debugger;
+
+namespace MonoDevelop.Debugger
+{ + internal class BreakpointGlyphTagger : ITagger<BaseBreakpointGlyphTag> + { + private readonly ITextView textView;
+ private readonly ITextDocumentFactoryService textDocumentFactoryService; + + public BreakpointGlyphTagger (ITextDocumentFactoryService textDocumentFactoryService, ITextView textView) + { + this.textView = textView;
+ this.textDocumentFactoryService = textDocumentFactoryService; + DebuggingService.Breakpoints.Changed += OnBreakpointsChanged; + this.textView.Closed += (s, e) => DebuggingService.Breakpoints.Changed -= OnBreakpointsChanged; + } + + private void OnBreakpointsChanged (object sender, EventArgs eventArgs) + { + if (TagsChanged != null) { + var snapshot = textView.TextBuffer.CurrentSnapshot; + var snapshotSpan = new SnapshotSpan (snapshot, 0, snapshot.Length); + var args = new SnapshotSpanEventArgs (snapshotSpan); + TagsChanged (this, args); + } + } + + public IEnumerable<ITagSpan<BaseBreakpointGlyphTag>> GetTags (NormalizedSnapshotSpanCollection spans) + {
+ var found = textDocumentFactoryService.TryGetTextDocument (textView.TextBuffer, out var document);
+ if (!found || document.FilePath == null)
+ yield break;
+ + foreach (var breakpoint in DebuggingService.Breakpoints.GetBreakpointsAtFile (document.FilePath)) { + var span = textView.TextBuffer.CurrentSnapshot.GetLineFromLineNumber (breakpoint.Line - 1).Extent;
+ if (spans.IntersectsWith (span)) {
+ bool tracepoint = (breakpoint.HitAction & HitAction.Break) == HitAction.None;
+ if (breakpoint.Enabled) {
+ var status = DebuggingService.GetBreakpointStatus (breakpoint); + if (status == BreakEventStatus.Bound || status == BreakEventStatus.Disconnected) { + if (tracepoint) + yield return new TagSpan<TracepointGlyphTag> (span, new TracepointGlyphTag (breakpoint)); + else + yield return new TagSpan<BreakpointGlyphTag> (span, new BreakpointGlyphTag (breakpoint));
+ } else { + if (tracepoint) + yield return new TagSpan<TracepointInvalidGlyphTag> (span, new TracepointInvalidGlyphTag (breakpoint)); + else + yield return new TagSpan<BreakpointInvalidGlyphTag> (span, new BreakpointInvalidGlyphTag (breakpoint)); + } + } else { + if (tracepoint) + yield return new TagSpan<TracepointDisabledGlyphTag> (span, new TracepointDisabledGlyphTag (breakpoint)); + else + yield return new TagSpan<BreakpointDisabledGlyphTag> (span, new BreakpointDisabledGlyphTag (breakpoint)); + } + } + } + } + + public event System.EventHandler<SnapshotSpanEventArgs> TagsChanged; + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphTaggerProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphTaggerProvider.cs new file mode 100644 index 0000000000..4463b5024e --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/BreakpointGlyphTaggerProvider.cs @@ -0,0 +1,27 @@ +using System.ComponentModel.Composition;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (IViewTaggerProvider))] + [ContentType ("code")] + [TagType (typeof (BreakpointGlyphTag))]
+ [TagType (typeof (BreakpointDisabledGlyphTag))]
+ [TagType (typeof (BreakpointInvalidGlyphTag))]
+ [TagType (typeof (TracepointGlyphTag))]
+ [TagType (typeof (TracepointDisabledGlyphTag))]
+ [TagType (typeof (TracepointInvalidGlyphTag))] + internal class BreakpointGlyphTaggerProvider : IViewTaggerProvider + { + [Import] + public ITextDocumentFactoryService TextDocumentFactoryService { get; set; } + + public ITagger<T> CreateTagger<T> (ITextView textView, ITextBuffer buffer) where T : ITag + { + return new BreakpointGlyphTagger (TextDocumentFactoryService, textView) as ITagger<T>; + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/CurrentStatementGlyphFactoryProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/CurrentStatementGlyphFactoryProvider.cs new file mode 100644 index 0000000000..49b9bd0fea --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/CurrentStatementGlyphFactoryProvider.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.Composition;
+using Microsoft.Ide.Editor;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (IGlyphFactoryProvider))] + [Name ("CurrentStatementGlyph")] + [Order (After = "BreakpointGlyph")] + [ContentType ("code")] + [TagType (typeof (CurrentStatementGlyphTag))] + internal class CurrentStatementGlyphFactoryProvider : IGlyphFactoryProvider + { + public IGlyphFactory GetGlyphFactory (ICocoaTextView view, ICocoaTextViewMargin margin) + { + return new ImageSourceGlyphFactory<CurrentStatementGlyphTag> ("md-gutter-execution"); + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/CurrentStatementGlyphTag.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/CurrentStatementGlyphTag.cs new file mode 100644 index 0000000000..58d596e087 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/CurrentStatementGlyphTag.cs @@ -0,0 +1,9 @@ +using Microsoft.VisualStudio.Text.Editor;
+
+namespace MonoDevelop.Debugger
+{ + internal class CurrentStatementGlyphTag : IGlyphTag + { + public static readonly CurrentStatementGlyphTag Instance = new CurrentStatementGlyphTag (); + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/CurrentStatementGlyphTagger.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/CurrentStatementGlyphTagger.cs new file mode 100644 index 0000000000..9f0874cbea --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/CurrentStatementGlyphTagger.cs @@ -0,0 +1,12 @@ +using Microsoft.VisualStudio.Text;
+
+namespace MonoDevelop.Debugger
+{ + internal class CurrentStatementGlyphTagger : AbstractCurrentStatementTagger<CurrentStatementGlyphTag> + { + public CurrentStatementGlyphTagger (ITextBuffer textBuffer) + : base (CurrentStatementGlyphTag.Instance, textBuffer, isGreen: false) + { + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/CurrentStatementGlyphTaggerProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/CurrentStatementGlyphTaggerProvider.cs new file mode 100644 index 0000000000..bfa1425db7 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/CurrentStatementGlyphTaggerProvider.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.Composition;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (IViewTaggerProvider))] + [ContentType ("code")] + [TagType (typeof (CurrentStatementGlyphTag))] + internal class CurrentStatementGlyphTaggerProvider : IViewTaggerProvider + { + public ITagger<T> CreateTagger<T> (ITextView textView, ITextBuffer buffer) where T : ITag + { + return new CurrentStatementGlyphTagger (buffer) as ITagger<T>; + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/GlyphCommandType.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/GlyphCommandType.cs new file mode 100644 index 0000000000..6dd9dd8095 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/GlyphCommandType.cs @@ -0,0 +1,8 @@ +namespace MonoDevelop.Debugger
+{ + public enum GlyphCommandType + { + SingleClick, + RightClick + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/IActiveGlyphDropHandler.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/IActiveGlyphDropHandler.cs new file mode 100644 index 0000000000..ddb02bda0e --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/IActiveGlyphDropHandler.cs @@ -0,0 +1,8 @@ +namespace MonoDevelop.Debugger
+{ + public interface IActiveGlyphDropHandler + { + bool CanDrop (int line, int column); + void DropAtLocation (int line, int column); + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/IInteractiveGlyph.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/IInteractiveGlyph.cs new file mode 100644 index 0000000000..fa4a94a435 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/IInteractiveGlyph.cs @@ -0,0 +1,13 @@ +using AppKit; + +namespace MonoDevelop.Debugger
+{ + public interface IInteractiveGlyph + { + NSCursor HoverCursor { get; } + IActiveGlyphDropHandler DropHandler { get; } + bool IsEnabled { get; } + bool ExecuteCommand (GlyphCommandType markerCommand); + string TooltipText { get; } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ImageSourceGlyphFactory.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ImageSourceGlyphFactory.cs new file mode 100644 index 0000000000..1465ab11e6 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ImageSourceGlyphFactory.cs @@ -0,0 +1,32 @@ +using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Formatting; +using AppKit;
+using Microsoft.VisualStudio.Core.Imaging;
+using MonoDevelop.Ide;
+
+namespace Microsoft.Ide.Editor
+{ + public class ImageSourceGlyphFactory<T> : IGlyphFactory + where T : IGlyphTag + { + private readonly string imageSource; + + public ImageSourceGlyphFactory (string imageSource) + { + this.imageSource = imageSource; + } + + public object GenerateGlyph (ICocoaFormattedLine line, IGlyphTag tag) + { + if (tag == null || !(tag is T) || imageSource == null) { + return null; + } + Xwt.Drawing.Image xwtImage = ImageService.GetIcon (imageSource); + var nsImage = (NSImage)Xwt.Toolkit.NativeEngine.GetNativeImage (xwtImage);
+
+ var imageView = NSImageView.FromImage (nsImage);
+ imageView.SetFrameSize (imageView.FittingSize); + return imageView; + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ReturnStatementGlyphFactoryProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ReturnStatementGlyphFactoryProvider.cs new file mode 100644 index 0000000000..e1ede8d823 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ReturnStatementGlyphFactoryProvider.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.Composition;
+using Microsoft.Ide.Editor;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (IGlyphFactoryProvider))] + [Name ("ReturnStatementGlyph")] + [Order (After = "CurrentStatementGlyph")] + [ContentType ("code")] + [TagType (typeof (ReturnStatementGlyphTag))] + internal class ReturnStatementGlyphFactoryProvider : IGlyphFactoryProvider + { + public IGlyphFactory GetGlyphFactory (ICocoaTextView view, ICocoaTextViewMargin margin) + { + return new ImageSourceGlyphFactory<ReturnStatementGlyphTag> ("md-gutter-stack"); + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ReturnStatementGlyphTag.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ReturnStatementGlyphTag.cs new file mode 100644 index 0000000000..796d6e6341 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ReturnStatementGlyphTag.cs @@ -0,0 +1,9 @@ +using Microsoft.VisualStudio.Text.Editor;
+
+namespace MonoDevelop.Debugger
+{ + internal class ReturnStatementGlyphTag : IGlyphTag + { + public static readonly ReturnStatementGlyphTag Instance = new ReturnStatementGlyphTag (); + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ReturnStatementGlyphTagger.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ReturnStatementGlyphTagger.cs new file mode 100644 index 0000000000..14a8782866 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ReturnStatementGlyphTagger.cs @@ -0,0 +1,12 @@ +using Microsoft.VisualStudio.Text;
+
+namespace MonoDevelop.Debugger
+{ + internal class ReturnStatementGlyphTagger : AbstractCurrentStatementTagger<ReturnStatementGlyphTag> + { + public ReturnStatementGlyphTagger (ITextBuffer textBuffer) + : base (ReturnStatementGlyphTag.Instance, textBuffer, isGreen: true) + { + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ReturnStatementGlyphTaggerProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ReturnStatementGlyphTaggerProvider.cs new file mode 100644 index 0000000000..7ce5db1223 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Glyphs/ReturnStatementGlyphTaggerProvider.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.Composition;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (IViewTaggerProvider))] + [ContentType ("code")] + [TagType (typeof (ReturnStatementGlyphTag))] + internal class ReturnStatementGlyphTaggerProvider : IViewTaggerProvider + { + public ITagger<T> CreateTagger<T> (ITextView textView, ITextBuffer buffer) where T : ITag + { + return new ReturnStatementGlyphTagger (buffer) as ITagger<T>; + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/DebuggerQuickInfoSource.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/DebuggerQuickInfoSource.cs new file mode 100644 index 0000000000..6a022b56d0 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/DebuggerQuickInfoSource.cs @@ -0,0 +1,109 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using MonoDevelop.Core; +using Microsoft.VisualStudio.Text.Editor; + +namespace MonoDevelop.Debugger.VSTextView.QuickInfo +{ + class DebuggerQuickInfoSource : IAsyncQuickInfoSource + { + readonly DebuggerQuickInfoSourceProvider provider; + readonly ITextBuffer textBuffer; + DebugValueWindow window; + + public DebuggerQuickInfoSource (DebuggerQuickInfoSourceProvider provider, ITextBuffer textBuffer) + { + this.provider = provider; + this.textBuffer = textBuffer; + DebuggingService.CurrentFrameChanged += CurrentFrameChanged; + DebuggingService.StoppedEvent += TargetProcessExited; + } + + void CurrentFrameChanged (object sender, EventArgs e) + { + if (window != null) { + window.Destroy (); + window = null; + } + } + + void TargetProcessExited (object sender, EventArgs e) + { + if (window == null) + return; + var debuggerSession = window.tree.Frame?.DebuggerSession; + if (debuggerSession == null || debuggerSession == sender) { + window.Destroy (); + window = null; + } + } + + public void Dispose () + { + if (window != null) + Runtime.RunInMainThread (() => { + window?.Destroy (); + window = null; + }).Ignore (); + } + + public async Task<QuickInfoItem> GetQuickInfoItemAsync (IAsyncQuickInfoSession session, CancellationToken cancellationToken) + { + Task destroyTask = null; + if (window != null) + destroyTask = Runtime.RunInMainThread (() => { + window?.Destroy (); + window = null; + }); + if (DebuggingService.CurrentFrame == null) + return null; + var view = session.TextView; + + var textViewLines = view.TextViewLines; + var snapshot = textViewLines.FormattedSpan.Snapshot; + var triggerPoint = session.GetTriggerPoint (textBuffer); + var point = triggerPoint.GetPoint (snapshot); + + foreach (var debugInfoProvider in provider.debugInfoProviders) { + var debugInfo = await debugInfoProvider.Value.GetDebugInfoAsync (point); + if (debugInfo == null || debugInfo.Text == null) { + continue; + } + + var options = DebuggingService.DebuggerSession.EvaluationOptions.Clone (); + options.AllowMethodEvaluation = true; + options.AllowTargetInvoke = true; + + var val = DebuggingService.CurrentFrame.GetExpressionValue (debugInfo.Text, options); + + if (val == null || val.IsUnknown || val.IsNotSupported) + return null; + + if (!view.Properties.TryGetProperty (typeof (Gtk.Widget), out Gtk.Widget gtkParent)) + return null; + provider.textDocumentFactoryService.TryGetTextDocument (textBuffer, out var textDocument); + + // This is a bit hacky, since AsyncQuickInfo is designed to display multiple elements if multiple sources + // return value, we don't want that for debugger value hovering, hence we dismiss AsyncQuickInfo + // and do our own thing, notice VS does same thing + await session.DismissAsync (); + if (destroyTask != null) + await destroyTask; + await provider.joinableTaskContext.Factory.SwitchToMainThreadAsync (); + val.Name = debugInfo.Text; + window = new DebugValueWindow ((Gtk.Window)gtkParent.Toplevel, textDocument?.FilePath, textBuffer.CurrentSnapshot.GetLineNumberFromPosition (debugInfo.Span.GetStartPoint (textBuffer.CurrentSnapshot)), DebuggingService.CurrentFrame, val, null); + Ide.IdeApp.CommandService.RegisterTopWindow (window); + var bounds = view.TextViewLines.GetCharacterBounds (point); + var cocoaView = ((ICocoaTextView)view); + var cgPoint = cocoaView.VisualElement.ConvertPointToView (new CoreGraphics.CGPoint (bounds.Left - view.ViewportLeft, bounds.Top - view.ViewportTop), cocoaView.VisualElement.Superview); + cgPoint.Y = cocoaView.VisualElement.Superview.Frame.Height - cgPoint.Y; + window.ShowPopup (gtkParent, new Gdk.Rectangle ((int)cgPoint.X, (int)cgPoint.Y, (int)bounds.Width, (int)bounds.Height), Components.PopupPosition.TopLeft); + return null; + } + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/DebuggerQuickInfoSourceProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/DebuggerQuickInfoSourceProvider.cs new file mode 100644 index 0000000000..4eb135299f --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/DebuggerQuickInfoSourceProvider.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Threading; +using Microsoft.VisualStudio.Utilities; + +namespace MonoDevelop.Debugger.VSTextView.QuickInfo +{ + [Export (typeof (IAsyncQuickInfoSourceProvider))] + [Name ("MonodevelopDebugger")] + [Order] + [ContentType ("any")] + class DebuggerQuickInfoSourceProvider : IAsyncQuickInfoSourceProvider + { + [ImportMany] + internal IEnumerable<Lazy<IDebugInfoProvider>> debugInfoProviders = null; + + [Import] + internal ITextDocumentFactoryService textDocumentFactoryService { get; set; } + + [Import] + internal JoinableTaskContext joinableTaskContext; + + public IAsyncQuickInfoSource TryCreateQuickInfoSource (ITextBuffer textBuffer) + { + return new DebuggerQuickInfoSource (this, textBuffer); + } + } +} diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/IDebugInfoProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/IDebugInfoProvider.cs new file mode 100644 index 0000000000..e9d41b9034 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/QuickInfo/IDebugInfoProvider.cs @@ -0,0 +1,29 @@ +using System; +using System.Threading.Tasks; +using Microsoft.VisualStudio.Text; + +namespace MonoDevelop.Debugger.VSTextView.QuickInfo +{ + public interface IDebugInfoProvider + { + Task<DataTipInfo> GetDebugInfoAsync (SnapshotPoint snapshotPoint); + } + + public class DataTipInfo + { + public readonly ITrackingSpan Span; + public readonly string Text; + + public DataTipInfo (ITrackingSpan span, string text) + { + this.Span = span; + this.Text = text; + } + + public bool IsDefault { + get { return Span == null && Text == null; } + } + + public override string ToString () => $"{Span} {Text}"; + } +} diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/AbstractBreakpointTagger.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/AbstractBreakpointTagger.cs new file mode 100644 index 0000000000..a8d09fe388 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/AbstractBreakpointTagger.cs @@ -0,0 +1,66 @@ +using System;
+using System.Collections.Generic;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+using Mono.Debugging.Client; +using MonoDevelop.Debugger;
+using MonoDevelop.Ide; + +namespace MonoDevelop.Debugger
+{ + internal abstract class AbstractBreakpointTagger<T> : ITagger<T> where T : ITag + { + private readonly ITextView textView; + private readonly T tag; + private readonly T disabled; + private readonly T invalid; + private readonly string file; + + public AbstractBreakpointTagger ( + T tag, T disabled, T invalid, ITextView textView) + { + this.textView = textView; + this.tag = tag; + this.disabled = disabled; + this.invalid = invalid; + file = this.textView.TextBuffer.GetFilePathOrNull (); + DebuggingService.Breakpoints.Changed += OnBreakpointsChanged; + this.textView.Closed += (s, e) => DebuggingService.Breakpoints.Changed -= OnBreakpointsChanged; + } + + private void OnBreakpointsChanged (object sender, EventArgs eventArgs) + { + if (TagsChanged != null) { + var snapshot = textView.TextBuffer.CurrentSnapshot; + var snapshotSpan = new SnapshotSpan (snapshot, 0, snapshot.Length); + var args = new SnapshotSpanEventArgs (snapshotSpan); + TagsChanged (this, args); + } + } + + public IEnumerable<ITagSpan<T>> GetTags (NormalizedSnapshotSpanCollection spans) + {
+ if (file == null)
+ yield break; + foreach (var breakpoint in DebuggingService.Breakpoints.GetBreakpointsAtFile (file)) {
+ var snapshot = textView.TextBuffer.CurrentSnapshot;
+ if (snapshot.LineCount <= breakpoint.Line)
+ continue;
+ var span = snapshot.GetLineFromLineNumber (breakpoint.Line - 1).Extent; + if (spans.IntersectsWith (span)) {
+ var status = DebuggingService.GetBreakpointStatus (breakpoint);
+ if (breakpoint.Enabled)
+ if (status == BreakEventStatus.Bound || status == BreakEventStatus.Disconnected) + yield return new TagSpan<T> (span, tag); + else
+ yield return new TagSpan<T> (span, invalid); + else + yield return new TagSpan<T> (span, disabled); + } + } + } + + public event System.EventHandler<SnapshotSpanEventArgs> TagsChanged; + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/AbstractCurrentStatementTagger.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/AbstractCurrentStatementTagger.cs new file mode 100644 index 0000000000..e80acf8286 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/AbstractCurrentStatementTagger.cs @@ -0,0 +1,75 @@ +using System;
+using System.Collections.Generic;
+using Microsoft.Ide.Editor;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Tagging;
+using MonoDevelop.Debugger;
+using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide;
+
+namespace MonoDevelop.Debugger
+{
+ internal class AbstractCurrentStatementTagger<T> : ITagger<T>, IDisposable + where T : ITag + { + private readonly ITextBuffer textBuffer; + private readonly T tag; + private readonly string filePath; + private readonly bool isGreen; + + public AbstractCurrentStatementTagger (T tag, ITextBuffer textBuffer, bool isGreen) + { + this.textBuffer = textBuffer; + this.filePath = textBuffer.GetFilePathOrNull (); + this.tag = tag; + this.isGreen = isGreen;
+ DebuggingService.CurrentFrameChanged += OnDebuggerCurrentStatementChanged; + } + + private void OnDebuggerCurrentStatementChanged (object sender, EventArgs eventArgs) + { + var handler = TagsChanged; + if (handler != null) { + var snapshot = textBuffer.CurrentSnapshot; + var snapshotSpan = new SnapshotSpan (snapshot, 0, snapshot.Length); + var args = new SnapshotSpanEventArgs (snapshotSpan); + handler (this, args); + } + }
+
+ public IEnumerable<ITagSpan<T>> GetTags (NormalizedSnapshotSpanCollection spans)
+ {
+ if (DebuggingService.CurrentCallStack == null)
+ yield break;
+ if (isGreen) {
+ if (DebuggingService.CurrentFrameIndex > 0) {
+ var newTag = CreateTag (DebuggingService.CurrentFrameIndex);
+ if (newTag != null && spans.IntersectsWith (newTag.Span))
+ yield return newTag;
+ }
+ } else {
+ if (DebuggingService.CurrentFrameIndex == 0) {
+ var newTag = CreateTag (0);
+ if (newTag != null && spans.IntersectsWith (newTag.Span))
+ yield return newTag;
+ }
+ }
+ }
+
+ private TagSpan<T> CreateTag (int stackIndex)
+ {
+ var sourceLocation = DebuggingService.CurrentCallStack.GetFrame (stackIndex).SourceLocation;
+ if (sourceLocation.FileName != filePath)
+ return null;
+ var span = textBuffer.CurrentSnapshot.SpanFromMDColumnAndLine (sourceLocation.Line, sourceLocation.Column, sourceLocation.EndLine, sourceLocation.EndColumn);
+ return new TagSpan<T> (span, tag);
+ }
+
+ public void Dispose ()
+ {
+ DebuggingService.CurrentFrameChanged -= OnDebuggerCurrentStatementChanged;
+ } + + public event System.EventHandler<SnapshotSpanEventArgs> TagsChanged; + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointForegroundTagger.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointForegroundTagger.cs new file mode 100644 index 0000000000..c1cd77c406 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointForegroundTagger.cs @@ -0,0 +1,17 @@ +using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+
+namespace MonoDevelop.Debugger
+{ + internal class BreakpointForegroundTagger : AbstractBreakpointTagger<ClassificationTag> + { + public BreakpointForegroundTagger ( + ClassificationTag tag,
+ ClassificationTag disabled,
+ ClassificationTag invalid, + ITextView textView) + : base (tag, disabled, invalid, textView) + { + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointForegroundTaggerProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointForegroundTaggerProvider.cs new file mode 100644 index 0000000000..859eea7658 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointForegroundTaggerProvider.cs @@ -0,0 +1,32 @@ +using System.ComponentModel.Composition;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Classification;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (IViewTaggerProvider))] + [TagType (typeof (IClassificationTag))] + [ContentType ("text")] + public class BreakpointForegroundTaggerProvider : IViewTaggerProvider + {
+ private readonly ClassificationTag tag;
+ private readonly ClassificationTag disabled;
+ private readonly ClassificationTag invalid; + + [ImportingConstructor] + public BreakpointForegroundTaggerProvider (IClassificationTypeRegistryService classificationTypeRegistryService) + {
+ tag = new ClassificationTag (classificationTypeRegistryService.GetClassificationType (ClassificationTypes.BreakpointForegroundTypeName));
+ disabled = new ClassificationTag (classificationTypeRegistryService.GetClassificationType (ClassificationTypes.BreakpointDisabledForegroundTypeName));
+ invalid = new ClassificationTag (classificationTypeRegistryService.GetClassificationType (ClassificationTypes.BreakpointInvalidForegroundTypeName)); + } + + public ITagger<T> CreateTagger<T> (ITextView textView, ITextBuffer buffer) where T : ITag + { + return new BreakpointForegroundTagger (tag, disabled, invalid, textView) as ITagger<T>; + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointMarkerDefinition.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointMarkerDefinition.cs new file mode 100644 index 0000000000..21176ceefb --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointMarkerDefinition.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.Composition;
+using System.Windows.Media;
+using Microsoft.VisualStudio.Text.Classification;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (EditorFormatDefinition))] + [Name (BreakpointTag.TagId)] + [UserVisible (true)] + [Priority (1)] // necessary to override the standard one from TextMarkerProviderFactory.cs + internal class BreakpointMarkerDefinition : MarkerFormatDefinition + { + public BreakpointMarkerDefinition () + { + this.ZOrder = 2; + this.Fill = new SolidColorBrush (Color.FromArgb (204, 150, 58, 70)); + this.Fill.Freeze (); + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointTag.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointTag.cs new file mode 100644 index 0000000000..ea29de1367 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointTag.cs @@ -0,0 +1,40 @@ +using Microsoft.VisualStudio.Text.Tagging;
+
+namespace MonoDevelop.Debugger
+{ + class BreakpointTag : TextMarkerTag + { + internal const string TagId = "breakpoint"; + + public static readonly BreakpointTag Instance = new BreakpointTag (); + + private BreakpointTag () + : base (TagId) + { + } + }
+
+ class BreakpointDisabledTag : TextMarkerTag
+ {
+ internal const string TagId = "breakpoint-disabled";
+
+ public static readonly BreakpointDisabledTag Instance = new BreakpointDisabledTag ();
+
+ private BreakpointDisabledTag ()
+ : base (TagId)
+ {
+ }
+ }
+
+ class BreakpointInvalidTag : TextMarkerTag
+ {
+ internal const string TagId = "breakpoint-invalid";
+
+ public static readonly BreakpointInvalidTag Instance = new BreakpointInvalidTag ();
+
+ private BreakpointInvalidTag ()
+ : base (TagId)
+ {
+ }
+ }
+}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointTagger.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointTagger.cs new file mode 100644 index 0000000000..62b40f8473 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointTagger.cs @@ -0,0 +1,13 @@ +using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging; + +namespace MonoDevelop.Debugger
+{ + internal class BreakpointTagger : AbstractBreakpointTagger<TextMarkerTag> + { + public BreakpointTagger (ITextView textView) + : base (BreakpointTag.Instance, BreakpointDisabledTag.Instance, BreakpointInvalidTag.Instance, textView) + { + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointTaggerProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointTaggerProvider.cs new file mode 100644 index 0000000000..410512eb78 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/BreakpointTaggerProvider.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.Composition;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (IViewTaggerProvider))] + [ContentType ("text")] + [TagType (typeof (BreakpointTag))] + [TagType (typeof (BreakpointDisabledTag))] + [TagType (typeof (BreakpointInvalidTag))] + internal class BreakpointTaggerProvider : IViewTaggerProvider + { + public ITagger<T> CreateTagger<T> (ITextView textView, ITextBuffer buffer) where T : ITag + { + return new BreakpointTagger (textView) as ITagger<T>; + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ClassificationTypes.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ClassificationTypes.cs new file mode 100644 index 0000000000..84cd73f54e --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ClassificationTypes.cs @@ -0,0 +1,118 @@ +using System.ComponentModel.Composition;
+using System.Windows.Media;
+using Microsoft.VisualStudio.Language.StandardClassification;
+using Microsoft.VisualStudio.Text.Classification;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + public class ClassificationTypes + { + public const string BreakpointForegroundTypeName = "BreakpointForeground"; + public const string BreakpointDisabledForegroundTypeName = "BreakpointDisabledForeground"; + public const string BreakpointInvalidForegroundTypeName = "BreakpointInvalidForeground"; + public const string CurrentStatementForegroundTypeName = "CurrentStatementForeground"; + public const string ReturnStatementForegroundTypeName = "ReturnStatementForeground"; + + [Export] + [Name (BreakpointForegroundTypeName)] + [BaseDefinition (PredefinedClassificationTypeNames.FormalLanguage)] + internal readonly ClassificationTypeDefinition BreakpointForegroundTypeDefinition = null; + + [Export (typeof (EditorFormatDefinition))] + [ClassificationType (ClassificationTypeNames = BreakpointForegroundTypeName)] + [Name (BreakpointForegroundTypeName + "Format")] + [Order (After = LanguagePriority.FormalLanguage, Before = Priority.High)] + [UserVisible (true)] + private sealed class BreakpointForegroundClassificationFormat + : ClassificationFormatDefinition + { + private BreakpointForegroundClassificationFormat () + { + this.DisplayName = BreakpointForegroundTypeName; + this.ForegroundColor = Colors.White; + } + } + + + [Export] + [Name (BreakpointDisabledForegroundTypeName)] + [BaseDefinition (PredefinedClassificationTypeNames.FormalLanguage)] + internal readonly ClassificationTypeDefinition BreakpointDisabledForegroundTypeDefinition = null; + + [Export (typeof (EditorFormatDefinition))] + [ClassificationType (ClassificationTypeNames = BreakpointDisabledForegroundTypeName)] + [Name (BreakpointDisabledForegroundTypeName + "Format")] + [Order (After = LanguagePriority.FormalLanguage, Before = Priority.High)] + [UserVisible (true)] + private sealed class BreakpointDisabledForegroundClassificationFormat + : ClassificationFormatDefinition + { + private BreakpointDisabledForegroundClassificationFormat () + { + this.DisplayName = BreakpointDisabledForegroundTypeName; + this.ForegroundColor = Colors.White; + } + } + + [Export] + [Name (BreakpointInvalidForegroundTypeName)] + [BaseDefinition (PredefinedClassificationTypeNames.FormalLanguage)] + internal readonly ClassificationTypeDefinition BreakpointInvalidForegroundTypeDefinition = null; + + [Export (typeof (EditorFormatDefinition))] + [ClassificationType (ClassificationTypeNames = BreakpointInvalidForegroundTypeName)] + [Name (BreakpointInvalidForegroundTypeName + "Format")] + [Order (After = LanguagePriority.FormalLanguage, Before = Priority.High)] + [UserVisible (true)] + private sealed class BreakpointInvalidForegroundClassificationFormat + : ClassificationFormatDefinition + { + private BreakpointInvalidForegroundClassificationFormat () + { + this.DisplayName = BreakpointInvalidForegroundTypeName; + this.ForegroundColor = Colors.White; + } + }
+ + [Export] + [Name (CurrentStatementForegroundTypeName)] + [BaseDefinition (PredefinedClassificationTypeNames.FormalLanguage)] + internal readonly ClassificationTypeDefinition CurrentStatementForegroundTypeDefinition = null; + + [Export (typeof (EditorFormatDefinition))] + [ClassificationType (ClassificationTypeNames = CurrentStatementForegroundTypeName)] + [Name (CurrentStatementForegroundTypeName + "Format")] + [Order (After = LanguagePriority.FormalLanguage, Before = Priority.High)] + [UserVisible (true)] + private sealed class CurrentStatementForegroundClassificationFormat + : ClassificationFormatDefinition + { + private CurrentStatementForegroundClassificationFormat () + { + this.DisplayName = CurrentStatementForegroundTypeName; + this.ForegroundColor = Colors.Black; + } + } + + [Export] + [Name (ReturnStatementForegroundTypeName)] + [BaseDefinition (PredefinedClassificationTypeNames.FormalLanguage)] + internal readonly ClassificationTypeDefinition ReturnStatementForegroundTypeDefinition = null; + + [Export (typeof (EditorFormatDefinition))] + [ClassificationType (ClassificationTypeNames = ReturnStatementForegroundTypeName)] + [Name (ReturnStatementForegroundTypeName + "Format")] + [Order (After = LanguagePriority.FormalLanguage, Before = Priority.High)] + [UserVisible (true)] + private sealed class ReturnStatementForegroundClassificationFormat + : ClassificationFormatDefinition + { + private ReturnStatementForegroundClassificationFormat () + { + this.DisplayName = ReturnStatementForegroundTypeName; + this.ForegroundColor = Colors.Black; + } + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementForegroundTagger.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementForegroundTagger.cs new file mode 100644 index 0000000000..124b48f806 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementForegroundTagger.cs @@ -0,0 +1,16 @@ +using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Tagging;
+
+namespace MonoDevelop.Debugger
+{ + internal class CurrentStatementForegroundTagger : AbstractCurrentStatementTagger<ClassificationTag> + { + public CurrentStatementForegroundTagger ( + ClassificationTag tag, + ITextBuffer textBuffer, + bool isGreen) + : base (tag, textBuffer, isGreen) + { + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementForegroundTaggerProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementForegroundTaggerProvider.cs new file mode 100644 index 0000000000..655582c63d --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementForegroundTaggerProvider.cs @@ -0,0 +1,32 @@ +using System.ComponentModel.Composition;
+using Microsoft.Ide.Editor;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Classification;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (ITaggerProvider))] + [TagType (typeof (IClassificationTag))] + [ContentType ("text")] + public class CurrentStatementForegroundTaggerProvider : ITaggerProvider + { + private readonly IClassificationTypeRegistryService classificationTypeRegistryService; + private readonly IClassificationType classificationType; + private readonly ClassificationTag tag; + + [ImportingConstructor] + public CurrentStatementForegroundTaggerProvider (IClassificationTypeRegistryService classificationTypeRegistryService) + { + this.classificationTypeRegistryService = classificationTypeRegistryService; + this.classificationType = classificationTypeRegistryService.GetClassificationType (ClassificationTypes.CurrentStatementForegroundTypeName); + this.tag = new ClassificationTag (classificationType); + } + + public ITagger<T> CreateTagger<T> (ITextBuffer buffer) where T : ITag + { + return new CurrentStatementForegroundTagger (tag, buffer, isGreen: false) as ITagger<T>; + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementMarkerDefinition.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementMarkerDefinition.cs new file mode 100644 index 0000000000..f0adbc69bc --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementMarkerDefinition.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.Composition;
+using System.Windows.Media;
+using Microsoft.VisualStudio.Text.Classification;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (EditorFormatDefinition))] + [Name (CurrentStatementTag.TagId)] + [UserVisible (true)] + [Priority (1)] + internal class CurrentStatementMarkerDefinition : MarkerFormatDefinition + { + public CurrentStatementMarkerDefinition () + { + this.ZOrder = 3; + this.Fill = new SolidColorBrush (Color.FromArgb (255, 255, 238, 98)); + this.Fill.Freeze (); + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementTag.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementTag.cs new file mode 100644 index 0000000000..857b89c678 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementTag.cs @@ -0,0 +1,16 @@ +using Microsoft.VisualStudio.Text.Tagging;
+
+namespace MonoDevelop.Debugger
+{ + internal class CurrentStatementTag : TextMarkerTag + { + internal const string TagId = "currentstatement"; + + public static readonly CurrentStatementTag Instance = new CurrentStatementTag (); + + private CurrentStatementTag () + : base (TagId) + { + } + }
+}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementTagger.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementTagger.cs new file mode 100644 index 0000000000..bab3493fe9 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementTagger.cs @@ -0,0 +1,12 @@ +using Microsoft.VisualStudio.Text;
+
+namespace MonoDevelop.Debugger
+{ + internal class CurrentStatementTagger : AbstractCurrentStatementTagger<CurrentStatementTag> + { + public CurrentStatementTagger (ITextBuffer textBuffer) + : base (CurrentStatementTag.Instance, textBuffer, isGreen: false) + { + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementTaggerProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementTaggerProvider.cs new file mode 100644 index 0000000000..ad385fa208 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/CurrentStatementTaggerProvider.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.Composition;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (IViewTaggerProvider))] + [ContentType ("text")] + [TagType (typeof (CurrentStatementTag))] + internal class CurrentStatementTaggerProvider : IViewTaggerProvider + { + public ITagger<T> CreateTagger<T> (ITextView textView, ITextBuffer buffer) where T : ITag + { + return new CurrentStatementTagger (buffer) as ITagger<T>; + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementForegroundTaggerProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementForegroundTaggerProvider.cs new file mode 100644 index 0000000000..5809d218a2 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementForegroundTaggerProvider.cs @@ -0,0 +1,31 @@ +using System.ComponentModel.Composition;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Classification;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (ITaggerProvider))] + [TagType (typeof (IClassificationTag))] + [ContentType ("text")] + public class ReturnStatementForegroundTaggerProvider : ITaggerProvider + { + private readonly IClassificationTypeRegistryService classificationTypeRegistryService; + private readonly IClassificationType classificationType; + private readonly ClassificationTag tag; + + [ImportingConstructor] + public ReturnStatementForegroundTaggerProvider (IClassificationTypeRegistryService classificationTypeRegistryService) + { + this.classificationTypeRegistryService = classificationTypeRegistryService; + this.classificationType = classificationTypeRegistryService.GetClassificationType (ClassificationTypes.ReturnStatementForegroundTypeName); + this.tag = new ClassificationTag (classificationType); + } + + public ITagger<T> CreateTagger<T> (ITextBuffer buffer) where T : ITag + { + return new CurrentStatementForegroundTagger (tag, buffer, isGreen: true) as ITagger<T>; + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementMarkerDefinition.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementMarkerDefinition.cs new file mode 100644 index 0000000000..f978353661 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementMarkerDefinition.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.Composition;
+using System.Windows.Media;
+using Microsoft.VisualStudio.Text.Classification;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (EditorFormatDefinition))] + [Name (ReturnStatementTag.TagId)] + [UserVisible (true)] + [Priority (1)] + internal class ReturnStatementMarkerDefinition : MarkerFormatDefinition + { + public ReturnStatementMarkerDefinition () + { + this.ZOrder = 4; + this.Fill = new SolidColorBrush (Color.FromArgb (255, 180, 228, 180)); + this.Fill.Freeze (); + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementTag.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementTag.cs new file mode 100644 index 0000000000..ca2ac54eb9 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementTag.cs @@ -0,0 +1,16 @@ +using Microsoft.VisualStudio.Text.Tagging;
+
+namespace MonoDevelop.Debugger
+{ + internal class ReturnStatementTag : TextMarkerTag + { + internal const string TagId = "returnstatement"; + + public static readonly ReturnStatementTag Instance = new ReturnStatementTag (); + + private ReturnStatementTag () + : base (TagId) + { + } + }
+}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementTagger.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementTagger.cs new file mode 100644 index 0000000000..f2d1e94149 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementTagger.cs @@ -0,0 +1,12 @@ +using Microsoft.VisualStudio.Text;
+
+namespace MonoDevelop.Debugger
+{ + internal class ReturnStatementTagger : AbstractCurrentStatementTagger<ReturnStatementTag> + { + public ReturnStatementTagger (ITextBuffer textBuffer) + : base (ReturnStatementTag.Instance, textBuffer, isGreen: true) + { + } + }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementTaggerProvider.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementTaggerProvider.cs new file mode 100644 index 0000000000..e5ac8feb86 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/Tags/ReturnStatementTaggerProvider.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.Composition;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Utilities;
+
+namespace MonoDevelop.Debugger
+{ + [Export (typeof (IViewTaggerProvider))] + [ContentType ("text")] + [TagType (typeof (ReturnStatementTag))] + internal class ReturnStatementTaggerProvider : IViewTaggerProvider + { + public ITagger<T> CreateTagger<T> (ITextView textView, ITextBuffer buffer) where T : ITag + { + return new ReturnStatementTagger (buffer) as ITagger<T>; + } + }
+}
|