Browse Source

add interfaces required for system dialogs

Dan Walmsley 7 years ago
parent
commit
7b4275b2d5

+ 1 - 0
src/Avalonia.Native/AvaloniaNativePlatform.cs

@@ -74,6 +74,7 @@ namespace Avalonia.Native
                 .Bind<IClipboard>().ToSingleton<ClipboardImpl>()
                 .Bind<IRenderLoop>().ToConstant(new RenderLoop())
                 .Bind<IRenderTimer>().ToConstant(new DefaultRenderTimer(60))
+                .Bind<ISystemDialogImpl>().ToConstant(new SystemDialogs(_factory.CreateSystemDialogs()))
                 .Bind<IPlatformThreadingInterface>().ToConstant(new PlatformThreadingInterface(_factory.CreatePlatformThreadingInterface()));
         }
 

+ 85 - 0
src/Avalonia.Native/SystemDialogs.cs

@@ -0,0 +1,85 @@
+using System;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using Avalonia.Controls.Platform;
+using Avalonia.Native.Interop;
+using Avalonia.Platform;
+
+namespace Avalonia.Native
+{
+    public class SystemDialogs : ISystemDialogImpl
+    {
+        IAvnSystemDialogs _native;
+
+        public SystemDialogs(IAvnSystemDialogs native)
+        {
+            _native = native;
+        }
+
+        public Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent)
+        {
+            var events = new SystemDialogEvents();
+
+            if(dialog is OpenFileDialog ofd)
+            {
+                _native.OpenFileDialog(events, ofd.AllowMultiple,
+                                        ofd.Title,
+                                        ofd.InitialDirectory,
+                                        ofd.InitialFileName,
+                                        string.Join(";", dialog.Filters.SelectMany(f => f.Extensions)));
+            }
+            else
+            {
+                _native.SaveFileDialog(events,
+                                        dialog.Title,
+                                        dialog.InitialDirectory,
+                                        dialog.InitialFileName,
+                                        string.Join(";", dialog.Filters.SelectMany(f => f.Extensions)));
+            }
+
+            return events.Task;
+        }
+
+        public async Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
+        {
+            var events = new SystemDialogEvents();
+
+            _native.SelectFolderDialog(events, dialog.Title, dialog.InitialDirectory);
+
+            return (await events.Task).FirstOrDefault();
+        }
+    }
+
+    public class SystemDialogEvents : CallbackBase, IAvnSystemDialogEvents
+    {
+        private TaskCompletionSource<string[]> _tcs;
+
+        public SystemDialogEvents()
+        {
+            _tcs = new TaskCompletionSource<string[]>();
+        }
+
+        public Task<string[]> Task => _tcs.Task;
+
+        public void OnCompleted(int numResults, IntPtr trFirstResultRef)
+        {
+            string[] results = new string[numResults];
+
+            unsafe
+            {
+                var ptr = (IntPtr*)trFirstResultRef.ToPointer();
+
+                for (int i = 0; i < numResults; i++)
+                {
+                    results[i] = Marshal.PtrToStringAnsi(*ptr);
+
+                    ptr++;
+                }
+            }
+
+            _tcs.SetResult(results);
+        }
+    }
+}

+ 28 - 0
src/headers/avalonia-native.h

@@ -7,6 +7,8 @@ struct IAvnWindow;
 struct IAvnPopup;
 struct IAvnMacOptions;
 struct IAvnPlatformThreadingInterface;
+struct IAvnSystemDialogEvents;
+struct IAvnSystemDialogs;
 
 struct AvnSize
 {
@@ -62,6 +64,7 @@ public:
     virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnWindow** ppv) = 0;
     virtual HRESULT CreatePopup (IAvnWindowEvents* cb, IAvnPopup** ppv) = 0;
     virtual HRESULT CreatePlatformThreadingInterface(IAvnPlatformThreadingInterface** ppv) = 0;
+    virtual HRESULT CreateSystemDialogs (IAvnSystemDialogs** ppv) = 0;
 };
 
 AVNCOM(IAvnWindowBase, 02) : virtual IUnknown
@@ -143,4 +146,29 @@ AVNCOM(IAvnPlatformThreadingInterface, 0b) : virtual IUnknown
     virtual IUnknown* StartTimer(int priority, int ms, IAvnActionCallback* callback) = 0;
 };
 
+AVNCOM(IAvnSystemDialogEvents, 0c) : virtual IUnknown
+{
+    virtual void OnCompleted (int numResults, void* ptrFirstResult) = 0;
+};
+
+AVNCOM(IAvnSystemDialogs, 0d) : virtual IUnknown
+{
+    virtual void SelectFolderDialog (IAvnSystemDialogEvents* events,
+                                   const char* title,
+                                   const char* initialPath) = 0;
+    
+    virtual void OpenFileDialog (IAvnSystemDialogEvents* events,
+                                 bool allowMultiple,
+                                 const char* title,
+                                 const char* initialDirectory,
+                                 const char* intialFile,
+                                 const char* filters) = 0;
+    
+    virtual void SaveFileDialog (IAvnSystemDialogEvents* events,
+                                 const char* title,
+                                 const char* initialDirectory,
+                                 const char* intialFile,
+                                 const char* filters) = 0;
+};
+
 extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative();