From 1123bf827822358d5c2b0b73f2a26f13850070ed Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 26 Sep 2010 18:38:27 +0200 Subject: [PATCH] Allow dragging the CurrentLineBookmark in the IconBarMargin. --- .../AvalonEdit.AddIn/Src/IconBarMargin.cs | 128 +++++++++++++++--- .../Project/Src/Bookmarks/BookmarkBase.cs | 12 ++ .../Src/Bookmarks/ClassMemberBookmark.cs | 26 ++++ .../Project/Src/Bookmarks/IBookmarkMargin.cs | 15 ++ .../Services/Debugger/CurrentLineBookmark.cs | 14 ++ 5 files changed, 178 insertions(+), 17 deletions(-) diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/IconBarMargin.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/IconBarMargin.cs index 6c5f569a018..940db01918d 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/IconBarMargin.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/IconBarMargin.cs @@ -88,32 +88,40 @@ protected override void OnRender(DrawingContext drawingContext) IBookmark bm; if (bookmarkDict.TryGetValue(lineNumber, out bm)) { Rect rect = new Rect(0, PixelSnapHelpers.Round(line.VisualTop - textView.VerticalOffset, pixelSize.Height), 16, 16); + if (dragDropBookmark == bm && dragStarted) + drawingContext.PushOpacity(0.5); drawingContext.DrawImage((bm.Image ?? BookmarkBase.DefaultBookmarkImage).ImageSource, rect); + if (dragDropBookmark == bm && dragStarted) + drawingContext.Pop(); } } + if (dragDropBookmark != null && dragStarted) { + Rect rect = new Rect(0, PixelSnapHelpers.Round(dragDropCurrentPoint - 8, pixelSize.Height), 16, 16); + drawingContext.DrawImage((dragDropBookmark.Image ?? BookmarkBase.DefaultBookmarkImage).ImageSource, rect); + } } } + IBookmark dragDropBookmark; // bookmark being dragged (!=null if drag'n'drop is active) + double dragDropStartPoint; + double dragDropCurrentPoint; + bool dragStarted; // whether drag'n'drop operation has started (mouse was moved minimum distance) + protected override void OnMouseDown(MouseButtonEventArgs e) { + CancelDragDrop(); base.OnMouseDown(e); - TextView textView = this.TextView; - if (!e.Handled && textView != null) { - VisualLine visualLine = textView.GetVisualLineFromVisualTop(e.GetPosition(textView).Y + textView.VerticalOffset); - if (visualLine != null) { - int line = visualLine.FirstDocumentLine.LineNumber; - foreach (IBookmark bm in manager.Bookmarks) { - if (bm.LineNumber == line) { - bm.MouseDown(e); - if (e.Handled) - return; - } - } - if (e.ChangedButton == MouseButton.Left) { - // no bookmark on the line: create a new breakpoint - ITextEditor textEditor = textView.Services.GetService(typeof(ITextEditor)) as ITextEditor; - if (textEditor != null) { - ICSharpCode.SharpDevelop.Debugging.DebuggerService.ToggleBreakpointAt(textEditor, line); + int line = GetLineFromMousePosition(e); + if (!e.Handled && line > 0) { + foreach (IBookmark bm in manager.Bookmarks) { + if (bm.LineNumber == line) { + bm.MouseDown(e); + if (e.Handled) + return; + if (e.ChangedButton == MouseButton.Left && bm.CanDragDrop && CaptureMouse()) { + StartDragDrop(bm, e); + e.Handled = true; + return; } } } @@ -122,5 +130,91 @@ protected override void OnMouseDown(MouseButtonEventArgs e) if (e.ChangedButton == MouseButton.Left) e.Handled = true; } + + protected override void OnLostMouseCapture(MouseEventArgs e) + { + CancelDragDrop(); + base.OnLostMouseCapture(e); + } + + void StartDragDrop(IBookmark bm, MouseEventArgs e) + { + dragDropBookmark = bm; + dragDropStartPoint = dragDropCurrentPoint = e.GetPosition(this).Y; + if (TextView != null) + TextView.PreviewKeyDown += TextView_PreviewKeyDown; + } + + void CancelDragDrop() + { + if (dragDropBookmark != null) { + dragDropBookmark = null; + dragStarted = false; + if (TextView != null) + TextView.PreviewKeyDown -= TextView_PreviewKeyDown; + ReleaseMouseCapture(); + InvalidateVisual(); + } + } + + void TextView_PreviewKeyDown(object sender, KeyEventArgs e) + { + // any key press cancels drag'n'drop + CancelDragDrop(); + if (e.Key == Key.Escape) + e.Handled = true; + } + + int GetLineFromMousePosition(MouseEventArgs e) + { + TextView textView = this.TextView; + if (textView == null) + return 0; + VisualLine vl = textView.GetVisualLineFromVisualTop(e.GetPosition(textView).Y + textView.ScrollOffset.Y); + if (vl == null) + return 0; + return vl.FirstDocumentLine.LineNumber; + } + + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); + if (dragDropBookmark != null) { + dragDropCurrentPoint = e.GetPosition(this).Y; + if (Math.Abs(dragDropCurrentPoint - dragDropStartPoint) > SystemParameters.MinimumVerticalDragDistance) + dragStarted = true; + InvalidateVisual(); + } + } + + protected override void OnMouseUp(MouseButtonEventArgs e) + { + base.OnMouseUp(e); + int line = GetLineFromMousePosition(e); + if (!e.Handled && dragDropBookmark != null) { + if (dragStarted) { + if (line != 0) + dragDropBookmark.Drop(line); + e.Handled = true; + } + CancelDragDrop(); + } + if (!e.Handled && line != 0) { + foreach (IBookmark bm in manager.Bookmarks) { + if (bm.LineNumber == line) { + bm.MouseUp(e); + if (e.Handled) + return; + } + } + if (e.ChangedButton == MouseButton.Left && TextView != null) { + // no bookmark on the line: create a new breakpoint + ITextEditor textEditor = TextView.Services.GetService(typeof(ITextEditor)) as ITextEditor; + if (textEditor != null) { + ICSharpCode.SharpDevelop.Debugging.DebuggerService.ToggleBreakpointAt(textEditor, line); + } + } + } + } } } diff --git a/src/Main/Base/Project/Src/Bookmarks/BookmarkBase.cs b/src/Main/Base/Project/Src/Bookmarks/BookmarkBase.cs index 9451b57d527..dfcaf720fc5 100644 --- a/src/Main/Base/Project/Src/Bookmarks/BookmarkBase.cs +++ b/src/Main/Base/Project/Src/Bookmarks/BookmarkBase.cs @@ -149,11 +149,23 @@ public BookmarkBase(Location location) } public virtual void MouseDown(MouseButtonEventArgs e) + { + } + + public virtual void MouseUp(MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Left && CanToggle) { RemoveMark(); e.Handled = true; } } + + public virtual bool CanDragDrop { + get { return false; } + } + + public virtual void Drop(int lineNumber) + { + } } } diff --git a/src/Main/Base/Project/Src/Bookmarks/ClassMemberBookmark.cs b/src/Main/Base/Project/Src/Bookmarks/ClassMemberBookmark.cs index c960b9f58c6..b0e28b445ed 100644 --- a/src/Main/Base/Project/Src/Bookmarks/ClassMemberBookmark.cs +++ b/src/Main/Base/Project/Src/Bookmarks/ClassMemberBookmark.cs @@ -49,6 +49,19 @@ public virtual void MouseDown(MouseButtonEventArgs e) e.Handled = true; } } + + public virtual void MouseUp(MouseButtonEventArgs e) + { + } + + bool IBookmark.CanDragDrop { + get { return false; } + } + + void IBookmark.Drop(int lineNumber) + { + throw new NotSupportedException(); + } } public class ClassBookmark : IBookmark @@ -90,5 +103,18 @@ public virtual void MouseDown(MouseButtonEventArgs e) e.Handled = true; } } + + public virtual void MouseUp(MouseButtonEventArgs e) + { + } + + bool IBookmark.CanDragDrop { + get { return false; } + } + + void IBookmark.Drop(int lineNumber) + { + throw new NotSupportedException(); + } } } diff --git a/src/Main/Base/Project/Src/Bookmarks/IBookmarkMargin.cs b/src/Main/Base/Project/Src/Bookmarks/IBookmarkMargin.cs index 52afc0fdb95..331d0ce1958 100644 --- a/src/Main/Base/Project/Src/Bookmarks/IBookmarkMargin.cs +++ b/src/Main/Base/Project/Src/Bookmarks/IBookmarkMargin.cs @@ -42,5 +42,20 @@ public interface IBookmark /// Handles the mouse down event. /// void MouseDown(MouseButtonEventArgs e); + + /// + /// Handles the mouse up event. + /// + void MouseUp(MouseButtonEventArgs e); + + /// + /// Gets whether this bookmark can be dragged around. + /// + bool CanDragDrop { get; } + + /// + /// Notifies the bookmark that it was dropped on the specified line. + /// + void Drop(int lineNumber); } } diff --git a/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs b/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs index 1f15ce007b6..1bbee51ee2a 100644 --- a/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs +++ b/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs @@ -88,5 +88,19 @@ protected override ITextMarker CreateMarker(ITextMarkerService markerService) marker.ForegroundColor = Colors.Blue; return marker; } + + public override bool CanDragDrop { + get { return true; } + } + + public override void Drop(int lineNumber) + { + // call async because the Debugger seems to use Application.DoEvents(), but we don't want to process events + // because Drag'N'Drop operation has finished + WorkbenchSingleton.SafeThreadAsyncCall( + delegate { + DebuggerService.CurrentDebugger.SetInstructionPointer(this.FileName, lineNumber, 1); + }); + } } }