Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Control.DragEnd event #2288

Merged
merged 1 commit into from
Aug 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ public event EventHandler<DragEventArgs> DragLeave
/// <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 static implicit operator Control(Image image)
/// </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
Loading