5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-03 02:31:58 +08:00

Fixed and refactored context menu support

This commit is contained in:
Lea Anthony 2021-01-13 22:51:44 +11:00
parent de06fc7dcc
commit e65118e962
No known key found for this signature in database
GPG Key ID: 33DAF7BB90A58405
21 changed files with 223 additions and 325 deletions

View File

@ -63,10 +63,8 @@ func CreateApp(appoptions *options.App) (*App, error) {
// Process context menus
contextMenus := options.GetContextMenus(appoptions)
if contextMenus != nil {
for contextMenuID, contextMenu := range contextMenus.Items {
menuManager.AddContextMenu(contextMenuID, contextMenu)
}
for _, contextMenu := range contextMenus {
menuManager.AddContextMenu(contextMenu)
}
// Process tray menus

View File

@ -8,9 +8,20 @@
#include "contextmenus_darwin.h"
#include "menu_darwin.h"
ContextMenu* NewContextMenu(JsonNode* menuData, ContextMenuStore *store) {
ContextMenu* NewContextMenu(const char* contextMenuJSON) {
ContextMenu* result = malloc(sizeof(ContextMenu));
result->menu = NewMenu(menuData);
JsonNode* processedJSON = json_decode(contextMenuJSON);
if( processedJSON == NULL ) {
ABORT("[NewTrayMenu] Unable to parse TrayMenu JSON: %s", contextMenuJSON);
}
// Save reference to this json
result->processedJSON = processedJSON;
result->ID = mustJSONString(processedJSON, "ID");
JsonNode* processedMenu = mustJSONObject(processedJSON, "ProcessedMenu");
result->menu = NewMenu(processedMenu);
result->nsmenu = NULL;
result->menu->menuType = ContextMenuType;
result->menu->parentData = result;
@ -18,9 +29,8 @@ ContextMenu* NewContextMenu(JsonNode* menuData, ContextMenuStore *store) {
return result;
}
ContextMenu* GetContextMenuByID(ContextMenuStore* store, const char *contextMenuID) {
return (ContextMenu*)hashmap_get(&store->contextMenuStore, (char*)contextMenuID, strlen(contextMenuID));
return (ContextMenu*)hashmap_get(&store->contextMenuMap, (char*)contextMenuID, strlen(contextMenuID));
}
void DeleteContextMenu(ContextMenu* contextMenu) {
@ -32,6 +42,12 @@ void DeleteContextMenu(ContextMenu* contextMenu) {
MEMFREE(contextMenu->contextMenuData);
}
// Free JSON
if (contextMenu->processedJSON != NULL ) {
json_delete(contextMenu->processedJSON);
contextMenu->processedJSON = NULL;
}
// Free context menu
free(contextMenu);
}
@ -41,43 +57,6 @@ int freeContextMenu(void *const context, struct hashmap_element_s *const e) {
return -1;
}
void ProcessContextMenus(ContextMenuStore* store) {
// Decode the context menus JSON
store->processedContextMenus = json_decode(store->contextMenusAsJSON);
if( store->processedContextMenus == NULL ) {
ABORT("[ProcessContextMenus] Unable to parse Context Menus JSON: %s", store->contextMenusAsJSON);
}
// // Get the context menu items
// JsonNode *contextMenuItems = json_find_member(store->processedContextMenus, "Items");
// if( contextMenuItems == NULL ) {
// ABORT("[ProcessContextMenus] Unable to find Items in processedContextMenus!");
// }
// Iterate context menus
JsonNode *contextMenu;
json_foreach(contextMenu, store->processedContextMenus) {
const char* ID = getJSONString(contextMenu, "ID");
if ( ID == NULL ) {
ABORT("Unable to read ID of contextMenu\n");
}
JsonNode* processedMenu = json_find_member(contextMenu, "ProcessedMenu");
if ( processedMenu == NULL ) {
ABORT("Unable to read ProcessedMenu of contextMenu\n");
}
// Create a new context menu instance
ContextMenu *thisContextMenu = NewContextMenu(processedMenu, store);
thisContextMenu->ID = ID;
// Store the item in the context menu map
hashmap_put(&store->contextMenuStore, (char*)ID, strlen(ID), thisContextMenu);
}
}
void ShowContextMenu(ContextMenuStore* store, id mainWindow, const char *contextMenuID, const char *contextMenuData) {
// If no context menu ID was given, abort

View File

@ -14,17 +14,19 @@ typedef struct {
id nsmenu;
Menu* menu;
// The optional data that may be passed with a context menu selection
JsonNode* processedJSON;
// Context menu data is given by the frontend when clicking a context menu.
// We send this to the backend when an item is selected
const char* contextMenuData;
} ContextMenu;
ContextMenu* NewContextMenu(JsonNode* menuData, ContextMenuStore* store);
ContextMenu* NewContextMenu(const char* contextMenuJSON);
ContextMenu* GetContextMenuByID( ContextMenuStore* store, const char *contextMenuID);
void DeleteContextMenu(ContextMenu* contextMenu);
int freeContextMenu(void *const context, struct hashmap_element_s *const e);
void ProcessContextMenus( ContextMenuStore* store);
void ShowContextMenu(ContextMenuStore* store, id mainWindow, const char *contextMenuID, const char *contextMenuData);

View File

@ -2,22 +2,48 @@
#include "contextmenus_darwin.h"
#include "contextmenustore_darwin.h"
ContextMenuStore* NewContextMenuStore(const char* contextMenusAsJSON) {
ContextMenuStore* NewContextMenuStore() {
ContextMenuStore* result = malloc(sizeof(ContextMenuStore));
// Init members
result->contextMenusAsJSON = contextMenusAsJSON;
result->processedContextMenus = NULL;
// Allocate Context Menu Store
if( 0 != hashmap_create((const unsigned)4, &result->contextMenuStore)) {
if( 0 != hashmap_create((const unsigned)4, &result->contextMenuMap)) {
ABORT("[NewContextMenus] Not enough memory to allocate contextMenuStore!");
}
return result;
}
void AddContextMenuToStore(ContextMenuStore* store, const char* contextMenuJSON) {
ContextMenu* newMenu = NewContextMenu(contextMenuJSON);
//TODO: check if there is already an entry for this menu
hashmap_put(&store->contextMenuMap, newMenu->ID, strlen(newMenu->ID), newMenu);
}
ContextMenu* GetContextMenuFromStore(ContextMenuStore* store, const char* menuID) {
// Get the current menu
return hashmap_get(&store->contextMenuMap, menuID, strlen(menuID));
}
void UpdateContextMenuInStore(ContextMenuStore* store, const char* menuJSON) {
ContextMenu* newContextMenu = NewContextMenu(menuJSON);
// Get the current menu
ContextMenu *currentMenu = GetContextMenuFromStore(store, newContextMenu->ID);
if ( currentMenu == NULL ) {
ABORT("Attempted to update unknown context menu with ID '%s'.", newContextMenu->ID);
}
hashmap_remove(&store->contextMenuMap, newContextMenu->ID, strlen(newContextMenu->ID));
// Save the status bar reference
DeleteContextMenu(currentMenu);
hashmap_put(&store->contextMenuMap, newContextMenu->ID, strlen(newContextMenu->ID), newContextMenu);
}
void DeleteContextMenuStore(ContextMenuStore* store) {
@ -27,19 +53,13 @@ void DeleteContextMenuStore(ContextMenuStore* store) {
}
// Delete context menus
if( hashmap_num_entries(&store->contextMenuStore) > 0 ) {
if (0 != hashmap_iterate_pairs(&store->contextMenuStore, freeContextMenu, NULL)) {
if( hashmap_num_entries(&store->contextMenuMap) > 0 ) {
if (0 != hashmap_iterate_pairs(&store->contextMenuMap, freeContextMenu, NULL)) {
ABORT("[DeleteContextMenuStore] Failed to release contextMenuStore entries!");
}
}
// Free context menu hashmap
hashmap_destroy(&store->contextMenuStore);
// Destroy processed Context Menus
if( store->processedContextMenus != NULL) {
json_delete(store->processedContextMenus);
store->processedContextMenus = NULL;
}
hashmap_destroy(&store->contextMenuMap);
}

View File

@ -8,19 +8,20 @@
#include "common.h"
typedef struct {
int dummy;
// This is our context menu store which keeps track
// of all instances of ContextMenus
struct hashmap_s contextMenuStore;
// The raw JSON defining the context menus
const char* contextMenusAsJSON;
// The processed context menus
JsonNode* processedContextMenus;
struct hashmap_s contextMenuMap;
} ContextMenuStore;
ContextMenuStore* NewContextMenuStore(const char* contextMenusAsJSON);
ContextMenuStore* NewContextMenuStore();
void DeleteContextMenuStore(ContextMenuStore* store);
void UpdateContextMenuInStore(ContextMenuStore* store, const char* menuJSON);
void AddContextMenuToStore(ContextMenuStore* store, const char* contextMenuJSON);
#endif //CONTEXTMENUSTORE_DARWIN_H

View File

@ -35,11 +35,9 @@ extern void SaveDialog(struct Application*, char *callbackID, char *title, char
extern void MessageDialog(struct Application*, char *callbackID, char *type, char *title, char *message, char *icon, char *button1, char *button2, char *button3, char *button4, char *defaultButton, char *cancelButton);
extern void DarkModeEnabled(struct Application*, char *callbackID);
extern void SetApplicationMenu(struct Application*, const char *);
extern void UpdateTray(struct Application*, char *menuAsJSON);
extern void UpdateContextMenus(struct Application*, char *contextMenusAsJSON);
extern void UpdateTrayLabel(struct Application*, const char *label);
extern void UpdateTrayIcon(struct Application*, const char *label);
extern void AddTrayMenu(struct Application*, const char *trayAsJSON);
extern void UpdateTrayMenu(struct Application*, const char *trayAsJSON);
extern void AddTrayMenu(struct Application*, const char *menuTrayJSON);
extern void UpdateTrayMenu(struct Application*, const char *menuTrayJSON);
extern void AddContextMenu(struct Application*, char *contextMenuJSON);
extern void UpdateContextMenu(struct Application*, char *contextMenuJSON);
#endif

View File

@ -12,7 +12,6 @@ package ffenestri
import "C"
import (
"github.com/wailsapp/wails/v2/pkg/menu"
"strconv"
"github.com/wailsapp/wails/v2/internal/logger"
@ -193,17 +192,6 @@ func (c *Client) UpdateTrayMenu(trayMenuJSON string) {
C.UpdateTrayMenu(c.app.app, c.app.string2CString(trayMenuJSON))
}
func (c *Client) UpdateContextMenus(contextMenus *menu.ContextMenus) {
//
// // Guard against nil contextMenus
// if contextMenus == nil {
// return
// }
// // Process the menu
// contextMenusJSON, err := processContextMenus(contextMenus)
// if err != nil {
// c.app.logger.Error("Error processing updated Context Menu: %s", err.Error())
// return
// }
// C.UpdateContextMenus(c.app.app, c.app.string2CString(contextMenusJSON))
func (c *Client) UpdateContextMenu(contextMenuJSON string) {
C.UpdateContextMenu(c.app.app, c.app.string2CString(contextMenuJSON))
}

View File

@ -117,8 +117,6 @@ struct Application {
// Context Menus
ContextMenuStore *contextMenuStore;
const char *contextMenusAsJSON;
JsonNode *processedContextMenus;
// Callback
ffenestriCallback sendMessageToBackend;
@ -427,9 +425,12 @@ void DestroyApplication(struct Application *app) {
DeleteMenu(app->applicationMenu);
}
// Delete the tray menu store
// Delete the tray menu store
DeleteTrayMenuStore(app->trayMenuStore);
// Delete the context menu store
DeleteContextMenuStore(app->contextMenuStore);
// Destroy the context menus
destroyContextMenus(app);
@ -439,11 +440,6 @@ void DestroyApplication(struct Application *app) {
// Unload the tray Icons
UnloadTrayIcons();
// Clear context menu data if we have it
if( contextMenuData != NULL ) {
MEMFREE(contextMenuData);
}
// Remove script handlers
msg(app->manager, s("removeScriptMessageHandlerForName:"), str("contextMenu"));
msg(app->manager, s("removeScriptMessageHandlerForName:"), str("windowDrag"));
@ -916,17 +912,20 @@ void SetDebug(void *applicationPointer, int flag) {
// SetContextMenus sets the context menu map for this application
void SetContextMenus(struct Application *app, const char *contextMenusAsJSON) {
app->contextMenuStore = NewContextMenuStore(contextMenusAsJSON);
void AddContextMenu(struct Application *app, const char *contextMenuJSON) {
AddContextMenuToStore(app->contextMenuStore, contextMenuJSON);
}
void AddTrayMenu(struct Application *app, const char *trayJSON) {
AddTrayMenuToStore(app->trayMenuStore, trayJSON);
void UpdateContextMenu(struct Application *app, const char* contextMenuJSON) {
UpdateContextMenuInStore(app->contextMenuStore, contextMenuJSON);
}
void UpdateTrayMenu(struct Application *app, const char* trayJSON) {
UpdateTrayMenuInStore(app->trayMenuStore, trayJSON);
void AddTrayMenu(struct Application *app, const char *trayMenuJSON) {
AddTrayMenuToStore(app->trayMenuStore, trayMenuJSON);
}
void UpdateTrayMenu(struct Application *app, const char* trayMenuJSON) {
UpdateTrayMenuInStore(app->trayMenuStore, trayMenuJSON);
}
void SetBindings(struct Application *app, const char *bindings) {
@ -1428,84 +1427,6 @@ void SetApplicationMenu(struct Application *app, const char *menuAsJSON) {
updateMenu(app, menuAsJSON);
}
//void dumpContextMenus(struct Application *app) {
// dumpHashmap("menuItemMapForContextMenus", &menuItemMapForContextMenus);
// printf("&menuItemMapForContextMenus = %p\n", &menuItemMapForContextMenus);
//
// //Free radio groups hashmap
// dumpHashmap("radioGroupMapForContextMenus", &radioGroupMapForContextMenus);
// printf("&radioGroupMapForContextMenus = %p\n", &radioGroupMapForContextMenus);
//
// //Free context menu map
// dumpHashmap("contextMenuMap", &contextMenuMap);
// printf("&contextMenuMap = %p\n", &contextMenuMap);
//}
//void parseContextMenus(struct Application *app) {
//
// // Parse the context menu json
// app->processedContextMenus = json_decode(app->contextMenusAsJSON);
//
// if( app->processedContextMenus == NULL ) {
// // Parse error!
// Fatal(app, "Unable to parse Context Menus JSON: %s", app->contextMenusAsJSON);
// return;
// }
//
// JsonNode *contextMenuItems = json_find_member(app->processedContextMenus, "Items");
// if( contextMenuItems == NULL ) {
// // Parse error!
// Fatal(app, "Unable to find Items:", app->processedContextMenus);
// return;
// }
// // Iterate context menus
// JsonNode *contextMenu;
// json_foreach(contextMenu, contextMenuItems) {
// // Create a new menu
// id menu = createMenu(str(""));
//
// // parse the menu
// parseMenu(app, menu, contextMenu, &menuItemMapForContextMenus,
// "checkboxMenuCallbackForContextMenus:", "radioMenuCallbackForContextMenus:", "menuCallbackForContextMenus:");
//
// // Store the item in the context menu map
// hashmap_put(&contextMenuMap, (char*)contextMenu->key, strlen(contextMenu->key), menu);
// }
//
//// dumpContextMenus(app);
//}
void UpdateTrayLabel(struct Application *app, const char *label) {
// TBD
}
void UpdateTrayIcon(struct Application *app, const char *name) {
// TBD
}
// UpdateTray replaces the current tray menu with the given one
void UpdateTray(struct Application *app, const char *trayMenuAsJSON) {
ON_MAIN_THREAD (
// TBD
);
}
void UpdateContextMenus(struct Application *app, const char *contextMenusAsJSON) {
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[]) {
unsigned int count = 0;
@ -1727,11 +1648,6 @@ void Run(struct Application *app, int argc, char **argv) {
// Setup initial trays
ShowTrayMenusInStore(app->trayMenuStore);
// If we have context menus, process them
if( app->contextMenuStore != NULL ) {
ProcessContextMenus(app->contextMenuStore);
}
// Process dialog icons
processUserDialogIcons(app);
@ -1793,10 +1709,7 @@ void* NewApplication(const char *title, int width, int height, int resizable, in
result->trayMenuStore = NewTrayMenuStore();
// Context Menus
result->contextMenuStore = NULL;
result->contextMenusAsJSON = NULL;
result->processedContextMenus = NULL;
contextMenuData = NULL;
result->contextMenuStore = NewContextMenuStore();
// Window Appearance
result->titlebarAppearsTransparent = 0;

View File

@ -72,20 +72,20 @@ func (a *Application) processPlatformSettings() error {
}
if trays != nil {
for _, tray := range trays {
println("Adding tray menu: " + tray)
C.AddTrayMenu(a.app, a.string2CString(tray))
}
}
// Process context menus
//contextMenus := options.GetContextMenus(a.config)
//if contextMenus != nil {
// contextMenusJSON, err := processContextMenus(contextMenus)
// if err != nil {
// return err
// }
// C.SetContextMenus(a.app, a.string2CString(contextMenusJSON))
//}
contextMenus, err := a.menuManager.GetContextMenus()
if err != nil {
return err
}
if contextMenus != nil {
for _, contextMenu := range contextMenus {
C.AddContextMenu(a.app, a.string2CString(contextMenu))
}
}
return nil
}

View File

@ -30,6 +30,8 @@ void DumpTrayMenuStore(TrayMenuStore* store) {
void AddTrayMenuToStore(TrayMenuStore* store, const char* menuJSON) {
TrayMenu* newMenu = NewTrayMenu(menuJSON);
//TODO: check if there is already an entry for this menu
hashmap_put(&store->trayMenuMap, newMenu->ID, strlen(newMenu->ID), newMenu);
}

View File

@ -1,47 +1,60 @@
package menumanager
import (
"encoding/json"
"fmt"
"github.com/wailsapp/wails/v2/pkg/menu"
)
type ContextMenu struct {
ID string
JSON string
menuItemMap *MenuItemMap
menu *menu.Menu
ID string
ProcessedMenu *WailsMenu
menuItemMap *MenuItemMap
menu *menu.Menu
}
func NewContextMenu(ID string, menu *menu.Menu) *ContextMenu {
func (t *ContextMenu) AsJSON() (string, error) {
data, err := json.Marshal(t)
if err != nil {
return "", err
}
return string(data), nil
}
func NewContextMenu(contextMenu *menu.ContextMenu) *ContextMenu {
result := &ContextMenu{
ID: ID,
JSON: "",
menu: menu,
ID: contextMenu.ID,
menu: contextMenu.Menu,
menuItemMap: NewMenuItemMap(),
}
result.menuItemMap.AddMenu(menu)
result.menuItemMap.AddMenu(contextMenu.Menu)
result.ProcessedMenu = NewWailsMenu(result.menuItemMap, result.menu)
return result
}
func (m *Manager) AddContextMenu(menuID string, menu *menu.Menu) error {
contextMenu := NewContextMenu(menuID, menu)
m.contextMenus[menuID] = contextMenu
return contextMenu.process()
func (m *Manager) AddContextMenu(contextMenu *menu.ContextMenu) {
newContextMenu := NewContextMenu(contextMenu)
// Save the references
m.contextMenus[contextMenu.ID] = newContextMenu
m.contextMenuPointers[contextMenu] = contextMenu.ID
}
func (c *ContextMenu) process() error {
// Process the menu
processedApplicationMenu := NewWailsMenu(c.menuItemMap, c.menu)
JSON, err := processedApplicationMenu.AsJSON()
if err != nil {
return err
func (m *Manager) UpdateContextMenu(contextMenu *menu.ContextMenu) (string, error) {
contextMenuID, contextMenuKnown := m.contextMenuPointers[contextMenu]
if !contextMenuKnown {
return "", fmt.Errorf("unknown Context Menu '%s'. Please add the context menu using AddContextMenu()", contextMenu.ID)
}
c.JSON = JSON
fmt.Printf("Processed context menu '%s':", c.ID)
println(JSON)
return nil
// Create the updated context menu
updatedContextMenu := NewContextMenu(contextMenu)
// Save the reference
m.contextMenus[contextMenuID] = updatedContextMenu
return updatedContextMenu.AsJSON()
}

View File

@ -15,7 +15,8 @@ type Manager struct {
applicationMenuItemMap *MenuItemMap
// Context menus
contextMenus map[string]*ContextMenu
contextMenus map[string]*ContextMenu
contextMenuPointers map[*menu.ContextMenu]string
// Tray menu stores
trayMenus map[string]*TrayMenu
@ -26,6 +27,7 @@ func NewManager() *Manager {
return &Manager{
applicationMenuItemMap: NewMenuItemMap(),
contextMenus: make(map[string]*ContextMenu),
contextMenuPointers: make(map[*menu.ContextMenu]string),
trayMenus: make(map[string]*TrayMenu),
trayMenuPointers: make(map[*menu.TrayMenu]string),
}

View File

@ -90,3 +90,16 @@ func (m *Manager) GetTrayMenus() ([]string, error) {
return result, nil
}
func (m *Manager) GetContextMenus() ([]string, error) {
result := []string{}
for _, contextMenu := range m.contextMenus {
JSON, err := contextMenu.AsJSON()
if err != nil {
return nil, err
}
result = append(result, JSON)
}
return result, nil
}

View File

@ -2,8 +2,6 @@ package messagedispatcher
import (
"fmt"
"github.com/wailsapp/wails/v2/pkg/menu"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/internal/messagedispatcher/message"
"github.com/wailsapp/wails/v2/internal/servicebus"
@ -33,8 +31,8 @@ type Client interface {
WindowSetColour(colour int)
DarkModeEnabled(callbackID string)
SetApplicationMenu(menuJSON string)
UpdateTrayMenu(menuJSON string)
UpdateContextMenus(contextMenus *menu.ContextMenus)
UpdateTrayMenu(trayMenuJSON string)
UpdateContextMenu(contextMenuJSON string)
}
// DispatchClient is what the frontends use to interface with the

View File

@ -2,7 +2,6 @@ package messagedispatcher
import (
"encoding/json"
"github.com/wailsapp/wails/v2/pkg/menu"
"strconv"
"strings"
"sync"
@ -17,15 +16,14 @@ import (
// Dispatcher translates messages received from the frontend
// and publishes them onto the service bus
type Dispatcher struct {
quitChannel <-chan *servicebus.Message
resultChannel <-chan *servicebus.Message
eventChannel <-chan *servicebus.Message
windowChannel <-chan *servicebus.Message
dialogChannel <-chan *servicebus.Message
systemChannel <-chan *servicebus.Message
menuChannel <-chan *servicebus.Message
contextMenuChannel <-chan *servicebus.Message
running bool
quitChannel <-chan *servicebus.Message
resultChannel <-chan *servicebus.Message
eventChannel <-chan *servicebus.Message
windowChannel <-chan *servicebus.Message
dialogChannel <-chan *servicebus.Message
systemChannel <-chan *servicebus.Message
menuChannel <-chan *servicebus.Message
running bool
servicebus *servicebus.ServiceBus
logger logger.CustomLogger
@ -77,23 +75,17 @@ func New(servicebus *servicebus.ServiceBus, logger *logger.Logger) (*Dispatcher,
return nil, err
}
contextMenuChannel, err := servicebus.Subscribe("contextmenufrontend:")
if err != nil {
return nil, err
}
result := &Dispatcher{
servicebus: servicebus,
eventChannel: eventChannel,
logger: logger.CustomLogger("Message Dispatcher"),
clients: make(map[string]*DispatchClient),
resultChannel: resultChannel,
quitChannel: quitChannel,
windowChannel: windowChannel,
dialogChannel: dialogChannel,
systemChannel: systemChannel,
menuChannel: menuChannel,
contextMenuChannel: contextMenuChannel,
servicebus: servicebus,
eventChannel: eventChannel,
logger: logger.CustomLogger("Message Dispatcher"),
clients: make(map[string]*DispatchClient),
resultChannel: resultChannel,
quitChannel: quitChannel,
windowChannel: windowChannel,
dialogChannel: dialogChannel,
systemChannel: systemChannel,
menuChannel: menuChannel,
}
return result, nil
@ -125,8 +117,6 @@ func (d *Dispatcher) Start() error {
d.processSystemMessage(systemMessage)
case menuMessage := <-d.menuChannel:
d.processMenuMessage(menuMessage)
case contextMenuMessage := <-d.contextMenuChannel:
d.processContextMenuMessage(contextMenuMessage)
}
}
@ -468,25 +458,10 @@ func (d *Dispatcher) processMenuMessage(result *servicebus.Message) {
for _, client := range d.clients {
client.frontend.UpdateTrayMenu(updatedTrayMenu)
}
default:
d.logger.Error("Unknown menufrontend command: %s", command)
}
}
func (d *Dispatcher) processContextMenuMessage(result *servicebus.Message) {
splitTopic := strings.Split(result.Topic(), ":")
if len(splitTopic) < 2 {
d.logger.Error("Invalid contextmenu message : %#v", result.Data())
return
}
command := splitTopic[1]
switch command {
case "update":
updatedContextMenus, ok := result.Data().(*menu.ContextMenus)
case "updatecontextmenu":
updatedContextMenu, ok := result.Data().(string)
if !ok {
d.logger.Error("Invalid data for 'contextmenufrontend:update' : %#v",
d.logger.Error("Invalid data for 'menufrontend:updatecontextmenu' : %#v",
result.Data())
return
}
@ -494,10 +469,10 @@ func (d *Dispatcher) processContextMenuMessage(result *servicebus.Message) {
// TODO: Work out what we mean in a multi window environment...
// For now we will just pick the first one
for _, client := range d.clients {
client.frontend.UpdateContextMenus(updatedContextMenus)
client.frontend.UpdateContextMenu(updatedContextMenu)
}
default:
d.logger.Error("Unknown contextmenufrontend command: %s", command)
d.logger.Error("Unknown menufrontend command: %s", command)
}
}

View File

@ -110,16 +110,16 @@ func (m *Menu) Start() error {
m.bus.Publish("menufrontend:updateappmenu", updatedMenu)
case "updatecontextmenu":
m.logger.Info("Update Context Menu TBD")
//contextMenu := menuMessage.Data().(*menu.ContextMenu)
//updatedMenu, err := m.menuManager.UpdateContextMenu(contextMenu)
//if err != nil {
// m.logger.Trace("%s", err.Error())
// return
//}
//
//// Notify frontend of menu change
//m.bus.Publish("menufrontend:updatecontextmenu", updatedMenu)
contextMenu := menuMessage.Data().(*menu.ContextMenu)
updatedMenu, err := m.menuManager.UpdateContextMenu(contextMenu)
if err != nil {
m.logger.Trace("%s", err.Error())
return
}
// Notify frontend of menu change
m.bus.Publish("menufrontend:updatecontextmenu", updatedMenu)
case "updatetraymenu":
trayMenu := menuMessage.Data().(*menu.TrayMenu)
updatedMenu, err := m.menuManager.UpdateTrayMenu(trayMenu)

View File

@ -1,19 +1,5 @@
package menu
type ContextMenus struct {
Items map[string]*Menu
}
func NewContextMenus() *ContextMenus {
return &ContextMenus{
Items: make(map[string]*Menu),
}
}
func (c *ContextMenus) AddMenu(ID string, menu *Menu) {
c.Items[ID] = menu
}
type ContextMenu struct {
ID string
Menu *Menu

View File

@ -10,5 +10,5 @@ type Options struct {
WindowBackgroundIsTranslucent bool
Menu *menu.Menu
TrayMenus []*menu.TrayMenu
ContextMenus *menu.ContextMenus
ContextMenus []*menu.ContextMenu
}

View File

@ -24,7 +24,7 @@ type App struct {
StartHidden bool
DevTools bool
RGBA int
ContextMenus *menu.ContextMenus
ContextMenus []*menu.ContextMenu
TrayMenus []*menu.TrayMenu
Menu *menu.Menu
Mac *mac.Options
@ -89,15 +89,13 @@ func GetApplicationMenu(appoptions *App) *menu.Menu {
return result
}
func GetContextMenus(appoptions *App) *menu.ContextMenus {
var result *menu.ContextMenus
func GetContextMenus(appoptions *App) []*menu.ContextMenu {
var result []*menu.ContextMenu
result = appoptions.ContextMenus
var contextMenuOverrides *menu.ContextMenus
switch runtime.GOOS {
case "darwin":
if appoptions.Mac != nil {
contextMenuOverrides = appoptions.Mac.ContextMenus
result = appoptions.Mac.ContextMenus
}
//case "linux":
// if appoptions.Linux != nil {
@ -109,11 +107,8 @@ func GetContextMenus(appoptions *App) *menu.ContextMenus {
// }
}
// Overwrite defaults with OS Specific context menus
if contextMenuOverrides != nil {
for id, contextMenu := range contextMenuOverrides.Items {
result.AddMenu(id, contextMenu)
}
if result == nil {
result = appoptions.ContextMenus
}
return result

View File

@ -1,6 +1,7 @@
package main
import (
"fmt"
"sync"
"github.com/wailsapp/wails/v2"
@ -9,9 +10,11 @@ import (
// ContextMenu struct
type ContextMenu struct {
runtime *wails.Runtime
counter int
lock sync.Mutex
runtime *wails.Runtime
counter int
lock sync.Mutex
testContextMenu *menu.ContextMenu
clickedMenu *menu.MenuItem
}
// WailsInit is called at application startup
@ -22,10 +25,19 @@ func (c *ContextMenu) WailsInit(runtime *wails.Runtime) error {
return nil
}
func createContextMenus() *menu.ContextMenus {
result := menu.NewContextMenus()
result.AddMenu("test", menu.NewMenuFromItems(
menu.Text("Clicked 0 times", nil, nil),
// Setup Menu Listeners
func (c *ContextMenu) updateContextMenu(_ *menu.CallbackData) {
c.lock.Lock()
c.counter++
c.clickedMenu.Label = fmt.Sprintf("Clicked %d times", c.counter)
c.lock.Unlock()
c.runtime.Menu.UpdateContextMenu(c.testContextMenu)
}
func (c *ContextMenu) createContextMenus() []*menu.ContextMenu {
c.clickedMenu = menu.Text("Clicked 0 times", nil, c.updateContextMenu)
c.testContextMenu = menu.NewContextMenu("test", menu.NewMenuFromItems(
c.clickedMenu,
menu.Separator(),
menu.Checkbox("I am a checkbox", false, nil, nil),
menu.Separator(),
@ -37,5 +49,7 @@ func createContextMenus() *menu.ContextMenus {
menu.Text("Hello", nil, nil),
)),
))
return result
return []*menu.ContextMenu{
c.testContextMenu,
}
}

View File

@ -12,6 +12,7 @@ func main() {
Menu := &Menu{}
Tray := &Tray{}
ContextMenu := &ContextMenu{}
// Create application with options
app, err := wails.CreateAppWithOptions(&options.App{
@ -23,7 +24,7 @@ func main() {
//Tray: menu.NewMenuFromItems(menu.AppMenu()),
//Menu: menu.NewMenuFromItems(menu.AppMenu()),
//StartHidden: true,
ContextMenus: createContextMenus(),
ContextMenus: ContextMenu.createContextMenus(),
Mac: &mac.Options{
WebviewIsTransparent: true,
WindowBackgroundIsTranslucent: true,
@ -47,7 +48,7 @@ func main() {
app.Bind(&Window{})
app.Bind(Menu)
app.Bind(Tray)
app.Bind(&ContextMenu{})
app.Bind(ContextMenu)
err = app.Run()
if err != nil {