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