9 changed files with 474 additions and 10 deletions
@ -0,0 +1,10 @@ |
|||
#ifndef igetnative_h |
|||
#define igetnative_h |
|||
|
|||
class IGetNative |
|||
{ |
|||
public: |
|||
virtual void* GetNative() = 0; |
|||
}; |
|||
|
|||
#endif |
|||
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>IDEDidComputeMac32BitWarning</key> |
|||
<true/> |
|||
</dict> |
|||
</plist> |
|||
@ -0,0 +1,79 @@ |
|||
//
|
|||
// menu.h
|
|||
// Avalonia.Native.OSX
|
|||
//
|
|||
// Created by Dan Walmsley on 01/08/2019.
|
|||
// Copyright © 2019 Avalonia. All rights reserved.
|
|||
//
|
|||
|
|||
#ifndef menu_h |
|||
#define menu_h |
|||
|
|||
#include "common.h" |
|||
|
|||
class AvnAppMenuItem; |
|||
class AvnAppMenu; |
|||
|
|||
@interface AvnMenu : NSMenu // for some reason it doesnt detect nsmenu here but compiler doesnt complain
|
|||
|
|||
@end |
|||
|
|||
@interface AvnMenuItem : NSMenuItem |
|||
- (id) initWithAvnAppMenuItem: (AvnAppMenuItem*)menuItem; |
|||
- (void)didSelectItem:(id)sender; |
|||
@end |
|||
|
|||
class AvnAppMenuItem : public ComSingleObject<IAvnAppMenuItem, &IID_IAvnAppMenuItem> |
|||
{ |
|||
private: |
|||
AvnMenuItem* _native; // here we hold a pointer to an AvnMenuItem
|
|||
IAvnActionCallback* _callback; |
|||
IAvnPredicateCallback* _predicate; |
|||
|
|||
public: |
|||
FORWARD_IUNKNOWN() |
|||
|
|||
AvnAppMenuItem(); |
|||
|
|||
AvnMenuItem* GetNative(); |
|||
|
|||
virtual HRESULT SetSubMenu (IAvnAppMenu* menu) override; |
|||
|
|||
virtual HRESULT SetTitle (void* utf8String) override; |
|||
|
|||
virtual HRESULT SetGesture (void* key, AvnInputModifiers modifiers) override; |
|||
|
|||
virtual HRESULT SetAction (IAvnPredicateCallback* predicate, IAvnActionCallback* callback) override; |
|||
|
|||
bool EvaluateItemEnabled(); |
|||
|
|||
void RaiseOnClicked(); |
|||
}; |
|||
|
|||
|
|||
class AvnAppMenu : public ComSingleObject<IAvnAppMenu, &IID_IAvnAppMenu> |
|||
{ |
|||
private: |
|||
AvnMenu* _native; |
|||
|
|||
public: |
|||
FORWARD_IUNKNOWN() |
|||
|
|||
AvnAppMenu(); |
|||
|
|||
AvnAppMenu(AvnMenu* native); |
|||
|
|||
AvnMenu* GetNative(); |
|||
|
|||
virtual HRESULT AddItem (IAvnAppMenuItem* item) override; |
|||
|
|||
virtual HRESULT RemoveItem (IAvnAppMenuItem* item) override; |
|||
|
|||
virtual HRESULT SetTitle (void* utf8String) override; |
|||
|
|||
virtual HRESULT Clear () override; |
|||
}; |
|||
|
|||
|
|||
#endif |
|||
|
|||
@ -0,0 +1,211 @@ |
|||
|
|||
#include "common.h" |
|||
#include "IGetNative.h" |
|||
#include "menu.h" |
|||
|
|||
@implementation AvnMenu |
|||
@end |
|||
|
|||
@implementation AvnMenuItem |
|||
{ |
|||
AvnAppMenuItem* _item; |
|||
} |
|||
|
|||
- (id) initWithAvnAppMenuItem: (AvnAppMenuItem*)menuItem |
|||
{ |
|||
if(self != nil) |
|||
{ |
|||
_item = menuItem; |
|||
self = [super initWithTitle:@"" |
|||
action:@selector(didSelectItem:) |
|||
keyEquivalent:@""]; |
|||
|
|||
[self setEnabled:YES]; |
|||
|
|||
[self setTarget:self]; |
|||
} |
|||
|
|||
return self; |
|||
} |
|||
|
|||
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem |
|||
{ |
|||
if([self submenu] != nil) |
|||
{ |
|||
return YES; |
|||
} |
|||
|
|||
return _item->EvaluateItemEnabled(); |
|||
} |
|||
|
|||
- (void)didSelectItem:(nullable id)sender |
|||
{ |
|||
_item->RaiseOnClicked(); |
|||
} |
|||
@end |
|||
|
|||
AvnAppMenuItem::AvnAppMenuItem() |
|||
{ |
|||
_native = [[AvnMenuItem alloc] initWithAvnAppMenuItem: this]; |
|||
_callback = nullptr; |
|||
} |
|||
|
|||
AvnMenuItem* AvnAppMenuItem::GetNative() |
|||
{ |
|||
return _native; |
|||
} |
|||
|
|||
HRESULT AvnAppMenuItem::SetSubMenu (IAvnAppMenu* menu) |
|||
{ |
|||
auto nsMenu = dynamic_cast<AvnAppMenu*>(menu)->GetNative(); |
|||
|
|||
[_native setSubmenu: nsMenu]; |
|||
|
|||
return S_OK; |
|||
} |
|||
|
|||
HRESULT AvnAppMenuItem::SetTitle (void* utf8String) |
|||
{ |
|||
[_native setTitle:[NSString stringWithUTF8String:(const char*)utf8String]]; |
|||
|
|||
return S_OK; |
|||
} |
|||
|
|||
HRESULT AvnAppMenuItem::SetGesture (void* key, AvnInputModifiers modifiers) |
|||
{ |
|||
NSEventModifierFlags flags = 0; |
|||
|
|||
if (modifiers & Control) |
|||
flags |= NSEventModifierFlagControl; |
|||
if (modifiers & Shift) |
|||
flags |= NSEventModifierFlagShift; |
|||
if (modifiers & Alt) |
|||
flags |= NSEventModifierFlagOption; |
|||
if (modifiers & Windows) |
|||
flags |= NSEventModifierFlagCommand; |
|||
|
|||
[_native setKeyEquivalent:[NSString stringWithUTF8String:(const char*)key]]; |
|||
[_native setKeyEquivalentModifierMask:flags]; |
|||
|
|||
return S_OK; |
|||
} |
|||
|
|||
HRESULT AvnAppMenuItem::SetAction (IAvnPredicateCallback* predicate, IAvnActionCallback* callback) |
|||
{ |
|||
_predicate = predicate; |
|||
_callback = callback; |
|||
return S_OK; |
|||
} |
|||
|
|||
bool AvnAppMenuItem::EvaluateItemEnabled() |
|||
{ |
|||
if(_predicate != nullptr) |
|||
{ |
|||
auto result = _predicate->Evaluate (); |
|||
|
|||
return result; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
void AvnAppMenuItem::RaiseOnClicked() |
|||
{ |
|||
if(_callback != nullptr) |
|||
{ |
|||
_callback->Run(); |
|||
} |
|||
} |
|||
|
|||
AvnAppMenu::AvnAppMenu() |
|||
{ |
|||
_native = [AvnMenu new]; |
|||
} |
|||
|
|||
AvnAppMenu::AvnAppMenu(AvnMenu* native) |
|||
{ |
|||
_native = native; |
|||
} |
|||
|
|||
AvnMenu* AvnAppMenu::GetNative() |
|||
{ |
|||
return _native; |
|||
} |
|||
|
|||
HRESULT AvnAppMenu::AddItem (IAvnAppMenuItem* item) |
|||
{ |
|||
auto avnMenuItem = dynamic_cast<AvnAppMenuItem*>(item); |
|||
|
|||
if(avnMenuItem != nullptr) |
|||
{ |
|||
|
|||
[_native addItem: avnMenuItem->GetNative()]; |
|||
} |
|||
|
|||
return S_OK; |
|||
} |
|||
|
|||
HRESULT AvnAppMenu::RemoveItem (IAvnAppMenuItem* item) |
|||
{ |
|||
auto avnMenuItem = dynamic_cast<AvnAppMenuItem*>(item); |
|||
|
|||
if(avnMenuItem != nullptr) |
|||
{ |
|||
[_native removeItem:avnMenuItem->GetNative()]; |
|||
} |
|||
|
|||
return S_OK; |
|||
} |
|||
|
|||
HRESULT AvnAppMenu::SetTitle (void* utf8String) |
|||
{ |
|||
[_native setTitle:[NSString stringWithUTF8String:(const char*)utf8String]]; |
|||
|
|||
return S_OK; |
|||
} |
|||
|
|||
HRESULT AvnAppMenu::Clear() |
|||
{ |
|||
[_native removeAllItems]; |
|||
return S_OK; |
|||
} |
|||
|
|||
static IAvnAppMenu* s_AppMenu = nullptr; |
|||
|
|||
extern IAvnAppMenu* GetAppMenu() |
|||
{ |
|||
@autoreleasepool |
|||
{ |
|||
if(s_AppMenu == nullptr) |
|||
{ |
|||
id menubar = [NSMenu new]; |
|||
[menubar setTitle:@"Test"]; |
|||
[NSApp setMainMenu:menubar]; |
|||
|
|||
id appMenuItem = [AvnMenuItem new]; |
|||
[[NSApp mainMenu] addItem:appMenuItem]; |
|||
|
|||
[appMenuItem setSubmenu:[AvnMenu new]]; |
|||
|
|||
s_AppMenu = new AvnAppMenu([[NSApplication sharedApplication] mainMenu]); |
|||
} |
|||
|
|||
return s_AppMenu; |
|||
} |
|||
} |
|||
|
|||
extern IAvnAppMenu* CreateAppMenu() |
|||
{ |
|||
@autoreleasepool |
|||
{ |
|||
return new AvnAppMenu(); |
|||
} |
|||
} |
|||
|
|||
extern IAvnAppMenuItem* CreateAppMenuItem() |
|||
{ |
|||
@autoreleasepool |
|||
{ |
|||
return new AvnAppMenuItem(); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue