Skip to content

Commit

Permalink
Merge pull request #2288 from cwensley/curtis/drag-end
Browse files Browse the repository at this point in the history
Add Control.DragEnd event
  • Loading branch information
cwensley committed Aug 24, 2022
2 parents d51f5e4 + 9712ee5 commit bb66855
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/Eto.Gtk/Forms/Controls/GridViewHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ protected class GridViewConnector : GridConnector

public new GridViewHandler Handler { get { return (GridViewHandler)base.Handler; } }

protected override DragEventArgs GetDragEventArgs(Gdk.DragContext context, PointF? location, uint time = 0, object controlObject = null)
protected override DragEventArgs GetDragEventArgs(Gdk.DragContext context, PointF? location, uint time = 0, object controlObject = null, DataObject data = null)
{
var t = Handler?.Control;
GridViewDragInfo dragInfo = _dragInfo;
Expand All @@ -264,7 +264,7 @@ protected override DragEventArgs GetDragEventArgs(Gdk.DragContext context, Point
}
}

return base.GetDragEventArgs(context, location, time, dragInfo);
return base.GetDragEventArgs(context, location, time, dragInfo, data);
}

public override void HandleDragMotion(object o, Gtk.DragMotionArgs args)
Expand Down
4 changes: 2 additions & 2 deletions src/Eto.Gtk/Forms/Controls/TreeGridViewHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ public void HandleRowActivated(object o, Gtk.RowActivatedArgs args)
Handler?.Callback.OnActivated(Handler.Widget, new TreeGridViewItemEventArgs(Handler.model.GetItemAtPath(args.Path)));
}

protected override DragEventArgs GetDragEventArgs(Gdk.DragContext context, PointF? location, uint time = 0, object controlObject = null)
protected override DragEventArgs GetDragEventArgs(Gdk.DragContext context, PointF? location, uint time = 0, object controlObject = null, DataObject data = null)
{
var h = Handler;
var t = h?.Control;
Expand All @@ -298,7 +298,7 @@ protected override DragEventArgs GetDragEventArgs(Gdk.DragContext context, Point
}
}

return base.GetDragEventArgs(context, location, time, dragInfo);
return base.GetDragEventArgs(context, location, time, dragInfo, data);
}

public override void HandleDragMotion(object o, Gtk.DragMotionArgs args)
Expand Down
29 changes: 27 additions & 2 deletions src/Eto.Gtk/Forms/GtkControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ static class GtkControl
public static readonly object ScrollAmount_Key = new object();
public static readonly object DragInfo_Key = new object();
public static readonly object DropSource_Key = new object();
public static readonly object DropSourceData_Key = new object();
public static readonly object Font_Key = new object();
public static readonly object TabIndex_Key = new object();
public static readonly object Cursor_Key = new object();
Expand Down Expand Up @@ -455,6 +456,9 @@ public override void AttachEvent(string id)
HandleEvent(Eto.Forms.Control.DragOverEvent);
DragControl.DragLeave += Connector.HandleDragLeave;
break;
case Eto.Forms.Control.DragEndEvent:
DragControl.DragEnd += Connector.HandleDragEnd;
break;
case Eto.Forms.Control.EnabledChangedEvent:
#if GTK3
ContainerControl.StateFlagsChanged += Connector.HandleStateFlagsChangedForEnabled;
Expand Down Expand Up @@ -720,7 +724,7 @@ public virtual void MappedEvent(object sender, EventArgs e)
Handler?.Callback.OnShown(Handler.Widget, EventArgs.Empty);
}

protected virtual DragEventArgs GetDragEventArgs(Gdk.DragContext context, PointF? location, uint time = 0, object controlObject = null)
protected virtual DragEventArgs GetDragEventArgs(Gdk.DragContext context, PointF? location = null, uint time = 0, object controlObject = null, DataObject data = null)
{
var widget = Gtk.Drag.GetSourceWidget(context);
var source = widget?.Data[GtkControl.DropSource_Key] as Eto.Forms.Control;
Expand All @@ -731,7 +735,7 @@ protected virtual DragEventArgs GetDragEventArgs(Gdk.DragContext context, PointF
var action = context.SelectedAction;
#endif

var data = new DataObject(new DataObjectHandler(Handler.DragControl, context, time));
data = data ?? new DataObject(new DataObjectHandler(Handler.DragControl, context, time));
if (location == null)
location = Handler.PointFromScreen(Mouse.Position);

Expand Down Expand Up @@ -809,6 +813,23 @@ public virtual void HandleDragLeave(object o, Gtk.DragLeaveArgs args)
Eto.Forms.Application.Instance.AsyncInvoke(() => DragArgs = null);
}

public virtual void HandleDragEnd(object o, Gtk.DragEndArgs args)
{
var handler = Handler;
if (handler == null)
return;
var data = handler.DragControl.Data[GtkControl.DropSourceData_Key] as DataObject;

var e = GetDragEventArgs(args.Context, data: data);
#if GTK2
e.Effects = args.Context.Action.ToEto();
#else
e.Effects = args.Context.SelectedAction.ToEto();
#endif
handler.Callback.OnDragEnd(handler.Widget, e);
handler.DragControl.Data[GtkControl.DropSourceData_Key] = null;
}

#if GTK3
public virtual void HandleStateFlagsChangedForEnabled(object o, Gtk.StateFlagsChangedArgs args)
{
Expand Down Expand Up @@ -971,6 +992,10 @@ public void DoDragDrop(DataObject data, DragEffects allowedEffects, Image image,
DragInfo = new DragInfoObject { Data = data, AllowedEffects = allowedEffects };

DragControl.Data[GtkControl.DropSource_Key] = Widget;

// set data and ensure it gets cleared out.
DragControl.Data[GtkControl.DropSourceData_Key] = data;
HandleEvent(Eto.Forms.Control.DragEndEvent);

#if GTKCORE
var context = Gtk.Drag.BeginWithCoordinates(DragControl, targets, allowedEffects.ToGdk(), 1, Gtk.Application.CurrentEvent, -1, -1);
Expand Down
5 changes: 4 additions & 1 deletion src/Eto.Mac/Forms/Controls/GridHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ class GridDragInfo
public NSDragOperation AllowedOperation { get; set; }
public NSImage DragImage { get; set; }
public PointF ImageOffset { get; set; }

public DataObject Data { get; set; }

public CGPoint GetDragImageOffset()
{
Expand Down Expand Up @@ -722,7 +724,8 @@ public override void DoDragDrop(DataObject data, DragEffects allowedAction, Imag
{
AllowedOperation = allowedAction.ToNS(),
DragImage = image.ToNS(),
ImageOffset = origin
ImageOffset = origin,
Data = data
};
}
else
Expand Down
6 changes: 6 additions & 0 deletions src/Eto.Mac/Forms/Controls/GridViewHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,12 @@ public override void DraggingSessionEnded(NSTableView tableView, NSDraggingSessi
h.CustomSelectedRows = null;
h.Callback.OnSelectionChanged(h.Widget, EventArgs.Empty);
}

var allowedOperation = h.DragInfo?.AllowedOperation ?? NSDragOperation.None;
var data = h.DragInfo?.Data;
var args = new DragEventArgs(h.Widget, data, allowedOperation.ToEto(), endedAtScreenPoint.ToEto(h.ContainerControl), Keyboard.Modifiers, Mouse.Buttons);
args.Effects = operation.ToEto();
h.Callback.OnDragEnd(h.Widget, args);
}

public override bool WriteRows(NSTableView tableView, NSIndexSet rowIndexes, NSPasteboard pboard)
Expand Down
6 changes: 6 additions & 0 deletions src/Eto.Mac/Forms/Controls/TreeGridViewHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,12 @@ public override void DraggingSessionEnded(NSOutlineView outlineView, NSDraggingS
h.CustomSelectedItems = null;
h.Callback.OnSelectionChanged(h.Widget, EventArgs.Empty);
}

var allowedOperation = h.DragInfo?.AllowedOperation ?? NSDragOperation.None;
var data = h.DragInfo?.Data;
var args = new DragEventArgs(h.Widget, data, allowedOperation.ToEto(), screenPoint.ToEto(h.ContainerControl), Keyboard.Modifiers, Mouse.Buttons);
args.Effects = operation.ToEto();
h.Callback.OnDragEnd(h.Widget, args);
}

public override bool OutlineViewwriteItemstoPasteboard(NSOutlineView outlineView, NSArray items, NSPasteboard pboard)
Expand Down
16 changes: 15 additions & 1 deletion src/Eto.Mac/Forms/EtoDragSource.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System;

using Eto.Forms;

namespace Eto.Mac.Forms
{
class EtoDragSource : NSDraggingSource
{
public DataObject Data { get; set; }
public IMacViewHandler Handler { get; set; }

[Export("sourceView")]
public NSView SourceView { get; set; }

Expand All @@ -16,5 +19,16 @@ public NSDragOperation DraggingSessionSourceOperationMask(NSDraggingSession sess
{
return AllowedOperation;
}

[Export("draggingSession:endedAtPoint:operation:")]
public void DraggingSessionEnded(NSDraggingSession session, CGPoint point, NSDragOperation operation)
{
var h = Handler;
if (h == null)
return;
var args = new DragEventArgs(h.Widget, Data, AllowedOperation.ToEto(), point.ToEto(), Keyboard.Modifiers, Mouse.Buttons, this);
args.Effects = operation.ToEto();
h.Callback.OnDragEnd(h.Widget, args);
}
}
}
5 changes: 4 additions & 1 deletion src/Eto.Mac/Forms/MacView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,9 @@ public override void AttachEvent(string id)
case Eto.Forms.Control.DragLeaveEvent:
AddMethod(MacView.selDraggingExited, MacView.TriggerDraggingExited_Delegate, "v@:@", DragControl);
break;
case Eto.Forms.Control.DragEndEvent:
// handled in EtoDragSource, TreeGridViewHandler.EtoDragSource, and GridViewHandler.EtoDragSource
break;
default:
base.AttachEvent(id);
break;
Expand Down Expand Up @@ -1268,7 +1271,7 @@ public virtual void DoDragDrop(DataObject data, DragEffects allowedAction, Image
{
var handler = data.Handler as IDataObjectHandler;

var source = new EtoDragSource { AllowedOperation = allowedAction.ToNS(), SourceView = ContainerControl };
var source = new EtoDragSource { AllowedOperation = allowedAction.ToNS(), SourceView = ContainerControl, Handler = this, Data = data };

NSDraggingItem[] draggingItems = null;
if (image != null)
Expand Down
7 changes: 6 additions & 1 deletion src/Eto.Mac/MacConversions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,12 @@ public static NSBorderType ToNS(this BorderType border)
}
}

public static DataObject ToEto(this NSPasteboard pasteboard) => new DataObject(new DataObjectHandler(pasteboard));
public static DataObject ToEto(this NSPasteboard pasteboard)
{
if (pasteboard == null)
return null;
return new DataObject(new DataObjectHandler(pasteboard));
}

public static NSPasteboard ToNS(this DataObject data) => DataObjectHandler.GetControl(data);

Expand Down
16 changes: 13 additions & 3 deletions src/Eto.WinForms/Forms/WindowsControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,9 @@ public override void AttachEvent(string id)
Callback.OnDragLeave(Widget, new DragEventArgs(null, new DataObject(), DragEffects.None, PointF.Empty, Keys.None, MouseButtons.None));
};
break;
case Eto.Forms.Control.DragEndEvent:
// Handled in DoDragDrop as it is blocking on Windows.
break;
case Eto.Forms.Control.EnabledChangedEvent:
Control.EnabledChanged += Control_EnabledChanged;
break;
Expand All @@ -496,7 +499,9 @@ DragEventArgs GetDragEventArgs(swf.DragEventArgs data)
var modifiers = data.GetEtoModifiers();
var buttons = data.GetEtoButtons();
var location = PointFromScreen(new PointF(data.X, data.Y));
return new SwfDragEventArgs(source, dragData, data.AllowedEffect.ToEto(), location, modifiers, buttons);
var args = new SwfDragEventArgs(source, dragData, data.AllowedEffect.ToEto(), location, modifiers, buttons);
args.Effects = data.Effect.ToEto();
return args;
}

void HandleMouseWheel(object sender, swf.MouseEventArgs e)
Expand Down Expand Up @@ -1000,6 +1005,7 @@ public void DoDragDrop(DataObject data, DragEffects allowedEffects, Image image,
{
var dataObject = data.ToSwf();
WindowsControl.DragSourceControl = Widget;
swf.DragDropEffects effects;
if (UseShellDropManager)
{
swf.DragSourceHelper.AllowDropDescription(true);
Expand All @@ -1010,17 +1016,21 @@ public void DoDragDrop(DataObject data, DragEffects allowedEffects, Image image,

swf.SwfDataObjectExtensions.SetDragImage(dataObject, image.ToSD(), cursorOffset.ToSDPoint());
swf.DragSourceHelper.RegisterDefaultDragSource(Control, dataObject);
Control.DoDragDrop(dataObject, allowedEffects.ToSwf());
effects = Control.DoDragDrop(dataObject, allowedEffects.ToSwf());
swf.DragSourceHelper.UnregisterDefaultDragSource(Control);
}
else
{
if (image != null)
Debug.WriteLine("DoDragDrop cannot show drag image when UseShellDropManager is false");

Control.DoDragDrop(dataObject, allowedEffects.ToSwf());
effects = Control.DoDragDrop(dataObject, allowedEffects.ToSwf());
}
WindowsControl.DragSourceControl = null;

var args = new DragEventArgs(Widget, data, allowedEffects, PointFromScreen(Mouse.Position), Keyboard.Modifiers, Mouse.Buttons);
args.Effects = effects.ToEto();
Callback.OnDragEnd(Widget, args);
}

public Window GetNativeParentWindow() => ContainerControl.FindForm().ToEtoWindow();
Expand Down
9 changes: 8 additions & 1 deletion src/Eto.Wpf/Forms/WpfFrameworkElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,9 @@ public override void AttachEvent(string id)
Control.DragLeave += Control_DragLeave;
HandleEvent(Eto.Forms.Control.DragEnterEvent); // need DragEnter so it doesn't get called when going over children
break;
case Eto.Forms.Control.DragEndEvent:
// handled in DoDragDrop, as it is blocking on Windows
break;
case Eto.Forms.Control.EnabledChangedEvent:
Control.IsEnabledChanged += Control_IsEnabledChanged;
break;
Expand Down Expand Up @@ -1028,10 +1031,14 @@ public void DoDragDrop(DataObject data, DragEffects allowedAction, Image image,
sw.WpfDataObjectExtensions.SetDragImage(dataObject, image.ToWpf(), PointF.Empty.ToWpf());
}

sw.DragDrop.DoDragDrop(Control, dataObject, allowedAction.ToWpf());
var effects = sw.DragDrop.DoDragDrop(Control, dataObject, allowedAction.ToWpf());

WpfFrameworkElement.DragSourceControl = null;
sw.DragSourceHelper.UnregisterDefaultDragSource(Control);

var args = new DragEventArgs(Widget, data, allowedAction, PointFromScreen(Mouse.Position), Keyboard.Modifiers, Mouse.Buttons);
args.Effects = effects.ToEto();
Callback.OnDragEnd(Widget, args);
}


Expand Down
47 changes: 47 additions & 0 deletions src/Eto/Forms/Controls/Control.cs
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,31 @@ protected virtual void OnDragDrop(DragEventArgs e)
/// <param name="e">Event arguments</param>
protected virtual void OnDragLeave(DragEventArgs e) => Properties.TriggerEvent(DragLeaveEvent, this, e);


/// <summary>
/// Event identifier for handlers when attaching the <see cref="DragEnd"/> event
/// </summary>
public const string DragEndEvent = "Control.DragEnd";

/// <summary>
/// Occurs for a source control after a call to <see cref="DoDragDrop(DataObject, DragEffects, Image, PointF)"/> when the drag operation has ended.
/// The <see cref="DragEventArgs.Effects"/> is the final <see cref="DragEffects"/> used at the drop destination.
/// </summary>
/// <remarks>
/// For controls that you are dragging from this event is useful to know what to do with the dragged content after it is dropped in a different control or application.
/// </remarks>
public event EventHandler<DragEventArgs> DragEnd
{
add { Properties.AddHandlerEvent(DragEndEvent, value); }
remove { Properties.RemoveEvent(DragEndEvent, value); }
}

/// <summary>
/// Raises the <see cref="DragEnd"/> event.
/// </summary>
/// <param name="e">Event arguments</param>
protected virtual void OnDragEnd(DragEventArgs e) => Properties.TriggerEvent(DragEndEvent, this, e);

/// <summary>
/// Event identifier for handlers when attaching the <see cref="EnabledChanged"/> event
/// </summary>
Expand Down Expand Up @@ -724,6 +749,7 @@ static Control()
EventLookup.Register<Control>(c => c.OnDragOver(null), Control.DragOverEvent);
EventLookup.Register<Control>(c => c.OnDragEnter(null), Control.DragEnterEvent);
EventLookup.Register<Control>(c => c.OnDragLeave(null), Control.DragLeaveEvent);
EventLookup.Register<Control>(c => c.OnDragEnd(null), Control.DragEndEvent);
EventLookup.Register<Control>(c => c.OnEnabledChanged(null), Control.EnabledChangedEvent);
}

Expand Down Expand Up @@ -1313,6 +1339,10 @@ public virtual bool AllowDrop
/// <summary>
/// Starts drag operation using this control as drag source.
/// </summary>
/// <remarks>
/// This method can be blocking on some platforms (Wpf, WinForms), and non-blocking on others (Mac, Gtk).
/// Use the <see cref="DragEnd"/> event to determine when the drag operation is completed and get its resulting DragEffects.
/// </remarks>
/// <param name="data">Drag data.</param>
/// <param name="allowedEffects">Allowed action.</param>
public virtual void DoDragDrop(DataObject data, DragEffects allowedEffects)
Expand All @@ -1323,6 +1353,10 @@ public virtual void DoDragDrop(DataObject data, DragEffects allowedEffects)
/// <summary>
/// Starts drag operation using this control as drag source.
/// </summary>
/// <remarks>
/// This method can be blocking on some platforms (Wpf, WinForms), and non-blocking on others (Mac, Gtk).
/// Use the <see cref="DragEnd"/> event to determine when the drag operation is completed and get its resulting DragEffects.
/// </remarks>
/// <param name="data">Drag data.</param>
/// <param name="allowedEffects">Allowed effects.</param>
/// <param name="image">Custom drag image</param>
Expand Down Expand Up @@ -1510,6 +1544,10 @@ public new interface ICallback : Widget.ICallback
/// </summary>
void OnDragLeave(Control widget, DragEventArgs e);
/// <summary>
/// Raises the DragEnd event.
/// </summary>
void OnDragEnd(Control widget, DragEventArgs e);
/// <summary>
/// Raises the EnabledChanged event.
/// </summary>
void OnEnabledChanged(Control widget, EventArgs e);
Expand Down Expand Up @@ -1669,6 +1707,15 @@ public void OnDragLeave(Control widget, DragEventArgs e)
widget.OnDragLeave(e);
}

/// <summary>
/// Raises the DragEnd event.
/// </summary>
public void OnDragEnd(Control widget, DragEventArgs e)
{
using (widget.Platform.Context)
widget.OnDragEnd(e);
}

/// <summary>
/// Raises the EnabledChanged event.
/// </summary>
Expand Down

0 comments on commit bb66855

Please sign in to comment.