Browse Source

work towards dialogs with parent window handle

pull/1977/head
Dan Walmsley 8 years ago
parent
commit
668a4aca9e
  1. 2
      src/Avalonia.Native.OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
  2. 39
      src/Avalonia.Native.OSX/SystemDialogs.mm
  3. 182
      src/Avalonia.Native.OSX/window.h
  4. 171
      src/Avalonia.Native.OSX/window.mm
  5. 50
      src/Avalonia.Native/SystemDialogs.cs
  6. 2
      src/Avalonia.Native/WindowImpl.cs
  7. 13
      src/headers/avalonia-native.h

2
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 */,

39
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
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 */

171
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
{

50
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
src/Avalonia.Native/WindowImpl.cs

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

13
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,

Loading…
Cancel
Save