mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-03 19:51:15 +08:00
[WIP] New menu processor
This commit is contained in:
parent
3a2d01813a
commit
8ee8c9b07c
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/wailsapp/wails/v2/internal/binding"
|
"github.com/wailsapp/wails/v2/internal/binding"
|
||||||
"github.com/wailsapp/wails/v2/internal/ffenestri"
|
"github.com/wailsapp/wails/v2/internal/ffenestri"
|
||||||
"github.com/wailsapp/wails/v2/internal/logger"
|
"github.com/wailsapp/wails/v2/internal/logger"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/menumanager"
|
||||||
"github.com/wailsapp/wails/v2/internal/messagedispatcher"
|
"github.com/wailsapp/wails/v2/internal/messagedispatcher"
|
||||||
"github.com/wailsapp/wails/v2/internal/runtime"
|
"github.com/wailsapp/wails/v2/internal/runtime"
|
||||||
"github.com/wailsapp/wails/v2/internal/servicebus"
|
"github.com/wailsapp/wails/v2/internal/servicebus"
|
||||||
@ -33,6 +34,8 @@ type App struct {
|
|||||||
contextmenus *subsystem.ContextMenus
|
contextmenus *subsystem.ContextMenus
|
||||||
dispatcher *messagedispatcher.Dispatcher
|
dispatcher *messagedispatcher.Dispatcher
|
||||||
|
|
||||||
|
menuManager *menumanager.Manager
|
||||||
|
|
||||||
// Indicates if the app is in debug mode
|
// Indicates if the app is in debug mode
|
||||||
debug bool
|
debug bool
|
||||||
|
|
||||||
@ -54,13 +57,18 @@ func CreateApp(appoptions *options.App) (*App, error) {
|
|||||||
myLogger := logger.New(appoptions.Logger)
|
myLogger := logger.New(appoptions.Logger)
|
||||||
myLogger.SetLogLevel(appoptions.LogLevel)
|
myLogger.SetLogLevel(appoptions.LogLevel)
|
||||||
|
|
||||||
window := ffenestri.NewApplicationWithConfig(appoptions, myLogger)
|
// Create the menu manager
|
||||||
|
menuManager := menumanager.NewManager()
|
||||||
|
menuManager.SetApplicationMenu(options.GetApplicationMenu(appoptions))
|
||||||
|
|
||||||
|
window := ffenestri.NewApplicationWithConfig(appoptions, myLogger, menuManager)
|
||||||
|
|
||||||
result := &App{
|
result := &App{
|
||||||
window: window,
|
window: window,
|
||||||
servicebus: servicebus.New(myLogger),
|
servicebus: servicebus.New(myLogger),
|
||||||
logger: myLogger,
|
logger: myLogger,
|
||||||
bindings: binding.NewBindings(myLogger),
|
bindings: binding.NewBindings(myLogger),
|
||||||
|
menuManager: menuManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
result.options = appoptions
|
result.options = appoptions
|
||||||
@ -157,7 +165,7 @@ func (a *App) Run() error {
|
|||||||
|
|
||||||
// Optionally start the menu subsystem
|
// Optionally start the menu subsystem
|
||||||
if applicationMenu != nil {
|
if applicationMenu != nil {
|
||||||
menusubsystem, err := subsystem.NewMenu(applicationMenu, a.servicebus, a.logger)
|
menusubsystem, err := subsystem.NewMenu(a.servicebus, a.logger, a.menuManager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package ffenestri
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/menumanager"
|
||||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@ -35,6 +36,9 @@ type Application struct {
|
|||||||
// This is the main app pointer
|
// This is the main app pointer
|
||||||
app unsafe.Pointer
|
app unsafe.Pointer
|
||||||
|
|
||||||
|
// Manages menus
|
||||||
|
menuManager *menumanager.Manager
|
||||||
|
|
||||||
// Logger
|
// Logger
|
||||||
logger logger.CustomLogger
|
logger logger.CustomLogger
|
||||||
}
|
}
|
||||||
@ -54,10 +58,11 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewApplicationWithConfig creates a new application based on the given config
|
// NewApplicationWithConfig creates a new application based on the given config
|
||||||
func NewApplicationWithConfig(config *options.App, logger *logger.Logger) *Application {
|
func NewApplicationWithConfig(config *options.App, logger *logger.Logger, menuManager *menumanager.Manager) *Application {
|
||||||
return &Application{
|
return &Application{
|
||||||
config: config,
|
config: config,
|
||||||
logger: logger.CustomLogger("Ffenestri"),
|
logger: logger.CustomLogger("Ffenestri"),
|
||||||
|
menuManager: menuManager,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,23 +76,10 @@ func (a *Application) processPlatformSettings() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process menu
|
// Process menu
|
||||||
applicationMenu := options.GetApplicationMenu(a.config)
|
//applicationMenu := options.GetApplicationMenu(a.config)
|
||||||
if applicationMenu != nil {
|
applicationMenu := a.menuManager.GetApplicationMenuJSON()
|
||||||
|
if applicationMenu != "" {
|
||||||
/*
|
C.SetMenu(a.app, a.string2CString(applicationMenu))
|
||||||
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(applicationMenu)
|
|
||||||
applicationMenuJSON, err := json.Marshal(processedMenu)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
C.SetMenu(a.app, a.string2CString(string(applicationMenuJSON)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process tray
|
// Process tray
|
||||||
|
54
v2/internal/menumanager/menuitemmap.go
Normal file
54
v2/internal/menumanager/menuitemmap.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package menumanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MenuItemMap holds a mapping between menuIDs and menu items
|
||||||
|
type MenuItemMap struct {
|
||||||
|
idToMenuItemMap map[string]*menu.MenuItem
|
||||||
|
menuItemToIDMap map[*menu.MenuItem]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMenuItemMap() *MenuItemMap {
|
||||||
|
result := &MenuItemMap{
|
||||||
|
idToMenuItemMap: make(map[string]*menu.MenuItem),
|
||||||
|
menuItemToIDMap: make(map[*menu.MenuItem]string),
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MenuItemMap) AddMenu(menu *menu.Menu) {
|
||||||
|
for _, item := range menu.Items {
|
||||||
|
m.processMenuItem(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MenuItemMap) Dump() {
|
||||||
|
println("idToMenuItemMap:")
|
||||||
|
for key, value := range m.idToMenuItemMap {
|
||||||
|
fmt.Printf(" %s\t%p\n", key, value)
|
||||||
|
}
|
||||||
|
println("\nmenuItemToIDMap")
|
||||||
|
for key, value := range m.menuItemToIDMap {
|
||||||
|
fmt.Printf(" %p\t%s\n", key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MenuItemMap) processMenuItem(item *menu.MenuItem) {
|
||||||
|
|
||||||
|
if item.SubMenu != nil {
|
||||||
|
for _, submenuitem := range item.SubMenu.Items {
|
||||||
|
m.processMenuItem(submenuitem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a unique ID for this menu item
|
||||||
|
menuID := fmt.Sprintf("%d", len(m.idToMenuItemMap))
|
||||||
|
|
||||||
|
// Store references
|
||||||
|
m.idToMenuItemMap[menuID] = item
|
||||||
|
m.menuItemToIDMap[item] = menuID
|
||||||
|
}
|
82
v2/internal/menumanager/menumanager.go
Normal file
82
v2/internal/menumanager/menumanager.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package menumanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Manager struct {
|
||||||
|
|
||||||
|
// The application menu.
|
||||||
|
applicationMenu *menu.Menu
|
||||||
|
applicationMenuJSON string
|
||||||
|
|
||||||
|
// Our menu mappings
|
||||||
|
menuItemMap *MenuItemMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewManager() *Manager {
|
||||||
|
return &Manager{
|
||||||
|
menuItemMap: NewMenuItemMap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) SetApplicationMenu(applicationMenu *menu.Menu) error {
|
||||||
|
if applicationMenu == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
m.applicationMenu = applicationMenu
|
||||||
|
m.menuItemMap.AddMenu(applicationMenu)
|
||||||
|
return m.processApplicationMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) GetApplicationMenuJSON() string {
|
||||||
|
return m.applicationMenuJSON
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) processApplicationMenu() error {
|
||||||
|
|
||||||
|
// Process the menu
|
||||||
|
processedApplicationMenu := m.NewWailsMenu(m.applicationMenu)
|
||||||
|
applicationMenuJSON, err := processedApplicationMenu.AsJSON()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m.applicationMenuJSON = applicationMenuJSON
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) getMenuItemByID(menuId string) *menu.MenuItem {
|
||||||
|
return m.menuItemMap.idToMenuItemMap[menuId]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) ProcessClick(menuID string) error {
|
||||||
|
|
||||||
|
// Get the menu item
|
||||||
|
menuItem := m.getMenuItemByID(menuID)
|
||||||
|
if menuItem == nil {
|
||||||
|
return fmt.Errorf("Cannot process menuid %s - unknown", menuID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the menu item a checkbox?
|
||||||
|
if menuItem.Type == menu.CheckboxType {
|
||||||
|
// Toggle state
|
||||||
|
menuItem.Checked = !menuItem.Checked
|
||||||
|
}
|
||||||
|
|
||||||
|
if menuItem.Click == nil {
|
||||||
|
// No callback
|
||||||
|
return fmt.Errorf("No callback for menu '%s'", menuItem.Label)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new Callback struct
|
||||||
|
callbackData := &menu.CallbackData{
|
||||||
|
MenuItem: menuItem,
|
||||||
|
ContextData: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call back!
|
||||||
|
go menuItem.Click(callbackData)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
156
v2/internal/menumanager/processedMenu.go
Normal file
156
v2/internal/menumanager/processedMenu.go
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
package menumanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/menu/keys"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProcessedMenuItem struct {
|
||||||
|
ID string
|
||||||
|
// Label is what appears as the menu text
|
||||||
|
Label string
|
||||||
|
// Role is a predefined menu type
|
||||||
|
Role menu.Role `json:"Role,omitempty"`
|
||||||
|
// Accelerator holds a representation of a key binding
|
||||||
|
Accelerator *keys.Accelerator `json:"Accelerator,omitempty"`
|
||||||
|
// Type of MenuItem, EG: Checkbox, Text, Separator, Radio, Submenu
|
||||||
|
Type menu.Type
|
||||||
|
// Disabled makes the item unselectable
|
||||||
|
Disabled bool
|
||||||
|
// Hidden ensures that the item is not shown in the menu
|
||||||
|
Hidden bool
|
||||||
|
// Checked indicates if the item is selected (used by Checkbox and Radio types only)
|
||||||
|
Checked bool
|
||||||
|
// Submenu contains a list of menu items that will be shown as a submenu
|
||||||
|
//SubMenu []*MenuItem `json:"SubMenu,omitempty"`
|
||||||
|
SubMenu *ProcessedMenu `json:"SubMenu,omitempty"`
|
||||||
|
|
||||||
|
// Foreground colour in hex RGBA format EG: 0xFF0000FF = #FF0000FF = red
|
||||||
|
Foreground int
|
||||||
|
|
||||||
|
// Background colour
|
||||||
|
Background int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) NewProcessedMenuItem(menuItem *menu.MenuItem) *ProcessedMenuItem {
|
||||||
|
|
||||||
|
ID := m.menuItemMap.menuItemToIDMap[menuItem]
|
||||||
|
result := &ProcessedMenuItem{
|
||||||
|
ID: ID,
|
||||||
|
Label: menuItem.Label,
|
||||||
|
Role: menuItem.Role,
|
||||||
|
Accelerator: menuItem.Accelerator,
|
||||||
|
Type: menuItem.Type,
|
||||||
|
Disabled: menuItem.Disabled,
|
||||||
|
Hidden: menuItem.Hidden,
|
||||||
|
Checked: menuItem.Checked,
|
||||||
|
Foreground: menuItem.Foreground,
|
||||||
|
Background: menuItem.Background,
|
||||||
|
}
|
||||||
|
|
||||||
|
if menuItem.SubMenu != nil {
|
||||||
|
result.SubMenu = m.NewProcessedMenu(menuItem.SubMenu)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProcessedMenu struct {
|
||||||
|
Items []*ProcessedMenuItem
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) NewProcessedMenu(menu *menu.Menu) *ProcessedMenu {
|
||||||
|
|
||||||
|
result := &ProcessedMenu{}
|
||||||
|
for _, item := range menu.Items {
|
||||||
|
processedMenuItem := m.NewProcessedMenuItem(item)
|
||||||
|
result.Items = append(result.Items, processedMenuItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// WailsMenu is the original menu with the addition
|
||||||
|
// of radio groups extracted from the menu data
|
||||||
|
type WailsMenu struct {
|
||||||
|
Menu *ProcessedMenu
|
||||||
|
RadioGroups []*RadioGroup
|
||||||
|
currentRadioGroup []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// RadioGroup holds all the members of the same radio group
|
||||||
|
type RadioGroup struct {
|
||||||
|
Members []string
|
||||||
|
Length int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) NewWailsMenu(menu *menu.Menu) *WailsMenu {
|
||||||
|
result := &WailsMenu{}
|
||||||
|
|
||||||
|
// Process the menus
|
||||||
|
result.Menu = m.NewProcessedMenu(menu)
|
||||||
|
|
||||||
|
// Process the radio groups
|
||||||
|
result.processRadioGroups()
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WailsMenu) AsJSON() (string, error) {
|
||||||
|
|
||||||
|
menuAsJSON, err := json.Marshal(w)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(menuAsJSON), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WailsMenu) processRadioGroups() {
|
||||||
|
// Loop over top level menus
|
||||||
|
for _, item := range w.Menu.Items {
|
||||||
|
// Process MenuItem
|
||||||
|
w.processMenuItem(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.finaliseRadioGroup()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WailsMenu) processMenuItem(item *ProcessedMenuItem) {
|
||||||
|
|
||||||
|
switch item.Type {
|
||||||
|
|
||||||
|
// We need to recurse submenus
|
||||||
|
case menu.SubmenuType:
|
||||||
|
|
||||||
|
// Finalise any current radio groups as they don't trickle down to submenus
|
||||||
|
w.finaliseRadioGroup()
|
||||||
|
|
||||||
|
// Process each submenu item
|
||||||
|
for _, subitem := range item.SubMenu.Items {
|
||||||
|
w.processMenuItem(subitem)
|
||||||
|
}
|
||||||
|
case menu.RadioType:
|
||||||
|
// Add the item to the radio group
|
||||||
|
w.currentRadioGroup = append(w.currentRadioGroup, item.ID)
|
||||||
|
default:
|
||||||
|
w.finaliseRadioGroup()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WailsMenu) finaliseRadioGroup() {
|
||||||
|
|
||||||
|
// If we were processing a radio group, fix up the references
|
||||||
|
if len(w.currentRadioGroup) > 0 {
|
||||||
|
|
||||||
|
// Create new radiogroup
|
||||||
|
group := &RadioGroup{
|
||||||
|
Members: w.currentRadioGroup,
|
||||||
|
Length: len(w.currentRadioGroup),
|
||||||
|
}
|
||||||
|
w.RadioGroups = append(w.RadioGroups, group)
|
||||||
|
|
||||||
|
// Empty the radio group
|
||||||
|
w.currentRadioGroup = []string{}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package subsystem
|
package subsystem
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/wailsapp/wails/v2/internal/menumanager"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@ -35,15 +36,15 @@ type Menu struct {
|
|||||||
// logger
|
// logger
|
||||||
logger logger.CustomLogger
|
logger logger.CustomLogger
|
||||||
|
|
||||||
// The application menu
|
|
||||||
applicationMenu *menu.Menu
|
|
||||||
|
|
||||||
// Service Bus
|
// Service Bus
|
||||||
bus *servicebus.ServiceBus
|
bus *servicebus.ServiceBus
|
||||||
|
|
||||||
|
// Menu Manager
|
||||||
|
menuManager *menumanager.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMenu creates a new menu subsystem
|
// NewMenu creates a new menu subsystem
|
||||||
func NewMenu(applicationMenu *menu.Menu, bus *servicebus.ServiceBus, logger *logger.Logger) (*Menu, error) {
|
func NewMenu(bus *servicebus.ServiceBus, logger *logger.Logger, menuManager *menumanager.Manager) (*Menu, error) {
|
||||||
|
|
||||||
// Register quit channel
|
// Register quit channel
|
||||||
quitChannel, err := bus.Subscribe("quit")
|
quitChannel, err := bus.Subscribe("quit")
|
||||||
@ -58,18 +59,15 @@ func NewMenu(applicationMenu *menu.Menu, bus *servicebus.ServiceBus, logger *log
|
|||||||
}
|
}
|
||||||
|
|
||||||
result := &Menu{
|
result := &Menu{
|
||||||
quitChannel: quitChannel,
|
quitChannel: quitChannel,
|
||||||
menuChannel: menuChannel,
|
menuChannel: menuChannel,
|
||||||
logger: logger.CustomLogger("Menu Subsystem"),
|
logger: logger.CustomLogger("Menu Subsystem"),
|
||||||
listeners: make(map[string][]func(*menu.MenuItem)),
|
listeners: make(map[string][]func(*menu.MenuItem)),
|
||||||
menuItems: make(map[string]*menu.MenuItem),
|
menuItems: make(map[string]*menu.MenuItem),
|
||||||
applicationMenu: applicationMenu,
|
bus: bus,
|
||||||
bus: bus,
|
menuManager: menuManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build up list of item/id pairs
|
|
||||||
result.processMenu(applicationMenu)
|
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,21 +97,11 @@ func (m *Menu) Start() error {
|
|||||||
m.logger.Trace("Got Menu clicked Message: %s %+v", menuMessage.Topic(), menuMessage.Data())
|
m.logger.Trace("Got Menu clicked Message: %s %+v", menuMessage.Topic(), menuMessage.Data())
|
||||||
menuid := menuMessage.Data().(string)
|
menuid := menuMessage.Data().(string)
|
||||||
|
|
||||||
// Get the menu item
|
err := m.menuManager.ProcessClick(menuid)
|
||||||
menuItem := m.menuItems[menuid]
|
if err != nil {
|
||||||
if menuItem == nil {
|
m.logger.Trace("%s", err.Error())
|
||||||
m.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
|
|
||||||
m.notifyListeners(menuid, menuItem)
|
|
||||||
case "on":
|
case "on":
|
||||||
listenerDetails := menuMessage.Data().(*message.MenuOnMessage)
|
listenerDetails := menuMessage.Data().(*message.MenuOnMessage)
|
||||||
id := listenerDetails.MenuID
|
id := listenerDetails.MenuID
|
||||||
@ -121,11 +109,11 @@ func (m *Menu) Start() error {
|
|||||||
|
|
||||||
// Make sure we catch any menu updates
|
// Make sure we catch any menu updates
|
||||||
case "update":
|
case "update":
|
||||||
updatedMenu := menuMessage.Data().(*menu.Menu)
|
//updatedMenu := menuMessage.Data().(*menu.Menu)
|
||||||
m.processMenu(updatedMenu)
|
//m.processMenu(updatedMenu)
|
||||||
|
//
|
||||||
// Notify frontend of menu change
|
//// Notify frontend of menu change
|
||||||
m.bus.Publish("menufrontend:update", updatedMenu)
|
//m.bus.Publish("menufrontend:update", updatedMenu)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
m.logger.Error("unknown menu message: %+v", menuMessage)
|
m.logger.Error("unknown menu message: %+v", menuMessage)
|
||||||
@ -140,56 +128,6 @@ func (m *Menu) Start() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Menu) processMenu(applicationMenu *menu.Menu) {
|
|
||||||
// Initialise the variables
|
|
||||||
m.menuItems = make(map[string]*menu.MenuItem)
|
|
||||||
m.applicationMenu = applicationMenu
|
|
||||||
|
|
||||||
for _, item := range applicationMenu.Items {
|
|
||||||
m.processMenuItem(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Menu) processMenuItem(item *menu.MenuItem) {
|
|
||||||
|
|
||||||
if item.SubMenu != nil {
|
|
||||||
for _, submenuitem := range item.SubMenu.Items {
|
|
||||||
m.processMenuItem(submenuitem)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if item.ID != "" {
|
|
||||||
if m.menuItems[item.ID] != nil {
|
|
||||||
m.logger.Error("Menu id '%s' is used by multiple menu items: %s %s", m.menuItems[item.ID].Label, item.Label)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m.menuItems[item.ID] = item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notifies listeners that the given menu was clicked
|
|
||||||
func (m *Menu) notifyListeners(menuid string, menuItem *menu.MenuItem) {
|
|
||||||
|
|
||||||
// Get list of menu listeners
|
|
||||||
listeners := m.listeners[menuid]
|
|
||||||
if listeners == nil {
|
|
||||||
m.logger.Trace("No listeners for MenuItem with ID '%s'", menuid)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lock the listeners
|
|
||||||
m.notifyLock.Lock()
|
|
||||||
|
|
||||||
// Callback in goroutine
|
|
||||||
for _, listener := range listeners {
|
|
||||||
go listener(menuItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unlock
|
|
||||||
m.notifyLock.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Menu) shutdown() {
|
func (m *Menu) shutdown() {
|
||||||
m.logger.Trace("Shutdown")
|
m.logger.Trace("Shutdown")
|
||||||
}
|
}
|
||||||
|
8
v2/pkg/menu/callback.go
Normal file
8
v2/pkg/menu/callback.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package menu
|
||||||
|
|
||||||
|
type CallbackData struct {
|
||||||
|
MenuItem *MenuItem
|
||||||
|
ContextData string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Callback func(*CallbackData)
|
@ -24,6 +24,9 @@ type MenuItem struct {
|
|||||||
//SubMenu []*MenuItem `json:"SubMenu,omitempty"`
|
//SubMenu []*MenuItem `json:"SubMenu,omitempty"`
|
||||||
SubMenu *Menu `json:"SubMenu,omitempty"`
|
SubMenu *Menu `json:"SubMenu,omitempty"`
|
||||||
|
|
||||||
|
// Callback function when menu clicked
|
||||||
|
Click Callback `json:"-"`
|
||||||
|
|
||||||
// Foreground colour in hex RGBA format EG: 0xFF0000FF = #FF0000FF = red
|
// Foreground colour in hex RGBA format EG: 0xFF0000FF = #FF0000FF = red
|
||||||
Foreground int
|
Foreground int
|
||||||
|
|
||||||
@ -226,12 +229,13 @@ func (m *MenuItem) insertItemAtIndex(index int, target *MenuItem) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Text is a helper to create basic Text menu items
|
// Text is a helper to create basic Text menu items
|
||||||
func Text(label string, id string, accelerator *keys.Accelerator) *MenuItem {
|
func Text(label string, id string, accelerator *keys.Accelerator, click Callback) *MenuItem {
|
||||||
return &MenuItem{
|
return &MenuItem{
|
||||||
ID: id,
|
ID: id,
|
||||||
Label: label,
|
Label: label,
|
||||||
Type: TextType,
|
Type: TextType,
|
||||||
Accelerator: accelerator,
|
Accelerator: accelerator,
|
||||||
|
Click: click,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,24 +247,26 @@ func Separator() *MenuItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Radio is a helper to create basic Radio menu items with an accelerator
|
// Radio is a helper to create basic Radio menu items with an accelerator
|
||||||
func Radio(label string, id string, selected bool, accelerator *keys.Accelerator) *MenuItem {
|
func Radio(label string, id string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem {
|
||||||
return &MenuItem{
|
return &MenuItem{
|
||||||
ID: id,
|
ID: id,
|
||||||
Label: label,
|
Label: label,
|
||||||
Type: RadioType,
|
Type: RadioType,
|
||||||
Checked: selected,
|
Checked: selected,
|
||||||
Accelerator: accelerator,
|
Accelerator: accelerator,
|
||||||
|
Click: click,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checkbox is a helper to create basic Checkbox menu items
|
// Checkbox is a helper to create basic Checkbox menu items
|
||||||
func Checkbox(label string, id string, checked bool, accelerator *keys.Accelerator) *MenuItem {
|
func Checkbox(label string, id string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem {
|
||||||
return &MenuItem{
|
return &MenuItem{
|
||||||
ID: id,
|
ID: id,
|
||||||
Label: label,
|
Label: label,
|
||||||
Type: CheckboxType,
|
Type: CheckboxType,
|
||||||
Checked: checked,
|
Checked: checked,
|
||||||
Accelerator: accelerator,
|
Accelerator: accelerator,
|
||||||
|
Click: click,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/wailsapp/wails/v2"
|
"github.com/wailsapp/wails/v2"
|
||||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/options"
|
"github.com/wailsapp/wails/v2/pkg/options"
|
||||||
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
||||||
"log"
|
"log"
|
||||||
@ -11,6 +10,8 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
|
Menu := &Menu{}
|
||||||
|
|
||||||
// Create application with options
|
// Create application with options
|
||||||
app, err := wails.CreateAppWithOptions(&options.App{
|
app, err := wails.CreateAppWithOptions(&options.App{
|
||||||
Title: "Kitchen Sink",
|
Title: "Kitchen Sink",
|
||||||
@ -21,17 +22,17 @@ func main() {
|
|||||||
//Tray: menu.NewMenuFromItems(menu.AppMenu()),
|
//Tray: menu.NewMenuFromItems(menu.AppMenu()),
|
||||||
//Menu: menu.NewMenuFromItems(menu.AppMenu()),
|
//Menu: menu.NewMenuFromItems(menu.AppMenu()),
|
||||||
//StartHidden: true,
|
//StartHidden: true,
|
||||||
ContextMenus: createContextMenus(),
|
//ContextMenus: createContextMenus(),
|
||||||
Mac: &mac.Options{
|
Mac: &mac.Options{
|
||||||
WebviewIsTransparent: true,
|
WebviewIsTransparent: true,
|
||||||
WindowBackgroundIsTranslucent: true,
|
WindowBackgroundIsTranslucent: true,
|
||||||
// Comment out line below to see Window.SetTitle() work
|
// Comment out line below to see Window.SetTitle() work
|
||||||
TitleBar: mac.TitleBarHiddenInset(),
|
TitleBar: mac.TitleBarHiddenInset(),
|
||||||
Menu: createApplicationMenu(),
|
Menu: Menu.createApplicationMenu(),
|
||||||
Tray: &menu.Tray{
|
//Tray: &menu.Tray{
|
||||||
Icon: "light",
|
// Icon: "light",
|
||||||
Menu: createApplicationTray(),
|
// Menu: createApplicationTray(),
|
||||||
},
|
//},
|
||||||
},
|
},
|
||||||
LogLevel: logger.TRACE,
|
LogLevel: logger.TRACE,
|
||||||
})
|
})
|
||||||
@ -46,7 +47,7 @@ func main() {
|
|||||||
app.Bind(&System{})
|
app.Bind(&System{})
|
||||||
app.Bind(&Dialog{})
|
app.Bind(&Dialog{})
|
||||||
app.Bind(&Window{})
|
app.Bind(&Window{})
|
||||||
app.Bind(&Menu{})
|
app.Bind(Menu)
|
||||||
app.Bind(&Tray{})
|
app.Bind(&Tray{})
|
||||||
app.Bind(&ContextMenu{})
|
app.Bind(&ContextMenu{})
|
||||||
|
|
||||||
|
@ -69,13 +69,13 @@ func (m *Menu) addMenu(mi *menu.MenuItem) {
|
|||||||
parent := mi.Parent()
|
parent := mi.Parent()
|
||||||
counter := m.incrementcounter()
|
counter := m.incrementcounter()
|
||||||
menuText := "Dynamic Menu Item " + strconv.Itoa(counter)
|
menuText := "Dynamic Menu Item " + strconv.Itoa(counter)
|
||||||
parent.Append(menu.Text(menuText, menuText, nil))
|
parent.Append(menu.Text(menuText, menuText, nil, nil))
|
||||||
// parent.Append(menu.Text(menuText, menuText, menu.Key("[")))
|
// parent.Append(menu.Text(menuText, menuText, menu.Key("[")))
|
||||||
|
|
||||||
// If this is the first dynamic menu added, let's add a remove menu item
|
// If this is the first dynamic menu added, let's add a remove menu item
|
||||||
if counter == 1 {
|
if counter == 1 {
|
||||||
removeMenu := menu.Text("Remove "+menuText,
|
removeMenu := menu.Text("Remove "+menuText,
|
||||||
"Remove Last Item", keys.CmdOrCtrl("-"))
|
"Remove Last Item", keys.CmdOrCtrl("-"), nil)
|
||||||
parent.Prepend(removeMenu)
|
parent.Prepend(removeMenu)
|
||||||
m.runtime.Menu.On("Remove Last Item", m.removeMenu)
|
m.runtime.Menu.On("Remove Last Item", m.removeMenu)
|
||||||
} else {
|
} else {
|
||||||
@ -126,9 +126,9 @@ func (m *Menu) createDynamicMenuTwo() {
|
|||||||
// Create our submenu
|
// Create our submenu
|
||||||
dm2 := menu.SubMenu("Dynamic Menus 2", menu.NewMenuFromItems(
|
dm2 := menu.SubMenu("Dynamic Menus 2", menu.NewMenuFromItems(
|
||||||
menu.Text("Insert Before Random Menu Item",
|
menu.Text("Insert Before Random Menu Item",
|
||||||
"Insert Before Random", keys.CmdOrCtrl("]")),
|
"Insert Before Random", keys.CmdOrCtrl("]"), nil),
|
||||||
menu.Text("Insert After Random Menu Item",
|
menu.Text("Insert After Random Menu Item",
|
||||||
"Insert After Random", keys.CmdOrCtrl("[")),
|
"Insert After Random", keys.CmdOrCtrl("["), nil),
|
||||||
menu.Separator(),
|
menu.Separator(),
|
||||||
))
|
))
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ func (m *Menu) createDynamicMenuTwo() {
|
|||||||
m.anotherDynamicMenuCounter = 5
|
m.anotherDynamicMenuCounter = 5
|
||||||
for index := 0; index < m.anotherDynamicMenuCounter; index++ {
|
for index := 0; index < m.anotherDynamicMenuCounter; index++ {
|
||||||
text := "Other Dynamic Menu Item " + strconv.Itoa(index+1)
|
text := "Other Dynamic Menu Item " + strconv.Itoa(index+1)
|
||||||
item := menu.Text(text, text, nil)
|
item := menu.Text(text, text, nil, nil)
|
||||||
m.dynamicMenuItems[text] = item
|
m.dynamicMenuItems[text] = item
|
||||||
dm2.Append(item)
|
dm2.Append(item)
|
||||||
}
|
}
|
||||||
@ -176,7 +176,7 @@ func (m *Menu) insertBeforeRandom(_ *menu.MenuItem) {
|
|||||||
m.anotherDynamicMenuCounter++
|
m.anotherDynamicMenuCounter++
|
||||||
text := "Other Dynamic Menu Item " + strconv.Itoa(
|
text := "Other Dynamic Menu Item " + strconv.Itoa(
|
||||||
m.anotherDynamicMenuCounter+1)
|
m.anotherDynamicMenuCounter+1)
|
||||||
newItem := menu.Text(text, text, nil)
|
newItem := menu.Text(text, text, nil, nil)
|
||||||
m.dynamicMenuItems[text] = newItem
|
m.dynamicMenuItems[text] = newItem
|
||||||
|
|
||||||
item := m.runtime.Menu.GetByID(randomItemID)
|
item := m.runtime.Menu.GetByID(randomItemID)
|
||||||
@ -211,7 +211,7 @@ func (m *Menu) insertAfterRandom(_ *menu.MenuItem) {
|
|||||||
m.anotherDynamicMenuCounter++
|
m.anotherDynamicMenuCounter++
|
||||||
text := "Other Dynamic Menu Item " + strconv.Itoa(
|
text := "Other Dynamic Menu Item " + strconv.Itoa(
|
||||||
m.anotherDynamicMenuCounter+1)
|
m.anotherDynamicMenuCounter+1)
|
||||||
newItem := menu.Text(text, text, nil)
|
newItem := menu.Text(text, text, nil, nil)
|
||||||
|
|
||||||
item := m.runtime.Menu.GetByID(randomItemID)
|
item := m.runtime.Menu.GetByID(randomItemID)
|
||||||
m.dynamicMenuItems[text] = newItem
|
m.dynamicMenuItems[text] = newItem
|
||||||
@ -224,7 +224,11 @@ func (m *Menu) insertAfterRandom(_ *menu.MenuItem) {
|
|||||||
m.runtime.Menu.Update()
|
m.runtime.Menu.Update()
|
||||||
}
|
}
|
||||||
|
|
||||||
func createApplicationMenu() *menu.Menu {
|
func (m *Menu) processPlainText(callbackData *menu.CallbackData) {
|
||||||
|
println("\n\n\n\n\n\n\nCallback successful\n\n\n\n\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Menu) createApplicationMenu() *menu.Menu {
|
||||||
|
|
||||||
// Create menu
|
// Create menu
|
||||||
myMenu := menu.DefaultMacMenu()
|
myMenu := menu.DefaultMacMenu()
|
||||||
@ -245,62 +249,62 @@ func createApplicationMenu() *menu.Menu {
|
|||||||
menu.Front(),
|
menu.Front(),
|
||||||
|
|
||||||
menu.SubMenu("Test Submenu", menu.NewMenuFromItems(
|
menu.SubMenu("Test Submenu", menu.NewMenuFromItems(
|
||||||
menu.Text("Plain text", "plain text", nil),
|
menu.Text("Plain text", "plain text", nil, m.processPlainText),
|
||||||
menu.Text("Show Dynamic Menus 2 Submenu", "show-dynamic-menus-2", nil),
|
menu.Text("Show Dynamic Menus 2 Submenu", "show-dynamic-menus-2", nil, nil),
|
||||||
menu.SubMenu("Accelerators", menu.NewMenuFromItems(
|
menu.SubMenu("Accelerators", menu.NewMenuFromItems(
|
||||||
menu.SubMenu("Modifiers", menu.NewMenuFromItems(
|
menu.SubMenu("Modifiers", menu.NewMenuFromItems(
|
||||||
menu.Text("Shift accelerator", "Shift", keys.Shift("o")),
|
menu.Text("Shift accelerator", "Shift", keys.Shift("o"), nil),
|
||||||
menu.Text("Control accelerator", "Control", keys.Control("o")),
|
menu.Text("Control accelerator", "Control", keys.Control("o"), nil),
|
||||||
menu.Text("Command accelerator", "Command", keys.CmdOrCtrl("o")),
|
menu.Text("Command accelerator", "Command", keys.CmdOrCtrl("o"), nil),
|
||||||
menu.Text("Option accelerator", "Option", keys.OptionOrAlt("o")),
|
menu.Text("Option accelerator", "Option", keys.OptionOrAlt("o"), nil),
|
||||||
menu.Text("Combo accelerator", "Combo", keys.Combo("o", keys.CmdOrCtrlKey, keys.ShiftKey)),
|
menu.Text("Combo accelerator", "Combo", keys.Combo("o", keys.CmdOrCtrlKey, keys.ShiftKey), nil),
|
||||||
)),
|
)),
|
||||||
menu.SubMenu("System Keys", menu.NewMenuFromItems(
|
menu.SubMenu("System Keys", menu.NewMenuFromItems(
|
||||||
menu.Text("Backspace", "Backspace", keys.Key("Backspace")),
|
menu.Text("Backspace", "Backspace", keys.Key("Backspace"), nil),
|
||||||
menu.Text("Tab", "Tab", keys.Key("Tab")),
|
menu.Text("Tab", "Tab", keys.Key("Tab"), nil),
|
||||||
menu.Text("Return", "Return", keys.Key("Return")),
|
menu.Text("Return", "Return", keys.Key("Return"), nil),
|
||||||
menu.Text("Escape", "Escape", keys.Key("Escape")),
|
menu.Text("Escape", "Escape", keys.Key("Escape"), nil),
|
||||||
menu.Text("Left", "Left", keys.Key("Left")),
|
menu.Text("Left", "Left", keys.Key("Left"), nil),
|
||||||
menu.Text("Right", "Right", keys.Key("Right")),
|
menu.Text("Right", "Right", keys.Key("Right"), nil),
|
||||||
menu.Text("Up", "Up", keys.Key("Up")),
|
menu.Text("Up", "Up", keys.Key("Up"), nil),
|
||||||
menu.Text("Down", "Down", keys.Key("Down")),
|
menu.Text("Down", "Down", keys.Key("Down"), nil),
|
||||||
menu.Text("Space", "Space", keys.Key("Space")),
|
menu.Text("Space", "Space", keys.Key("Space"), nil),
|
||||||
menu.Text("Delete", "Delete", keys.Key("Delete")),
|
menu.Text("Delete", "Delete", keys.Key("Delete"), nil),
|
||||||
menu.Text("Home", "Home", keys.Key("Home")),
|
menu.Text("Home", "Home", keys.Key("Home"), nil),
|
||||||
menu.Text("End", "End", keys.Key("End")),
|
menu.Text("End", "End", keys.Key("End"), nil),
|
||||||
menu.Text("Page Up", "Page Up", keys.Key("Page Up")),
|
menu.Text("Page Up", "Page Up", keys.Key("Page Up"), nil),
|
||||||
menu.Text("Page Down", "Page Down", keys.Key("Page Down")),
|
menu.Text("Page Down", "Page Down", keys.Key("Page Down"), nil),
|
||||||
menu.Text("NumLock", "NumLock", keys.Key("NumLock")),
|
menu.Text("NumLock", "NumLock", keys.Key("NumLock"), nil),
|
||||||
)),
|
)),
|
||||||
menu.SubMenu("Function Keys", menu.NewMenuFromItems(
|
menu.SubMenu("Function Keys", menu.NewMenuFromItems(
|
||||||
menu.Text("F1", "F1", keys.Key("F1")),
|
menu.Text("F1", "F1", keys.Key("F1"), nil),
|
||||||
menu.Text("F2", "F2", keys.Key("F2")),
|
menu.Text("F2", "F2", keys.Key("F2"), nil),
|
||||||
menu.Text("F3", "F3", keys.Key("F3")),
|
menu.Text("F3", "F3", keys.Key("F3"), nil),
|
||||||
menu.Text("F4", "F4", keys.Key("F4")),
|
menu.Text("F4", "F4", keys.Key("F4"), nil),
|
||||||
menu.Text("F5", "F5", keys.Key("F5")),
|
menu.Text("F5", "F5", keys.Key("F5"), nil),
|
||||||
menu.Text("F6", "F6", keys.Key("F6")),
|
menu.Text("F6", "F6", keys.Key("F6"), nil),
|
||||||
menu.Text("F7", "F7", keys.Key("F7")),
|
menu.Text("F7", "F7", keys.Key("F7"), nil),
|
||||||
menu.Text("F8", "F8", keys.Key("F8")),
|
menu.Text("F8", "F8", keys.Key("F8"), nil),
|
||||||
menu.Text("F9", "F9", keys.Key("F9")),
|
menu.Text("F9", "F9", keys.Key("F9"), nil),
|
||||||
menu.Text("F10", "F10", keys.Key("F10")),
|
menu.Text("F10", "F10", keys.Key("F10"), nil),
|
||||||
menu.Text("F11", "F11", keys.Key("F11")),
|
menu.Text("F11", "F11", keys.Key("F11"), nil),
|
||||||
menu.Text("F12", "F12", keys.Key("F12")),
|
menu.Text("F12", "F12", keys.Key("F12"), nil),
|
||||||
menu.Text("F13", "F13", keys.Key("F13")),
|
menu.Text("F13", "F13", keys.Key("F13"), nil),
|
||||||
menu.Text("F14", "F14", keys.Key("F14")),
|
menu.Text("F14", "F14", keys.Key("F14"), nil),
|
||||||
menu.Text("F15", "F15", keys.Key("F15")),
|
menu.Text("F15", "F15", keys.Key("F15"), nil),
|
||||||
menu.Text("F16", "F16", keys.Key("F16")),
|
menu.Text("F16", "F16", keys.Key("F16"), nil),
|
||||||
menu.Text("F17", "F17", keys.Key("F17")),
|
menu.Text("F17", "F17", keys.Key("F17"), nil),
|
||||||
menu.Text("F18", "F18", keys.Key("F18")),
|
menu.Text("F18", "F18", keys.Key("F18"), nil),
|
||||||
menu.Text("F19", "F19", keys.Key("F19")),
|
menu.Text("F19", "F19", keys.Key("F19"), nil),
|
||||||
menu.Text("F20", "F20", keys.Key("F20")),
|
menu.Text("F20", "F20", keys.Key("F20"), nil),
|
||||||
)),
|
)),
|
||||||
menu.SubMenu("Standard Keys", menu.NewMenuFromItems(
|
menu.SubMenu("Standard Keys", menu.NewMenuFromItems(
|
||||||
menu.Text("Backtick", "Backtick", keys.Key("`")),
|
menu.Text("Backtick", "Backtick", keys.Key("`"), nil),
|
||||||
menu.Text("Plus", "Plus", keys.Key("+")),
|
menu.Text("Plus", "Plus", keys.Key("+"), nil),
|
||||||
)),
|
)),
|
||||||
)),
|
)),
|
||||||
menu.SubMenuWithID("Dynamic Menus 1", "Dynamic Menus 1", menu.NewMenuFromItems(
|
menu.SubMenuWithID("Dynamic Menus 1", "Dynamic Menus 1", menu.NewMenuFromItems(
|
||||||
menu.Text("Add Menu Item", "Add Menu Item", keys.CmdOrCtrl("+")),
|
menu.Text("Add Menu Item", "Add Menu Item", keys.CmdOrCtrl("+"), nil),
|
||||||
menu.Separator(),
|
menu.Separator(),
|
||||||
)),
|
)),
|
||||||
&menu.MenuItem{
|
&menu.MenuItem{
|
||||||
@ -321,11 +325,11 @@ func createApplicationMenu() *menu.Menu {
|
|||||||
Accelerator: keys.CmdOrCtrl("l"),
|
Accelerator: keys.CmdOrCtrl("l"),
|
||||||
Checked: true,
|
Checked: true,
|
||||||
},
|
},
|
||||||
menu.Checkbox("Checkbox Menu 2", "checkbox-menu 2", false, nil),
|
menu.Checkbox("Checkbox Menu 2", "checkbox-menu 2", false, nil, nil),
|
||||||
menu.Separator(),
|
menu.Separator(),
|
||||||
menu.Radio("😀 Option 1", "😀option-1", true, nil),
|
menu.Radio("😀 Option 1", "😀option-1", true, nil, nil),
|
||||||
menu.Radio("😺 Option 2", "option-2", false, nil),
|
menu.Radio("😺 Option 2", "option-2", false, nil, nil),
|
||||||
menu.Radio("❤️ Option 3", "option-3", false, nil),
|
menu.Radio("❤️ Option 3", "option-3", false, nil, nil),
|
||||||
)),
|
)),
|
||||||
))
|
))
|
||||||
|
|
||||||
|
@ -78,13 +78,13 @@ func (t *Tray) addMenu(mi *menu.MenuItem) {
|
|||||||
parent := mi.Parent()
|
parent := mi.Parent()
|
||||||
counter := t.incrementcounter()
|
counter := t.incrementcounter()
|
||||||
menuText := "Dynamic Menu Item " + strconv.Itoa(counter)
|
menuText := "Dynamic Menu Item " + strconv.Itoa(counter)
|
||||||
parent.Append(menu.Text(menuText, menuText, nil))
|
parent.Append(menu.Text(menuText, menuText, nil, nil))
|
||||||
// parent.Append(menu.Text(menuText, menuText, menu.Key("[")))
|
// parent.Append(menu.Text(menuText, menuText, menu.Key("[")))
|
||||||
|
|
||||||
// If this is the first dynamic menu added, let's add a remove menu item
|
// If this is the first dynamic menu added, let's add a remove menu item
|
||||||
if counter == 1 {
|
if counter == 1 {
|
||||||
removeMenu := menu.Text("Remove "+menuText,
|
removeMenu := menu.Text("Remove "+menuText,
|
||||||
"Remove Last Item", keys.CmdOrCtrl("-"))
|
"Remove Last Item", keys.CmdOrCtrl("-"), nil)
|
||||||
parent.Prepend(removeMenu)
|
parent.Prepend(removeMenu)
|
||||||
t.runtime.Tray.On("Remove Last Item", t.removeMenu)
|
t.runtime.Tray.On("Remove Last Item", t.removeMenu)
|
||||||
} else {
|
} else {
|
||||||
@ -136,9 +136,9 @@ func (t *Tray) SetIcon(trayIconID string) {
|
|||||||
|
|
||||||
func createApplicationTray() *menu.Menu {
|
func createApplicationTray() *menu.Menu {
|
||||||
trayMenu := &menu.Menu{}
|
trayMenu := &menu.Menu{}
|
||||||
trayMenu.Append(menu.Text("Show Window", "Show Window", nil))
|
trayMenu.Append(menu.Text("Show Window", "Show Window", nil, nil))
|
||||||
trayMenu.Append(menu.Text("Hide Window", "Hide Window", nil))
|
trayMenu.Append(menu.Text("Hide Window", "Hide Window", nil, nil))
|
||||||
trayMenu.Append(menu.Text("Minimise Window", "Minimise Window", nil))
|
trayMenu.Append(menu.Text("Minimise Window", "Minimise Window", nil, nil))
|
||||||
trayMenu.Append(menu.Text("Unminimise Window", "Unminimise Window", nil))
|
trayMenu.Append(menu.Text("Unminimise Window", "Unminimise Window", nil, nil))
|
||||||
return trayMenu
|
return trayMenu
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user