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