Support UpdateContextMenus. Submenus are now *menu.Menu. Tidy up++

This commit is contained in:
Lea Anthony
2021-01-08 06:28:51 +11:00
parent 2a69786d7e
commit fbee9ba240
14 changed files with 133 additions and 92 deletions

View File

@@ -207,8 +207,6 @@ void ProcessContextMenus(ContextMenuStore* store) {
void ShowContextMenu(ContextMenuStore* store, id mainWindow, const char *contextMenuID, const char *contextMenuData) {
printf("Show context menu '%s'. Also got data '%s'.\n\n", contextMenuID, contextMenuData);
// If no context menu ID was given, abort
if( contextMenuID == NULL ) {
return;
@@ -241,8 +239,6 @@ void ShowContextMenu(ContextMenuStore* store, id mainWindow, const char *context
contextMenu->nsmenu = GetMenu(contextMenu->menu);
}
printf("\n\nContext menu NSMenu = %p\n\n", contextMenu->menu->menu);
// Show popup
msg(c("NSMenu"), s("popUpContextMenu:withEvent:forView:"), contextMenu->nsmenu, menuEvent, contentView);

View File

@@ -1,6 +1,8 @@
package ffenestri
import (
"encoding/json"
"github.com/wailsapp/wails/v2/pkg/menu"
"runtime"
"strings"
"unsafe"
@@ -152,7 +154,10 @@ func (a *Application) Run(incomingDispatcher Dispatcher, bindings string, debug
dispatcher = incomingDispatcher.RegisterClient(newClient(a))
// Process platform settings
a.processPlatformSettings()
err := a.processPlatformSettings()
if err != nil {
return err
}
// Check we could initialise the application
if app != nil {
@@ -175,3 +180,28 @@ func (a *Application) Run(incomingDispatcher Dispatcher, bindings string, debug
func messageFromWindowCallback(data *C.char) {
dispatcher.DispatchMessage(C.GoString(data))
}
type ProcessedContextMenu struct {
ID string
ProcessedMenu *ProcessedMenu
}
func processContextMenus(contextMenus *menu.ContextMenus) (string, error) {
var processedContextMenus []*ProcessedContextMenu
// We need to iterate each context menu and pre-process it
for contextMenuID, contextMenu := range contextMenus.Items {
thisContextMenu := &ProcessedContextMenu{
ID: contextMenuID,
ProcessedMenu: NewProcessedMenu(contextMenu),
}
processedContextMenus = append(processedContextMenus, thisContextMenu)
}
contextMenusJSON, err := json.Marshal(processedContextMenus)
if err != nil {
return "", err
}
return string(contextMenusJSON), nil
}

View File

@@ -233,10 +233,10 @@ func (c *Client) UpdateContextMenus(contextMenus *menu.ContextMenus) {
return
}
// Process the menu
contextMenusJSON, err := json.Marshal(contextMenus)
contextMenusJSON, err := processContextMenus(contextMenus)
if err != nil {
c.app.logger.Error("Error processing updated Context Menus: %s", err.Error())
c.app.logger.Error("Error processing updated Context Menu: %s", err.Error())
return
}
C.UpdateContextMenus(c.app.app, c.app.string2CString(string(contextMenusJSON)))
C.UpdateContextMenus(c.app.app, c.app.string2CString(contextMenusJSON))
}

View File

@@ -1805,17 +1805,19 @@ void UpdateTray(struct Application *app, const char *trayMenuAsJSON) {
}
void UpdateContextMenus(struct Application *app, const char *contextMenusAsJSON) {
// ON_MAIN_THREAD (
//
// dumpContextMenus(app);
//
// // Free up memory
// destroyContextMenus(app);
//
// // Set the context menu JSON
// app->contextMenusAsJSON = contextMenusAsJSON;
// parseContextMenus(app);
// );
ON_MAIN_THREAD (
// Free up memory
DeleteContextMenuStore(app->contextMenuStore);
// Recreate Context Menus
app->contextMenuStore = NewContextMenuStore(contextMenusAsJSON);
// Process them
ProcessContextMenus(app->contextMenuStore);
);
}
void processDialogIcons(struct hashmap_s *hashmap, const unsigned char *dialogIcons[]) {

View File

@@ -24,7 +24,6 @@ extern void SetContextMenus(void *, const char *);
import "C"
import (
"encoding/json"
"fmt"
"github.com/wailsapp/wails/v2/pkg/options"
)
@@ -119,29 +118,11 @@ func (a *Application) processPlatformSettings() error {
// Process context menus
contextMenus := options.GetContextMenus(a.config)
if contextMenus != nil {
type ProcessedContextMenu struct {
ID string
ProcessedMenu *ProcessedMenu
}
var processedContextMenus []*ProcessedContextMenu
// We need to iterate each context menu and pre-process it
for contextMenuID, contextMenu := range contextMenus.Items {
thisContextMenu := &ProcessedContextMenu{
ID: contextMenuID,
ProcessedMenu: NewProcessedMenu(contextMenu),
}
processedContextMenus = append(processedContextMenus, thisContextMenu )
}
contextMenusJSON, err := json.Marshal(processedContextMenus)
fmt.Printf("\n\nCONTEXT MENUS:\n %+v\n\n", string(contextMenusJSON))
contextMenusJSON, err := processContextMenus(contextMenus)
if err != nil {
return err
}
C.SetContextMenus(a.app, a.string2CString(string(contextMenusJSON)))
C.SetContextMenus(a.app, a.string2CString(contextMenusJSON))
}
return nil

View File

@@ -51,7 +51,7 @@ func (p *ProcessedMenu) processMenuItem(item *menu.MenuItem) {
p.finaliseRadioGroup()
// Process each submenu item
for _, subitem := range item.SubMenu {
for _, subitem := range item.SubMenu.Items {
p.processMenuItem(subitem)
}
case menu.RadioType:

View File

@@ -652,9 +652,15 @@ void processMenuItem(Menu *menu, id parentMenu, JsonNode *item) {
msg(thisMenuItem, s("setSubmenu:"), thisMenu);
msg(parentMenu, s("addItem:"), thisMenuItem);
JsonNode *submenuItems = json_find_member(submenu, "Items");
// If we have no items, just return
if ( submenuItems == NULL ) {
return;
}
// Loop over submenu items
JsonNode *item;
json_foreach(item, submenu) {
json_foreach(item, submenuItems) {
// Get item label
processMenuItem(menu, thisMenu, item);
}

View File

@@ -158,7 +158,7 @@ func (c *ContextMenus) processContextMenus(contextMenus *menu.ContextMenus) {
func (c *ContextMenus) processMenuItem(item *menu.MenuItem) {
if item.SubMenu != nil {
for _, submenuitem := range item.SubMenu {
for _, submenuitem := range item.SubMenu.Items {
c.processMenuItem(submenuitem)
}
return

View File

@@ -153,7 +153,7 @@ func (m *Menu) processMenu(applicationMenu *menu.Menu) {
func (m *Menu) processMenuItem(item *menu.MenuItem) {
if item.SubMenu != nil {
for _, submenuitem := range item.SubMenu {
for _, submenuitem := range item.SubMenu.Items {
m.processMenuItem(submenuitem)
}
return

View File

@@ -160,7 +160,7 @@ func (t *Tray) processMenu(trayMenu *menu.Menu) {
func (t *Tray) processMenuItem(item *menu.MenuItem) {
if item.SubMenu != nil {
for _, submenuitem := range item.SubMenu {
for _, submenuitem := range item.SubMenu.Items {
t.processMenuItem(submenuitem)
}
return

View File

@@ -12,6 +12,10 @@ func (m *Menu) Append(item *MenuItem) {
m.Items = append(m.Items, item)
}
func (m *Menu) Prepend(item *MenuItem) {
m.Items = append([]*MenuItem{item}, m.Items...)
}
func NewMenuFromItems(first *MenuItem, rest ...*MenuItem) *Menu {
var result = NewMenu()
@@ -49,3 +53,9 @@ func (m *Menu) RemoveByID(id string) bool {
}
return false
}
func (m *Menu) setParent(menuItem *MenuItem) {
for _, item := range m.Items {
item.parent = menuItem
}
}

View File

@@ -21,7 +21,8 @@ type MenuItem struct {
// Checked indicates if the item is selected (used by Checkbox and Radio types only)
Checked bool
// Submenu contains a list of menu items that will be shown as a submenu
SubMenu []*MenuItem `json:"SubMenu,omitempty"`
//SubMenu []*MenuItem `json:"SubMenu,omitempty"`
SubMenu *Menu `json:"SubMenu,omitempty"`
// Foreground colour in hex RGBA format EG: 0xFF0000FF = #FF0000FF = red
Foreground int
@@ -48,7 +49,7 @@ func (m *MenuItem) Append(item *MenuItem) bool {
return false
}
item.parent = m
m.SubMenu = append(m.SubMenu, item)
m.SubMenu.Append(item)
return true
}
@@ -61,7 +62,7 @@ func (m *MenuItem) Prepend(item *MenuItem) bool {
return false
}
item.parent = m
m.SubMenu = append([]*MenuItem{item}, m.SubMenu...)
m.SubMenu.Prepend(item)
return true
}
@@ -72,8 +73,13 @@ func (m *MenuItem) getByID(id string) *MenuItem {
return m
}
// If we have no submenu then exit early
if m.SubMenu == nil {
return nil
}
// Check submenus
for _, submenu := range m.SubMenu {
for _, submenu := range m.SubMenu.Items {
result := submenu.getByID(id)
if result != nil {
return result
@@ -85,9 +91,14 @@ func (m *MenuItem) getByID(id string) *MenuItem {
func (m *MenuItem) removeByID(id string) bool {
for index, item := range m.SubMenu {
// If we have no submenu, return
if m.SubMenu == nil {
return false
}
for index, item := range m.SubMenu.Items {
if item.ID == id {
m.SubMenu = append(m.SubMenu[:index], m.SubMenu[index+1:]...)
m.SubMenu.Items = append(m.SubMenu.Items[:index], m.SubMenu.Items[index+1:]...)
return true
}
if item.isSubMenu() {
@@ -181,7 +192,7 @@ func (m *MenuItem) getItemIndex(target *MenuItem) int {
}
// hunt down that bad boy
for index, item := range m.SubMenu {
for index, item := range m.SubMenu.Items {
if item == target {
return index
}
@@ -196,7 +207,7 @@ func (m *MenuItem) getItemIndex(target *MenuItem) int {
func (m *MenuItem) insertItemAtIndex(index int, target *MenuItem) bool {
// If index is OOB, return false
if index > len(m.SubMenu) {
if index > len(m.SubMenu.Items) {
return false
}
@@ -204,13 +215,13 @@ func (m *MenuItem) insertItemAtIndex(index int, target *MenuItem) bool {
target.parent = m
// If index is last item, then just regular append
if index == len(m.SubMenu) {
m.SubMenu = append(m.SubMenu, target)
if index == len(m.SubMenu.Items) {
m.SubMenu.Items = append(m.SubMenu.Items, target)
return true
}
m.SubMenu = append(m.SubMenu[:index+1], m.SubMenu[index:]...)
m.SubMenu[index] = target
m.SubMenu.Items = append(m.SubMenu.Items[:index+1], m.SubMenu.Items[index:]...)
m.SubMenu.Items[index] = target
return true
}
@@ -254,34 +265,28 @@ func Checkbox(label string, id string, checked bool, accelerator *keys.Accelerat
}
// SubMenu is a helper to create Submenus
func SubMenu(label string, items []*MenuItem) *MenuItem {
func SubMenu(label string, menu *Menu) *MenuItem {
result := &MenuItem{
Label: label,
SubMenu: items,
SubMenu: menu,
Type: SubmenuType,
}
// Fix up parent pointers
for _, item := range items {
item.parent = result
}
menu.setParent(result)
return result
}
// SubMenuWithID is a helper to create Submenus with an ID
func SubMenuWithID(label string, id string, items []*MenuItem) *MenuItem {
func SubMenuWithID(label string, id string, menu *Menu) *MenuItem {
result := &MenuItem{
Label: label,
SubMenu: items,
SubMenu: menu,
ID: id,
Type: SubmenuType,
}
// Fix up parent pointers
for _, item := range items {
item.parent = result
}
menu.setParent(result)
return result
}

View File

@@ -22,7 +22,6 @@ func (c *ContextMenu) WailsInit(runtime *wails.Runtime) error {
// Setup Menu Listeners
c.runtime.ContextMenu.On("Test Context Menu", func(mi *menu.MenuItem, contextData string) {
fmt.Printf("\n\nContext Data = '%s'\n\n", contextData)
c.lock.Lock()
c.counter++
mi.Label = fmt.Sprintf("Clicked %d times", c.counter)
@@ -35,6 +34,18 @@ func (c *ContextMenu) WailsInit(runtime *wails.Runtime) error {
func createContextMenus() *menu.ContextMenus {
result := menu.NewContextMenus()
result.AddMenu("test", menu.NewMenuFromItems(menu.Text("Clicked 0 times", "Test Context Menu", nil)))
result.AddMenu("test", menu.NewMenuFromItems(
menu.Text("Clicked 0 times", "Test Context Menu", nil),
menu.Separator(),
menu.Checkbox("I am a checkbox", "checkbox", false, nil),
menu.Separator(),
menu.Radio("Radio Option 1", "Radio Option 1", true, nil),
menu.Radio("Radio Option 2", "Radio Option 2", false, nil),
menu.Radio("Radio Option 3", "Radio Option 3", false, nil),
menu.Separator(),
menu.SubMenu("A Submenu", menu.NewMenuFromItems(
menu.Text("Hello", "Hello", nil),
)),
))
return result
}

View File

@@ -124,13 +124,13 @@ func (m *Menu) removeMenu(_ *menu.MenuItem) {
func (m *Menu) createDynamicMenuTwo() {
// Create our submenu
dm2 := menu.SubMenu("Dynamic Menus 2", []*menu.MenuItem{
dm2 := menu.SubMenu("Dynamic Menus 2", menu.NewMenuFromItems(
menu.Text("Insert Before Random Menu Item",
"Insert Before Random", keys.CmdOrCtrl("]")),
menu.Text("Insert After Random Menu Item",
"Insert After Random", keys.CmdOrCtrl("[")),
menu.Separator(),
})
))
m.runtime.Menu.On("Insert Before Random", m.insertBeforeRandom)
m.runtime.Menu.On("Insert After Random", m.insertAfterRandom)
@@ -229,7 +229,7 @@ func createApplicationMenu() *menu.Menu {
// Create menu
myMenu := menu.DefaultMacMenu()
windowMenu := menu.SubMenu("Test", []*menu.MenuItem{
windowMenu := menu.SubMenu("Test", menu.NewMenuFromItems(
menu.Togglefullscreen(),
menu.Minimize(),
menu.Zoom(),
@@ -244,17 +244,17 @@ func createApplicationMenu() *menu.Menu {
menu.Front(),
menu.SubMenu("Test Submenu", []*menu.MenuItem{
menu.SubMenu("Test Submenu", menu.NewMenuFromItems(
menu.Text("Plain text", "plain text", nil),
menu.Text("Show Dynamic Menus 2 Submenu", "show-dynamic-menus-2", nil),
menu.SubMenu("Accelerators", []*menu.MenuItem{
menu.SubMenu("Modifiers", []*menu.MenuItem{
menu.SubMenu("Accelerators", menu.NewMenuFromItems(
menu.SubMenu("Modifiers", menu.NewMenuFromItems(
menu.Text("Shift accelerator", "Shift", keys.Shift("o")),
menu.Text("Control accelerator", "Control", keys.Control("o")),
menu.Text("Command accelerator", "Command", keys.CmdOrCtrl("o")),
menu.Text("Option accelerator", "Option", keys.OptionOrAlt("o")),
}),
menu.SubMenu("System Keys", []*menu.MenuItem{
)),
menu.SubMenu("System Keys", menu.NewMenuFromItems(
menu.Text("Backspace", "Backspace", keys.Key("Backspace")),
menu.Text("Tab", "Tab", keys.Key("Tab")),
menu.Text("Return", "Return", keys.Key("Return")),
@@ -270,8 +270,8 @@ func createApplicationMenu() *menu.Menu {
menu.Text("Page Up", "Page Up", keys.Key("Page Up")),
menu.Text("Page Down", "Page Down", keys.Key("Page Down")),
menu.Text("NumLock", "NumLock", keys.Key("NumLock")),
}),
menu.SubMenu("Function Keys", []*menu.MenuItem{
)),
menu.SubMenu("Function Keys", menu.NewMenuFromItems(
menu.Text("F1", "F1", keys.Key("F1")),
menu.Text("F2", "F2", keys.Key("F2")),
menu.Text("F3", "F3", keys.Key("F3")),
@@ -292,28 +292,28 @@ func createApplicationMenu() *menu.Menu {
menu.Text("F18", "F18", keys.Key("F18")),
menu.Text("F19", "F19", keys.Key("F19")),
menu.Text("F20", "F20", keys.Key("F20")),
}),
menu.SubMenu("Standard Keys", []*menu.MenuItem{
)),
menu.SubMenu("Standard Keys", menu.NewMenuFromItems(
menu.Text("Backtick", "Backtick", keys.Key("`")),
menu.Text("Plus", "Plus", keys.Key("+")),
}),
}),
menu.SubMenuWithID("Dynamic Menus 1", "Dynamic Menus 1", []*menu.MenuItem{
)),
)),
menu.SubMenuWithID("Dynamic Menus 1", "Dynamic Menus 1", menu.NewMenuFromItems(
menu.Text("Add Menu Item", "Add Menu Item", keys.CmdOrCtrl("+")),
menu.Separator(),
}),
{
)),
&menu.MenuItem{
Label: "Disabled Menu",
Type: menu.TextType,
Accelerator: keys.Combo("p", keys.CmdOrCtrlKey, keys.ShiftKey),
Disabled: true,
},
{
&menu.MenuItem{
Label: "Hidden Menu",
Type: menu.TextType,
Hidden: true,
},
{
&menu.MenuItem{
ID: "checkbox-menu 1",
Label: "Checkbox Menu 1",
Type: menu.CheckboxType,
@@ -325,8 +325,8 @@ func createApplicationMenu() *menu.Menu {
menu.Radio("😀 Option 1", "😀option-1", true, nil),
menu.Radio("😺 Option 2", "option-2", false, nil),
menu.Radio("❤️ Option 3", "option-3", false, nil),
}),
})
)),
))
myMenu.Append(windowMenu)
return myMenu