Skip to content

Commit

Permalink
Merge pull request #4 from AvaloniaUI/features/popup-implementation
Browse files Browse the repository at this point in the history
implement popups.
  • Loading branch information
danwalmsley authored Sep 23, 2018
2 parents e6f8076 + 62ce672 commit a09c365
Show file tree
Hide file tree
Showing 9 changed files with 272 additions and 39 deletions.
5 changes: 5 additions & 0 deletions src/Avalonia.Native.OSX/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,9 @@

extern IAvnPlatformThreadingInterface* CreatePlatformThreading();
extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events);
extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events);

extern NSPoint ToNSPoint (AvnPoint p);
extern AvnPoint ToAvnPoint (NSPoint p);
extern AvnPoint ConvertPointY (AvnPoint p);
#endif
50 changes: 49 additions & 1 deletion src/Avalonia.Native.OSX/main.mm
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,62 @@ virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnWindow** ppv)
return S_OK;
};

virtual HRESULT CreatePopup(IAvnWindowEvents* cb, IAvnPopup** ppv)
{
if(cb == nullptr || ppv == nullptr)
return E_POINTER;

*ppv = CreateAvnPopup(cb);
return S_OK;
}

virtual HRESULT CreatePlatformThreadingInterface(IAvnPlatformThreadingInterface** ppv)
{
*ppv = CreatePlatformThreading();
return S_OK;
};
}
};

extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative()
{
return new AvaloniaNative();
};


NSPoint ToNSPoint (AvnPoint p)
{
@autoreleasepool
{
NSPoint result;
result.x = p.X;
result.y = p.Y;

return result;
}
}

AvnPoint ToAvnPoint (NSPoint p)
{
@autoreleasepool
{
AvnPoint result;
result.X = p.x;
result.Y = p.y;

return result;
}
}


AvnPoint ConvertPointY (AvnPoint p)
{
@autoreleasepool
{
auto sw = [NSScreen.screens objectAtIndex:0].frame;

auto t = MAX(sw.origin.y, sw.origin.y + sw.size.height);
p.Y = t - p.Y;

return p;
}
}
118 changes: 113 additions & 5 deletions src/Avalonia.Native.OSX/window.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
class WindowBaseImpl;

@interface AvnView : NSView
-(AvnView*) initWithParent: (WindowBaseImpl*) parent;
-(NSEvent*) lastMouseDownEvent;
-(AvnView*) initWithParent: (WindowBaseImpl*) parent;
-(NSEvent*) lastMouseDownEvent;
-(AvnPoint) translateLocalPoint:(AvnPoint)pt;
@end

@interface AvnWindow : NSWindow <NSWindowDelegate>
Expand All @@ -18,23 +19,38 @@ -(void) setCanBecomeKeyAndMain;
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];
Expand All @@ -51,6 +67,21 @@ virtual HRESULT GetClientSize(AvnSize* ret)
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}];
Expand All @@ -74,6 +105,59 @@ virtual void BeginMoveDrag ()
[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()
{
Expand Down Expand Up @@ -160,7 +244,7 @@ - (void)drawRect:(NSRect)dirtyRect
free(ptr);
}

- (AvnPoint)translateLocalPoint:(AvnPoint)pt
- (AvnPoint) translateLocalPoint:(AvnPoint)pt
{
pt.Y = [self bounds].size.height - pt.Y;
return pt;
Expand Down Expand Up @@ -194,7 +278,6 @@ - (void)mouseEvent:(NSEvent *)event withType:(AvnRawMouseEventType) type
}
}


auto timestamp = [event timestamp] * 1000;
auto modifiers = [self getModifiers:[event modifierFlags]];

Expand Down Expand Up @@ -368,6 +451,32 @@ -(void)resignKeyWindow

@end

class PopupImpl : public WindowBaseImpl, public IAvnPopup
{
private:
BEGIN_INTERFACE_MAP()
INHERIT_INTERFACE_MAP(WindowBaseImpl)
INTERFACE_MAP_ENTRY(IAvnPopup, IID_IAvnPopup)
END_INTERFACE_MAP()
ComPtr<IAvnWindowEvents> WindowEvents;
PopupImpl(IAvnWindowEvents* events) : WindowBaseImpl(events)
{
WindowEvents = events;
[Window setLevel:NSPopUpMenuWindowLevel];
}

protected:
virtual NSWindowStyleMask GetStyle()
{
return NSWindowStyleMaskBorderless;
}
};

extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events)
{
IAvnPopup* ptr = dynamic_cast<IAvnPopup*>(new PopupImpl(events));
return ptr;
}

class WindowImpl : public WindowBaseImpl, public IAvnWindow
{
Expand Down Expand Up @@ -413,7 +522,6 @@ virtual NSWindowStyleMask GetStyle()
}
};


extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events)
{
IAvnWindow* ptr = dynamic_cast<IAvnWindow*>(new WindowImpl(events));
Expand Down
8 changes: 8 additions & 0 deletions src/Avalonia.Native/Avalonia.Native.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,12 @@
<PackageReference Include="Avalonia" Version="0.6.2-build6248-beta" />
<SharpGenMapping Include="Mappings.xml" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Generated\LocalInterop.cs" />
<Compile Remove="Generated\Structures.cs" />
<Compile Remove="Generated\Functions.cs" />
<Compile Remove="Generated\Interfaces.cs" />
<Compile Remove="Generated\LocalInterop.cs" />
<Compile Remove="Generated\Structures.cs" />
</ItemGroup>
</Project>
4 changes: 2 additions & 2 deletions src/Avalonia.Native/AvaloniaNativePlatform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ public IEmbeddableWindowImpl CreateEmbeddableWindow()
}

public IPopupImpl CreatePopup()
{
throw new NotImplementedException();
{
return new PopupImpl(_factory);
}
}

Expand Down
18 changes: 18 additions & 0 deletions src/Avalonia.Native/Helpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using Avalonia.Native.Interop;

namespace Avalonia.Native
{
public static class Helpers
{
public static Point ToAvaloniaPoint (this AvnPoint pt)
{
return new Point(pt.X, pt.Y);
}

public static AvnPoint ToAvnPoint (this Point pt)
{
return new AvnPoint { X = pt.X, Y = pt.Y };
}
}
}
27 changes: 27 additions & 0 deletions src/Avalonia.Native/PopupImpl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using Avalonia.Native.Interop;
using Avalonia.Platform;

namespace Avalonia.Native
{
public class PopupImpl : WindowBaseImpl, IPopupImpl
{
IAvnPopup _native;

public PopupImpl(IAvaloniaNativeFactory factory)
{
using (var e = new PopupEvents(this))
Init(_native = factory.CreatePopup(e));
}

class PopupEvents : WindowBaseEvents, IAvnWindowEvents
{
readonly PopupImpl _parent;

public PopupEvents(PopupImpl parent) : base(parent)
{
_parent = parent;
}
}
}
}
Loading

0 comments on commit a09c365

Please sign in to comment.