ソースを参照

work towards dialogs with parent window handle

Dan Walmsley 7 年 前
コミット
668a4aca9e

+ 2 - 0
src/Avalonia.Native.OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj

@@ -17,6 +17,7 @@
 /* Begin PBXFileReference section */
 		379A4506214D0F6500CC143D /* headers */ = {isa = PBXFileReference; lastKnownFileType = folder; name = headers; path = ../headers; sourceTree = "<group>"; };
 		37C09D8721580FE4006A6758 /* SystemDialogs.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SystemDialogs.mm; sourceTree = "<group>"; };
+		37C09D8A21581EF2006A6758 /* window.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = window.h; sourceTree = "<group>"; };
 		AB00E4F62147CA920032A60A /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
 		AB661C1D2148230F00291242 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
 		AB661C1F2148286E00291242 /* window.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = window.mm; sourceTree = "<group>"; };
@@ -52,6 +53,7 @@
 				AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */,
 				AB661C212148288600291242 /* common.h */,
 				AB661C1F2148286E00291242 /* window.mm */,
+				37C09D8A21581EF2006A6758 /* window.h */,
 				AB00E4F62147CA920032A60A /* main.mm */,
 				37C09D8721580FE4006A6758 /* SystemDialogs.mm */,
 				AB7A61F02147C815003C5833 /* Products */,

+ 35 - 4
src/Avalonia.Native.OSX/SystemDialogs.mm

@@ -1,25 +1,56 @@
 #include "common.h"
+#include "window.h"
 
 class SystemDialogs : public ComSingleObject<IAvnSystemDialogs, &IID_IAvnSystemDialogs>
 {
-    virtual void SelectFolderDialog (IAvnSystemDialogEvents* events,
+    virtual void SelectFolderDialog (IAvnWindow* parentWindowHandle,
+                                     IAvnSystemDialogEvents* events,
                                      const char* title,
                                      const char* initialPath)
     {
         
     }
     
-    virtual void OpenFileDialog (IAvnSystemDialogEvents* events,
+    virtual void OpenFileDialog (IAvnWindow* parentWindowHandle,
+                                 IAvnSystemDialogEvents* events,
                                  bool allowMultiple,
                                  const char* title,
                                  const char* initialDirectory,
                                  const char* intialFile,
                                  const char* filters)
     {
-        events->OnCompleted(0, nullptr);
+        auto panel = [NSOpenPanel openPanel];
+        
+        panel.allowsMultipleSelection = allowMultiple;
+        
+        if(parentWindowHandle != nullptr)
+        {
+            auto windowBase = dynamic_cast<WindowBaseImpl*>(parentWindowHandle);
+            
+            [panel beginSheet:windowBase->Window completionHandler:^(NSModalResponse result) {
+                if(result == NSFileHandlingPanelOKButton)
+                {
+                    
+                }
+                
+                events->OnCompleted(0, nullptr);
+            }];
+        }
+        else
+        {
+            [panel beginWithCompletionHandler:^(NSModalResponse result) {
+                if(result == NSFileHandlingPanelOKButton)
+                {
+                    
+                }
+                
+                events->OnCompleted(0, nullptr);
+            }];
+        }
     }
     
-    virtual void SaveFileDialog (IAvnSystemDialogEvents* events,
+    virtual void SaveFileDialog (IAvnWindow* parentWindowHandle,
+                                 IAvnSystemDialogEvents* events,
                                  const char* title,
                                  const char* initialDirectory,
                                  const char* intialFile,

+ 182 - 0
src/Avalonia.Native.OSX/window.h

@@ -0,0 +1,182 @@
+//
+//  window.h
+//  Avalonia.Native.OSX
+//
+//  Created by Dan Walmsley on 23/09/2018.
+//  Copyright © 2018 Avalonia. All rights reserved.
+//
+
+#ifndef window_h
+#define window_h
+
+class WindowBaseImpl;
+
+@interface AvnView : NSView
+-(AvnView*) initWithParent: (WindowBaseImpl*) parent;
+-(NSEvent*) lastMouseDownEvent;
+-(AvnPoint) translateLocalPoint:(AvnPoint)pt;
+@end
+
+@interface AvnWindow : NSWindow <NSWindowDelegate>
+-(AvnWindow*) initWithParent: (WindowBaseImpl*) parent;
+-(void) setCanBecomeKeyAndMain;
+@end
+
+class WindowBaseImpl : public ComSingleObject<IAvnWindowBase, &IID_IAvnWindowBase>
+{
+public:
+    AvnView* View;
+    AvnWindow* Window;
+    ComPtr<IAvnWindowBaseEvents> BaseEvents;
+    AvnPoint lastPositionSet;
+    WindowBaseImpl(IAvnWindowBaseEvents* events)
+    {
+        BaseEvents = events;
+        View = [[AvnView alloc] initWithParent:this];
+        Window = [[AvnWindow alloc] initWithParent:this];
+        
+        lastPositionSet.X = 100;
+        lastPositionSet.Y = 100;
+        
+        [Window setStyleMask:NSWindowStyleMaskBorderless];
+        [Window setBackingType:NSBackingStoreBuffered];
+        [Window setContentView: View];
+    }
+    
+    virtual HRESULT Show()
+    {
+        SetPosition(lastPositionSet);
+        UpdateStyle();
+        [Window makeKeyAndOrderFront:Window];
+        return S_OK;
+    }
+    
+    virtual HRESULT Hide ()
+    {
+        if(Window != nullptr)
+        {
+            [Window orderOut:Window];
+        }
+        return S_OK;
+    }
+    
+    virtual HRESULT Close()
+    {
+        [Window close];
+        return S_OK;
+    }
+    
+    virtual HRESULT GetClientSize(AvnSize* ret)
+    {
+        if(ret == nullptr)
+            return E_POINTER;
+        auto frame = [View frame];
+        ret->Width = frame.size.width;
+        ret->Height = frame.size.height;
+        return S_OK;
+    }
+    
+    virtual HRESULT GetScaling (double* ret)
+    {
+        if(ret == nullptr)
+            return E_POINTER;
+        
+        if(Window == nullptr)
+        {
+            *ret = 1;
+            return S_OK;
+        }
+        
+        *ret = [Window backingScaleFactor];
+        return S_OK;
+    }
+    
+    virtual HRESULT Resize(double x, double y)
+    {
+        [Window setContentSize:NSSize{x, y}];
+        return S_OK;
+    }
+    
+    virtual void Invalidate (AvnRect rect)
+    {
+        [View setNeedsDisplayInRect:[View frame]];
+    }
+    
+    virtual void BeginMoveDrag ()
+    {
+        auto lastEvent = [View lastMouseDownEvent];
+        
+        if(lastEvent == nullptr)
+        {
+            return;
+        }
+        
+        [Window performWindowDragWithEvent:lastEvent];
+    }
+    
+    
+    virtual HRESULT GetPosition (AvnPoint* ret)
+    {
+        if(ret == nullptr)
+        {
+            return E_POINTER;
+        }
+        
+        auto frame = [Window frame];
+        
+        ret->X = frame.origin.x;
+        ret->Y = frame.origin.y + frame.size.height;
+        
+        *ret = ConvertPointY(*ret);
+        
+        return S_OK;
+    }
+    
+    virtual void SetPosition (AvnPoint point)
+    {
+        lastPositionSet = point;
+        [Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(point))];
+    }
+    
+    virtual HRESULT PointToClient (AvnPoint point, AvnPoint* ret)
+    {
+        if(ret == nullptr)
+        {
+            return E_POINTER;
+        }
+        
+        point = ConvertPointY(point);
+        auto viewPoint = [Window convertPointFromScreen:ToNSPoint(point)];
+        
+        *ret = [View translateLocalPoint:ToAvnPoint(viewPoint)];
+        
+        return S_OK;
+    }
+    
+    virtual HRESULT PointToScreen (AvnPoint point, AvnPoint* ret)
+    {
+        if(ret == nullptr)
+        {
+            return E_POINTER;
+        }
+        
+        auto cocoaViewPoint =  ToNSPoint([View translateLocalPoint:point]);
+        auto cocoaScreenPoint = [Window convertPointToScreen:cocoaViewPoint];
+        *ret = ConvertPointY(ToAvnPoint(cocoaScreenPoint));
+        
+        return S_OK;
+    }
+    
+protected:
+    virtual NSWindowStyleMask GetStyle()
+    {
+        return NSWindowStyleMaskBorderless;
+    }
+    
+    void UpdateStyle()
+    {
+        [Window setStyleMask:GetStyle()];
+    }
+};
+
+#endif /* window_h */

+ 1 - 170
src/Avalonia.Native.OSX/window.mm

@@ -1,174 +1,5 @@
 #include "common.h"
-
-class WindowBaseImpl;
-
-@interface AvnView : NSView
--(AvnView*) initWithParent: (WindowBaseImpl*) parent;
--(NSEvent*) lastMouseDownEvent;
--(AvnPoint) translateLocalPoint:(AvnPoint)pt;
-@end
-
-@interface AvnWindow : NSWindow <NSWindowDelegate>
--(AvnWindow*) initWithParent: (WindowBaseImpl*) parent;
--(void) setCanBecomeKeyAndMain;
-@end
-
-class WindowBaseImpl : public ComSingleObject<IAvnWindowBase, &IID_IAvnWindowBase>
-{
-public:
-    AvnView* View;
-    AvnWindow* Window;
-    ComPtr<IAvnWindowBaseEvents> BaseEvents;
-    AvnPoint lastPositionSet;
-    WindowBaseImpl(IAvnWindowBaseEvents* events)
-    {
-        BaseEvents = events;
-        View = [[AvnView alloc] initWithParent:this];
-        Window = [[AvnWindow alloc] initWithParent:this];
-        
-        lastPositionSet.X = 100;
-        lastPositionSet.Y = 100;
-        
-        [Window setStyleMask:NSWindowStyleMaskBorderless];
-        [Window setBackingType:NSBackingStoreBuffered];
-        [Window setContentView: View];
-    }
-    
-    virtual HRESULT Show()
-    {
-        SetPosition(lastPositionSet);
-        UpdateStyle();
-        [Window makeKeyAndOrderFront:Window];
-        return S_OK;
-    }
-    
-    virtual HRESULT Hide ()
-    {
-        if(Window != nullptr)
-        {
-            [Window orderOut:Window];
-        }
-        return S_OK;
-    }
-    
-    virtual HRESULT Close()
-    {
-        [Window close];
-        return S_OK;
-    }
-    
-    virtual HRESULT GetClientSize(AvnSize* ret)
-    {
-        if(ret == nullptr)
-            return E_POINTER;
-        auto frame = [View frame];
-        ret->Width = frame.size.width;
-        ret->Height = frame.size.height;
-        return S_OK;
-    }
-    
-    virtual HRESULT GetScaling (double* ret)
-    {
-        if(ret == nullptr)
-            return E_POINTER;
-        
-        if(Window == nullptr)
-        {
-            *ret = 1;
-            return S_OK;
-        }
-        
-        *ret = [Window backingScaleFactor];
-        return S_OK;
-    }
-    
-    virtual HRESULT Resize(double x, double y)
-    {
-        [Window setContentSize:NSSize{x, y}];
-        return S_OK;
-    }
-    
-    virtual void Invalidate (AvnRect rect)
-    {
-        [View setNeedsDisplayInRect:[View frame]];
-    }
-    
-    virtual void BeginMoveDrag ()
-    {
-        auto lastEvent = [View lastMouseDownEvent];
-        
-        if(lastEvent == nullptr)
-        {
-            return;
-        }
-        
-        [Window performWindowDragWithEvent:lastEvent];
-    }
-    
-    
-    virtual HRESULT GetPosition (AvnPoint* ret)
-    {
-        if(ret == nullptr)
-        {
-            return E_POINTER;
-        }
-        
-        auto frame = [Window frame];
-        
-        ret->X = frame.origin.x;
-        ret->Y = frame.origin.y + frame.size.height;
-        
-        *ret = ConvertPointY(*ret);
-        
-        return S_OK;
-    }
-    
-    virtual void SetPosition (AvnPoint point)
-    {
-        lastPositionSet = point;
-        [Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(point))];
-    }
-    
-    virtual HRESULT PointToClient (AvnPoint point, AvnPoint* ret)
-    {
-        if(ret == nullptr)
-        {
-            return E_POINTER;
-        }
-        
-        point = ConvertPointY(point);
-        auto viewPoint = [Window convertPointFromScreen:ToNSPoint(point)];
-        
-        *ret = [View translateLocalPoint:ToAvnPoint(viewPoint)];
-        
-        return S_OK;
-    }
-    
-    virtual HRESULT PointToScreen (AvnPoint point, AvnPoint* ret)
-    {
-        if(ret == nullptr)
-        {
-            return E_POINTER;
-        }
-        
-        auto cocoaViewPoint =  ToNSPoint([View translateLocalPoint:point]);
-        auto cocoaScreenPoint = [Window convertPointToScreen:cocoaViewPoint];
-        *ret = ConvertPointY(ToAvnPoint(cocoaScreenPoint));
-        
-        return S_OK;
-    }
-    
-protected:
-    virtual NSWindowStyleMask GetStyle()
-    {
-        return NSWindowStyleMaskBorderless;
-    }
-    
-    void UpdateStyle()
-    {
-        [Window setStyleMask:GetStyle()];
-    }
-};
+#include "window.h"
 
 @implementation AvnView
 {

+ 25 - 25
src/Avalonia.Native/SystemDialogs.cs

@@ -20,37 +20,37 @@ namespace Avalonia.Native
 
         public Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent)
         {
-            using (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)));
-                }
+            var events = new SystemDialogEvents();
 
-                return events.Task;
+            if (dialog is OpenFileDialog ofd)
+            {
+                _native.OpenFileDialog((parent as WindowImpl).Native,
+                                        events, ofd.AllowMultiple,
+                                        ofd.Title,
+                                        ofd.InitialDirectory,
+                                        ofd.InitialFileName,
+                                        string.Join(";", dialog.Filters.SelectMany(f => f.Extensions)));
             }
+            else
+            {
+                _native.SaveFileDialog((parent as WindowImpl).Native,
+                                        events,
+                                        dialog.Title,
+                                        dialog.InitialDirectory,
+                                        dialog.InitialFileName,
+                                        string.Join(";", dialog.Filters.SelectMany(f => f.Extensions)));
+            }
+
+            return events.Task.ContinueWith(t => { events.Dispose(); return t.Result; });
         }
 
-        public async Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
+        public Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
         {
-            using (var events = new SystemDialogEvents())
-            {
-                _native.SelectFolderDialog(events, dialog.Title, dialog.InitialDirectory);
+            var events = new SystemDialogEvents();
 
-                return (await events.Task).FirstOrDefault();
-            }
+            _native.SelectFolderDialog((parent as WindowImpl).Native, events, dialog.Title, dialog.InitialDirectory);
+
+            return events.Task.ContinueWith(t => { events.Dispose(); return t.Result.FirstOrDefault(); });
         }
     }
 

+ 2 - 0
src/Avalonia.Native/WindowImpl.cs

@@ -24,6 +24,8 @@ namespace Avalonia.Native
             }
         }
 
+        public IAvnWindow Native => _native;
+
         public IDisposable ShowDialog()
         {
             return null;

+ 8 - 5
src/headers/avalonia-native.h

@@ -153,18 +153,21 @@ AVNCOM(IAvnSystemDialogEvents, 0c) : virtual IUnknown
 
 AVNCOM(IAvnSystemDialogs, 0d) : virtual IUnknown
 {
-    virtual void SelectFolderDialog (IAvnSystemDialogEvents* events,
-                                   const char* title,
-                                   const char* initialPath) = 0;
+    virtual void SelectFolderDialog (IAvnWindow* parentWindowHandle,
+                                     IAvnSystemDialogEvents* events,
+                                     const char* title,
+                                     const char* initialPath) = 0;
     
-    virtual void OpenFileDialog (IAvnSystemDialogEvents* events,
+    virtual void OpenFileDialog (IAvnWindow* parentWindowHandle,
+                                 IAvnSystemDialogEvents* events,
                                  bool allowMultiple,
                                  const char* title,
                                  const char* initialDirectory,
                                  const char* intialFile,
                                  const char* filters) = 0;
     
-    virtual void SaveFileDialog (IAvnSystemDialogEvents* events,
+    virtual void SaveFileDialog (IAvnWindow* parentWindowHandle,
+                                 IAvnSystemDialogEvents* events,
                                  const char* title,
                                  const char* initialDirectory,
                                  const char* intialFile,