223 lines
5.1 KiB
Go
223 lines
5.1 KiB
Go
|
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"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
trayMenuID int
|
||
|
trayMenuIDMutex sync.Mutex
|
||
|
)
|
||
|
|
||
|
func generateTrayID() string {
|
||
|
var idStr string
|
||
|
trayMenuIDMutex.Lock()
|
||
|
idStr = strconv.Itoa(trayMenuID)
|
||
|
trayMenuID++
|
||
|
trayMenuIDMutex.Unlock()
|
||
|
return idStr
|
||
|
}
|
||
|
|
||
|
type TrayMenu struct {
|
||
|
ID string
|
||
|
Label string
|
||
|
FontSize int
|
||
|
FontName string
|
||
|
Disabled bool
|
||
|
Tooltip string `json:",omitempty"`
|
||
|
Image string
|
||
|
MacTemplateImage bool
|
||
|
RGBA string
|
||
|
menuItemMap *MenuItemMap
|
||
|
menu *menu.Menu
|
||
|
ProcessedMenu *WailsMenu
|
||
|
trayMenu *menu.TrayMenu
|
||
|
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
|
||
|
}
|