From 5c394678797bb034b2393c19d49c8d3f0b82cd7c Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 29 Nov 2020 14:18:53 +1100 Subject: [PATCH] Support more accelerator keys --- v2/internal/ffenestri/ffenestri_darwin.c | 57 ++++++++++++++++++++++-- v2/pkg/menu/acelerators.go | 7 +++ v2/test/kitchensink/main.go | 24 ++++++++-- 3 files changed, 81 insertions(+), 7 deletions(-) diff --git a/v2/internal/ffenestri/ffenestri_darwin.c b/v2/internal/ffenestri/ffenestri_darwin.c index 00763b4cf..aa0672c4f 100644 --- a/v2/internal/ffenestri/ffenestri_darwin.c +++ b/v2/internal/ffenestri/ffenestri_darwin.c @@ -14,6 +14,7 @@ #define s(str) sel_registerName(str) #define u(str) sel_getUid(str) #define str(input) msg(c("NSString"), s("stringWithUTF8String:"), input) +#define strunicode(input) msg(c("NSString"), s("stringWithFormat:"), str("%C"), input) #define cstr(input) (const char *)msg(input, s("UTF8String")) #define url(input) msg(c("NSURL"), s("fileURLWithPath:"), str(input)) @@ -1265,11 +1266,60 @@ unsigned long parseModifiers(const char **modifiers) { return result; } +id processAcceleratorKey(const char *key) { + if( STREQ(key, "Backspace") ) { + return strunicode(0x0008); + } + if( STREQ(key, "Tab") ) { + return strunicode(0x0009); + } + if( STREQ(key, "Return") ) { + return strunicode(0x000d); + } + if( STREQ(key, "Escape") ) { + return strunicode(0x001b); + } + if( STREQ(key, "Left") ) { + return strunicode(0x001c); + } + if( STREQ(key, "Right") ) { + return strunicode(0x001d); + } + if( STREQ(key, "Up") ) { + return strunicode(0x001e); + } + if( STREQ(key, "Down") ) { + return strunicode(0x001f); + } + if( STREQ(key, "Space") ) { + return strunicode(0x0020); + } + if( STREQ(key, "Delete") ) { + return strunicode(0x007f); + } + if( STREQ(key, "Home") ) { + return strunicode(0x2196); + } + if( STREQ(key, "End") ) { + return strunicode(0x2198); + } + if( STREQ(key, "Page Up") ) { + return strunicode(0x21de); + } + if( STREQ(key, "Page Down") ) { + return strunicode(0x21df); + } + return str(key); +} + + id parseTextMenuItem(struct Application *app, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers) { id item = ALLOC("NSMenuItem"); id wrappedId = msg(c("NSValue"), s("valueWithPointer:"), menuid); msg(item, s("setRepresentedObject:"), wrappedId); - msg(item, s("initWithTitle:action:keyEquivalent:"), str(title), s("menuCallback:"), str(acceleratorkey)); + + id key = processAcceleratorKey(acceleratorkey); + msg(item, s("initWithTitle:action:keyEquivalent:"), str(title), s("menuCallback:"), key); msg(item, s("setEnabled:"), !disabled); msg(item, s("autorelease")); @@ -1301,7 +1351,7 @@ id parseCheckboxMenuItem(struct Application *app, id parentmenu, const char *tit } -id parseRadioMenuItem(struct Application *app, id parentmenu, const char *title, const char *menuid, bool disabled, bool checked, const char *key) { +id parseRadioMenuItem(struct Application *app, id parentmenu, const char *title, const char *menuid, bool disabled, bool checked, const char *acceleratorkey) { id item = ALLOC("NSMenuItem"); // Store the item in the menu item map @@ -1309,7 +1359,8 @@ id parseRadioMenuItem(struct Application *app, id parentmenu, const char *title, id wrappedId = msg(c("NSValue"), s("valueWithPointer:"), menuid); msg(item, s("setRepresentedObject:"), wrappedId); - msg(item, s("initWithTitle:action:keyEquivalent:"), str(title), s("radioMenuCallback:"), str(key)); + id key = processAcceleratorKey(acceleratorkey); + msg(item, s("initWithTitle:action:keyEquivalent:"), str(title), s("radioMenuCallback:"), key); msg(item, s("setEnabled:"), !disabled); msg(item, s("autorelease")); msg(item, s("setState:"), (checked ? NSControlStateValueOn : NSControlStateValueOff)); diff --git a/v2/pkg/menu/acelerators.go b/v2/pkg/menu/acelerators.go index a3d652fe5..168f5db7d 100644 --- a/v2/pkg/menu/acelerators.go +++ b/v2/pkg/menu/acelerators.go @@ -22,6 +22,13 @@ type Accelerator struct { Modifiers []Modifier } +// Accel creates a standard key Accelerator +func Accel(key string) *Accelerator { + return &Accelerator{ + Key: key, + } +} + // CmdOrCtrlAccel creates a 'CmdOrCtrl' Accelerator func CmdOrCtrlAccel(key string) *Accelerator { return &Accelerator{ diff --git a/v2/test/kitchensink/main.go b/v2/test/kitchensink/main.go index d44a2b610..781875d4e 100644 --- a/v2/test/kitchensink/main.go +++ b/v2/test/kitchensink/main.go @@ -29,10 +29,26 @@ func main() { menu.Front(), menu.SubMenu("Test Submenu", []*menu.MenuItem{ - menu.TextWithAccelerator("Shift accelerator", "Shift", menu.ShiftAccel("o")), // Label = "Hi!", ID= "hello" - menu.TextWithAccelerator("Control accelerator", "Control", menu.ControlAccel("o")), // Label = "Hi!", ID= "hello" - menu.TextWithAccelerator("Command accelerator", "Command", menu.CmdOrCtrlAccel("o")), // Label = "Hi!", ID= "hello" - menu.TextWithAccelerator("Option accelerator", "Option", menu.OptionOrAltAccel("o")), // Label = "Hi!", ID= "hello" + menu.SubMenu("Accelerators", []*menu.MenuItem{ + menu.TextWithAccelerator("Shift accelerator", "Shift", menu.ShiftAccel("o")), + menu.TextWithAccelerator("Control accelerator", "Control", menu.ControlAccel("o")), + menu.TextWithAccelerator("Command accelerator", "Command", menu.CmdOrCtrlAccel("o")), + menu.TextWithAccelerator("Option accelerator", "Option", menu.OptionOrAltAccel("o")), + menu.TextWithAccelerator("Backspace", "Backspace", menu.Accel("Backspace")), + menu.TextWithAccelerator("Tab", "Tab", menu.Accel("Tab")), + menu.TextWithAccelerator("Return", "Return", menu.Accel("Return")), + menu.TextWithAccelerator("Escape", "Escape", menu.Accel("Escape")), + menu.TextWithAccelerator("Left", "Left", menu.Accel("Left")), + menu.TextWithAccelerator("Right", "Right", menu.Accel("Right")), + menu.TextWithAccelerator("Up", "Up", menu.Accel("Up")), + menu.TextWithAccelerator("Down", "Down", menu.Accel("Down")), + menu.TextWithAccelerator("Space", "Space", menu.Accel("Space")), + menu.TextWithAccelerator("Delete", "Delete", menu.Accel("Delete")), + menu.TextWithAccelerator("Home", "Home", menu.Accel("Home")), + menu.TextWithAccelerator("End", "End", menu.Accel("End")), + menu.TextWithAccelerator("Page Up", "Page Up", menu.Accel("Page Up")), + menu.TextWithAccelerator("Page Down", "Page Down", menu.Accel("Page Down")), + }), &menu.MenuItem{ Label: "Disabled Menu", Type: menu.TextType,