mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-02 20:03:01 +08:00
Support Menu updates!
This commit is contained in:
parent
7347d2caa2
commit
8053357d99
@ -33,7 +33,7 @@ extern void OpenDialog(void *appPointer, char *callbackID, char *title, char *fi
|
||||
extern void SaveDialog(void *appPointer, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int showHiddenFiles, int canCreateDirectories, int treatPackagesAsDirectories);
|
||||
extern void MessageDialog(void *appPointer, 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(void *appPointer, char *callbackID);
|
||||
extern void UpdateMenu(void *app, char *menuAsJSON);
|
||||
extern void SetApplicationMenu(void *, const char *);
|
||||
extern void UpdateTray(void *app, char *menuAsJSON);
|
||||
extern void UpdateContextMenus(void *app, char *contextMenusAsJSON);
|
||||
extern void UpdateTrayLabel(void *app, const char *label);
|
||||
|
@ -186,20 +186,8 @@ func (c *Client) DarkModeEnabled(callbackID string) {
|
||||
C.DarkModeEnabled(c.app.app, c.app.string2CString(callbackID))
|
||||
}
|
||||
|
||||
func (c *Client) UpdateMenu(menu *menu.Menu) {
|
||||
|
||||
// Guard against nil menus
|
||||
if menu == nil {
|
||||
return
|
||||
}
|
||||
// Process the menu
|
||||
processedMenu := NewProcessedMenu(menu)
|
||||
menuJSON, err := json.Marshal(processedMenu)
|
||||
if err != nil {
|
||||
c.app.logger.Error("Error processing updated Menu: %s", err.Error())
|
||||
return
|
||||
}
|
||||
C.UpdateMenu(c.app.app, c.app.string2CString(string(menuJSON)))
|
||||
func (c *Client) UpdateMenu(menuJSON string) {
|
||||
C.SetApplicationMenu(c.app.app, c.app.string2CString(menuJSON))
|
||||
}
|
||||
|
||||
func (c *Client) UpdateTray(menu *menu.Menu) {
|
||||
|
@ -485,68 +485,6 @@ void allocateTrayHashMaps(struct Application *app) {
|
||||
}
|
||||
}
|
||||
|
||||
void* NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden, int logLevel) {
|
||||
// Setup main application struct
|
||||
struct Application *result = malloc(sizeof(struct Application));
|
||||
result->title = title;
|
||||
result->width = width;
|
||||
result->height = height;
|
||||
result->minWidth = 0;
|
||||
result->minHeight = 0;
|
||||
result->maxWidth = 0;
|
||||
result->maxHeight = 0;
|
||||
result->resizable = resizable;
|
||||
result->devtools = devtools;
|
||||
result->fullscreen = fullscreen;
|
||||
result->maximised = 0;
|
||||
result->startHidden = startHidden;
|
||||
result->decorations = 0;
|
||||
result->logLevel = logLevel;
|
||||
|
||||
result->mainWindow = NULL;
|
||||
result->mouseEvent = NULL;
|
||||
result->mouseDownMonitor = NULL;
|
||||
result->mouseUpMonitor = NULL;
|
||||
|
||||
// Features
|
||||
result->frame = 1;
|
||||
result->hideTitle = 0;
|
||||
result->hideTitleBar = 0;
|
||||
result->fullSizeContent = 0;
|
||||
result->useToolBar = 0;
|
||||
result->hideToolbarSeparator = 0;
|
||||
result->appearance = NULL;
|
||||
result->windowBackgroundIsTranslucent = 0;
|
||||
|
||||
// Window data
|
||||
result->delegate = NULL;
|
||||
|
||||
// Menu
|
||||
result->applicationMenu = NULL;
|
||||
|
||||
// Tray
|
||||
result->trayMenuAsJSON = NULL;
|
||||
result->trayLabel = NULL;
|
||||
result->trayIconName = NULL;
|
||||
result->trayIconPosition = NSImageLeft; // Left of the text by default
|
||||
result->processedTrayMenu = NULL;
|
||||
result->statusItem = NULL;
|
||||
|
||||
// Context Menus
|
||||
result->contextMenuStore = NULL;
|
||||
result->contextMenusAsJSON = NULL;
|
||||
result->processedContextMenus = NULL;
|
||||
contextMenuData = NULL;
|
||||
|
||||
// Window Appearance
|
||||
result->titlebarAppearsTransparent = 0;
|
||||
result->webviewIsTranparent = 0;
|
||||
|
||||
result->sendMessageToBackend = (ffenestriCallback) messageFromWindowCallback;
|
||||
|
||||
return (void*) result;
|
||||
}
|
||||
|
||||
|
||||
int releaseNSObject(void *const context, struct hashmap_element_s *const e) {
|
||||
msg(e->data, s("release"));
|
||||
@ -1121,10 +1059,7 @@ void SetDebug(void *applicationPointer, int flag) {
|
||||
debug = flag;
|
||||
}
|
||||
|
||||
// SetMenu sets the initial menu for the application
|
||||
void SetMenu(struct Application *app, const char *menuAsJSON) {
|
||||
app->applicationMenu = NewApplicationMenu(menuAsJSON);
|
||||
}
|
||||
|
||||
|
||||
// SetTray sets the initial tray menu for the application
|
||||
void SetTray(struct Application *app, const char *trayMenuAsJSON, const char *trayLabel, const char *trayIconName) {
|
||||
@ -1623,8 +1558,8 @@ struct hashmap_s *radioGroupMap) {
|
||||
|
||||
}
|
||||
|
||||
// UpdateMenu replaces the current menu with the given one
|
||||
void UpdateMenu(struct Application *app, const char *menuAsJSON) {
|
||||
// updateMenu replaces the current menu with the given one
|
||||
void updateMenu(struct Application *app, const char *menuAsJSON) {
|
||||
Debug(app, "Menu is now: %s", menuAsJSON);
|
||||
ON_MAIN_THREAD (
|
||||
DeleteMenu(app->applicationMenu);
|
||||
@ -1635,6 +1570,17 @@ void UpdateMenu(struct Application *app, const char *menuAsJSON) {
|
||||
);
|
||||
}
|
||||
|
||||
// SetApplicationMenu sets the initial menu for the application
|
||||
void SetApplicationMenu(struct Application *app, const char *menuAsJSON) {
|
||||
if ( app->applicationMenu == NULL ) {
|
||||
app->applicationMenu = NewApplicationMenu(menuAsJSON);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update menu
|
||||
updateMenu(app, menuAsJSON);
|
||||
}
|
||||
|
||||
//void dumpContextMenus(struct Application *app) {
|
||||
// dumpHashmap("menuItemMapForContextMenus", &menuItemMapForContextMenus);
|
||||
// printf("&menuItemMapForContextMenus = %p\n", &menuItemMapForContextMenus);
|
||||
@ -2063,4 +2009,68 @@ void Run(struct Application *app, int argc, char **argv) {
|
||||
MEMFREE(internalCode);
|
||||
}
|
||||
|
||||
|
||||
void* NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden, int logLevel) {
|
||||
// Setup main application struct
|
||||
struct Application *result = malloc(sizeof(struct Application));
|
||||
result->title = title;
|
||||
result->width = width;
|
||||
result->height = height;
|
||||
result->minWidth = 0;
|
||||
result->minHeight = 0;
|
||||
result->maxWidth = 0;
|
||||
result->maxHeight = 0;
|
||||
result->resizable = resizable;
|
||||
result->devtools = devtools;
|
||||
result->fullscreen = fullscreen;
|
||||
result->maximised = 0;
|
||||
result->startHidden = startHidden;
|
||||
result->decorations = 0;
|
||||
result->logLevel = logLevel;
|
||||
|
||||
result->mainWindow = NULL;
|
||||
result->mouseEvent = NULL;
|
||||
result->mouseDownMonitor = NULL;
|
||||
result->mouseUpMonitor = NULL;
|
||||
|
||||
// Features
|
||||
result->frame = 1;
|
||||
result->hideTitle = 0;
|
||||
result->hideTitleBar = 0;
|
||||
result->fullSizeContent = 0;
|
||||
result->useToolBar = 0;
|
||||
result->hideToolbarSeparator = 0;
|
||||
result->appearance = NULL;
|
||||
result->windowBackgroundIsTranslucent = 0;
|
||||
|
||||
// Window data
|
||||
result->delegate = NULL;
|
||||
|
||||
// Menu
|
||||
result->applicationMenu = NULL;
|
||||
|
||||
// Tray
|
||||
result->trayMenuAsJSON = NULL;
|
||||
result->trayLabel = NULL;
|
||||
result->trayIconName = NULL;
|
||||
result->trayIconPosition = NSImageLeft; // Left of the text by default
|
||||
result->processedTrayMenu = NULL;
|
||||
result->statusItem = NULL;
|
||||
|
||||
// Context Menus
|
||||
result->contextMenuStore = NULL;
|
||||
result->contextMenusAsJSON = NULL;
|
||||
result->processedContextMenus = NULL;
|
||||
contextMenuData = NULL;
|
||||
|
||||
// Window Appearance
|
||||
result->titlebarAppearsTransparent = 0;
|
||||
result->webviewIsTranparent = 0;
|
||||
|
||||
result->sendMessageToBackend = (ffenestriCallback) messageFromWindowCallback;
|
||||
|
||||
return (void*) result;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -4,6 +4,7 @@ package ffenestri
|
||||
#cgo darwin CFLAGS: -DFFENESTRI_DARWIN=1
|
||||
#cgo darwin LDFLAGS: -framework WebKit -lobjc
|
||||
|
||||
#include "ffenestri.h"
|
||||
#include "ffenestri_darwin.h"
|
||||
|
||||
extern void TitlebarAppearsTransparent(void *);
|
||||
@ -16,7 +17,6 @@ extern void DisableFrame(void *);
|
||||
extern void SetAppearance(void *, const char *);
|
||||
extern void WebviewIsTransparent(void *);
|
||||
extern void WindowBackgroundIsTranslucent(void *);
|
||||
extern void SetMenu(void *, const char *);
|
||||
extern void SetTray(void *, const char *, const char *, const char *);
|
||||
extern void SetContextMenus(void *, const char *);
|
||||
|
||||
@ -79,7 +79,7 @@ func (a *Application) processPlatformSettings() error {
|
||||
//applicationMenu := options.GetApplicationMenu(a.config)
|
||||
applicationMenu := a.menuManager.GetApplicationMenuJSON()
|
||||
if applicationMenu != "" {
|
||||
C.SetMenu(a.app, a.string2CString(applicationMenu))
|
||||
C.SetApplicationMenu(a.app, a.string2CString(applicationMenu))
|
||||
}
|
||||
|
||||
// Process tray
|
||||
|
@ -9,7 +9,10 @@
|
||||
#include "contextmenustore_darwin.h"
|
||||
|
||||
enum MenuItemType {Text = 0, Checkbox = 1, Radio = 2};
|
||||
enum MenuType {ApplicationMenuType = 0, ContextMenuType = 1};
|
||||
enum MenuType {ApplicationMenuType = 0, ContextMenuType = 1, TrayMenuType = 2};
|
||||
static const char *MenuTypeAsString[] = {
|
||||
"ApplicationMenu", "ContextMenu", "TrayMenu",
|
||||
};
|
||||
|
||||
extern void messageFromWindowCallback(const char *);
|
||||
|
||||
@ -133,14 +136,17 @@ void DeleteMenu(Menu *menu) {
|
||||
}
|
||||
|
||||
// Creates a JSON message for the given menuItemID and data
|
||||
const char* createMenuClickedMessage(const char *menuItemID, const char *data) {
|
||||
const char* createMenuClickedMessage(const char *menuItemID, const char *data, enum MenuType menuType) {
|
||||
JsonNode *jsonObject = json_mkobject();
|
||||
json_append_member(jsonObject, "menuItemID", json_mkstring(menuItemID));
|
||||
json_append_member(jsonObject, "menuType", json_mkstring(MenuTypeAsString[(int)menuType]));
|
||||
if (data != NULL) {
|
||||
json_append_member(jsonObject, "data", json_mkstring(data));
|
||||
}
|
||||
const char *result = json_encode(jsonObject);
|
||||
const char *payload = json_encode(jsonObject);
|
||||
json_delete(jsonObject);
|
||||
const char *result = concat("MC", payload);
|
||||
MEMFREE(payload);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -177,19 +183,19 @@ void menuItemCallback(id self, SEL cmd, id sender) {
|
||||
msg(callbackData->menuItem, s("setState:"), NSControlStateValueOn);
|
||||
}
|
||||
|
||||
const char *menuID = callbackData->menuID;
|
||||
const char *data = NULL;
|
||||
enum MenuType menuType = callbackData->menu->menuType;
|
||||
|
||||
// Generate message to send to backend
|
||||
if( callbackData->menu->menuType == ApplicationMenuType ) {
|
||||
const char *clickMessage = createMenuClickedMessage(callbackData->menuID, NULL);
|
||||
message = concat("MC", clickMessage);
|
||||
MEMFREE(clickMessage);
|
||||
} else if( callbackData->menu->menuType == ContextMenuType ) {
|
||||
if( menuType == ContextMenuType ) {
|
||||
// Get the context menu data from the menu
|
||||
ContextMenuStore* store = (ContextMenuStore*) callbackData->menu->parentData;
|
||||
const char *clickMessage = createMenuClickedMessage(callbackData->menuID, store->contextMenuData);
|
||||
message = concat("XC", clickMessage);
|
||||
MEMFREE(clickMessage);
|
||||
data = store->contextMenuData;
|
||||
}
|
||||
|
||||
message = createMenuClickedMessage(menuID, data, menuType);
|
||||
|
||||
// TODO: Add other menu types here!
|
||||
|
||||
// Notify the backend
|
||||
|
@ -3,12 +3,17 @@ package menumanager
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// MenuItemMap holds a mapping between menuIDs and menu items
|
||||
type MenuItemMap struct {
|
||||
idToMenuItemMap map[string]*menu.MenuItem
|
||||
menuItemToIDMap map[*menu.MenuItem]string
|
||||
|
||||
// We use a simple counter to keep track of unique menu IDs
|
||||
menuIDCounter int64
|
||||
menuIDCounterMutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewMenuItemMap() *MenuItemMap {
|
||||
@ -37,6 +42,15 @@ func (m *MenuItemMap) Dump() {
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateMenuID returns a unique string ID for a menu item
|
||||
func (m *MenuItemMap) generateMenuID() string {
|
||||
m.menuIDCounterMutex.Lock()
|
||||
result := fmt.Sprintf("%d", m.menuIDCounter)
|
||||
m.menuIDCounter++
|
||||
m.menuIDCounterMutex.Unlock()
|
||||
return result
|
||||
}
|
||||
|
||||
func (m *MenuItemMap) processMenuItem(item *menu.MenuItem) {
|
||||
|
||||
if item.SubMenu != nil {
|
||||
@ -46,9 +60,13 @@ func (m *MenuItemMap) processMenuItem(item *menu.MenuItem) {
|
||||
}
|
||||
|
||||
// Create a unique ID for this menu item
|
||||
menuID := fmt.Sprintf("%d", len(m.idToMenuItemMap))
|
||||
menuID := m.generateMenuID()
|
||||
|
||||
// Store references
|
||||
m.idToMenuItemMap[menuID] = item
|
||||
m.menuItemToIDMap[item] = menuID
|
||||
}
|
||||
|
||||
func (m *MenuItemMap) getMenuItemByID(menuId string) *menu.MenuItem {
|
||||
return m.idToMenuItemMap[menuId]
|
||||
}
|
||||
|
@ -11,13 +11,13 @@ type Manager struct {
|
||||
applicationMenu *menu.Menu
|
||||
applicationMenuJSON string
|
||||
|
||||
// Our menu mappings
|
||||
menuItemMap *MenuItemMap
|
||||
// Our application menu mappings
|
||||
applicationMenuItemMap *MenuItemMap
|
||||
}
|
||||
|
||||
func NewManager() *Manager {
|
||||
return &Manager{
|
||||
menuItemMap: NewMenuItemMap(),
|
||||
applicationMenuItemMap: NewMenuItemMap(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,13 @@ func (m *Manager) SetApplicationMenu(applicationMenu *menu.Menu) error {
|
||||
return nil
|
||||
}
|
||||
m.applicationMenu = applicationMenu
|
||||
m.menuItemMap.AddMenu(applicationMenu)
|
||||
|
||||
// Reset the menu map
|
||||
m.applicationMenuItemMap = NewMenuItemMap()
|
||||
|
||||
// Add the menu to the menu map
|
||||
m.applicationMenuItemMap.AddMenu(applicationMenu)
|
||||
|
||||
return m.processApplicationMenu()
|
||||
}
|
||||
|
||||
@ -34,10 +40,20 @@ func (m *Manager) GetApplicationMenuJSON() string {
|
||||
return m.applicationMenuJSON
|
||||
}
|
||||
|
||||
// UpdateApplicationMenu reprocesses the application menu to pick up structure
|
||||
// changes etc
|
||||
// Returns the JSON representation of the updated menu
|
||||
func (m *Manager) UpdateApplicationMenu() (string, error) {
|
||||
m.applicationMenuItemMap = NewMenuItemMap()
|
||||
m.applicationMenuItemMap.AddMenu(m.applicationMenu)
|
||||
err := m.processApplicationMenu()
|
||||
return m.applicationMenuJSON, err
|
||||
}
|
||||
|
||||
func (m *Manager) processApplicationMenu() error {
|
||||
|
||||
// Process the menu
|
||||
processedApplicationMenu := m.NewWailsMenu(m.applicationMenu)
|
||||
processedApplicationMenu := m.NewWailsMenu(m.applicationMenuItemMap, m.applicationMenu)
|
||||
applicationMenuJSON, err := processedApplicationMenu.AsJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -46,14 +62,27 @@ func (m *Manager) processApplicationMenu() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) getMenuItemByID(menuId string) *menu.MenuItem {
|
||||
return m.menuItemMap.idToMenuItemMap[menuId]
|
||||
func (m *Manager) getMenuItemByID(menuMap *MenuItemMap, menuId string) *menu.MenuItem {
|
||||
return menuMap.idToMenuItemMap[menuId]
|
||||
}
|
||||
|
||||
func (m *Manager) ProcessClick(menuID string, data string) error {
|
||||
func (m *Manager) ProcessClick(menuID string, data string, menuType string) error {
|
||||
|
||||
var menuItemMap *MenuItemMap
|
||||
|
||||
switch menuType {
|
||||
case "ApplicationMenu":
|
||||
menuItemMap = m.applicationMenuItemMap
|
||||
//case "ContextMenu":
|
||||
// // TBD
|
||||
//case "TrayMenu":
|
||||
// // TBD
|
||||
default:
|
||||
return fmt.Errorf("unknown menutype: %s", menuType)
|
||||
}
|
||||
|
||||
// Get the menu item
|
||||
menuItem := m.getMenuItemByID(menuID)
|
||||
menuItem := menuItemMap.getMenuItemByID(menuID)
|
||||
if menuItem == nil {
|
||||
return fmt.Errorf("Cannot process menuid %s - unknown", menuID)
|
||||
}
|
||||
|
@ -33,9 +33,9 @@ type ProcessedMenuItem struct {
|
||||
Background int
|
||||
}
|
||||
|
||||
func (m *Manager) NewProcessedMenuItem(menuItem *menu.MenuItem) *ProcessedMenuItem {
|
||||
func (m *Manager) NewProcessedMenuItem(menuItemMap *MenuItemMap, menuItem *menu.MenuItem) *ProcessedMenuItem {
|
||||
|
||||
ID := m.menuItemMap.menuItemToIDMap[menuItem]
|
||||
ID := menuItemMap.menuItemToIDMap[menuItem]
|
||||
result := &ProcessedMenuItem{
|
||||
ID: ID,
|
||||
Label: menuItem.Label,
|
||||
@ -50,7 +50,7 @@ func (m *Manager) NewProcessedMenuItem(menuItem *menu.MenuItem) *ProcessedMenuIt
|
||||
}
|
||||
|
||||
if menuItem.SubMenu != nil {
|
||||
result.SubMenu = m.NewProcessedMenu(menuItem.SubMenu)
|
||||
result.SubMenu = m.NewProcessedMenu(menuItemMap, menuItem.SubMenu)
|
||||
}
|
||||
|
||||
return result
|
||||
@ -60,11 +60,11 @@ type ProcessedMenu struct {
|
||||
Items []*ProcessedMenuItem
|
||||
}
|
||||
|
||||
func (m *Manager) NewProcessedMenu(menu *menu.Menu) *ProcessedMenu {
|
||||
func (m *Manager) NewProcessedMenu(menuItemMap *MenuItemMap, menu *menu.Menu) *ProcessedMenu {
|
||||
|
||||
result := &ProcessedMenu{}
|
||||
for _, item := range menu.Items {
|
||||
processedMenuItem := m.NewProcessedMenuItem(item)
|
||||
processedMenuItem := m.NewProcessedMenuItem(menuItemMap, item)
|
||||
result.Items = append(result.Items, processedMenuItem)
|
||||
}
|
||||
|
||||
@ -85,11 +85,11 @@ type RadioGroup struct {
|
||||
Length int
|
||||
}
|
||||
|
||||
func (m *Manager) NewWailsMenu(menu *menu.Menu) *WailsMenu {
|
||||
func (m *Manager) NewWailsMenu(menuItemMap *MenuItemMap, menu *menu.Menu) *WailsMenu {
|
||||
result := &WailsMenu{}
|
||||
|
||||
// Process the menus
|
||||
result.Menu = m.NewProcessedMenu(menu)
|
||||
result.Menu = m.NewProcessedMenu(menuItemMap, menu)
|
||||
|
||||
// Process the radio groups
|
||||
result.processRadioGroups()
|
||||
|
@ -32,7 +32,7 @@ type Client interface {
|
||||
WindowUnFullscreen()
|
||||
WindowSetColour(colour int)
|
||||
DarkModeEnabled(callbackID string)
|
||||
UpdateMenu(menu *menu.Menu)
|
||||
UpdateMenu(menuJSON string)
|
||||
UpdateTray(menu *menu.Menu)
|
||||
UpdateTrayLabel(label string)
|
||||
UpdateTrayIcon(name string)
|
||||
|
@ -449,11 +449,11 @@ func (d *Dispatcher) processMenuMessage(result *servicebus.Message) {
|
||||
|
||||
command := splitTopic[1]
|
||||
switch command {
|
||||
case "update":
|
||||
case "updateappmenu":
|
||||
|
||||
updatedMenu, ok := result.Data().(*menu.Menu)
|
||||
updatedMenu, ok := result.Data().(string)
|
||||
if !ok {
|
||||
d.logger.Error("Invalid data for 'menufrontend:update' : %#v",
|
||||
d.logger.Error("Invalid data for 'menufrontend:updateappmenu' : %#v",
|
||||
result.Data())
|
||||
return
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ func (m *menuRuntime) On(menuID string, callback func(*menu.MenuItem)) {
|
||||
}
|
||||
|
||||
func (m *menuRuntime) Update() {
|
||||
m.bus.Publish("menu:update", m.menu)
|
||||
m.bus.Publish("menu:updateappmenu", nil)
|
||||
}
|
||||
|
||||
func (m *menuRuntime) GetByID(menuID string) *menu.MenuItem {
|
||||
|
@ -99,18 +99,19 @@ func (m *Menu) Start() error {
|
||||
|
||||
type ClickCallbackMessage struct {
|
||||
MenuItemID string `json:"menuItemID"`
|
||||
MenuType string `json:"menuType"`
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
var callbackData ClickCallbackMessage
|
||||
message := []byte(menuMessage.Data().(string))
|
||||
err := json.Unmarshal(message, &callbackData)
|
||||
payload := []byte(menuMessage.Data().(string))
|
||||
err := json.Unmarshal(payload, &callbackData)
|
||||
if err != nil {
|
||||
m.logger.Error("%s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = m.menuManager.ProcessClick(callbackData.MenuItemID, callbackData.Data)
|
||||
err = m.menuManager.ProcessClick(callbackData.MenuItemID, callbackData.Data, callbackData.MenuType)
|
||||
if err != nil {
|
||||
m.logger.Trace("%s", err.Error())
|
||||
}
|
||||
@ -121,12 +122,17 @@ func (m *Menu) Start() error {
|
||||
m.listeners[id] = append(m.listeners[id], listenerDetails.Callback)
|
||||
|
||||
// Make sure we catch any menu updates
|
||||
case "update":
|
||||
case "updateappmenu":
|
||||
updatedMenu, err := m.menuManager.UpdateApplicationMenu()
|
||||
if err != nil {
|
||||
m.logger.Trace("%s", err.Error())
|
||||
return
|
||||
}
|
||||
//updatedMenu := menuMessage.Data().(*menu.Menu)
|
||||
//m.processMenu(updatedMenu)
|
||||
//
|
||||
//// Notify frontend of menu change
|
||||
//m.bus.Publish("menufrontend:update", updatedMenu)
|
||||
m.bus.Publish("menufrontend:updateappmenu", updatedMenu)
|
||||
|
||||
default:
|
||||
m.logger.Error("unknown menu message: %+v", menuMessage)
|
||||
|
@ -148,6 +148,12 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
|
||||
// Default go build command
|
||||
commands := slicer.String([]string{"build"})
|
||||
|
||||
// Add better debugging flags
|
||||
if options.Mode == Debug {
|
||||
commands.Add("-gcflags")
|
||||
commands.Add(`"all=-N -l"`)
|
||||
}
|
||||
|
||||
// TODO: Work out if we can make this more efficient
|
||||
// We need to do a full build as CGO doesn't detect updates
|
||||
// to .h files, and we package assets into .h file. We could
|
||||
@ -180,11 +186,6 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Add better debugging flags
|
||||
if options.Mode == Debug {
|
||||
commands.Add(`-gcflags=all="-N -l"`)
|
||||
}
|
||||
|
||||
// Get application build directory
|
||||
appDir := options.BuildDirectory
|
||||
err := cleanBuildDirectory(options)
|
||||
@ -210,6 +211,7 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
|
||||
options.CompiledBinary = compiledBinary
|
||||
|
||||
// Create the command
|
||||
fmt.Printf("Compile command: %+v", commands.AsSlice())
|
||||
cmd := exec.Command(options.Compiler, commands.AsSlice()...)
|
||||
|
||||
// Set the directory
|
||||
|
@ -19,6 +19,9 @@ type Menu struct {
|
||||
lock sync.Mutex
|
||||
dynamicMenuItems map[string]*menu.MenuItem
|
||||
anotherDynamicMenuCounter int
|
||||
|
||||
// Menus
|
||||
removeMenuItem *menu.MenuItem
|
||||
}
|
||||
|
||||
// WailsInit is called at application startup
|
||||
@ -26,26 +29,6 @@ func (m *Menu) WailsInit(runtime *wails.Runtime) error {
|
||||
// Perform your setup here
|
||||
m.runtime = runtime
|
||||
|
||||
// Setup Menu Listeners
|
||||
m.runtime.Menu.On("hello", func(mi *menu.MenuItem) {
|
||||
fmt.Printf("The '%s' menu was clicked\n", mi.Label)
|
||||
})
|
||||
m.runtime.Menu.On("checkbox-menu", func(mi *menu.MenuItem) {
|
||||
fmt.Printf("The '%s' menu was clicked\n", mi.Label)
|
||||
fmt.Printf("It is now %v\n", mi.Checked)
|
||||
})
|
||||
m.runtime.Menu.On("😀option-1", func(mi *menu.MenuItem) {
|
||||
fmt.Printf("We can use UTF-8 IDs: %s\n", mi.Label)
|
||||
})
|
||||
|
||||
m.runtime.Menu.On("show-dynamic-menus-2", func(mi *menu.MenuItem) {
|
||||
mi.Hidden = true
|
||||
// Create dynamic menu items 2 submenu
|
||||
m.createDynamicMenuTwo()
|
||||
})
|
||||
|
||||
// Setup dynamic menus
|
||||
m.runtime.Menu.On("Add Menu Item", m.addMenu)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -59,13 +42,14 @@ func (m *Menu) decrementcounter() int {
|
||||
return m.dynamicMenuCounter
|
||||
}
|
||||
|
||||
func (m *Menu) addMenu(mi *menu.MenuItem) {
|
||||
func (m *Menu) addMenu(data *menu.CallbackData) {
|
||||
|
||||
// Lock because this method will be called in a gorouting
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
// Get this menu's parent
|
||||
mi := data.MenuItem
|
||||
parent := mi.Parent()
|
||||
counter := m.incrementcounter()
|
||||
menuText := "Dynamic Menu Item " + strconv.Itoa(counter)
|
||||
@ -74,10 +58,8 @@ func (m *Menu) addMenu(mi *menu.MenuItem) {
|
||||
|
||||
// If this is the first dynamic menu added, let's add a remove menu item
|
||||
if counter == 1 {
|
||||
removeMenu := menu.Text("Remove "+menuText,
|
||||
"Remove Last Item", keys.CmdOrCtrl("-"), nil)
|
||||
parent.Prepend(removeMenu)
|
||||
m.runtime.Menu.On("Remove Last Item", m.removeMenu)
|
||||
m.removeMenuItem = menu.Text("Remove "+menuText, "Remove Last Item", keys.CmdOrCtrl("-"), m.removeMenu)
|
||||
parent.Prepend(m.removeMenuItem)
|
||||
} else {
|
||||
removeMenu := m.runtime.Menu.GetByID("Remove Last Item")
|
||||
// Test if the remove menu hasn't already been removed in another thread
|
||||
@ -88,40 +70,41 @@ func (m *Menu) addMenu(mi *menu.MenuItem) {
|
||||
m.runtime.Menu.Update()
|
||||
}
|
||||
|
||||
func (m *Menu) removeMenu(_ *menu.MenuItem) {
|
||||
|
||||
// Lock because this method will be called in a goroutine
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
// Get the id of the last dynamic menu
|
||||
menuID := "Dynamic Menu Item " + strconv.Itoa(m.dynamicMenuCounter)
|
||||
|
||||
// Remove the last menu item by ID
|
||||
m.runtime.Menu.RemoveByID(menuID)
|
||||
|
||||
// Update the counter
|
||||
counter := m.decrementcounter()
|
||||
|
||||
// If we deleted the last dynamic menu, remove the "Remove Last Item" menu
|
||||
if counter == 0 {
|
||||
m.runtime.Menu.RemoveByID("Remove Last Item")
|
||||
} else {
|
||||
// Update label
|
||||
menuText := "Dynamic Menu Item " + strconv.Itoa(counter)
|
||||
removeMenu := m.runtime.Menu.GetByID("Remove Last Item")
|
||||
// Test if the remove menu hasn't already been removed in another thread
|
||||
if removeMenu == nil {
|
||||
return
|
||||
}
|
||||
removeMenu.Label = "Remove " + menuText
|
||||
}
|
||||
|
||||
// parent.Append(menu.Text(menuText, menuText, menu.Key("[")))
|
||||
m.runtime.Menu.Update()
|
||||
func (m *Menu) removeMenu(_ *menu.CallbackData) {
|
||||
//
|
||||
//// Lock because this method will be called in a goroutine
|
||||
//m.lock.Lock()
|
||||
//defer m.lock.Unlock()
|
||||
//
|
||||
//// Remove the last menu item by ID
|
||||
//m.runtime.Menu.RemoveMenuItem(menuID)
|
||||
//
|
||||
//// Update the counter
|
||||
//counter := m.decrementcounter()
|
||||
//
|
||||
//// If we deleted the last dynamic menu, remove the "Remove Last Item" menu
|
||||
//if counter == 0 {
|
||||
// m.runtime.Menu.RemoveByID("Remove Last Item")
|
||||
//} else {
|
||||
// // Update label
|
||||
// menuText := "Dynamic Menu Item " + strconv.Itoa(counter)
|
||||
// removeMenu := m.runtime.Menu.GetByID("Remove Last Item")
|
||||
// // Test if the remove menu hasn't already been removed in another thread
|
||||
// if removeMenu == nil {
|
||||
// return
|
||||
// }
|
||||
// removeMenu.Label = "Remove " + menuText
|
||||
//}
|
||||
//
|
||||
//// parent.Append(menu.Text(menuText, menuText, menu.Key("[")))
|
||||
//m.runtime.Menu.Update()
|
||||
}
|
||||
|
||||
func (m *Menu) createDynamicMenuTwo() {
|
||||
func (m *Menu) createDynamicMenuTwo(data *menu.CallbackData) {
|
||||
|
||||
println("\n\n\n\n\n\n\nCreating dynamic menu two\n\n\n\n\n\n")
|
||||
// Hide this menu
|
||||
data.MenuItem.Hidden = true
|
||||
|
||||
// Create our submenu
|
||||
dm2 := menu.SubMenu("Dynamic Menus 2", menu.NewMenuFromItems(
|
||||
@ -251,7 +234,7 @@ func (m *Menu) createApplicationMenu() *menu.Menu {
|
||||
|
||||
menu.SubMenu("Test Submenu", menu.NewMenuFromItems(
|
||||
menu.Text("Plain text", "plain text", nil, m.processPlainText),
|
||||
menu.Text("Show Dynamic Menus 2 Submenu", "show-dynamic-menus-2", nil, nil),
|
||||
menu.Text("Show Dynamic Menus 2 Submenu", "show-dynamic-menus-2", nil, m.createDynamicMenuTwo),
|
||||
menu.SubMenu("Accelerators", menu.NewMenuFromItems(
|
||||
menu.SubMenu("Modifiers", menu.NewMenuFromItems(
|
||||
menu.Text("Shift accelerator", "Shift", keys.Shift("o"), nil),
|
||||
@ -305,7 +288,7 @@ func (m *Menu) createApplicationMenu() *menu.Menu {
|
||||
)),
|
||||
)),
|
||||
menu.SubMenuWithID("Dynamic Menus 1", "Dynamic Menus 1", menu.NewMenuFromItems(
|
||||
menu.Text("Add Menu Item", "Add Menu Item", keys.CmdOrCtrl("+"), nil),
|
||||
menu.Text("Add Menu Item", "Add Menu Item", keys.CmdOrCtrl("+"), m.addMenu),
|
||||
menu.Separator(),
|
||||
)),
|
||||
&menu.MenuItem{
|
||||
@ -325,6 +308,10 @@ func (m *Menu) createApplicationMenu() *menu.Menu {
|
||||
Type: menu.CheckboxType,
|
||||
Accelerator: keys.CmdOrCtrl("l"),
|
||||
Checked: true,
|
||||
Click: func(data *menu.CallbackData) {
|
||||
fmt.Printf("The '%s' menu was clicked\n", data.MenuItem.Label)
|
||||
fmt.Printf("It is now %v\n", data.MenuItem.Checked)
|
||||
},
|
||||
},
|
||||
menu.Checkbox("Checkbox Menu 2", "checkbox-menu 2", false, nil, nil),
|
||||
menu.Separator(),
|
||||
|
Loading…
Reference in New Issue
Block a user