mirror of
https://github.com/taigrr/wails.git
synced 2026-04-02 05:08:54 -07:00
Support for dynamic menus.
Fixed bug in accelerator handling
This commit is contained in:
@@ -78,11 +78,11 @@ func CreateApp(options *options.App) *App {
|
||||
func (a *App) Run() error {
|
||||
|
||||
// Setup signal handler
|
||||
signal, err := signal.NewManager(a.servicebus, a.logger)
|
||||
signalsubsystem, err := signal.NewManager(a.servicebus, a.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.signal = signal
|
||||
a.signal = signalsubsystem
|
||||
a.signal.Start()
|
||||
|
||||
// Start the service bus
|
||||
@@ -90,11 +90,12 @@ func (a *App) Run() error {
|
||||
a.servicebus.Start()
|
||||
|
||||
// Start the runtime
|
||||
runtime, err := subsystem.NewRuntime(a.servicebus, a.logger)
|
||||
runtimesubsystem, err := subsystem.NewRuntime(a.servicebus, a.logger,
|
||||
a.options.Mac.Menu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.runtime = runtime
|
||||
a.runtime = runtimesubsystem
|
||||
a.runtime.Start()
|
||||
|
||||
// Application Stores
|
||||
@@ -102,11 +103,12 @@ func (a *App) Run() error {
|
||||
a.appconfigStore = a.runtime.GoRuntime().Store.New("wails:appconfig", a.options)
|
||||
|
||||
// Start the binding subsystem
|
||||
binding, err := subsystem.NewBinding(a.servicebus, a.logger, a.bindings, a.runtime.GoRuntime())
|
||||
bindingsubsystem, err := subsystem.NewBinding(a.servicebus, a.logger,
|
||||
a.bindings, a.runtime.GoRuntime())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.binding = binding
|
||||
a.binding = bindingsubsystem
|
||||
a.binding.Start()
|
||||
|
||||
// Start the logging subsystem
|
||||
@@ -145,11 +147,11 @@ func (a *App) Run() error {
|
||||
default:
|
||||
return fmt.Errorf("unsupported OS: %s", goruntime.GOOS)
|
||||
}
|
||||
menu, err := subsystem.NewMenu(platformMenu, a.servicebus, a.logger)
|
||||
menusubsystem, err := subsystem.NewMenu(platformMenu, a.servicebus, a.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.menu = menu
|
||||
a.menu = menusubsystem
|
||||
a.menu.Start()
|
||||
|
||||
// Start the call subsystem
|
||||
|
||||
@@ -32,4 +32,5 @@ extern void DisableFrame(void *app);
|
||||
extern void OpenDialog(void *appPointer, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int allowFiles, int allowDirs, int allowMultiple, int showHiddenFiles, int canCreateDirectories, int resolvesAliases, int treatPackagesAsDirectories);
|
||||
extern void SaveDialog(void *appPointer, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int showHiddenFiles, int canCreateDirectories, int treatPackagesAsDirectories);
|
||||
extern void DarkModeEnabled(void *appPointer, char *callbackID);
|
||||
extern void UpdateMenu(void *app, char *menuAsJSON);
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,8 @@ package ffenestri
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
"strconv"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
@@ -154,3 +156,19 @@ func (c *Client) SaveDialog(dialogOptions *options.SaveDialog, callbackID string
|
||||
func (c *Client) DarkModeEnabled(callbackID string) {
|
||||
C.DarkModeEnabled(c.app.app, c.app.string2CString(callbackID))
|
||||
}
|
||||
|
||||
func (c *Client) UpdateMenu(menu *menu.Menu) {
|
||||
|
||||
// Guard against nil menus
|
||||
if menu == nil {
|
||||
return
|
||||
}
|
||||
// Process the menu
|
||||
processedMenu := NewProcessedMenu(menu)
|
||||
menuJSON, err := json.Marshal(processedMenu)
|
||||
if err != nil {
|
||||
c.app.logger.Error("Error processing updated Menu: %s", err.Error())
|
||||
return
|
||||
}
|
||||
C.UpdateMenu(c.app.app, c.app.string2CString(string(menuJSON)))
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,8 +19,6 @@ extern void SetMenu(void *, const char *);
|
||||
import "C"
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
)
|
||||
|
||||
func (a *Application) processPlatformSettings() error {
|
||||
@@ -106,80 +104,3 @@ func (a *Application) processPlatformSettings() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ProcessedMenu is the original menu with the addition
|
||||
// of radio groups extracted from the menu data
|
||||
type ProcessedMenu struct {
|
||||
Menu *menu.Menu
|
||||
RadioGroups []*RadioGroup
|
||||
currentRadioGroup []string
|
||||
}
|
||||
|
||||
// RadioGroup holds all the members of the same radio group
|
||||
type RadioGroup struct {
|
||||
Members []string
|
||||
Length int
|
||||
}
|
||||
|
||||
// NewProcessedMenu processed the given menu and returns
|
||||
// the original menu with the extracted radio groups
|
||||
func NewProcessedMenu(menu *menu.Menu) *ProcessedMenu {
|
||||
result := &ProcessedMenu{
|
||||
Menu: menu,
|
||||
RadioGroups: []*RadioGroup{},
|
||||
currentRadioGroup: []string{},
|
||||
}
|
||||
|
||||
result.processMenu()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (p *ProcessedMenu) processMenu() {
|
||||
// Loop over top level menus
|
||||
for _, item := range p.Menu.Items {
|
||||
// Process MenuItem
|
||||
p.processMenuItem(item)
|
||||
}
|
||||
|
||||
p.finaliseRadioGroup()
|
||||
}
|
||||
|
||||
func (p *ProcessedMenu) processMenuItem(item *menu.MenuItem) {
|
||||
|
||||
switch item.Type {
|
||||
|
||||
// We need to recurse submenus
|
||||
case menu.SubmenuType:
|
||||
|
||||
// Finalise any current radio groups as they don't trickle down to submenus
|
||||
p.finaliseRadioGroup()
|
||||
|
||||
// Process each submenu item
|
||||
for _, subitem := range item.SubMenu {
|
||||
p.processMenuItem(subitem)
|
||||
}
|
||||
case menu.RadioType:
|
||||
// Add the item to the radio group
|
||||
p.currentRadioGroup = append(p.currentRadioGroup, item.ID)
|
||||
default:
|
||||
p.finaliseRadioGroup()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ProcessedMenu) finaliseRadioGroup() {
|
||||
|
||||
// If we were processing a radio group, fix up the references
|
||||
if len(p.currentRadioGroup) > 0 {
|
||||
|
||||
// Create new radiogroup
|
||||
group := &RadioGroup{
|
||||
Members: p.currentRadioGroup,
|
||||
Length: len(p.currentRadioGroup),
|
||||
}
|
||||
p.RadioGroups = append(p.RadioGroups, group)
|
||||
|
||||
// Empty the radio group
|
||||
p.currentRadioGroup = []string{}
|
||||
}
|
||||
}
|
||||
|
||||
80
v2/internal/ffenestri/menu.go
Normal file
80
v2/internal/ffenestri/menu.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package ffenestri
|
||||
|
||||
import "github.com/wailsapp/wails/v2/pkg/menu"
|
||||
|
||||
// ProcessedMenu is the original menu with the addition
|
||||
// of radio groups extracted from the menu data
|
||||
type ProcessedMenu struct {
|
||||
Menu *menu.Menu
|
||||
RadioGroups []*RadioGroup
|
||||
currentRadioGroup []string
|
||||
}
|
||||
|
||||
// RadioGroup holds all the members of the same radio group
|
||||
type RadioGroup struct {
|
||||
Members []string
|
||||
Length int
|
||||
}
|
||||
|
||||
// NewProcessedMenu processed the given menu and returns
|
||||
// the original menu with the extracted radio groups
|
||||
func NewProcessedMenu(menu *menu.Menu) *ProcessedMenu {
|
||||
result := &ProcessedMenu{
|
||||
Menu: menu,
|
||||
RadioGroups: []*RadioGroup{},
|
||||
currentRadioGroup: []string{},
|
||||
}
|
||||
|
||||
result.processMenu()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (p *ProcessedMenu) processMenu() {
|
||||
// Loop over top level menus
|
||||
for _, item := range p.Menu.Items {
|
||||
// Process MenuItem
|
||||
p.processMenuItem(item)
|
||||
}
|
||||
|
||||
p.finaliseRadioGroup()
|
||||
}
|
||||
|
||||
func (p *ProcessedMenu) processMenuItem(item *menu.MenuItem) {
|
||||
|
||||
switch item.Type {
|
||||
|
||||
// We need to recurse submenus
|
||||
case menu.SubmenuType:
|
||||
|
||||
// Finalise any current radio groups as they don't trickle down to submenus
|
||||
p.finaliseRadioGroup()
|
||||
|
||||
// Process each submenu item
|
||||
for _, subitem := range item.SubMenu {
|
||||
p.processMenuItem(subitem)
|
||||
}
|
||||
case menu.RadioType:
|
||||
// Add the item to the radio group
|
||||
p.currentRadioGroup = append(p.currentRadioGroup, item.ID)
|
||||
default:
|
||||
p.finaliseRadioGroup()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ProcessedMenu) finaliseRadioGroup() {
|
||||
|
||||
// If we were processing a radio group, fix up the references
|
||||
if len(p.currentRadioGroup) > 0 {
|
||||
|
||||
// Create new radiogroup
|
||||
group := &RadioGroup{
|
||||
Members: p.currentRadioGroup,
|
||||
Length: len(p.currentRadioGroup),
|
||||
}
|
||||
p.RadioGroups = append(p.RadioGroups, group)
|
||||
|
||||
// Empty the radio group
|
||||
p.currentRadioGroup = []string{}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package messagedispatcher
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
"github.com/wailsapp/wails/v2/internal/messagedispatcher/message"
|
||||
@@ -30,6 +31,7 @@ type Client interface {
|
||||
WindowUnFullscreen()
|
||||
WindowSetColour(colour int)
|
||||
DarkModeEnabled(callbackID string)
|
||||
UpdateMenu(menu *menu.Menu)
|
||||
}
|
||||
|
||||
// DispatchClient is what the frontends use to interface with the
|
||||
@@ -73,14 +75,6 @@ func (d *DispatchClient) DispatchMessage(incomingMessage string) {
|
||||
|
||||
d.logger.Trace("I got a parsedMessage: %+v", parsedMessage)
|
||||
|
||||
// Check error
|
||||
if err != nil {
|
||||
d.logger.Error(err.Error())
|
||||
// Hrm... what do we do with this?
|
||||
d.bus.PublishForTarget("generic:message", incomingMessage, d.id)
|
||||
return
|
||||
}
|
||||
|
||||
// Publish the parsed message
|
||||
d.bus.PublishForTarget(parsedMessage.Topic, parsedMessage.Data, d.id)
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package messagedispatcher
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -22,6 +23,7 @@ type Dispatcher struct {
|
||||
windowChannel <-chan *servicebus.Message
|
||||
dialogChannel <-chan *servicebus.Message
|
||||
systemChannel <-chan *servicebus.Message
|
||||
menuChannel <-chan *servicebus.Message
|
||||
running bool
|
||||
|
||||
servicebus *servicebus.ServiceBus
|
||||
@@ -69,6 +71,11 @@ func New(servicebus *servicebus.ServiceBus, logger *logger.Logger) (*Dispatcher,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
menuChannel, err := servicebus.Subscribe("menu:")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &Dispatcher{
|
||||
servicebus: servicebus,
|
||||
eventChannel: eventChannel,
|
||||
@@ -79,6 +86,7 @@ func New(servicebus *servicebus.ServiceBus, logger *logger.Logger) (*Dispatcher,
|
||||
windowChannel: windowChannel,
|
||||
dialogChannel: dialogChannel,
|
||||
systemChannel: systemChannel,
|
||||
menuChannel: menuChannel,
|
||||
}
|
||||
|
||||
return result, nil
|
||||
@@ -108,6 +116,8 @@ func (d *Dispatcher) Start() error {
|
||||
d.processDialogMessage(dialogMessage)
|
||||
case systemMessage := <-d.systemChannel:
|
||||
d.processSystemMessage(systemMessage)
|
||||
case menuMessage := <-d.menuChannel:
|
||||
d.processMenuMessage(menuMessage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +187,7 @@ func (d *Dispatcher) processCallResult(result *servicebus.Message) {
|
||||
if client == nil {
|
||||
// This is fatal - unknown target!
|
||||
d.logger.Fatal("Unknown target for call result: %+v", result)
|
||||
return
|
||||
}
|
||||
|
||||
d.logger.Trace("Sending message to client %s: R%s", target, result.Data().(string))
|
||||
@@ -397,3 +408,31 @@ func (d *Dispatcher) processDialogMessage(result *servicebus.Message) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (d *Dispatcher) processMenuMessage(result *servicebus.Message) {
|
||||
splitTopic := strings.Split(result.Topic(), ":")
|
||||
if len(splitTopic) < 2 {
|
||||
d.logger.Error("Invalid menu message : %#v", result.Data())
|
||||
return
|
||||
}
|
||||
|
||||
command := splitTopic[1]
|
||||
switch command {
|
||||
case "update":
|
||||
|
||||
updatedMenu, ok := result.Data().(*menu.Menu)
|
||||
if !ok {
|
||||
d.logger.Error("Invalid data for 'dialog:select:open' : %#v", result.Data())
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Work out what we mean in a multi window environment...
|
||||
// For now we will just pick the first one
|
||||
for _, client := range d.clients {
|
||||
client.frontend.UpdateMenu(updatedMenu)
|
||||
}
|
||||
|
||||
default:
|
||||
d.logger.Error("Unknown dialog command: %s", command)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,16 +9,19 @@ import (
|
||||
// Menu defines all Menu related operations
|
||||
type Menu interface {
|
||||
On(menuID string, callback func(*menu.MenuItem))
|
||||
Update()
|
||||
}
|
||||
|
||||
type menuRuntime struct {
|
||||
bus *servicebus.ServiceBus
|
||||
bus *servicebus.ServiceBus
|
||||
menu *menu.Menu
|
||||
}
|
||||
|
||||
// newMenu creates a new Menu struct
|
||||
func newMenu(bus *servicebus.ServiceBus) Menu {
|
||||
func newMenu(bus *servicebus.ServiceBus, menu *menu.Menu) Menu {
|
||||
return &menuRuntime{
|
||||
bus: bus,
|
||||
bus: bus,
|
||||
menu: menu,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,3 +32,7 @@ func (m *menuRuntime) On(menuID string, callback func(*menu.MenuItem)) {
|
||||
Callback: callback,
|
||||
})
|
||||
}
|
||||
|
||||
func (m *menuRuntime) Update() {
|
||||
m.bus.Publish("menu:update", m.menu)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package runtime
|
||||
|
||||
import "github.com/wailsapp/wails/v2/internal/servicebus"
|
||||
import (
|
||||
"github.com/wailsapp/wails/v2/internal/servicebus"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
)
|
||||
|
||||
// Runtime is a means for the user to interact with the application at runtime
|
||||
type Runtime struct {
|
||||
@@ -16,14 +19,14 @@ type Runtime struct {
|
||||
}
|
||||
|
||||
// New creates a new runtime
|
||||
func New(serviceBus *servicebus.ServiceBus) *Runtime {
|
||||
func New(serviceBus *servicebus.ServiceBus, menu *menu.Menu) *Runtime {
|
||||
result := &Runtime{
|
||||
Browser: newBrowser(),
|
||||
Events: newEvents(serviceBus),
|
||||
Window: newWindow(serviceBus),
|
||||
Dialog: newDialog(serviceBus),
|
||||
System: newSystem(serviceBus),
|
||||
Menu: newMenu(serviceBus),
|
||||
Menu: newMenu(serviceBus, menu),
|
||||
Log: newLog(serviceBus),
|
||||
bus: serviceBus,
|
||||
}
|
||||
|
||||
@@ -34,10 +34,13 @@ type Menu struct {
|
||||
|
||||
// logger
|
||||
logger logger.CustomLogger
|
||||
|
||||
// The application menu
|
||||
applicationMenu *menu.Menu
|
||||
}
|
||||
|
||||
// NewMenu creates a new menu subsystem
|
||||
func NewMenu(initialMenu *menu.Menu, bus *servicebus.ServiceBus, logger *logger.Logger) (*Menu, error) {
|
||||
func NewMenu(applicationMenu *menu.Menu, bus *servicebus.ServiceBus, logger *logger.Logger) (*Menu, error) {
|
||||
|
||||
// Register quit channel
|
||||
quitChannel, err := bus.Subscribe("quit")
|
||||
@@ -52,15 +55,16 @@ func NewMenu(initialMenu *menu.Menu, bus *servicebus.ServiceBus, logger *logger.
|
||||
}
|
||||
|
||||
result := &Menu{
|
||||
quitChannel: quitChannel,
|
||||
menuChannel: menuChannel,
|
||||
logger: logger.CustomLogger("Menu Subsystem"),
|
||||
listeners: make(map[string][]func(*menu.MenuItem)),
|
||||
menuItems: make(map[string]*menu.MenuItem),
|
||||
quitChannel: quitChannel,
|
||||
menuChannel: menuChannel,
|
||||
logger: logger.CustomLogger("Menu Subsystem"),
|
||||
listeners: make(map[string][]func(*menu.MenuItem)),
|
||||
menuItems: make(map[string]*menu.MenuItem),
|
||||
applicationMenu: applicationMenu,
|
||||
}
|
||||
|
||||
// Build up list of item/id pairs
|
||||
result.processMenu(initialMenu)
|
||||
result.processMenu(applicationMenu)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package subsystem
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
"strings"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
@@ -23,7 +24,7 @@ type Runtime struct {
|
||||
}
|
||||
|
||||
// NewRuntime creates a new runtime subsystem
|
||||
func NewRuntime(bus *servicebus.ServiceBus, logger *logger.Logger) (*Runtime, error) {
|
||||
func NewRuntime(bus *servicebus.ServiceBus, logger *logger.Logger, menu *menu.Menu) (*Runtime, error) {
|
||||
|
||||
// Register quit channel
|
||||
quitChannel, err := bus.Subscribe("quit")
|
||||
@@ -41,7 +42,7 @@ func NewRuntime(bus *servicebus.ServiceBus, logger *logger.Logger) (*Runtime, er
|
||||
quitChannel: quitChannel,
|
||||
runtimeChannel: runtimeChannel,
|
||||
logger: logger.CustomLogger("Runtime Subsystem"),
|
||||
runtime: runtime.New(bus),
|
||||
runtime: runtime.New(bus, menu),
|
||||
}
|
||||
|
||||
return result, nil
|
||||
@@ -75,7 +76,8 @@ func (r *Runtime) Start() error {
|
||||
case "browser":
|
||||
err = r.processBrowserMessage(method, runtimeMessage.Data())
|
||||
default:
|
||||
fmt.Errorf("unknown runtime message: %+v", runtimeMessage)
|
||||
err = fmt.Errorf("unknown runtime message: %+v",
|
||||
runtimeMessage)
|
||||
}
|
||||
|
||||
// If we had an error, log it
|
||||
|
||||
@@ -20,6 +20,27 @@ type MenuItem struct {
|
||||
Checked bool
|
||||
// Submenu contains a list of menu items that will be shown as a submenu
|
||||
SubMenu []*MenuItem `json:"SubMenu,omitempty"`
|
||||
|
||||
// This holds the menu item's parent.
|
||||
parent *MenuItem
|
||||
}
|
||||
|
||||
// Parent returns the parent of the menu item.
|
||||
// If it is a top level menu then it returns nil.
|
||||
func (m *MenuItem) Parent() *MenuItem {
|
||||
return m.parent
|
||||
}
|
||||
|
||||
// Append will attempt to append the given menu item to
|
||||
// this item's submenu items. If this menu item is not a
|
||||
// submenu, then this method will not add the item and
|
||||
// simply return false.
|
||||
func (m *MenuItem) Append(item *MenuItem) bool {
|
||||
if m.Type != SubmenuType {
|
||||
return false
|
||||
}
|
||||
m.SubMenu = append(m.SubMenu, item)
|
||||
return true
|
||||
}
|
||||
|
||||
// Text is a helper to create basic Text menu items
|
||||
@@ -78,9 +99,16 @@ func CheckboxWithAccelerator(label string, id string, checked bool, accelerator
|
||||
|
||||
// SubMenu is a helper to create Submenus
|
||||
func SubMenu(label string, items []*MenuItem) *MenuItem {
|
||||
return &MenuItem{
|
||||
result := &MenuItem{
|
||||
Label: label,
|
||||
SubMenu: items,
|
||||
Type: SubmenuType,
|
||||
}
|
||||
|
||||
// Fix up parent pointers
|
||||
for _, item := range items {
|
||||
item.parent = result
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
wails "github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
@@ -10,6 +11,8 @@ import (
|
||||
// Menu struct
|
||||
type Menu struct {
|
||||
runtime *wails.Runtime
|
||||
|
||||
dynamicMenuCounter int
|
||||
}
|
||||
|
||||
// WailsInit is called at application startup
|
||||
@@ -18,21 +21,32 @@ func (m *Menu) WailsInit(runtime *wails.Runtime) error {
|
||||
m.runtime = runtime
|
||||
|
||||
// Setup Menu Listeners
|
||||
m.runtime.Menu.On("hello", func(m *menu.MenuItem) {
|
||||
fmt.Printf("The '%s' menu was clicked\n", m.Label)
|
||||
m.runtime.Menu.On("hello", func(mi *menu.MenuItem) {
|
||||
fmt.Printf("The '%s' menu was clicked\n", mi.Label)
|
||||
})
|
||||
m.runtime.Menu.On("checkbox-menu", func(m *menu.MenuItem) {
|
||||
fmt.Printf("The '%s' menu was clicked\n", m.Label)
|
||||
fmt.Printf("It is now %v\n", m.Checked)
|
||||
// m.Checked = false
|
||||
// runtime.Menu.Update()
|
||||
m.runtime.Menu.On("checkbox-menu", func(mi *menu.MenuItem) {
|
||||
fmt.Printf("The '%s' menu was clicked\n", mi.Label)
|
||||
fmt.Printf("It is now %v\n", mi.Checked)
|
||||
})
|
||||
m.runtime.Menu.On("😀option-1", func(m *menu.MenuItem) {
|
||||
fmt.Printf("We can use UTF-8 IDs: %s\n", m.Label)
|
||||
m.runtime.Menu.On("😀option-1", func(mi *menu.MenuItem) {
|
||||
fmt.Printf("We can use UTF-8 IDs: %s\n", mi.Label)
|
||||
})
|
||||
|
||||
// Setup dynamic menus
|
||||
m.runtime.Menu.On("Add Menu Item", m.addMenu)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Menu) addMenu(mi *menu.MenuItem) {
|
||||
// Get this menu's parent
|
||||
parent := mi.Parent()
|
||||
m.dynamicMenuCounter++
|
||||
menuText := "Dynamic Menu Item " + strconv.Itoa(m.dynamicMenuCounter)
|
||||
parent.Append(menu.Text(menuText, menuText))
|
||||
// parent.Append(menu.TextWithAccelerator(menuText, menuText, menu.Accel("[")))
|
||||
m.runtime.Menu.Update()
|
||||
}
|
||||
|
||||
func createApplicationMenu() *menu.Menu {
|
||||
|
||||
// Create menu
|
||||
@@ -54,6 +68,7 @@ func createApplicationMenu() *menu.Menu {
|
||||
menu.Front(),
|
||||
|
||||
menu.SubMenu("Test Submenu", []*menu.MenuItem{
|
||||
menu.Text("Plain text", "plain text"),
|
||||
menu.SubMenu("Accelerators", []*menu.MenuItem{
|
||||
menu.SubMenu("Modifiers", []*menu.MenuItem{
|
||||
menu.TextWithAccelerator("Shift accelerator", "Shift", menu.ShiftAccel("o")),
|
||||
@@ -76,9 +91,6 @@ func createApplicationMenu() *menu.Menu {
|
||||
menu.TextWithAccelerator("End", "End", menu.Accel("End")),
|
||||
menu.TextWithAccelerator("Page Up", "Page Up", menu.Accel("Page Up")),
|
||||
menu.TextWithAccelerator("Page Down", "Page Down", menu.Accel("Page Down")),
|
||||
menu.TextWithAccelerator("Insert", "Insert", menu.Accel("Insert")),
|
||||
menu.TextWithAccelerator("PrintScreen", "PrintScreen", menu.Accel("PrintScreen")),
|
||||
menu.TextWithAccelerator("ScrollLock", "ScrollLock", menu.Accel("ScrollLock")),
|
||||
menu.TextWithAccelerator("NumLock", "NumLock", menu.Accel("NumLock")),
|
||||
}),
|
||||
menu.SubMenu("Function Keys", []*menu.MenuItem{
|
||||
@@ -102,39 +114,28 @@ func createApplicationMenu() *menu.Menu {
|
||||
menu.TextWithAccelerator("F18", "F18", menu.Accel("F18")),
|
||||
menu.TextWithAccelerator("F19", "F19", menu.Accel("F19")),
|
||||
menu.TextWithAccelerator("F20", "F20", menu.Accel("F20")),
|
||||
menu.TextWithAccelerator("F21", "F21", menu.Accel("F21")),
|
||||
menu.TextWithAccelerator("F22", "F22", menu.Accel("F22")),
|
||||
menu.TextWithAccelerator("F23", "F23", menu.Accel("F23")),
|
||||
menu.TextWithAccelerator("F24", "F24", menu.Accel("F24")),
|
||||
menu.TextWithAccelerator("F25", "F25", menu.Accel("F25")),
|
||||
menu.TextWithAccelerator("F26", "F26", menu.Accel("F26")),
|
||||
menu.TextWithAccelerator("F27", "F27", menu.Accel("F27")),
|
||||
menu.TextWithAccelerator("F28", "F28", menu.Accel("F28")),
|
||||
menu.TextWithAccelerator("F29", "F29", menu.Accel("F29")),
|
||||
menu.TextWithAccelerator("F30", "F30", menu.Accel("F30")),
|
||||
menu.TextWithAccelerator("F31", "F31", menu.Accel("F31")),
|
||||
menu.TextWithAccelerator("F32", "F32", menu.Accel("F32")),
|
||||
menu.TextWithAccelerator("F33", "F33", menu.Accel("F33")),
|
||||
menu.TextWithAccelerator("F34", "F34", menu.Accel("F34")),
|
||||
menu.TextWithAccelerator("F35", "F35", menu.Accel("F35")),
|
||||
}),
|
||||
menu.SubMenu("Standard Keys", []*menu.MenuItem{
|
||||
menu.TextWithAccelerator("Backtick", "Backtick", menu.Accel("`")),
|
||||
menu.TextWithAccelerator("Plus", "Plus", menu.Accel("+")),
|
||||
}),
|
||||
menu.SubMenu("Dynamic Menus", []*menu.MenuItem{
|
||||
menu.TextWithAccelerator("Add Menu Item", "Add Menu Item", menu.CmdOrCtrlAccel("+")),
|
||||
menu.Separator(),
|
||||
}),
|
||||
}),
|
||||
&menu.MenuItem{
|
||||
{
|
||||
Label: "Disabled Menu",
|
||||
Type: menu.TextType,
|
||||
Accelerator: menu.ComboAccel("p", menu.CmdOrCtrl, menu.Shift),
|
||||
Disabled: true,
|
||||
},
|
||||
&menu.MenuItem{
|
||||
{
|
||||
Label: "Hidden Menu",
|
||||
Type: menu.TextType,
|
||||
Hidden: true,
|
||||
},
|
||||
&menu.MenuItem{
|
||||
{
|
||||
ID: "checkbox-menu",
|
||||
Label: "Checkbox Menu",
|
||||
Type: menu.CheckboxType,
|
||||
|
||||
Reference in New Issue
Block a user