diff --git a/v2/internal/app/desktop.go b/v2/internal/app/desktop.go index 2a8d81e1..17ef6f05 100644 --- a/v2/internal/app/desktop.go +++ b/v2/internal/app/desktop.go @@ -24,15 +24,13 @@ type App struct { options *options.App // Subsystems - log *subsystem.Log - runtime *subsystem.Runtime - event *subsystem.Event - binding *subsystem.Binding - call *subsystem.Call - menu *subsystem.Menu - tray *subsystem.Tray - contextmenus *subsystem.ContextMenus - dispatcher *messagedispatcher.Dispatcher + log *subsystem.Log + runtime *subsystem.Runtime + event *subsystem.Event + binding *subsystem.Binding + call *subsystem.Call + menu *subsystem.Menu + dispatcher *messagedispatcher.Dispatcher menuManager *menumanager.Manager @@ -191,32 +189,6 @@ func (a *App) Run() error { } } - //// Optionally start the tray subsystem - //if trayMenu != nil { - // traysubsystem, err := subsystem.NewTray(trayMenu, a.servicebus, a.logger) - // if err != nil { - // return err - // } - // a.tray = traysubsystem - // err = a.tray.Start() - // if err != nil { - // return err - // } - //} - - // Optionally start the context menu subsystem - if contextMenus != nil { - contextmenussubsystem, err := subsystem.NewContextMenus(contextMenus, a.servicebus, a.logger) - if err != nil { - return err - } - a.contextmenus = contextmenussubsystem - err = a.contextmenus.Start() - if err != nil { - return err - } - } - // Start the call subsystem call, err := subsystem.NewCall(a.servicebus, a.logger, a.bindings.DB(), a.runtime.GoRuntime()) if err != nil { diff --git a/v2/internal/ffenestri/ffenestri.go b/v2/internal/ffenestri/ffenestri.go index 57fb1d66..28c0c4bd 100644 --- a/v2/internal/ffenestri/ffenestri.go +++ b/v2/internal/ffenestri/ffenestri.go @@ -1,9 +1,7 @@ package ffenestri import ( - "encoding/json" "github.com/wailsapp/wails/v2/internal/menumanager" - "github.com/wailsapp/wails/v2/pkg/menu" "runtime" "strings" "unsafe" @@ -185,28 +183,3 @@ 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 -} diff --git a/v2/internal/ffenestri/ffenestri_client.go b/v2/internal/ffenestri/ffenestri_client.go index 81a6fab3..ab1134dc 100644 --- a/v2/internal/ffenestri/ffenestri_client.go +++ b/v2/internal/ffenestri/ffenestri_client.go @@ -12,7 +12,6 @@ package ffenestri import "C" import ( - "encoding/json" "github.com/wailsapp/wails/v2/pkg/menu" "strconv" @@ -190,22 +189,6 @@ func (c *Client) UpdateMenu(menuJSON string) { C.SetApplicationMenu(c.app.app, c.app.string2CString(menuJSON)) } -func (c *Client) UpdateTray(menu *menu.Menu) { - - // Guard against nil menus - if menu == nil { - return - } - // Process the menu - processedMenu := NewProcessedMenu(menu) - trayMenuJSON, err := json.Marshal(processedMenu) - if err != nil { - c.app.logger.Error("Error processing updated TrayMenu: %s", err.Error()) - return - } - C.UpdateTray(c.app.app, c.app.string2CString(string(trayMenuJSON))) -} - func (c *Client) UpdateTrayMenu(trayMenuJSON string) { C.UpdateTrayMenu(c.app.app, c.app.string2CString(trayMenuJSON)) } @@ -219,16 +202,16 @@ func (c *Client) UpdateTrayIcon(name string) { } 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)) + // + // // 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)) } diff --git a/v2/internal/ffenestri/ffenestri_darwin.go b/v2/internal/ffenestri/ffenestri_darwin.go index 285cbd8e..0bb05912 100644 --- a/v2/internal/ffenestri/ffenestri_darwin.go +++ b/v2/internal/ffenestri/ffenestri_darwin.go @@ -7,13 +7,8 @@ package ffenestri #include "ffenestri.h" #include "ffenestri_darwin.h" - - */ import "C" -import ( - "github.com/wailsapp/wails/v2/pkg/options" -) func (a *Application) processPlatformSettings() error { @@ -83,14 +78,14 @@ func (a *Application) processPlatformSettings() error { } // 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 := options.GetContextMenus(a.config) + //if contextMenus != nil { + // contextMenusJSON, err := processContextMenus(contextMenus) + // if err != nil { + // return err + // } + // C.SetContextMenus(a.app, a.string2CString(contextMenusJSON)) + //} return nil } diff --git a/v2/internal/ffenestri/menu.go b/v2/internal/ffenestri/menu.go deleted file mode 100644 index f24c9ce8..00000000 --- a/v2/internal/ffenestri/menu.go +++ /dev/null @@ -1,80 +0,0 @@ -package ffenestri - -import "github.com/wailsapp/wails/v2/pkg/menu" - -// ProcessedMenu is the original menu with the addition -// of radio groups extracted from the menu data -type ProcessedMenu struct { - Menu *menu.Menu - RadioGroups []*RadioGroup - currentRadioGroup []string -} - -// RadioGroup holds all the members of the same radio group -type RadioGroup struct { - Members []string - Length int -} - -// NewProcessedMenu processed the given menu and returns -// the original menu with the extracted radio groups -func NewProcessedMenu(menu *menu.Menu) *ProcessedMenu { - result := &ProcessedMenu{ - Menu: menu, - RadioGroups: []*RadioGroup{}, - currentRadioGroup: []string{}, - } - - result.processMenu() - - return result -} - -func (p *ProcessedMenu) processMenu() { - // Loop over top level menus - for _, item := range p.Menu.Items { - // Process MenuItem - p.processMenuItem(item) - } - - p.finaliseRadioGroup() -} - -func (p *ProcessedMenu) processMenuItem(item *menu.MenuItem) { - - switch item.Type { - - // We need to recurse submenus - case menu.SubmenuType: - - // Finalise any current radio groups as they don't trickle down to submenus - p.finaliseRadioGroup() - - // Process each submenu item - for _, subitem := range item.SubMenu.Items { - p.processMenuItem(subitem) - } - case menu.RadioType: - // Add the item to the radio group - p.currentRadioGroup = append(p.currentRadioGroup, item.ID) - default: - p.finaliseRadioGroup() - } -} - -func (p *ProcessedMenu) finaliseRadioGroup() { - - // If we were processing a radio group, fix up the references - if len(p.currentRadioGroup) > 0 { - - // Create new radiogroup - group := &RadioGroup{ - Members: p.currentRadioGroup, - Length: len(p.currentRadioGroup), - } - p.RadioGroups = append(p.RadioGroups, group) - - // Empty the radio group - p.currentRadioGroup = []string{} - } -} diff --git a/v2/internal/messagedispatcher/dispatchclient.go b/v2/internal/messagedispatcher/dispatchclient.go index a44aa06b..cb41ebba 100644 --- a/v2/internal/messagedispatcher/dispatchclient.go +++ b/v2/internal/messagedispatcher/dispatchclient.go @@ -33,7 +33,6 @@ type Client interface { WindowSetColour(colour int) DarkModeEnabled(callbackID string) UpdateMenu(menuJSON string) - UpdateTray(menu *menu.Menu) UpdateTrayLabel(label string) UpdateTrayIcon(name string) UpdateTrayMenu(menuJSON string) diff --git a/v2/internal/messagedispatcher/messagedispatcher.go b/v2/internal/messagedispatcher/messagedispatcher.go index 630947c4..cf780494 100644 --- a/v2/internal/messagedispatcher/messagedispatcher.go +++ b/v2/internal/messagedispatcher/messagedispatcher.go @@ -25,7 +25,6 @@ type Dispatcher struct { systemChannel <-chan *servicebus.Message menuChannel <-chan *servicebus.Message contextMenuChannel <-chan *servicebus.Message - trayChannel <-chan *servicebus.Message running bool servicebus *servicebus.ServiceBus @@ -83,11 +82,6 @@ func New(servicebus *servicebus.ServiceBus, logger *logger.Logger) (*Dispatcher, return nil, err } - trayChannel, err := servicebus.Subscribe("trayfrontend:") - if err != nil { - return nil, err - } - result := &Dispatcher{ servicebus: servicebus, eventChannel: eventChannel, @@ -99,7 +93,6 @@ func New(servicebus *servicebus.ServiceBus, logger *logger.Logger) (*Dispatcher, dialogChannel: dialogChannel, systemChannel: systemChannel, menuChannel: menuChannel, - trayChannel: trayChannel, contextMenuChannel: contextMenuChannel, } @@ -134,8 +127,6 @@ func (d *Dispatcher) Start() error { d.processMenuMessage(menuMessage) case contextMenuMessage := <-d.contextMenuChannel: d.processContextMenuMessage(contextMenuMessage) - case trayMessage := <-d.trayChannel: - d.processTrayMessage(trayMessage) } } @@ -510,62 +501,3 @@ func (d *Dispatcher) processContextMenuMessage(result *servicebus.Message) { d.logger.Error("Unknown contextmenufrontend command: %s", command) } } - -func (d *Dispatcher) processTrayMessage(result *servicebus.Message) { - splitTopic := strings.Split(result.Topic(), ":") - if len(splitTopic) < 2 { - d.logger.Error("Invalid tray message : %#v", result.Data()) - return - } - - command := splitTopic[1] - switch command { - case "update": - - updatedMenu, ok := result.Data().(*menu.Menu) - if !ok { - d.logger.Error("Invalid data for 'trayfrontend:update' : %#v", - result.Data()) - return - } - - // 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.UpdateTray(updatedMenu) - } - - case "setlabel": - - updatedLabel, ok := result.Data().(string) - if !ok { - d.logger.Error("Invalid data for 'trayfrontend:setlabel' : %#v", - result.Data()) - return - } - - // 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.UpdateTrayLabel(updatedLabel) - } - - case "seticon": - - iconname, ok := result.Data().(string) - if !ok { - d.logger.Error("Invalid data for 'trayfrontend:seticon' : %#v", - result.Data()) - return - } - - // 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.UpdateTrayIcon(iconname) - } - - default: - d.logger.Error("Unknown menufrontend command: %s", command) - } -} diff --git a/v2/internal/runtime/contextmenus.go b/v2/internal/runtime/contextmenus.go deleted file mode 100644 index 787752dc..00000000 --- a/v2/internal/runtime/contextmenus.go +++ /dev/null @@ -1,48 +0,0 @@ -package runtime - -import ( - "github.com/wailsapp/wails/v2/internal/messagedispatcher/message" - "github.com/wailsapp/wails/v2/internal/servicebus" - "github.com/wailsapp/wails/v2/pkg/menu" -) - -// ContextMenus defines all ContextMenu related operations -type ContextMenus interface { - On(menuID string, callback func(*menu.MenuItem, string)) - Update() - GetByID(menuID string) *menu.MenuItem - RemoveByID(id string) bool -} - -type contextMenus struct { - bus *servicebus.ServiceBus - contextmenus *menu.ContextMenus -} - -// newContextMenus creates a new ContextMenu struct -func newContextMenus(bus *servicebus.ServiceBus, contextmenus *menu.ContextMenus) ContextMenus { - return &contextMenus{ - bus: bus, - contextmenus: contextmenus, - } -} - -// On registers a listener for a particular event -func (t *contextMenus) On(menuID string, callback func(*menu.MenuItem, string)) { - t.bus.Publish("contextmenus:on", &message.ContextMenusOnMessage{ - MenuID: menuID, - Callback: callback, - }) -} - -func (t *contextMenus) Update() { - t.bus.Publish("contextmenus:update", t.contextmenus) -} - -func (t *contextMenus) GetByID(menuItemID string) *menu.MenuItem { - return t.contextmenus.GetByID(menuItemID) -} - -func (t *contextMenus) RemoveByID(menuItemID string) bool { - return t.contextmenus.RemoveByID(menuItemID) -} diff --git a/v2/internal/runtime/tray.go b/v2/internal/runtime/tray.go deleted file mode 100644 index 343b3afe..00000000 --- a/v2/internal/runtime/tray.go +++ /dev/null @@ -1,59 +0,0 @@ -package runtime - -import ( - "github.com/wailsapp/wails/v2/internal/messagedispatcher/message" - "github.com/wailsapp/wails/v2/internal/servicebus" - "github.com/wailsapp/wails/v2/pkg/menu" -) - -// Tray defines all Tray related operations -type Tray interface { - On(menuID string, callback func(*menu.MenuItem)) - Update(tray ...*menu.TrayMenu) - GetByID(menuID string) *menu.MenuItem - RemoveByID(id string) bool - SetLabel(label string) - SetIcon(name string) -} - -type trayRuntime struct { - bus *servicebus.ServiceBus - trayMenu *menu.TrayMenu -} - -// newTray creates a new Menu struct -func newTray(bus *servicebus.ServiceBus, menu *menu.TrayMenu) Tray { - return &trayRuntime{ - bus: bus, - trayMenu: menu, - } -} - -// On registers a listener for a particular event -func (t *trayRuntime) On(menuID string, callback func(*menu.MenuItem)) { - t.bus.Publish("tray:on", &message.TrayOnMessage{ - MenuID: menuID, - Callback: callback, - }) -} - -func (t *trayRuntime) Update(tray ...*menu.TrayMenu) { - - //trayToUpdate := t.trayMenu - t.bus.Publish("tray:update", t.trayMenu) -} - -func (t *trayRuntime) SetLabel(label string) { - t.bus.Publish("tray:setlabel", label) -} -func (t *trayRuntime) SetIcon(name string) { - t.bus.Publish("tray:seticon", name) -} - -func (t *trayRuntime) GetByID(menuID string) *menu.MenuItem { - return t.trayMenu.Menu.GetByID(menuID) -} - -func (t *trayRuntime) RemoveByID(id string) bool { - return t.trayMenu.Menu.RemoveByID(id) -} diff --git a/v2/internal/subsystem/contextmenus.go b/v2/internal/subsystem/contextmenus.go deleted file mode 100644 index 652b70cd..00000000 --- a/v2/internal/subsystem/contextmenus.go +++ /dev/null @@ -1,200 +0,0 @@ -package subsystem - -import ( - "encoding/json" - "strings" - "sync" - - "github.com/wailsapp/wails/v2/internal/logger" - "github.com/wailsapp/wails/v2/internal/messagedispatcher/message" - "github.com/wailsapp/wails/v2/internal/servicebus" - "github.com/wailsapp/wails/v2/pkg/menu" -) - -// ContextMenus is the subsystem that handles the operation of context menus. It manages all service bus messages -// starting with "contextmenus". -type ContextMenus struct { - quitChannel <-chan *servicebus.Message - menuChannel <-chan *servicebus.Message - running bool - - // Event listeners - listeners map[string][]func(*menu.MenuItem, string) - menuItems map[string]*menu.MenuItem - notifyLock sync.RWMutex - - // logger - logger logger.CustomLogger - - // The context menus - contextMenus *menu.ContextMenus - - // Service Bus - bus *servicebus.ServiceBus -} - -// NewContextMenus creates a new context menu subsystem -func NewContextMenus(contextMenus *menu.ContextMenus, bus *servicebus.ServiceBus, logger *logger.Logger) (*ContextMenus, error) { - - // Register quit channel - quitChannel, err := bus.Subscribe("quit") - if err != nil { - return nil, err - } - - // Subscribe to menu messages - menuChannel, err := bus.Subscribe("contextmenus:") - if err != nil { - return nil, err - } - - result := &ContextMenus{ - quitChannel: quitChannel, - menuChannel: menuChannel, - logger: logger.CustomLogger("Context Menu Subsystem"), - listeners: make(map[string][]func(*menu.MenuItem, string)), - menuItems: make(map[string]*menu.MenuItem), - contextMenus: contextMenus, - bus: bus, - } - - // Build up list of item/id pairs - result.processContextMenus(contextMenus) - - return result, nil -} - -type contextMenuData struct { - MenuItemID string `json:"menuItemID"` - Data string `json:"data"` -} - -// Start the subsystem -func (c *ContextMenus) Start() error { - - c.logger.Trace("Starting") - - c.running = true - - // Spin off a go routine - go func() { - for c.running { - select { - case <-c.quitChannel: - c.running = false - break - case menuMessage := <-c.menuChannel: - splitTopic := strings.Split(menuMessage.Topic(), ":") - menuMessageType := splitTopic[1] - switch menuMessageType { - case "clicked": - if len(splitTopic) != 2 { - c.logger.Error("Received clicked message with invalid topic format. Expected 2 sections in topic, got %s", splitTopic) - continue - } - c.logger.Trace("Got Context Menu clicked Message: %s %+v", menuMessage.Topic(), menuMessage.Data()) - contextMenuDataJSON := menuMessage.Data().(string) - - var data contextMenuData - err := json.Unmarshal([]byte(contextMenuDataJSON), &data) - if err != nil { - c.logger.Trace("Cannot process contextMenuDataJSON %s", string(contextMenuDataJSON)) - return - } - - // Get the menu item - menuItem := c.menuItems[data.MenuItemID] - if menuItem == nil { - c.logger.Trace("Cannot process menuitem id %s - unknown", data.MenuItemID) - return - } - - // Is the menu item a checkbox? - if menuItem.Type == menu.CheckboxType { - // Toggle state - menuItem.Checked = !menuItem.Checked - } - - // Notify listeners - c.notifyListeners(data, menuItem) - case "on": - listenerDetails := menuMessage.Data().(*message.ContextMenusOnMessage) - id := listenerDetails.MenuID - c.listeners[id] = append(c.listeners[id], listenerDetails.Callback) - - // Make sure we catch any menu updates - case "update": - updatedMenu := menuMessage.Data().(*menu.ContextMenus) - c.processContextMenus(updatedMenu) - - // Notify frontend of menu change - c.bus.Publish("contextmenufrontend:update", updatedMenu) - - default: - c.logger.Error("unknown context menu message: %+v", menuMessage) - } - } - } - - // Call shutdown - c.shutdown() - }() - - return nil -} - -func (c *ContextMenus) processContextMenus(contextMenus *menu.ContextMenus) { - // Initialise the variables - c.menuItems = make(map[string]*menu.MenuItem) - c.contextMenus = contextMenus - - for _, contextMenu := range contextMenus.Items { - for _, item := range contextMenu.Items { - c.processMenuItem(item) - } - } -} - -func (c *ContextMenus) processMenuItem(item *menu.MenuItem) { - - if item.SubMenu != nil { - for _, submenuitem := range item.SubMenu.Items { - c.processMenuItem(submenuitem) - } - return - } - - if item.ID != "" { - if c.menuItems[item.ID] != nil { - c.logger.Error("Context Menu id '%s' is used by multiple menu items: %s %s", c.menuItems[item.ID].Label, item.Label) - return - } - c.menuItems[item.ID] = item - } -} - -// Notifies listeners that the given menu was clicked -func (c *ContextMenus) notifyListeners(contextData contextMenuData, menuItem *menu.MenuItem) { - - // Get list of menu listeners - listeners := c.listeners[contextData.MenuItemID] - if listeners == nil { - c.logger.Trace("No listeners for MenuItem with ID '%s'", contextData.MenuItemID) - return - } - - // Lock the listeners - c.notifyLock.Lock() - - // Callback in goroutine - for _, listener := range listeners { - go listener(menuItem, contextData.Data) - } - - // Unlock - c.notifyLock.Unlock() -} - -func (c *ContextMenus) shutdown() { - c.logger.Trace("Shutdown") -} diff --git a/v2/internal/subsystem/tray.go b/v2/internal/subsystem/tray.go deleted file mode 100644 index c153bf5e..00000000 --- a/v2/internal/subsystem/tray.go +++ /dev/null @@ -1,202 +0,0 @@ -package subsystem - -import ( - "strings" - "sync" - - "github.com/wailsapp/wails/v2/internal/logger" - "github.com/wailsapp/wails/v2/internal/messagedispatcher/message" - "github.com/wailsapp/wails/v2/internal/servicebus" - "github.com/wailsapp/wails/v2/pkg/menu" -) - -// Tray is the subsystem that handles the operation of the tray menu. -// It manages all service bus messages starting with "tray". -type Tray struct { - quitChannel <-chan *servicebus.Message - trayChannel <-chan *servicebus.Message - running bool - - // Event listeners - listeners map[string][]func(*menu.MenuItem) - menuItems map[string]*menu.MenuItem - notifyLock sync.RWMutex - - // logger - logger logger.CustomLogger - - // The tray menu - trayMenu *menu.TrayMenu - - // Service Bus - bus *servicebus.ServiceBus -} - -// NewTray creates a new menu subsystem -func NewTray(trayMenu *menu.TrayMenu, bus *servicebus.ServiceBus, - logger *logger.Logger) (*Tray, error) { - - // Register quit channel - quitChannel, err := bus.Subscribe("quit") - if err != nil { - return nil, err - } - - // Subscribe to menu messages - trayChannel, err := bus.Subscribe("tray:") - if err != nil { - return nil, err - } - - result := &Tray{ - quitChannel: quitChannel, - trayChannel: trayChannel, - logger: logger.CustomLogger("TrayMenu Subsystem"), - listeners: make(map[string][]func(*menu.MenuItem)), - menuItems: make(map[string]*menu.MenuItem), - trayMenu: trayMenu, - bus: bus, - } - - // Build up list of item/id pairs - result.processMenu(trayMenu.Menu) - - return result, nil -} - -// Start the subsystem -func (t *Tray) Start() error { - - t.logger.Trace("Starting") - - t.running = true - - // Spin off a go routine - go func() { - for t.running { - select { - case <-t.quitChannel: - t.running = false - break - case menuMessage := <-t.trayChannel: - splitTopic := strings.Split(menuMessage.Topic(), ":") - menuMessageType := splitTopic[1] - switch menuMessageType { - case "clicked": - if len(splitTopic) != 2 { - t.logger.Error("Received clicked message with invalid topic format. Expected 2 sections in topic, got %s", splitTopic) - continue - } - t.logger.Trace("Got TrayMenu Menu clicked Message: %s %+v", menuMessage.Topic(), menuMessage.Data()) - menuid := menuMessage.Data().(string) - - // Get the menu item - menuItem := t.menuItems[menuid] - if menuItem == nil { - t.logger.Trace("Cannot process menuid %s - unknown", menuid) - return - } - - // Is the menu item a checkbox? - if menuItem.Type == menu.CheckboxType { - // Toggle state - menuItem.Checked = !menuItem.Checked - } - - // Notify listeners - t.notifyListeners(menuid, menuItem) - case "on": - listenerDetails := menuMessage.Data().(*message.TrayOnMessage) - id := listenerDetails.MenuID - t.listeners[id] = append(t.listeners[id], listenerDetails.Callback) - - // Make sure we catch any menu updates - case "update": - updatedMenu := menuMessage.Data().(*menu.Menu) - t.processMenu(updatedMenu) - - // Notify frontend of menu change - t.bus.Publish("trayfrontend:update", updatedMenu) - - // Make sure we catch any menu updates - case "setlabel": - updatedLabel := menuMessage.Data().(string) - t.trayMenu.Label = updatedLabel - - // Notify frontend of menu change - t.bus.Publish("trayfrontend:setlabel", updatedLabel) - - // Make sure we catch any icon updates - case "seticon": - iconname := menuMessage.Data().(string) - t.trayMenu.Label = iconname - - // Notify frontend of menu change - t.bus.Publish("trayfrontend:seticon", iconname) - - default: - t.logger.Error("unknown tray message: %+v", menuMessage) - } - } - } - - // Call shutdown - t.shutdown() - }() - - return nil -} - -func (t *Tray) processMenu(trayMenu *menu.Menu) { - // Initialise the variables - t.menuItems = make(map[string]*menu.MenuItem) - t.trayMenu.Menu = trayMenu - - for _, item := range trayMenu.Items { - t.processMenuItem(item) - } -} - -func (t *Tray) processMenuItem(item *menu.MenuItem) { - - if item.SubMenu != nil { - for _, submenuitem := range item.SubMenu.Items { - t.processMenuItem(submenuitem) - } - return - } - - if item.ID != "" { - if t.menuItems[item.ID] != nil { - t.logger.Error("Menu id '%s' is used by multiple menu items: %s %s", t.menuItems[item.ID].Label, item.Label) - return - } - t.menuItems[item.ID] = item - } -} - -// Notifies listeners that the given menu was clicked -func (t *Tray) notifyListeners(menuid string, menuItem *menu.MenuItem) { - - // Get list of menu listeners - listeners := t.listeners[menuid] - if listeners == nil { - t.logger.Trace("No listeners for MenuItem with ID '%s'", menuid) - return - } - - // Lock the listeners - t.notifyLock.Lock() - - // Callback in goroutine - for _, listener := range listeners { - go listener(menuItem) - } - - // Unlock - t.notifyLock.Unlock() -} - -func (t *Tray) shutdown() { - t.logger.Trace("Shutdown") -} diff --git a/v2/pkg/menu/contextmenu.go b/v2/pkg/menu/contextmenu.go index 502a3829..869991e4 100644 --- a/v2/pkg/menu/contextmenu.go +++ b/v2/pkg/menu/contextmenu.go @@ -14,29 +14,6 @@ func (c *ContextMenus) AddMenu(ID string, menu *Menu) { c.Items[ID] = menu } -func (c *ContextMenus) GetByID(menuID string) *MenuItem { - - // Loop over menu items - for _, item := range c.Items { - result := item.GetByID(menuID) - if result != nil { - return result - } - } - return nil -} - -func (c *ContextMenus) RemoveByID(id string) bool { - // Loop over menu items - for _, item := range c.Items { - result := item.RemoveByID(id) - if result == true { - return result - } - } - return false -} - type ContextMenu struct { ID string Menu *Menu diff --git a/v2/pkg/menu/menu.go b/v2/pkg/menu/menu.go index 137584a2..bb4ca909 100644 --- a/v2/pkg/menu/menu.go +++ b/v2/pkg/menu/menu.go @@ -27,33 +27,6 @@ func NewMenuFromItems(first *MenuItem, rest ...*MenuItem) *Menu { return result } -func (m *Menu) GetByID(menuID string) *MenuItem { - - // Loop over menu items - for _, item := range m.Items { - result := item.getByID(menuID) - if result != nil { - return result - } - } - return nil -} - -func (m *Menu) RemoveByID(id string) bool { - // Loop over menu items - for index, item := range m.Items { - if item.ID == id { - m.Items = append(m.Items[:index], m.Items[index+1:]...) - return true - } - result := item.removeByID(id) - if result == true { - return result - } - } - return false -} - func (m *Menu) setParent(menuItem *MenuItem) { for _, item := range m.Items { item.parent = menuItem diff --git a/v2/pkg/menu/menuitem.go b/v2/pkg/menu/menuitem.go index 1f52e155..d4bb8f45 100644 --- a/v2/pkg/menu/menuitem.go +++ b/v2/pkg/menu/menuitem.go @@ -7,8 +7,6 @@ import ( // MenuItem represents a menuitem contained in a menu type MenuItem struct { - // The unique identifier of this menu item - ID string `json:"ID,omitempty"` // Label is what appears as the menu text Label string // Role is a predefined menu type @@ -75,29 +73,6 @@ func (m *MenuItem) Prepend(item *MenuItem) bool { return true } -func (m *MenuItem) getByID(id string) *MenuItem { - - // If I have the ID return me! - if m.ID == id { - return m - } - - // If we have no submenu then exit early - if m.SubMenu == nil { - return nil - } - - // Check submenus - for _, submenu := range m.SubMenu.Items { - result := submenu.getByID(id) - if result != nil { - return result - } - } - - return nil -} - func (m *MenuItem) Remove() { // Iterate my parent's children m.Parent().removeChild(m) @@ -113,28 +88,6 @@ func (m *MenuItem) removeChild(item *MenuItem) { m.removeLock.Unlock() } -func (m *MenuItem) removeByID(id string) bool { - - // 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.Items = append(m.SubMenu.Items[:index], m.SubMenu.Items[index+1:]...) - return true - } - if item.isSubMenu() { - result := item.removeByID(id) - if result == true { - return result - } - } - } - return false -} - // InsertAfter attempts to add the given item after this item in the parent // menu. If there is no parent menu (we are a top level menu) then false is // returned @@ -250,9 +203,8 @@ func (m *MenuItem) insertItemAtIndex(index int, target *MenuItem) bool { } // Text is a helper to create basic Text menu items -func Text(label string, id string, accelerator *keys.Accelerator, click Callback) *MenuItem { +func Text(label string, accelerator *keys.Accelerator, click Callback) *MenuItem { return &MenuItem{ - ID: id, Label: label, Type: TextType, Accelerator: accelerator, @@ -268,9 +220,8 @@ func Separator() *MenuItem { } // Radio is a helper to create basic Radio menu items with an accelerator -func Radio(label string, id string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem { +func Radio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem { return &MenuItem{ - ID: id, Label: label, Type: RadioType, Checked: selected, @@ -280,9 +231,8 @@ func Radio(label string, id string, selected bool, accelerator *keys.Accelerator } // Checkbox is a helper to create basic Checkbox menu items -func Checkbox(label string, id string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem { +func Checkbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem { return &MenuItem{ - ID: id, Label: label, Type: CheckboxType, Checked: checked, @@ -305,11 +255,10 @@ func SubMenu(label string, menu *Menu) *MenuItem { } // SubMenuWithID is a helper to create Submenus with an ID -func SubMenuWithID(label string, id string, menu *Menu) *MenuItem { +func SubMenuWithID(label string, menu *Menu) *MenuItem { result := &MenuItem{ Label: label, SubMenu: menu, - ID: id, Type: SubmenuType, } diff --git a/v2/test/kitchensink/contextmenus.go b/v2/test/kitchensink/contextmenus.go index f8b2c816..82662a15 100644 --- a/v2/test/kitchensink/contextmenus.go +++ b/v2/test/kitchensink/contextmenus.go @@ -25,16 +25,16 @@ 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, nil), + menu.Text("Clicked 0 times", nil, nil), menu.Separator(), - menu.Checkbox("I am a checkbox", "checkbox", false, nil, nil), + menu.Checkbox("I am a checkbox", false, nil, nil), menu.Separator(), - menu.Radio("Radio Option 1", "Radio Option 1", true, nil, nil), - menu.Radio("Radio Option 2", "Radio Option 2", false, nil, nil), - menu.Radio("Radio Option 3", "Radio Option 3", false, nil, nil), + menu.Radio("Radio Option 1", true, nil, nil), + menu.Radio("Radio Option 2", false, nil, nil), + menu.Radio("Radio Option 3", false, nil, nil), menu.Separator(), menu.SubMenu("A Submenu", menu.NewMenuFromItems( - menu.Text("Hello", "Hello", nil, nil), + menu.Text("Hello", nil, nil), )), )) return result diff --git a/v2/test/kitchensink/menu.go b/v2/test/kitchensink/menu.go index 016cbe39..769e8af5 100644 --- a/v2/test/kitchensink/menu.go +++ b/v2/test/kitchensink/menu.go @@ -54,13 +54,13 @@ func (m *Menu) addDynamicMenusOneMenu(data *menu.CallbackData) { parent := mi.Parent() counter := m.incrementcounter() menuText := "Dynamic Menu Item " + strconv.Itoa(counter) - newDynamicMenu := menu.Text(menuText, menuText, nil, nil) + newDynamicMenu := menu.Text(menuText, nil, nil) m.dynamicMenuOneItems = append(m.dynamicMenuOneItems, newDynamicMenu) parent.Append(newDynamicMenu) // If this is the first dynamic menu added, let's add a remove menu item if counter == 1 { - m.removeMenuItem = menu.Text("Remove "+menuText, "Remove Last Item", keys.CmdOrCtrl("-"), m.removeDynamicMenuOneMenu) + m.removeMenuItem = menu.Text("Remove "+menuText, keys.CmdOrCtrl("-"), m.removeDynamicMenuOneMenu) parent.Prepend(m.removeMenuItem) } else { // Test if the remove menu hasn't already been removed in another thread @@ -111,8 +111,8 @@ func (m *Menu) createDynamicMenuTwo(data *menu.CallbackData) { // Create our submenu dm2 := menu.SubMenu("Dynamic Menus 2", menu.NewMenuFromItems( - menu.Text("Insert Before Random Menu Item", "Insert Before Random", keys.CmdOrCtrl("]"), m.insertBeforeRandom), - menu.Text("Insert After Random Menu Item", "Insert After Random", keys.CmdOrCtrl("["), m.insertAfterRandom), + menu.Text("Insert Before Random Menu Item", keys.CmdOrCtrl("]"), m.insertBeforeRandom), + menu.Text("Insert After Random Menu Item", keys.CmdOrCtrl("["), m.insertAfterRandom), menu.Separator(), )) @@ -126,7 +126,7 @@ func (m *Menu) createDynamicMenuTwo(data *menu.CallbackData) { m.anotherDynamicMenuCounter = 5 for index := 0; index < m.anotherDynamicMenuCounter; index++ { text := "Other Dynamic Menu Item " + strconv.Itoa(index+1) - item := menu.Text(text, text, nil, nil) + item := menu.Text(text, nil, nil) m.dynamicMenuItems[text] = item dm2.Append(item) } @@ -153,7 +153,7 @@ func (m *Menu) insertBeforeRandom(_ *menu.CallbackData) { m.anotherDynamicMenuCounter++ text := "Other Dynamic Menu Item " + strconv.Itoa(m.anotherDynamicMenuCounter) - newItem := menu.Text(text, text, nil, nil) + newItem := menu.Text(text, nil, nil) m.dynamicMenuItems[text] = newItem m.runtime.Log.Info(fmt.Sprintf("Inserting menu item '%s' before menu item '%s'", newItem.Label, randomMenuItem.Label)) @@ -176,7 +176,7 @@ func (m *Menu) insertAfterRandom(_ *menu.CallbackData) { m.anotherDynamicMenuCounter++ text := "Other Dynamic Menu Item " + strconv.Itoa(m.anotherDynamicMenuCounter) - newItem := menu.Text(text, text, nil, nil) + newItem := menu.Text(text, nil, nil) m.dynamicMenuItems[text] = newItem m.runtime.Log.Info(fmt.Sprintf("Inserting menu item '%s' after menu item '%s'", newItem.Label, randomMenuItem.Label)) @@ -192,8 +192,8 @@ func (m *Menu) processPlainText(callbackData *menu.CallbackData) { func (m *Menu) createApplicationMenu() *menu.Menu { - m.dynamicMenuOneSubmenu = menu.SubMenuWithID("Dynamic Menus 1", "Dynamic Menus 1", menu.NewMenuFromItems( - menu.Text("Add Menu Item", "Add Menu Item", keys.CmdOrCtrl("+"), m.addDynamicMenusOneMenu), + m.dynamicMenuOneSubmenu = menu.SubMenuWithID("Dynamic Menus 1", menu.NewMenuFromItems( + menu.Text("Add Menu Item", keys.CmdOrCtrl("+"), m.addDynamicMenusOneMenu), menu.Separator(), )) @@ -216,58 +216,58 @@ func (m *Menu) createApplicationMenu() *menu.Menu { menu.Front(), 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, m.createDynamicMenuTwo), + menu.Text("Plain text", nil, m.processPlainText), + menu.Text("Show Dynamic Menus 2 Submenu", nil, m.createDynamicMenuTwo), menu.SubMenu("Accelerators", menu.NewMenuFromItems( menu.SubMenu("Modifiers", menu.NewMenuFromItems( - menu.Text("Shift accelerator", "Shift", keys.Shift("o"), nil), - menu.Text("Control accelerator", "Control", keys.Control("o"), nil), - menu.Text("Command accelerator", "Command", keys.CmdOrCtrl("o"), nil), - menu.Text("Option accelerator", "Option", keys.OptionOrAlt("o"), nil), - menu.Text("Combo accelerator", "Combo", keys.Combo("o", keys.CmdOrCtrlKey, keys.ShiftKey), nil), + menu.Text("Shift accelerator", keys.Shift("o"), nil), + menu.Text("Control accelerator", keys.Control("o"), nil), + menu.Text("Command accelerator", keys.CmdOrCtrl("o"), nil), + menu.Text("Option accelerator", keys.OptionOrAlt("o"), nil), + menu.Text("Combo accelerator", keys.Combo("o", keys.CmdOrCtrlKey, keys.ShiftKey), nil), )), menu.SubMenu("System Keys", menu.NewMenuFromItems( - menu.Text("Backspace", "Backspace", keys.Key("Backspace"), nil), - menu.Text("Tab", "Tab", keys.Key("Tab"), nil), - menu.Text("Return", "Return", keys.Key("Return"), nil), - menu.Text("Escape", "Escape", keys.Key("Escape"), nil), - menu.Text("Left", "Left", keys.Key("Left"), nil), - menu.Text("Right", "Right", keys.Key("Right"), nil), - menu.Text("Up", "Up", keys.Key("Up"), nil), - menu.Text("Down", "Down", keys.Key("Down"), nil), - menu.Text("Space", "Space", keys.Key("Space"), nil), - menu.Text("Delete", "Delete", keys.Key("Delete"), nil), - menu.Text("Home", "Home", keys.Key("Home"), nil), - menu.Text("End", "End", keys.Key("End"), nil), - menu.Text("Page Up", "Page Up", keys.Key("Page Up"), nil), - menu.Text("Page Down", "Page Down", keys.Key("Page Down"), nil), - menu.Text("NumLock", "NumLock", keys.Key("NumLock"), nil), + menu.Text("Backspace", keys.Key("Backspace"), nil), + menu.Text("Tab", keys.Key("Tab"), nil), + menu.Text("Return", keys.Key("Return"), nil), + menu.Text("Escape", keys.Key("Escape"), nil), + menu.Text("Left", keys.Key("Left"), nil), + menu.Text("Right", keys.Key("Right"), nil), + menu.Text("Up", keys.Key("Up"), nil), + menu.Text("Down", keys.Key("Down"), nil), + menu.Text("Space", keys.Key("Space"), nil), + menu.Text("Delete", keys.Key("Delete"), nil), + menu.Text("Home", keys.Key("Home"), nil), + menu.Text("End", keys.Key("End"), nil), + menu.Text("Page Up", keys.Key("Page Up"), nil), + menu.Text("Page Down", keys.Key("Page Down"), nil), + menu.Text("NumLock", keys.Key("NumLock"), nil), )), menu.SubMenu("Function Keys", menu.NewMenuFromItems( - menu.Text("F1", "F1", keys.Key("F1"), nil), - menu.Text("F2", "F2", keys.Key("F2"), nil), - menu.Text("F3", "F3", keys.Key("F3"), nil), - menu.Text("F4", "F4", keys.Key("F4"), nil), - menu.Text("F5", "F5", keys.Key("F5"), nil), - menu.Text("F6", "F6", keys.Key("F6"), nil), - menu.Text("F7", "F7", keys.Key("F7"), nil), - menu.Text("F8", "F8", keys.Key("F8"), nil), - menu.Text("F9", "F9", keys.Key("F9"), nil), - menu.Text("F10", "F10", keys.Key("F10"), nil), - menu.Text("F11", "F11", keys.Key("F11"), nil), - menu.Text("F12", "F12", keys.Key("F12"), nil), - menu.Text("F13", "F13", keys.Key("F13"), nil), - menu.Text("F14", "F14", keys.Key("F14"), nil), - menu.Text("F15", "F15", keys.Key("F15"), nil), - menu.Text("F16", "F16", keys.Key("F16"), nil), - menu.Text("F17", "F17", keys.Key("F17"), nil), - menu.Text("F18", "F18", keys.Key("F18"), nil), - menu.Text("F19", "F19", keys.Key("F19"), nil), - menu.Text("F20", "F20", keys.Key("F20"), nil), + menu.Text("F1", keys.Key("F1"), nil), + menu.Text("F2", keys.Key("F2"), nil), + menu.Text("F3", keys.Key("F3"), nil), + menu.Text("F4", keys.Key("F4"), nil), + menu.Text("F5", keys.Key("F5"), nil), + menu.Text("F6", keys.Key("F6"), nil), + menu.Text("F7", keys.Key("F7"), nil), + menu.Text("F8", keys.Key("F8"), nil), + menu.Text("F9", keys.Key("F9"), nil), + menu.Text("F10", keys.Key("F10"), nil), + menu.Text("F11", keys.Key("F11"), nil), + menu.Text("F12", keys.Key("F12"), nil), + menu.Text("F13", keys.Key("F13"), nil), + menu.Text("F14", keys.Key("F14"), nil), + menu.Text("F15", keys.Key("F15"), nil), + menu.Text("F16", keys.Key("F16"), nil), + menu.Text("F17", keys.Key("F17"), nil), + menu.Text("F18", keys.Key("F18"), nil), + menu.Text("F19", keys.Key("F19"), nil), + menu.Text("F20", keys.Key("F20"), nil), )), menu.SubMenu("Standard Keys", menu.NewMenuFromItems( - menu.Text("Backtick", "Backtick", keys.Key("`"), nil), - menu.Text("Plus", "Plus", keys.Key("+"), nil), + menu.Text("Backtick", keys.Key("`"), nil), + menu.Text("Plus", keys.Key("+"), nil), )), )), m.dynamicMenuOneSubmenu, @@ -283,7 +283,6 @@ func (m *Menu) createApplicationMenu() *menu.Menu { Hidden: true, }, &menu.MenuItem{ - ID: "checkbox-menu 1", Label: "Checkbox Menu 1", Type: menu.CheckboxType, Accelerator: keys.CmdOrCtrl("l"), @@ -293,11 +292,11 @@ func (m *Menu) createApplicationMenu() *menu.Menu { fmt.Printf("It is now %v\n", data.MenuItem.Checked) }, }, - menu.Checkbox("Checkbox Menu 2", "checkbox-menu 2", false, nil, nil), + menu.Checkbox("Checkbox Menu 2", false, nil, nil), menu.Separator(), - menu.Radio("๐Ÿ˜€ Option 1", "๐Ÿ˜€option-1", true, nil, nil), - menu.Radio("๐Ÿ˜บ Option 2", "option-2", false, nil, nil), - menu.Radio("โค๏ธ Option 3", "option-3", false, nil, nil), + menu.Radio("๐Ÿ˜€ Option 1", true, nil, nil), + menu.Radio("๐Ÿ˜บ Option 2", false, nil, nil), + menu.Radio("โค๏ธ Option 3", false, nil, nil), )), )) diff --git a/v2/test/kitchensink/tray.go b/v2/test/kitchensink/tray.go index 33dd5ba0..a2ca047e 100644 --- a/v2/test/kitchensink/tray.go +++ b/v2/test/kitchensink/tray.go @@ -127,10 +127,10 @@ func (t *Tray) createTrayMenus() []*menu.TrayMenu { trayMenu := &menu.TrayMenu{} trayMenu.Label = "Test Tray Label" trayMenu.Menu = menu.NewMenuFromItems( - menu.Text("Show Window", "Show Window", nil, t.showWindow), - menu.Text("Hide Window", "Hide Window", nil, t.hideWindow), - menu.Text("Minimise Window", "Minimise Window", nil, t.minimiseWindow), - menu.Text("Unminimise Window", "Unminimise Window", nil, t.unminimiseWindow), + menu.Text("Show Window", nil, t.showWindow), + menu.Text("Hide Window", nil, t.hideWindow), + menu.Text("Minimise Window", nil, t.minimiseWindow), + menu.Text("Unminimise Window", nil, t.unminimiseWindow), ) t.trayMenu = trayMenu @@ -138,7 +138,7 @@ func (t *Tray) createTrayMenus() []*menu.TrayMenu { secondTrayMenu.Label = "Another tray label" secondTrayMenu.Icon = "svelte" secondTrayMenu.Menu = menu.NewMenuFromItems( - menu.Text("Update Label", "Update Label", nil, func(_ *menu.CallbackData) { + menu.Text("Update Label", nil, func(_ *menu.CallbackData) { // Lock because this method will be called in a goroutine t.lock.Lock() defer t.lock.Unlock() @@ -149,10 +149,10 @@ func (t *Tray) createTrayMenus() []*menu.TrayMenu { t.runtime.Menu.UpdateTrayMenu(t.secondTrayMenu) }), menu.SubMenu("Select Icon", menu.NewMenuFromItems( - menu.Text("Svelte", "Svelte", nil, t.SvelteIcon), - menu.Text("Light", "Light", nil, t.LightIcon), - menu.Text("Dark", "Dark", nil, t.DarkIcon), - menu.Text("None", "None", nil, t.NoIcon), + menu.Text("Svelte", nil, t.SvelteIcon), + menu.Text("Light", nil, t.LightIcon), + menu.Text("Dark", nil, t.DarkIcon), + menu.Text("None", nil, t.NoIcon), )), ) t.secondTrayMenu = secondTrayMenu