github.com/AlpineAIO/wails/v2@v2.0.0-beta.32.0.20240505041856-1047a8fa5fef/internal/menumanager/traymenu.go (about)

     1  package menumanager
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  	"sync"
     9  
    10  	"github.com/leaanthony/go-ansi-parser"
    11  
    12  	"github.com/AlpineAIO/wails/v2/pkg/menu"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  var (
    17  	trayMenuID      int
    18  	trayMenuIDMutex sync.Mutex
    19  )
    20  
    21  func generateTrayID() string {
    22  	var idStr string
    23  	trayMenuIDMutex.Lock()
    24  	idStr = strconv.Itoa(trayMenuID)
    25  	trayMenuID++
    26  	trayMenuIDMutex.Unlock()
    27  	return idStr
    28  }
    29  
    30  type TrayMenu struct {
    31  	ID               string
    32  	Label            string
    33  	FontSize         int
    34  	FontName         string
    35  	Disabled         bool
    36  	Tooltip          string `json:",omitempty"`
    37  	Image            string
    38  	MacTemplateImage bool
    39  	RGBA             string
    40  	menuItemMap      *MenuItemMap
    41  	menu             *menu.Menu
    42  	ProcessedMenu    *WailsMenu
    43  	trayMenu         *menu.TrayMenu
    44  	StyledLabel      []*ansi.StyledText `json:",omitempty"`
    45  }
    46  
    47  func (t *TrayMenu) AsJSON() (string, error) {
    48  	data, err := json.Marshal(t)
    49  	if err != nil {
    50  		return "", err
    51  	}
    52  	return string(data), nil
    53  }
    54  
    55  func NewTrayMenu(trayMenu *menu.TrayMenu) *TrayMenu {
    56  	// Parse ANSI text
    57  	var styledLabel []*ansi.StyledText
    58  	tempLabel := trayMenu.Label
    59  	if strings.Contains(tempLabel, "\033[") {
    60  		parsedLabel, err := ansi.Parse(tempLabel)
    61  		if err == nil {
    62  			styledLabel = parsedLabel
    63  		}
    64  	}
    65  
    66  	result := &TrayMenu{
    67  		Label:            trayMenu.Label,
    68  		FontName:         trayMenu.FontName,
    69  		FontSize:         trayMenu.FontSize,
    70  		Disabled:         trayMenu.Disabled,
    71  		Tooltip:          trayMenu.Tooltip,
    72  		Image:            trayMenu.Image,
    73  		MacTemplateImage: trayMenu.MacTemplateImage,
    74  		menu:             trayMenu.Menu,
    75  		RGBA:             trayMenu.RGBA,
    76  		menuItemMap:      NewMenuItemMap(),
    77  		trayMenu:         trayMenu,
    78  		StyledLabel:      styledLabel,
    79  	}
    80  
    81  	result.menuItemMap.AddMenu(trayMenu.Menu)
    82  	result.ProcessedMenu = NewWailsMenu(result.menuItemMap, result.menu)
    83  
    84  	return result
    85  }
    86  
    87  func (m *Manager) OnTrayMenuOpen(id string) {
    88  	trayMenu, ok := m.trayMenus[id]
    89  	if !ok {
    90  		return
    91  	}
    92  	if trayMenu.trayMenu.OnOpen == nil {
    93  		return
    94  	}
    95  	go trayMenu.trayMenu.OnOpen()
    96  }
    97  
    98  func (m *Manager) OnTrayMenuClose(id string) {
    99  	trayMenu, ok := m.trayMenus[id]
   100  	if !ok {
   101  		return
   102  	}
   103  	if trayMenu.trayMenu.OnClose == nil {
   104  		return
   105  	}
   106  	go trayMenu.trayMenu.OnClose()
   107  }
   108  
   109  func (m *Manager) AddTrayMenu(trayMenu *menu.TrayMenu) (string, error) {
   110  	newTrayMenu := NewTrayMenu(trayMenu)
   111  
   112  	// Hook up a new ID
   113  	trayID := generateTrayID()
   114  	newTrayMenu.ID = trayID
   115  
   116  	// Save the references
   117  	m.trayMenus[trayID] = newTrayMenu
   118  	m.trayMenuPointers[trayMenu] = trayID
   119  
   120  	return newTrayMenu.AsJSON()
   121  }
   122  
   123  func (m *Manager) GetTrayID(trayMenu *menu.TrayMenu) (string, error) {
   124  	trayID, exists := m.trayMenuPointers[trayMenu]
   125  	if !exists {
   126  		return "", fmt.Errorf("Unable to find menu ID for tray menu!")
   127  	}
   128  	return trayID, nil
   129  }
   130  
   131  // SetTrayMenu updates or creates a menu
   132  func (m *Manager) SetTrayMenu(trayMenu *menu.TrayMenu) (string, error) {
   133  	trayID, trayMenuKnown := m.trayMenuPointers[trayMenu]
   134  	if !trayMenuKnown {
   135  		return m.AddTrayMenu(trayMenu)
   136  	}
   137  
   138  	// Create the updated tray menu
   139  	updatedTrayMenu := NewTrayMenu(trayMenu)
   140  	updatedTrayMenu.ID = trayID
   141  
   142  	// Save the reference
   143  	m.trayMenus[trayID] = updatedTrayMenu
   144  
   145  	return updatedTrayMenu.AsJSON()
   146  }
   147  
   148  func (m *Manager) GetTrayMenus() ([]string, error) {
   149  	result := []string{}
   150  	for _, trayMenu := range m.trayMenus {
   151  		JSON, err := trayMenu.AsJSON()
   152  		if err != nil {
   153  			return nil, err
   154  		}
   155  		result = append(result, JSON)
   156  	}
   157  
   158  	return result, nil
   159  }
   160  
   161  func (m *Manager) UpdateTrayMenuLabel(trayMenu *menu.TrayMenu) (string, error) {
   162  	trayID, trayMenuKnown := m.trayMenuPointers[trayMenu]
   163  	if !trayMenuKnown {
   164  		return "", fmt.Errorf("[UpdateTrayMenuLabel] unknown tray id for tray %s", trayMenu.Label)
   165  	}
   166  
   167  	type LabelUpdate struct {
   168  		ID               string
   169  		Label            string `json:",omitempty"`
   170  		FontName         string `json:",omitempty"`
   171  		FontSize         int
   172  		RGBA             string `json:",omitempty"`
   173  		Disabled         bool
   174  		Tooltip          string `json:",omitempty"`
   175  		Image            string `json:",omitempty"`
   176  		MacTemplateImage bool
   177  		StyledLabel      []*ansi.StyledText `json:",omitempty"`
   178  	}
   179  
   180  	// Parse ANSI text
   181  	var styledLabel []*ansi.StyledText
   182  	tempLabel := trayMenu.Label
   183  	if strings.Contains(tempLabel, "\033[") {
   184  		parsedLabel, err := ansi.Parse(tempLabel)
   185  		if err == nil {
   186  			styledLabel = parsedLabel
   187  		}
   188  	}
   189  
   190  	update := &LabelUpdate{
   191  		ID:               trayID,
   192  		Label:            trayMenu.Label,
   193  		FontName:         trayMenu.FontName,
   194  		FontSize:         trayMenu.FontSize,
   195  		Disabled:         trayMenu.Disabled,
   196  		Tooltip:          trayMenu.Tooltip,
   197  		Image:            trayMenu.Image,
   198  		MacTemplateImage: trayMenu.MacTemplateImage,
   199  		RGBA:             trayMenu.RGBA,
   200  		StyledLabel:      styledLabel,
   201  	}
   202  
   203  	data, err := json.Marshal(update)
   204  	if err != nil {
   205  		return "", errors.Wrap(err, "[UpdateTrayMenuLabel] ")
   206  	}
   207  
   208  	return string(data), nil
   209  }
   210  
   211  func (m *Manager) GetContextMenus() ([]string, error) {
   212  	result := []string{}
   213  	for _, contextMenu := range m.contextMenus {
   214  		JSON, err := contextMenu.AsJSON()
   215  		if err != nil {
   216  			return nil, err
   217  		}
   218  		result = append(result, JSON)
   219  	}
   220  
   221  	return result, nil
   222  }