diff --git a/v2/internal/frontend/desktop/darwin/Application.h b/v2/internal/frontend/desktop/darwin/Application.h index 9c61eaae8..5600706f7 100644 --- a/v2/internal/frontend/desktop/darwin/Application.h +++ b/v2/internal/frontend/desktop/darwin/Application.h @@ -59,8 +59,9 @@ void UpdateApplicationMenu(void *inctx); void SetMenuItemChecked(void* nsMenuItem, int checked); /* Tray Menu */ -void* NewNSStatusItem(const char* label); +void NewNSStatusItem(int); void SetTrayMenu(void *nsStatusItem, void* nsMenu); +void SetTrayMenuLabel(void *nsStatusItem, const char *label); void SetAbout(void *inctx, const char* title, const char* description, void* imagedata, int datalen); void* AppendMenuItem(void* inctx, void* nsmenu, const char* label, const char* shortcutKey, int modifiers, int disabled, int checked, int menuItemID); @@ -69,4 +70,6 @@ void UpdateMenuItem(void* nsmenuitem, int checked); NSString* safeInit(const char* input); +void SetTrayImage(void *nsStatusItem, void *imageData, int imageDataLength, int template, int position); + #endif /* Application_h */ diff --git a/v2/internal/frontend/desktop/darwin/Application.m b/v2/internal/frontend/desktop/darwin/Application.m index 9106b2983..7f1436809 100644 --- a/v2/internal/frontend/desktop/darwin/Application.m +++ b/v2/internal/frontend/desktop/darwin/Application.m @@ -11,6 +11,7 @@ #import "AppDelegate.h" #import "WailsMenu.h" #import "WailsMenuItem.h" +#import "message.h" WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight) { @@ -274,12 +275,20 @@ void AppendRole(void *inctx, void *inMenu, int role) { [menu appendRole :ctx :role]; } -void* NewNSStatusItem(const char* label) { - NSString *_label = safeInit(label); - NSStatusBar *statusBar = [NSStatusBar systemStatusBar]; - NSStatusItem *result = [[statusBar statusItemWithLength:NSVariableStatusItemLength] retain]; - [result button].title = _label; - return result; +void NewNSStatusItem(int id) { + ON_MAIN_THREAD( + NSStatusBar *statusBar = [NSStatusBar systemStatusBar]; + NSStatusItem *result = [[statusBar statusItemWithLength:NSVariableStatusItemLength] retain]; + objectCreated(id,result); + ) +} + +void SetTrayMenuLabel(void *_nsStatusItem, const char *label) { + ON_MAIN_THREAD( + NSStatusItem *nsStatusItem = (NSStatusItem*) _nsStatusItem; + nsStatusItem.button.title = safeInit(label); + free((void*)label); + ) } void SetTrayMenu(void *nsStatusItem, void* nsMenu) { @@ -313,8 +322,8 @@ void SetAsApplicationMenu(void *inctx, void *inMenu) { void UpdateApplicationMenu(void *inctx) { WailsContext *ctx = (__bridge WailsContext*) inctx; ON_MAIN_THREAD( - NSApplication *app = [NSApplication sharedApplication]; - [app setMainMenu:ctx.applicationMenu]; + NSApplication *app = [NSApplication sharedApplication]; + [app setMainMenu:ctx.applicationMenu]; ) } @@ -339,7 +348,7 @@ void UpdateMenuItem(void* nsmenuitem, int checked) { ON_MAIN_THREAD( WailsMenuItem *menuItem = (__bridge WailsMenuItem*) nsmenuitem; [menuItem setState:(checked == 1?NSControlStateValueOn:NSControlStateValueOff)]; - ) + ) } @@ -348,6 +357,27 @@ void AppendSeparator(void* inMenu) { [menu AppendSeparator]; } +void SetTrayImage(void *nsStatusItem, void *imageData, int imageDataLength, int template, int position) { + ON_MAIN_THREAD( + NSStatusItem *statusItem = (NSStatusItem*) nsStatusItem; + NSData *nsdata = [NSData dataWithBytes:imageData length:imageDataLength]; + NSImage *image = [[[NSImage alloc] initWithData:nsdata] autorelease]; + if(template) { + image.template = true; + } + statusItem.button.image = image; + + // Swap NSNoImage and NSImageLeading because we wanted NSImageLeading to be default in Go + int actualPosition = position; + if( position == 7) { + actualPosition = 0; + } else if (position == 0) { + actualPosition = 7; + } + [statusItem.button setImagePosition:actualPosition]; + ) +} + void Run(void *inctx, const char* url, int activationPolicy) { WailsContext *ctx = (__bridge WailsContext*) inctx; NSApplication *app = [NSApplication sharedApplication]; diff --git a/v2/internal/frontend/desktop/darwin/menu.go b/v2/internal/frontend/desktop/darwin/menu.go index fc60f0c3b..c80efe3d3 100644 --- a/v2/internal/frontend/desktop/darwin/menu.go +++ b/v2/internal/frontend/desktop/darwin/menu.go @@ -14,24 +14,82 @@ package darwin */ import "C" import ( + "sync" "unsafe" + "github.com/google/uuid" + "github.com/wailsapp/wails/v2/pkg/menu" "github.com/wailsapp/wails/v2/pkg/menu/keys" ) +var createNSObjectMap = make(map[uint32]chan unsafe.Pointer) +var createNSObjectMapLock sync.RWMutex + +func waitNSObjectCreate(id uint32, fn func()) unsafe.Pointer { + waitchan := make(chan unsafe.Pointer) + createNSObjectMapLock.Lock() + createNSObjectMap[id] = waitchan + createNSObjectMapLock.Unlock() + fn() + result := <-waitchan + createNSObjectMapLock.Lock() + createNSObjectMap[id] = nil + createNSObjectMapLock.Unlock() + return result +} + +//export objectCreated +func objectCreated(id uint32, pointer unsafe.Pointer) { + createNSObjectMapLock.Lock() + createNSObjectMap[id] <- pointer + createNSObjectMapLock.Unlock() +} + func NewNSTrayMenu(context unsafe.Pointer, trayMenu *menu.TrayMenu) *NSTrayMenu { c := NewCalloc() defer c.Free() - theMenu := NewNSMenu(context, "") - processMenu(theMenu, trayMenu.Menu) - title := c.String(trayMenu.Label) - nsStatusItem := C.NewNSStatusItem(title) - C.SetTrayMenu(nsStatusItem, theMenu.nsmenu) - return &NSTrayMenu{ + + id := uuid.New().ID() + nsStatusItem := waitNSObjectCreate(id, func() { + C.NewNSStatusItem(C.int(id)) + }) + result := &NSTrayMenu{ context: context, nsStatusItem: nsStatusItem, } + + if trayMenu.Label != "" { + result.SetLabel(trayMenu.Label) + } + + // TODO: Move this into NSTrayMenu method + if trayMenu.Menu != nil { + theMenu := NewNSMenu(context, "") + processMenu(theMenu, trayMenu.Menu) + result.SetMenu(theMenu) + } + + if trayMenu.Image != nil { + result.SetImage(trayMenu.Image) + } + return result +} + +func (n *NSTrayMenu) SetImage(image *menu.TrayImage) { + if image.Image == nil { + return + } + C.SetTrayImage(n.nsStatusItem, + unsafe.Pointer(&image.Image[0]), + C.int(len(image.Image)), + bool2Cint(image.IsTemplate), + C.int(image.Position), + ) +} + +func (n *NSTrayMenu) SetMenu(menu *NSMenu) { + C.SetTrayMenu(n.nsStatusItem, menu.nsmenu) } type NSMenu struct { diff --git a/v2/internal/frontend/desktop/darwin/message.h b/v2/internal/frontend/desktop/darwin/message.h index 8ea2bda3e..a6e27ee0d 100644 --- a/v2/internal/frontend/desktop/darwin/message.h +++ b/v2/internal/frontend/desktop/darwin/message.h @@ -21,6 +21,7 @@ void processOpenFileDialogResponse(const char*); void processSaveFileDialogResponse(const char*); void processCallback(int); void processNotification(int); +void objectCreated(int, void*); #ifdef __cplusplus } diff --git a/v2/internal/frontend/desktop/darwin/traymenu.go b/v2/internal/frontend/desktop/darwin/traymenu.go index 3b214edf8..8ba366f30 100644 --- a/v2/internal/frontend/desktop/darwin/traymenu.go +++ b/v2/internal/frontend/desktop/darwin/traymenu.go @@ -9,7 +9,6 @@ package darwin #include */ - import "C" import ( "unsafe" @@ -17,13 +16,10 @@ import ( "github.com/wailsapp/wails/v2/pkg/menu" ) -func (f *Frontend) TrayMenuAdd(trayMenu *menu.TrayMenu) { - if f.applicationDidFinishLaunching == false { - f.trayMenusBuffer = append(f.trayMenusBuffer, trayMenu) - return - } +func (f *Frontend) TrayMenuAdd(trayMenu *menu.TrayMenu) menu.TrayMenuImpl { nsTrayMenu := f.mainWindow.TrayMenuAdd(trayMenu) f.trayMenus[trayMenu] = nsTrayMenu + return nsTrayMenu } type NSTrayMenu struct { @@ -31,6 +27,11 @@ type NSTrayMenu struct { nsStatusItem unsafe.Pointer // NSStatusItem } +func (n *NSTrayMenu) SetLabel(label string) { + cLabel := C.CString(label) + C.SetTrayMenuLabel(n.nsStatusItem, cLabel) +} + func (w *Window) TrayMenuAdd(trayMenu *menu.TrayMenu) *NSTrayMenu { return NewNSTrayMenu(w.context, trayMenu) } diff --git a/v2/internal/frontend/desktop/darwin/window.go b/v2/internal/frontend/desktop/darwin/window.go index 38cfb0b14..ed409b973 100644 --- a/v2/internal/frontend/desktop/darwin/window.go +++ b/v2/internal/frontend/desktop/darwin/window.go @@ -112,10 +112,6 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window { result.SetApplicationMenu(frontendOptions.Menu) } - if frontendOptions.TrayMenu != nil { - result.TrayMenuAdd(frontendOptions.TrayMenu) - } - return result } diff --git a/v2/internal/frontend/frontend.go b/v2/internal/frontend/frontend.go index 473712198..6cf14855f 100644 --- a/v2/internal/frontend/frontend.go +++ b/v2/internal/frontend/frontend.go @@ -103,5 +103,5 @@ type Frontend interface { BrowserOpenURL(url string) // Tray Menu - TrayMenuAdd(trayMenu *menu.TrayMenu) + TrayMenuAdd(trayMenu *menu.TrayMenu) menu.TrayMenuImpl } diff --git a/v2/internal/menumanager/contextmenu.go b/v2/internal/menumanager/contextmenu.go index 77c47891c..b87b476b7 100644 --- a/v2/internal/menumanager/contextmenu.go +++ b/v2/internal/menumanager/contextmenu.go @@ -1,12 +1,15 @@ package menumanager -import ( - "encoding/json" - "fmt" - - "github.com/wailsapp/wails/v2/pkg/menu" -) +import "github.com/wailsapp/wails/v2/pkg/menu" +// +//import ( +// "encoding/json" +// "fmt" +// +// "github.com/wailsapp/wails/v2/pkg/menu" +//) +// type ContextMenu struct { ID string ProcessedMenu *WailsMenu @@ -14,48 +17,49 @@ type ContextMenu struct { menu *menu.Menu } -func (t *ContextMenu) AsJSON() (string, error) { - data, err := json.Marshal(t) - if err != nil { - return "", err - } - return string(data), nil -} - -func NewContextMenu(contextMenu *menu.ContextMenu) *ContextMenu { - - result := &ContextMenu{ - ID: contextMenu.ID, - menu: contextMenu.Menu, - menuItemMap: NewMenuItemMap(), - } - - result.menuItemMap.AddMenu(contextMenu.Menu) - result.ProcessedMenu = NewWailsMenu(result.menuItemMap, result.menu) - - return result -} - -func (m *Manager) AddContextMenu(contextMenu *menu.ContextMenu) { - - newContextMenu := NewContextMenu(contextMenu) - - // Save the references - m.contextMenus[contextMenu.ID] = newContextMenu - m.contextMenuPointers[contextMenu] = contextMenu.ID -} - -func (m *Manager) UpdateContextMenu(contextMenu *menu.ContextMenu) (string, error) { - contextMenuID, contextMenuKnown := m.contextMenuPointers[contextMenu] - if !contextMenuKnown { - return "", fmt.Errorf("unknown Context Menu '%s'. Please add the context menu using AddContextMenu()", contextMenu.ID) - } - - // Create the updated context menu - updatedContextMenu := NewContextMenu(contextMenu) - - // Save the reference - m.contextMenus[contextMenuID] = updatedContextMenu - - return updatedContextMenu.AsJSON() -} +// +//func (t *ContextMenu) AsJSON() (string, error) { +// data, err := json.Marshal(t) +// if err != nil { +// return "", err +// } +// return string(data), nil +//} +// +//func NewContextMenu(contextMenu *menu.ContextMenu) *ContextMenu { +// +// result := &ContextMenu{ +// ID: contextMenu.ID, +// menu: contextMenu.Menu, +// menuItemMap: NewMenuItemMap(), +// } +// +// result.menuItemMap.AddMenu(contextMenu.Menu) +// result.ProcessedMenu = NewWailsMenu(result.menuItemMap, result.menu) +// +// return result +//} +// +//func (m *Manager) AddContextMenu(contextMenu *menu.ContextMenu) { +// +// newContextMenu := NewContextMenu(contextMenu) +// +// // Save the references +// m.contextMenus[contextMenu.ID] = newContextMenu +// m.contextMenuPointers[contextMenu] = contextMenu.ID +//} +// +//func (m *Manager) UpdateContextMenu(contextMenu *menu.ContextMenu) (string, error) { +// contextMenuID, contextMenuKnown := m.contextMenuPointers[contextMenu] +// if !contextMenuKnown { +// return "", fmt.Errorf("unknown Context Menu '%s'. Please add the context menu using AddContextMenu()", contextMenu.ID) +// } +// +// // Create the updated context menu +// updatedContextMenu := NewContextMenu(contextMenu) +// +// // Save the reference +// m.contextMenus[contextMenuID] = updatedContextMenu +// +// return updatedContextMenu.AsJSON() +//} diff --git a/v2/internal/menumanager/menumanager.go b/v2/internal/menumanager/menumanager.go index ea7939415..92756edff 100644 --- a/v2/internal/menumanager/menumanager.go +++ b/v2/internal/menumanager/menumanager.go @@ -2,6 +2,7 @@ package menumanager import ( "fmt" + "github.com/wailsapp/wails/v2/pkg/menu" ) diff --git a/v2/internal/menumanager/traymenu.go b/v2/internal/menumanager/traymenu.go index aed5b05ac..ebbbe7c3b 100644 --- a/v2/internal/menumanager/traymenu.go +++ b/v2/internal/menumanager/traymenu.go @@ -1,15 +1,11 @@ package menumanager import ( - "encoding/json" - "fmt" "strconv" - "strings" "sync" "github.com/leaanthony/go-ansi-parser" - "github.com/pkg/errors" "github.com/wailsapp/wails/v2/pkg/menu" ) @@ -32,7 +28,7 @@ type TrayMenu struct { FontName string Disabled bool Tooltip string `json:",omitempty"` - Image string + Image []byte MacTemplateImage bool RGBA string menuItemMap *MenuItemMap @@ -42,181 +38,182 @@ type TrayMenu struct { StyledLabel []*ansi.StyledText `json:",omitempty"` } -func (t *TrayMenu) AsJSON() (string, error) { - data, err := json.Marshal(t) - if err != nil { - return "", err - } - return string(data), nil -} - -func NewTrayMenu(trayMenu *menu.TrayMenu) *TrayMenu { - - // Parse ANSI text - var styledLabel []*ansi.StyledText - tempLabel := trayMenu.Label - if strings.Contains(tempLabel, "\033[") { - parsedLabel, err := ansi.Parse(tempLabel) - if err == nil { - styledLabel = parsedLabel - } - } - - result := &TrayMenu{ - Label: trayMenu.Label, - FontName: trayMenu.FontName, - FontSize: trayMenu.FontSize, - Disabled: trayMenu.Disabled, - Tooltip: trayMenu.Tooltip, - Image: trayMenu.Image, - MacTemplateImage: trayMenu.MacTemplateImage, - menu: trayMenu.Menu, - RGBA: trayMenu.RGBA, - menuItemMap: NewMenuItemMap(), - trayMenu: trayMenu, - StyledLabel: styledLabel, - } - - result.menuItemMap.AddMenu(trayMenu.Menu) - result.ProcessedMenu = NewWailsMenu(result.menuItemMap, result.menu) - - return result -} - -func (m *Manager) OnTrayMenuOpen(id string) { - trayMenu, ok := m.trayMenus[id] - if !ok { - return - } - if trayMenu.trayMenu.OnOpen == nil { - return - } - go trayMenu.trayMenu.OnOpen() -} - -func (m *Manager) OnTrayMenuClose(id string) { - trayMenu, ok := m.trayMenus[id] - if !ok { - return - } - if trayMenu.trayMenu.OnClose == nil { - return - } - go trayMenu.trayMenu.OnClose() -} - -func (m *Manager) AddTrayMenu(trayMenu *menu.TrayMenu) (string, error) { - newTrayMenu := NewTrayMenu(trayMenu) - - // Hook up a new ID - trayID := generateTrayID() - newTrayMenu.ID = trayID - - // Save the references - m.trayMenus[trayID] = newTrayMenu - m.trayMenuPointers[trayMenu] = trayID - - return newTrayMenu.AsJSON() -} - -func (m *Manager) GetTrayID(trayMenu *menu.TrayMenu) (string, error) { - trayID, exists := m.trayMenuPointers[trayMenu] - if !exists { - return "", fmt.Errorf("Unable to find menu ID for tray menu!") - } - return trayID, nil -} - -// SetTrayMenu updates or creates a menu -func (m *Manager) SetTrayMenu(trayMenu *menu.TrayMenu) (string, error) { - trayID, trayMenuKnown := m.trayMenuPointers[trayMenu] - if !trayMenuKnown { - return m.AddTrayMenu(trayMenu) - } - - // Create the updated tray menu - updatedTrayMenu := NewTrayMenu(trayMenu) - updatedTrayMenu.ID = trayID - - // Save the reference - m.trayMenus[trayID] = updatedTrayMenu - - return updatedTrayMenu.AsJSON() -} - -func (m *Manager) GetTrayMenus() ([]string, error) { - result := []string{} - for _, trayMenu := range m.trayMenus { - JSON, err := trayMenu.AsJSON() - if err != nil { - return nil, err - } - result = append(result, JSON) - } - - return result, nil -} - -func (m *Manager) UpdateTrayMenuLabel(trayMenu *menu.TrayMenu) (string, error) { - trayID, trayMenuKnown := m.trayMenuPointers[trayMenu] - if !trayMenuKnown { - return "", fmt.Errorf("[UpdateTrayMenuLabel] unknown tray id for tray %s", trayMenu.Label) - } - - type LabelUpdate struct { - ID string - Label string `json:",omitempty"` - FontName string `json:",omitempty"` - FontSize int - RGBA string `json:",omitempty"` - Disabled bool - Tooltip string `json:",omitempty"` - Image string `json:",omitempty"` - MacTemplateImage bool - StyledLabel []*ansi.StyledText `json:",omitempty"` - } - - // Parse ANSI text - var styledLabel []*ansi.StyledText - tempLabel := trayMenu.Label - if strings.Contains(tempLabel, "\033[") { - parsedLabel, err := ansi.Parse(tempLabel) - if err == nil { - styledLabel = parsedLabel - } - } - - update := &LabelUpdate{ - ID: trayID, - Label: trayMenu.Label, - FontName: trayMenu.FontName, - FontSize: trayMenu.FontSize, - Disabled: trayMenu.Disabled, - Tooltip: trayMenu.Tooltip, - Image: trayMenu.Image, - MacTemplateImage: trayMenu.MacTemplateImage, - RGBA: trayMenu.RGBA, - StyledLabel: styledLabel, - } - - data, err := json.Marshal(update) - if err != nil { - return "", errors.Wrap(err, "[UpdateTrayMenuLabel] ") - } - - return string(data), nil - -} - -func (m *Manager) GetContextMenus() ([]string, error) { - result := []string{} - for _, contextMenu := range m.contextMenus { - JSON, err := contextMenu.AsJSON() - if err != nil { - return nil, err - } - result = append(result, JSON) - } - - return result, nil -} +// +//func (t *TrayMenu) AsJSON() (string, error) { +// data, err := json.Marshal(t) +// if err != nil { +// return "", err +// } +// return string(data), nil +//} +// +//func NewTrayMenu(trayMenu *menu.TrayMenu) *TrayMenu { +// +// // Parse ANSI text +// var styledLabel []*ansi.StyledText +// tempLabel := trayMenu.Label +// if strings.Contains(tempLabel, "\033[") { +// parsedLabel, err := ansi.Parse(tempLabel) +// if err == nil { +// styledLabel = parsedLabel +// } +// } +// +// result := &TrayMenu{ +// Label: trayMenu.Label, +// FontName: trayMenu.FontName, +// FontSize: trayMenu.FontSize, +// Disabled: trayMenu.Disabled, +// Tooltip: trayMenu.Tooltip, +// Image: trayMenu.Image, +// MacTemplateImage: trayMenu.MacTemplateImage, +// menu: trayMenu.Menu, +// RGBA: trayMenu.RGBA, +// menuItemMap: NewMenuItemMap(), +// trayMenu: trayMenu, +// StyledLabel: styledLabel, +// } +// +// result.menuItemMap.AddMenu(trayMenu.Menu) +// result.ProcessedMenu = NewWailsMenu(result.menuItemMap, result.menu) +// +// return result +//} +// +//func (m *Manager) OnTrayMenuOpen(id string) { +// trayMenu, ok := m.trayMenus[id] +// if !ok { +// return +// } +// if trayMenu.trayMenu.OnOpen == nil { +// return +// } +// go trayMenu.trayMenu.OnOpen() +//} +// +//func (m *Manager) OnTrayMenuClose(id string) { +// trayMenu, ok := m.trayMenus[id] +// if !ok { +// return +// } +// if trayMenu.trayMenu.OnClose == nil { +// return +// } +// go trayMenu.trayMenu.OnClose() +//} +// +//func (m *Manager) AddTrayMenu(trayMenu *menu.TrayMenu) (string, error) { +// newTrayMenu := NewTrayMenu(trayMenu) +// +// // Hook up a new ID +// trayID := generateTrayID() +// newTrayMenu.ID = trayID +// +// // Save the references +// m.trayMenus[trayID] = newTrayMenu +// m.trayMenuPointers[trayMenu] = trayID +// +// return newTrayMenu.AsJSON() +//} +// +//func (m *Manager) GetTrayID(trayMenu *menu.TrayMenu) (string, error) { +// trayID, exists := m.trayMenuPointers[trayMenu] +// if !exists { +// return "", fmt.Errorf("Unable to find menu ID for tray menu!") +// } +// return trayID, nil +//} +// +//// SetTrayMenu updates or creates a menu +//func (m *Manager) SetTrayMenu(trayMenu *menu.TrayMenu) (string, error) { +// trayID, trayMenuKnown := m.trayMenuPointers[trayMenu] +// if !trayMenuKnown { +// return m.AddTrayMenu(trayMenu) +// } +// +// // Create the updated tray menu +// updatedTrayMenu := NewTrayMenu(trayMenu) +// updatedTrayMenu.ID = trayID +// +// // Save the reference +// m.trayMenus[trayID] = updatedTrayMenu +// +// return updatedTrayMenu.AsJSON() +//} +// +//func (m *Manager) GetTrayMenus() ([]string, error) { +// result := []string{} +// for _, trayMenu := range m.trayMenus { +// JSON, err := trayMenu.AsJSON() +// if err != nil { +// return nil, err +// } +// result = append(result, JSON) +// } +// +// return result, nil +//} +// +//func (m *Manager) UpdateTrayMenuLabel(trayMenu *menu.TrayMenu) (string, error) { +// trayID, trayMenuKnown := m.trayMenuPointers[trayMenu] +// if !trayMenuKnown { +// return "", fmt.Errorf("[UpdateTrayMenuLabel] unknown tray id for tray %s", trayMenu.Label) +// } +// +// type LabelUpdate struct { +// ID string +// Label string `json:",omitempty"` +// FontName string `json:",omitempty"` +// FontSize int +// RGBA string `json:",omitempty"` +// Disabled bool +// Tooltip string `json:",omitempty"` +// Image []byte `json:",omitempty"` +// MacTemplateImage bool +// StyledLabel []*ansi.StyledText `json:",omitempty"` +// } +// +// // Parse ANSI text +// var styledLabel []*ansi.StyledText +// tempLabel := trayMenu.Label +// if strings.Contains(tempLabel, "\033[") { +// parsedLabel, err := ansi.Parse(tempLabel) +// if err == nil { +// styledLabel = parsedLabel +// } +// } +// +// update := &LabelUpdate{ +// ID: trayID, +// Label: trayMenu.Label, +// FontName: trayMenu.FontName, +// FontSize: trayMenu.FontSize, +// Disabled: trayMenu.Disabled, +// Tooltip: trayMenu.Tooltip, +// Image: trayMenu.Image, +// MacTemplateImage: trayMenu.MacTemplateImage, +// RGBA: trayMenu.RGBA, +// StyledLabel: styledLabel, +// } +// +// data, err := json.Marshal(update) +// if err != nil { +// return "", errors.Wrap(err, "[UpdateTrayMenuLabel] ") +// } +// +// return string(data), nil +// +//} +// +//func (m *Manager) GetContextMenus() ([]string, error) { +// result := []string{} +// for _, contextMenu := range m.contextMenus { +// JSON, err := contextMenu.AsJSON() +// if err != nil { +// return nil, err +// } +// result = append(result, JSON) +// } +// +// return result, nil +//} diff --git a/v2/pkg/menu/tray.go b/v2/pkg/menu/tray.go index 87cca6629..6507f7c67 100644 --- a/v2/pkg/menu/tray.go +++ b/v2/pkg/menu/tray.go @@ -7,7 +7,32 @@ import ( ) type TrayMenuAdd interface { - TrayMenuAdd(menu *TrayMenu) + TrayMenuAdd(menu *TrayMenu) TrayMenuImpl +} + +type TrayMenuImpl interface { + SetLabel(string) + SetImage(*TrayImage) +} + +type ImagePosition int + +const ( + NSImageLeading ImagePosition = 0 + NSImageOnly ImagePosition = 1 + NSImageLeft ImagePosition = 2 + NSImageRight ImagePosition = 3 + NSImageBelow ImagePosition = 4 + NSImageAbove ImagePosition = 5 + NSImageOverlaps ImagePosition = 6 + NSNoImage ImagePosition = 7 + NSImageTrailing ImagePosition = 8 +) + +type TrayImage struct { + Image []byte + IsTemplate bool + Position ImagePosition } // TrayMenu are the options @@ -17,12 +42,7 @@ type TrayMenu struct { // Label is the text we wish to display in the tray Label string - // Image is the name of the tray icon we wish to display. - // These are read up during build from /trayicons and - // the filenames are used as IDs, minus the extension - // EG: /trayicons/main.png can be referenced here with "main" - // If the image is not a filename, it will be treated as base64 image data - Image string + Image *TrayImage // MacTemplateImage indicates that on a Mac, this image is a template image MacTemplateImage bool @@ -51,22 +71,39 @@ type TrayMenu struct { // OnClose is called when the Menu is closed OnClose func() + + impl TrayMenuImpl } -func NewTrayMenu(ctx context.Context) *TrayMenu { - return &TrayMenu{ - ctx: ctx, +func NewTrayMenu() *TrayMenu { + return &TrayMenu{} +} + +func (t *TrayMenu) Show(ctx context.Context) { + if ctx == nil { + log.Fatal("TrayMenu.Show() called before Run()") } -} - -func (t *TrayMenu) Show() { - result := t.ctx.Value("frontend") + t.ctx = ctx + result := ctx.Value("frontend") if result == nil { pc, _, _, _ := goruntime.Caller(1) funcName := goruntime.FuncForPC(pc).Name() log.Fatalf("invalid context at '%s'", funcName) } - println("\n\n\n\nFWEFWEFWFE") - result.(TrayMenuAdd).TrayMenuAdd(t) + t.impl = result.(TrayMenuAdd).TrayMenuAdd(t) } + +func (t *TrayMenu) SetLabel(label string) { + t.Label = label + if t.impl != nil { + t.impl.SetLabel(label) + } +} + +func (t *TrayMenu) SetImage(image *TrayImage) { + t.Image = image + if t.impl != nil { + t.impl.SetImage(image) + } +} diff --git a/v2/pkg/options/options.go b/v2/pkg/options/options.go index e75793903..1e0b9dfca 100644 --- a/v2/pkg/options/options.go +++ b/v2/pkg/options/options.go @@ -56,10 +56,9 @@ type App struct { //ContextMenus []*menu.ContextMenu //TrayMenus []*menu.TrayMenu - Windows *windows.Options - Mac *mac.Options - Linux *linux.Options - TrayMenu *menu.TrayMenu + Windows *windows.Options + Mac *mac.Options + Linux *linux.Options } type RGBA struct {