Browse Source

OSX drag cleanup

boombuler 7 years ago
parent
commit
1afb52b27d
1 changed files with 61 additions and 35 deletions
  1. 61 35
      src/OSX/Avalonia.MonoMac/DragSource.cs

+ 61 - 35
src/OSX/Avalonia.MonoMac/DragSource.cs

@@ -1,13 +1,19 @@
-using System.Data;
+using System;
+using System.Data;
+using System.IO;
+using System.Linq;
 using System.Linq.Expressions;
 using System.Reactive.Linq;
 using System.Reactive.Subjects;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization.Formatters.Binary;
 using System.Threading.Tasks;
 using Avalonia.Controls;
 using Avalonia.Controls.DragDrop;
 using Avalonia.Controls.Platform;
 using Avalonia.Input;
 using Avalonia.Input.Raw;
+using MonoMac;
 using MonoMac.AppKit;
 using MonoMac.CoreGraphics;
 using MonoMac.Foundation;
@@ -17,46 +23,54 @@ namespace Avalonia.MonoMac
 {
     public class DragSource : NSDraggingSource, IPlatformDragSource
     {
-        class DS : NSDraggingSource
-        {
-            private readonly DragDropEffects _allowedEffects;
-            public ReplaySubject<DragDropEffects> Result { get; } = new ReplaySubject<DragDropEffects>();
-
-            public DS(DragDropEffects allowedEffects)
-            {
-                _allowedEffects = allowedEffects;
-            }
-            
-            public override bool IgnoreModifierKeysWhileDragging => false;
-            
-            public override NSDragOperation DraggingSourceOperationMaskForLocal(bool flag)
-            {
-                return DraggingInfo.ConvertDragOperation(_allowedEffects);
-            }
-            
-            public override void DraggedImageEndedAtOperation(NSImage image, CGPoint screenPoint, NSDragOperation operation)
-            {
-                Result.OnNext(DraggingInfo.ConvertDragOperation(operation));
-                Result.OnCompleted();
-            }
-        }
-
-        
+        private const string NSPasteboardTypeString = "public.utf8-plain-text";
         
+        private readonly Subject<DragDropEffects> _result = new Subject<DragDropEffects>();
         private readonly IInputManager _inputManager;
+        private DragDropEffects _allowedEffects;
         
-
+        public override bool IgnoreModifierKeysWhileDragging => false;
+      
         public DragSource()
         {
             _inputManager = AvaloniaLocator.Current.GetService<IInputManager>();
         }
 
-        private NSDraggingItem[] ConvertDraggedItems(IDataObject data)
+        private string DataFormatToUTI(string s)
+        {
+            if (s == DataFormats.FileNames)
+                throw new NotImplementedException();
+            if (s == DataFormats.Text)
+                return NSPasteboardTypeString;
+            return s;
+        }
+        
+        private NSDraggingItem CreateDraggingItem(string format, object data)
         {
-            NSString s = new NSString("FOOBAR");
-            NSPasteboardWriting w = new NSPasteboardWriting(s.Handle);
-            var text = new NSDraggingItem(w);
-            return new[] {text};
+            
+            var pasteboardItem = new NSPasteboardItem();
+            NSData nsData;
+            if(data is string s)
+                nsData = NSData.FromString(s);
+            else if (data is Stream strm)
+                nsData = NSData.FromStream(strm);
+            else if (data is byte[] bytes)
+                nsData = NSData.FromArray(bytes);
+            else
+            {
+                BinaryFormatter bf = new BinaryFormatter();
+                using (var ms = new MemoryStream())
+                {
+                    bf.Serialize(ms, data);
+                    ms.Position = 0;
+                    nsData = NSData.FromStream(ms);
+                }
+            }
+            pasteboardItem.SetDataForType(nsData, DataFormatToUTI(format));
+
+            NSPasteboardWriting writing = new NSPasteboardWriting(pasteboardItem.Handle);
+  
+            return new NSDraggingItem(writing);
         }
         
         
@@ -72,10 +86,22 @@ namespace Avalonia.MonoMac
             var pt = view.TranslateLocalPoint(mouseEv.Position).ToMonoMacPoint();    
             var ev = NSEvent.MouseEvent(NSEventType.LeftMouseDown, pt, 0, 0, 0, null, 0, 0, 0);
 
-            var ds = new DS(allowedEffects);
-            view.BeginDraggingSession(ConvertDraggedItems(data) ,ev, ds);
+            _allowedEffects = allowedEffects;
+            var items = data.GetDataFormats().Select(fmt => CreateDraggingItem(fmt, data.Get(fmt))).ToArray();
+            view.BeginDraggingSession(items ,ev, this);
 
-            return await ds.Result;
+            return await _result;
+        }
+        
+        public override NSDragOperation DraggingSourceOperationMaskForLocal(bool flag)
+        {
+            return DraggingInfo.ConvertDragOperation(_allowedEffects);
+        }
+            
+        public override void DraggedImageEndedAtOperation(NSImage image, CGPoint screenPoint, NSDragOperation operation)
+        {
+            _result.OnNext(DraggingInfo.ConvertDragOperation(operation));
+            _result.OnCompleted();
         }
     }
 }