From db6dde3e50aec3a31525a52665e4e0f8ef1dbb51 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 12 Jan 2021 15:55:28 +1100 Subject: [PATCH] [WIP] Support tray in menu manager --- v2/internal/app/desktop.go | 33 ++-- v2/internal/ffenestri/ffenestri_client.go | 2 +- v2/internal/ffenestri/ffenestri_darwin.go | 29 ++- v2/internal/menumanager/menumanager.go | 4 + v2/internal/menumanager/traymenu.go | 62 ++++++ v2/internal/runtime/menu.go | 9 +- v2/internal/runtime/runtime.go | 6 +- v2/internal/runtime/tray.go | 16 +- v2/internal/subsystem/menu.go | 14 +- v2/internal/subsystem/runtime.go | 4 +- v2/internal/subsystem/tray.go | 8 +- v2/pkg/menu/tray.go | 7 +- v2/pkg/options/mac/mac.go | 2 +- v2/pkg/options/options.go | 22 +-- v2/test/kitchensink/main.go | 11 +- v2/test/kitchensink/tray.go | 230 +++++++++++----------- 16 files changed, 250 insertions(+), 209 deletions(-) create mode 100644 v2/internal/menumanager/traymenu.go diff --git a/v2/internal/app/desktop.go b/v2/internal/app/desktop.go index 749729b8..2a8d81e1 100644 --- a/v2/internal/app/desktop.go +++ b/v2/internal/app/desktop.go @@ -71,6 +71,12 @@ func CreateApp(appoptions *options.App) (*App, error) { } } + // Process tray menus + trayMenus := options.GetTrayMenus(appoptions) + for _, trayMenu := range trayMenus { + menuManager.AddTrayMenu(trayMenu) + } + window := ffenestri.NewApplicationWithConfig(appoptions, myLogger, menuManager) result := &App{ @@ -112,10 +118,9 @@ func (a *App) Run() error { // Start the runtime applicationMenu := options.GetApplicationMenu(a.options) - trayMenu := options.GetTray(a.options) contextMenus := options.GetContextMenus(a.options) - runtimesubsystem, err := subsystem.NewRuntime(a.servicebus, a.logger, applicationMenu, trayMenu, contextMenus) + runtimesubsystem, err := subsystem.NewRuntime(a.servicebus, a.logger, contextMenus) if err != nil { return err } @@ -186,18 +191,18 @@ 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 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 { diff --git a/v2/internal/ffenestri/ffenestri_client.go b/v2/internal/ffenestri/ffenestri_client.go index f516230a..c1e5f442 100644 --- a/v2/internal/ffenestri/ffenestri_client.go +++ b/v2/internal/ffenestri/ffenestri_client.go @@ -200,7 +200,7 @@ func (c *Client) UpdateTray(menu *menu.Menu) { processedMenu := NewProcessedMenu(menu) trayMenuJSON, err := json.Marshal(processedMenu) if err != nil { - c.app.logger.Error("Error processing updated Tray: %s", err.Error()) + c.app.logger.Error("Error processing updated TrayMenu: %s", err.Error()) return } C.UpdateTray(c.app.app, c.app.string2CString(string(trayMenuJSON))) diff --git a/v2/internal/ffenestri/ffenestri_darwin.go b/v2/internal/ffenestri/ffenestri_darwin.go index 95a34ff3..e495da1f 100644 --- a/v2/internal/ffenestri/ffenestri_darwin.go +++ b/v2/internal/ffenestri/ffenestri_darwin.go @@ -23,8 +23,8 @@ extern void SetContextMenus(void *, const char *); */ import "C" import ( - "encoding/json" "github.com/wailsapp/wails/v2/pkg/options" + "os" ) func (a *Application) processPlatformSettings() error { @@ -83,24 +83,17 @@ func (a *Application) processPlatformSettings() error { } // Process tray - tray := options.GetTray(a.config) - if tray != nil { - - /* - As radio groups need to be manually managed on OSX, - we preprocess the menu to determine the radio groups. - This is defined as any adjacent menu item of type "RadioType". - We keep a record of every radio group member we discover by saving - a list of all members of the group and the number of members - in the group (this last one is for optimisation at the C layer). - */ - processedMenu := NewProcessedMenu(tray.Menu) - trayMenuJSON, err := json.Marshal(processedMenu) - if err != nil { - return err - } - C.SetTray(a.app, a.string2CString(string(trayMenuJSON)), a.string2CString(tray.Label), a.string2CString(tray.Icon)) + trays, err := a.menuManager.GetTrayMenus() + if err != nil { + return err } + if trays != nil { + for _, tray := range trays { + println("Adding tray menu: " + tray) + //C.AddTray(a.app, a.string2CString(tray)) + } + } + os.Exit(1) // Process context menus contextMenus := options.GetContextMenus(a.config) diff --git a/v2/internal/menumanager/menumanager.go b/v2/internal/menumanager/menumanager.go index e6322409..c8cba150 100644 --- a/v2/internal/menumanager/menumanager.go +++ b/v2/internal/menumanager/menumanager.go @@ -16,12 +16,16 @@ type Manager struct { // Context menus contextMenus map[string]*ContextMenu + + // Tray menus + trayMenus map[string]*TrayMenu } func NewManager() *Manager { return &Manager{ applicationMenuItemMap: NewMenuItemMap(), contextMenus: make(map[string]*ContextMenu), + trayMenus: make(map[string]*TrayMenu), } } diff --git a/v2/internal/menumanager/traymenu.go b/v2/internal/menumanager/traymenu.go new file mode 100644 index 00000000..d62d3652 --- /dev/null +++ b/v2/internal/menumanager/traymenu.go @@ -0,0 +1,62 @@ +package menumanager + +import ( + "encoding/json" + "fmt" + "github.com/wailsapp/wails/v2/pkg/menu" + "sync" +) + +var trayMenuID int +var trayMenuIDMutex sync.Mutex + +func generateTrayID() string { + trayMenuIDMutex.Lock() + result := fmt.Sprintf("%d", trayMenuID) + trayMenuID++ + trayMenuIDMutex.Unlock() + return result +} + +type TrayMenu struct { + ID string + Label string + Icon string + menuItemMap *MenuItemMap + menu *menu.Menu + ProcessedMenu *WailsMenu +} + +func NewTrayMenu(trayMenu *menu.TrayMenu) *TrayMenu { + + result := &TrayMenu{ + ID: generateTrayID(), + Label: trayMenu.Label, + Icon: trayMenu.Icon, + menu: trayMenu.Menu, + menuItemMap: NewMenuItemMap(), + } + + result.menuItemMap.AddMenu(trayMenu.Menu) + result.ProcessedMenu = NewWailsMenu(result.menuItemMap, result.menu) + + return result +} + +func (m *Manager) AddTrayMenu(trayMenu *menu.TrayMenu) { + newTrayMenu := NewTrayMenu(trayMenu) + m.trayMenus[newTrayMenu.ID] = newTrayMenu +} + +func (m *Manager) GetTrayMenus() ([]string, error) { + result := []string{} + for _, trayMenu := range m.trayMenus { + data, err := json.Marshal(trayMenu) + if err != nil { + return nil, err + } + result = append(result, string(data)) + } + + return result, nil +} diff --git a/v2/internal/runtime/menu.go b/v2/internal/runtime/menu.go index e6a5ccfd..57abdfeb 100644 --- a/v2/internal/runtime/menu.go +++ b/v2/internal/runtime/menu.go @@ -2,7 +2,6 @@ package runtime import ( "github.com/wailsapp/wails/v2/internal/servicebus" - "github.com/wailsapp/wails/v2/pkg/menu" ) // Menu defines all Menu related operations @@ -11,15 +10,13 @@ type Menu interface { } type menuRuntime struct { - bus *servicebus.ServiceBus - menu *menu.Menu + bus *servicebus.ServiceBus } // newMenu creates a new Menu struct -func newMenu(bus *servicebus.ServiceBus, menu *menu.Menu) Menu { +func newMenu(bus *servicebus.ServiceBus) Menu { return &menuRuntime{ - bus: bus, - menu: menu, + bus: bus, } } diff --git a/v2/internal/runtime/runtime.go b/v2/internal/runtime/runtime.go index bbc413ff..d3618726 100644 --- a/v2/internal/runtime/runtime.go +++ b/v2/internal/runtime/runtime.go @@ -14,22 +14,20 @@ type Runtime struct { System System Menu Menu ContextMenu ContextMenus - Tray Tray Store *StoreProvider Log Log bus *servicebus.ServiceBus } // New creates a new runtime -func New(serviceBus *servicebus.ServiceBus, menu *menu.Menu, trayMenu *menu.Tray, contextMenus *menu.ContextMenus) *Runtime { +func New(serviceBus *servicebus.ServiceBus, contextMenus *menu.ContextMenus) *Runtime { result := &Runtime{ Browser: newBrowser(), Events: newEvents(serviceBus), Window: newWindow(serviceBus), Dialog: newDialog(serviceBus), System: newSystem(serviceBus), - Menu: newMenu(serviceBus, menu), - Tray: newTray(serviceBus, trayMenu), + Menu: newMenu(serviceBus), ContextMenu: newContextMenus(serviceBus, contextMenus), Log: newLog(serviceBus), bus: serviceBus, diff --git a/v2/internal/runtime/tray.go b/v2/internal/runtime/tray.go index f0dd6eb2..343b3afe 100644 --- a/v2/internal/runtime/tray.go +++ b/v2/internal/runtime/tray.go @@ -8,9 +8,8 @@ import ( // Tray defines all Tray related operations type Tray interface { - NewTray(id string) *menu.Tray On(menuID string, callback func(*menu.MenuItem)) - Update(tray ...*menu.Tray) + Update(tray ...*menu.TrayMenu) GetByID(menuID string) *menu.MenuItem RemoveByID(id string) bool SetLabel(label string) @@ -19,11 +18,11 @@ type Tray interface { type trayRuntime struct { bus *servicebus.ServiceBus - trayMenu *menu.Tray + trayMenu *menu.TrayMenu } // newTray creates a new Menu struct -func newTray(bus *servicebus.ServiceBus, menu *menu.Tray) Tray { +func newTray(bus *servicebus.ServiceBus, menu *menu.TrayMenu) Tray { return &trayRuntime{ bus: bus, trayMenu: menu, @@ -38,14 +37,7 @@ func (t *trayRuntime) On(menuID string, callback func(*menu.MenuItem)) { }) } -// NewTray creates a new Tray item -func (t *trayRuntime) NewTray(trayID string) *menu.Tray { - return &menu.Tray{ - ID: trayID, - } -} - -func (t *trayRuntime) Update(tray ...*menu.Tray) { +func (t *trayRuntime) Update(tray ...*menu.TrayMenu) { //trayToUpdate := t.trayMenu t.bus.Publish("tray:update", t.trayMenu) diff --git a/v2/internal/subsystem/menu.go b/v2/internal/subsystem/menu.go index df2e0b06..8c216dd2 100644 --- a/v2/internal/subsystem/menu.go +++ b/v2/internal/subsystem/menu.go @@ -2,13 +2,10 @@ package subsystem import ( "encoding/json" - "github.com/wailsapp/wails/v2/internal/menumanager" - "strings" - "sync" - "github.com/wailsapp/wails/v2/internal/logger" + "github.com/wailsapp/wails/v2/internal/menumanager" "github.com/wailsapp/wails/v2/internal/servicebus" - "github.com/wailsapp/wails/v2/pkg/menu" + "strings" ) // Menu is the subsystem that handles the operation of menus. It manages all service bus messages @@ -18,11 +15,6 @@ type Menu struct { menuChannel <-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 @@ -52,8 +44,6 @@ func NewMenu(bus *servicebus.ServiceBus, logger *logger.Logger, menuManager *men quitChannel: quitChannel, menuChannel: menuChannel, logger: logger.CustomLogger("Menu Subsystem"), - listeners: make(map[string][]func(*menu.MenuItem)), - menuItems: make(map[string]*menu.MenuItem), bus: bus, menuManager: menuManager, } diff --git a/v2/internal/subsystem/runtime.go b/v2/internal/subsystem/runtime.go index 878cfcd2..e0a1ac14 100644 --- a/v2/internal/subsystem/runtime.go +++ b/v2/internal/subsystem/runtime.go @@ -24,7 +24,7 @@ type Runtime struct { } // NewRuntime creates a new runtime subsystem -func NewRuntime(bus *servicebus.ServiceBus, logger *logger.Logger, menu *menu.Menu, trayMenu *menu.Tray, contextMenus *menu.ContextMenus) (*Runtime, error) { +func NewRuntime(bus *servicebus.ServiceBus, logger *logger.Logger, contextMenus *menu.ContextMenus) (*Runtime, error) { // Register quit channel quitChannel, err := bus.Subscribe("quit") @@ -42,7 +42,7 @@ func NewRuntime(bus *servicebus.ServiceBus, logger *logger.Logger, menu *menu.Me quitChannel: quitChannel, runtimeChannel: runtimeChannel, logger: logger.CustomLogger("Runtime Subsystem"), - runtime: runtime.New(bus, menu, trayMenu, contextMenus), + runtime: runtime.New(bus, contextMenus), } return result, nil diff --git a/v2/internal/subsystem/tray.go b/v2/internal/subsystem/tray.go index 99165707..c153bf5e 100644 --- a/v2/internal/subsystem/tray.go +++ b/v2/internal/subsystem/tray.go @@ -26,14 +26,14 @@ type Tray struct { logger logger.CustomLogger // The tray menu - trayMenu *menu.Tray + trayMenu *menu.TrayMenu // Service Bus bus *servicebus.ServiceBus } // NewTray creates a new menu subsystem -func NewTray(trayMenu *menu.Tray, bus *servicebus.ServiceBus, +func NewTray(trayMenu *menu.TrayMenu, bus *servicebus.ServiceBus, logger *logger.Logger) (*Tray, error) { // Register quit channel @@ -51,7 +51,7 @@ func NewTray(trayMenu *menu.Tray, bus *servicebus.ServiceBus, result := &Tray{ quitChannel: quitChannel, trayChannel: trayChannel, - logger: logger.CustomLogger("Tray Subsystem"), + logger: logger.CustomLogger("TrayMenu Subsystem"), listeners: make(map[string][]func(*menu.MenuItem)), menuItems: make(map[string]*menu.MenuItem), trayMenu: trayMenu, @@ -87,7 +87,7 @@ func (t *Tray) Start() error { t.logger.Error("Received clicked message with invalid topic format. Expected 2 sections in topic, got %s", splitTopic) continue } - t.logger.Trace("Got Tray Menu clicked Message: %s %+v", menuMessage.Topic(), menuMessage.Data()) + t.logger.Trace("Got TrayMenu Menu clicked Message: %s %+v", menuMessage.Topic(), menuMessage.Data()) menuid := menuMessage.Data().(string) // Get the menu item diff --git a/v2/pkg/menu/tray.go b/v2/pkg/menu/tray.go index 1701daf8..989df383 100644 --- a/v2/pkg/menu/tray.go +++ b/v2/pkg/menu/tray.go @@ -1,10 +1,7 @@ package menu -// Tray are the options -type Tray struct { - - // The ID of this tray - ID string +// TrayMenu are the options +type TrayMenu struct { // Label is the text we wish to display in the tray Label string diff --git a/v2/pkg/options/mac/mac.go b/v2/pkg/options/mac/mac.go index 2c74c8fe..fcf9d1cc 100644 --- a/v2/pkg/options/mac/mac.go +++ b/v2/pkg/options/mac/mac.go @@ -9,6 +9,6 @@ type Options struct { WebviewIsTransparent bool WindowBackgroundIsTranslucent bool Menu *menu.Menu - Tray *menu.Tray + TrayMenus []*menu.TrayMenu ContextMenus *menu.ContextMenus } diff --git a/v2/pkg/options/options.go b/v2/pkg/options/options.go index f37808d1..8df231cd 100644 --- a/v2/pkg/options/options.go +++ b/v2/pkg/options/options.go @@ -25,7 +25,7 @@ type App struct { DevTools bool RGBA int ContextMenus *menu.ContextMenus - Tray *menu.Tray + TrayMenus []*menu.TrayMenu Menu *menu.Menu Mac *mac.Options Logger logger.Logger `json:"-"` @@ -41,25 +41,25 @@ func MergeDefaults(appoptions *App) { } -func GetTray(appoptions *App) *menu.Tray { - var result *menu.Tray +func GetTrayMenus(appoptions *App) []*menu.TrayMenu { + var result []*menu.TrayMenu switch runtime.GOOS { case "darwin": if appoptions.Mac != nil { - result = appoptions.Mac.Tray + result = appoptions.Mac.TrayMenus } //case "linux": // if appoptions.Linux != nil { - // result = appoptions.Linux.Tray + // result = appoptions.Linux.TrayMenu // } //case "windows": // if appoptions.Windows != nil { - // result = appoptions.Windows.Tray + // result = appoptions.Windows.TrayMenu // } } if result == nil { - result = appoptions.Tray + result = appoptions.TrayMenus } return result @@ -74,11 +74,11 @@ func GetApplicationMenu(appoptions *App) *menu.Menu { } //case "linux": // if appoptions.Linux != nil { - // result = appoptions.Linux.Tray + // result = appoptions.Linux.TrayMenu // } //case "windows": // if appoptions.Windows != nil { - // result = appoptions.Windows.Tray + // result = appoptions.Windows.TrayMenu // } } @@ -101,11 +101,11 @@ func GetContextMenus(appoptions *App) *menu.ContextMenus { } //case "linux": // if appoptions.Linux != nil { - // result = appoptions.Linux.Tray + // result = appoptions.Linux.TrayMenu // } //case "windows": // if appoptions.Windows != nil { - // result = appoptions.Windows.Tray + // result = appoptions.Windows.TrayMenu // } } diff --git a/v2/test/kitchensink/main.go b/v2/test/kitchensink/main.go index 419e6d8e..79c62fbf 100644 --- a/v2/test/kitchensink/main.go +++ b/v2/test/kitchensink/main.go @@ -11,6 +11,7 @@ import ( func main() { Menu := &Menu{} + Tray := &Tray{} // Create application with options app, err := wails.CreateAppWithOptions(&options.App{ @@ -27,12 +28,9 @@ func main() { WebviewIsTransparent: true, WindowBackgroundIsTranslucent: true, // Comment out line below to see Window.SetTitle() work - TitleBar: mac.TitleBarHiddenInset(), - Menu: Menu.createApplicationMenu(), - //Tray: &menu.Tray{ - // Icon: "light", - // Menu: createApplicationTray(), - //}, + TitleBar: mac.TitleBarHiddenInset(), + Menu: Menu.createApplicationMenu(), + TrayMenus: Tray.createTrayMenus(), }, LogLevel: logger.TRACE, }) @@ -48,7 +46,6 @@ func main() { app.Bind(&Dialog{}) app.Bind(&Window{}) app.Bind(Menu) - app.Bind(&Tray{}) app.Bind(&ContextMenu{}) err = app.Run() diff --git a/v2/test/kitchensink/tray.go b/v2/test/kitchensink/tray.go index 2474c59c..b1b2f62e 100644 --- a/v2/test/kitchensink/tray.go +++ b/v2/test/kitchensink/tray.go @@ -3,19 +3,18 @@ package main import ( "github.com/wailsapp/wails/v2" "github.com/wailsapp/wails/v2/pkg/menu" - "github.com/wailsapp/wails/v2/pkg/menu/keys" - "strconv" - "sync" ) // Tray struct type Tray struct { runtime *wails.Runtime + // + //dynamicMenuCounter int + //lock sync.Mutex + //dynamicMenuItems map[string]*menu.MenuItem + //anotherDynamicMenuCounter int - dynamicMenuCounter int - lock sync.Mutex - dynamicMenuItems map[string]*menu.MenuItem - anotherDynamicMenuCounter int + trayMenu *menu.TrayMenu done bool } @@ -24,32 +23,32 @@ type Tray struct { func (t *Tray) WailsInit(runtime *wails.Runtime) error { // Perform your setup here t.runtime = runtime - - // Setup Menu Listeners - t.runtime.Tray.On("Show Window", func(mi *menu.MenuItem) { - t.runtime.Window.Show() - }) - t.runtime.Tray.On("Hide Window", func(mi *menu.MenuItem) { - t.runtime.Window.Hide() - }) - - t.runtime.Tray.On("Minimise Window", func(mi *menu.MenuItem) { - t.runtime.Window.Minimise() - }) - - t.runtime.Tray.On("Unminimise Window", func(mi *menu.MenuItem) { - t.runtime.Window.Unminimise() - }) - - // Auto switch between light / dark tray icons - t.runtime.Events.OnThemeChange(func(darkMode bool) { - if darkMode { - t.runtime.Tray.SetIcon("light") - return - } - - t.runtime.Tray.SetIcon("dark") - }) + // + //// Setup Menu Listeners + //t.runtime.Tray.On("Show Window", func(mi *menu.MenuItem) { + // t.runtime.Window.Show() + //}) + //t.runtime.Tray.On("Hide Window", func(mi *menu.MenuItem) { + // t.runtime.Window.Hide() + //}) + // + //t.runtime.Tray.On("Minimise Window", func(mi *menu.MenuItem) { + // t.runtime.Window.Minimise() + //}) + // + //t.runtime.Tray.On("Unminimise Window", func(mi *menu.MenuItem) { + // t.runtime.Window.Unminimise() + //}) + // + //// Auto switch between light / dark tray icons + //t.runtime.Events.OnThemeChange(func(darkMode bool) { + // if darkMode { + // t.runtime.Tray.SetIcon("light") + // return + // } + // + // t.runtime.Tray.SetIcon("dark") + //}) return nil } @@ -58,87 +57,94 @@ func (t *Tray) WailsShutdown() { t.done = true } -func (t *Tray) incrementcounter() int { - t.dynamicMenuCounter++ - return t.dynamicMenuCounter -} +//func (t *Tray) incrementcounter() int { +// t.dynamicMenuCounter++ +// return t.dynamicMenuCounter +//} +// +//func (t *Tray) decrementcounter() int { +// t.dynamicMenuCounter-- +// return t.dynamicMenuCounter +//} +// +//func (t *Tray) addMenu(mi *menu.MenuItem) { +// +// // Lock because this method will be called in a gorouting +// t.lock.Lock() +// defer t.lock.Unlock() +// +// // Get this menu's parent +// parent := mi.Parent() +// counter := t.incrementcounter() +// menuText := "Dynamic Menu Item " + strconv.Itoa(counter) +// parent.Append(menu.Text(menuText, menuText, nil, nil)) +// // parent.Append(menu.Text(menuText, menuText, menu.Key("["))) +// +// // 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) +// t.runtime.Tray.On("Remove Last Item", t.removeMenu) +// } else { +// removeMenu := t.runtime.Tray.GetByID("Remove Last Item") +// // Test if the remove menu hasn't already been removed in another thread +// if removeMenu != nil { +// removeMenu.Label = "Remove " + menuText +// } +// } +// t.runtime.Tray.Update() +//} +// +//func (t *Tray) removeMenu(_ *menu.MenuItem) { +// +// // Lock because this method will be called in a goroutine +// t.lock.Lock() +// defer t.lock.Unlock() +// +// // Get the id of the last dynamic menu +// menuID := "Dynamic Menu Item " + strconv.Itoa(t.dynamicMenuCounter) +// +// // Remove the last menu item by ID +// t.runtime.Tray.RemoveByID(menuID) +// +// // Update the counter +// counter := t.decrementcounter() +// +// // If we deleted the last dynamic menu, remove the "Remove Last Item" menu +// if counter == 0 { +// t.runtime.Tray.RemoveByID("Remove Last Item") +// } else { +// // Update label +// menuText := "Dynamic Menu Item " + strconv.Itoa(counter) +// removeMenu := t.runtime.Tray.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("["))) +// t.runtime.Tray.Update() +//} -func (t *Tray) decrementcounter() int { - t.dynamicMenuCounter-- - return t.dynamicMenuCounter -} +//func (t *Tray) SetIcon(trayIconID string) { +// t.runtime.Tray.SetIcon(trayIconID) +//} -func (t *Tray) addMenu(mi *menu.MenuItem) { +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, nil), + menu.Text("Hide Window", "Hide Window", nil, nil), + menu.Text("Minimise Window", "Minimise Window", nil, nil), + menu.Text("Unminimise Window", "Unminimise Window", nil, nil), + ) + t.trayMenu = trayMenu - // Lock because this method will be called in a gorouting - t.lock.Lock() - defer t.lock.Unlock() - - // Get this menu's parent - parent := mi.Parent() - counter := t.incrementcounter() - menuText := "Dynamic Menu Item " + strconv.Itoa(counter) - parent.Append(menu.Text(menuText, menuText, nil, nil)) - // parent.Append(menu.Text(menuText, menuText, menu.Key("["))) - - // 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) - t.runtime.Tray.On("Remove Last Item", t.removeMenu) - } else { - removeMenu := t.runtime.Tray.GetByID("Remove Last Item") - // Test if the remove menu hasn't already been removed in another thread - if removeMenu != nil { - removeMenu.Label = "Remove " + menuText - } + return []*menu.TrayMenu{ + trayMenu, } - t.runtime.Tray.Update() -} - -func (t *Tray) removeMenu(_ *menu.MenuItem) { - - // Lock because this method will be called in a goroutine - t.lock.Lock() - defer t.lock.Unlock() - - // Get the id of the last dynamic menu - menuID := "Dynamic Menu Item " + strconv.Itoa(t.dynamicMenuCounter) - - // Remove the last menu item by ID - t.runtime.Tray.RemoveByID(menuID) - - // Update the counter - counter := t.decrementcounter() - - // If we deleted the last dynamic menu, remove the "Remove Last Item" menu - if counter == 0 { - t.runtime.Tray.RemoveByID("Remove Last Item") - } else { - // Update label - menuText := "Dynamic Menu Item " + strconv.Itoa(counter) - removeMenu := t.runtime.Tray.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("["))) - t.runtime.Tray.Update() -} - -func (t *Tray) SetIcon(trayIconID string) { - t.runtime.Tray.SetIcon(trayIconID) -} - -func createApplicationTray() *menu.Menu { - trayMenu := &menu.Menu{} - trayMenu.Append(menu.Text("Show Window", "Show Window", nil, nil)) - trayMenu.Append(menu.Text("Hide Window", "Hide Window", nil, nil)) - trayMenu.Append(menu.Text("Minimise Window", "Minimise Window", nil, nil)) - trayMenu.Append(menu.Text("Unminimise Window", "Unminimise Window", nil, nil)) - return trayMenu }