145 lines
4.5 KiB
C#
145 lines
4.5 KiB
C#
// <file>
|
|
// <copyright see="prj:///doc/copyright.txt"/>
|
|
// <license see="prj:///doc/license.txt"/>
|
|
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
|
|
// <version>$Revision$</version>
|
|
// </file>
|
|
|
|
using System;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
|
|
using ICSharpCode.TextEditor.Document;
|
|
|
|
namespace ICSharpCode.TextEditor
|
|
{
|
|
public class TextAreaDragDropHandler
|
|
{
|
|
public static Action<Exception> OnDragDropException = ex => MessageBox.Show(ex.ToString());
|
|
|
|
TextArea textArea;
|
|
|
|
public void Attach(TextArea textArea)
|
|
{
|
|
this.textArea = textArea;
|
|
textArea.AllowDrop = true;
|
|
|
|
textArea.DragEnter += MakeDragEventHandler(OnDragEnter);
|
|
textArea.DragDrop += MakeDragEventHandler(OnDragDrop);
|
|
textArea.DragOver += MakeDragEventHandler(OnDragOver);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a drag'n'drop event handler.
|
|
/// Windows Forms swallows unhandled exceptions during drag'n'drop, so we report them here.
|
|
/// </summary>
|
|
static DragEventHandler MakeDragEventHandler(DragEventHandler h)
|
|
{
|
|
return (sender, e) => {
|
|
try {
|
|
h(sender, e);
|
|
} catch (Exception ex) {
|
|
OnDragDropException(ex);
|
|
}
|
|
};
|
|
}
|
|
|
|
static DragDropEffects GetDragDropEffect(DragEventArgs e)
|
|
{
|
|
if ((e.AllowedEffect & DragDropEffects.Move) > 0 &&
|
|
(e.AllowedEffect & DragDropEffects.Copy) > 0) {
|
|
return (e.KeyState & 8) > 0 ? DragDropEffects.Copy : DragDropEffects.Move;
|
|
} else if ((e.AllowedEffect & DragDropEffects.Move) > 0) {
|
|
return DragDropEffects.Move;
|
|
} else if ((e.AllowedEffect & DragDropEffects.Copy) > 0) {
|
|
return DragDropEffects.Copy;
|
|
}
|
|
return DragDropEffects.None;
|
|
}
|
|
|
|
protected void OnDragEnter(object sender, DragEventArgs e)
|
|
{
|
|
if (e.Data.GetDataPresent(typeof(string))) {
|
|
e.Effect = GetDragDropEffect(e);
|
|
}
|
|
}
|
|
|
|
|
|
void InsertString(int offset, string str)
|
|
{
|
|
textArea.Document.Insert(offset, str);
|
|
|
|
textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document,
|
|
textArea.Document.OffsetToPosition(offset),
|
|
textArea.Document.OffsetToPosition(offset + str.Length)));
|
|
textArea.Caret.Position = textArea.Document.OffsetToPosition(offset + str.Length);
|
|
textArea.Refresh();
|
|
}
|
|
|
|
protected void OnDragDrop(object sender, DragEventArgs e)
|
|
{
|
|
Point p = textArea.PointToClient(new Point(e.X, e.Y));
|
|
|
|
if (e.Data.GetDataPresent(typeof(string))) {
|
|
textArea.BeginUpdate();
|
|
textArea.Document.UndoStack.StartUndoGroup();
|
|
try {
|
|
int offset = textArea.Caret.Offset;
|
|
if (textArea.IsReadOnly(offset)) {
|
|
// prevent dragging text into readonly section
|
|
return;
|
|
}
|
|
if (e.Data.GetDataPresent(typeof(DefaultSelection))) {
|
|
ISelection sel = (ISelection)e.Data.GetData(typeof(DefaultSelection));
|
|
if (sel.ContainsPosition(textArea.Caret.Position)) {
|
|
return;
|
|
}
|
|
if (GetDragDropEffect(e) == DragDropEffects.Move) {
|
|
if (SelectionManager.SelectionIsReadOnly(textArea.Document, sel)) {
|
|
// prevent dragging text out of readonly section
|
|
return;
|
|
}
|
|
int len = sel.Length;
|
|
textArea.Document.Remove(sel.Offset, len);
|
|
if (sel.Offset < offset) {
|
|
offset -= len;
|
|
}
|
|
}
|
|
}
|
|
textArea.SelectionManager.ClearSelection();
|
|
InsertString(offset, (string)e.Data.GetData(typeof(string)));
|
|
textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea));
|
|
} finally {
|
|
textArea.Document.UndoStack.EndUndoGroup();
|
|
textArea.EndUpdate();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void OnDragOver(object sender, DragEventArgs e)
|
|
{
|
|
if (!textArea.Focused) {
|
|
textArea.Focus();
|
|
}
|
|
|
|
Point p = textArea.PointToClient(new Point(e.X, e.Y));
|
|
|
|
if (textArea.TextView.DrawingPosition.Contains(p.X, p.Y)) {
|
|
TextLocation realmousepos= textArea.TextView.GetLogicalPosition(p.X - textArea.TextView.DrawingPosition.X,
|
|
p.Y - textArea.TextView.DrawingPosition.Y);
|
|
int lineNr = Math.Min(textArea.Document.TotalNumberOfLines - 1, Math.Max(0, realmousepos.Y));
|
|
|
|
textArea.Caret.Position = new TextLocation(realmousepos.X, lineNr);
|
|
textArea.SetDesiredColumn();
|
|
if (e.Data.GetDataPresent(typeof(string)) && !textArea.IsReadOnly(textArea.Caret.Offset)) {
|
|
e.Effect = GetDragDropEffect(e);
|
|
} else {
|
|
e.Effect = DragDropEffects.None;
|
|
}
|
|
} else {
|
|
e.Effect = DragDropEffects.None;
|
|
}
|
|
}
|
|
}
|
|
}
|