github.com/secoba/wails/v2@v2.6.4/internal/frontend/desktop/darwin/menu.go (about) 1 //go:build darwin 2 // +build darwin 3 4 package darwin 5 6 /* 7 #cgo CFLAGS: -x objective-c 8 #cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit 9 #import <Foundation/Foundation.h> 10 #import "Application.h" 11 #import "WailsContext.h" 12 13 #include <stdlib.h> 14 */ 15 import "C" 16 17 import ( 18 "unsafe" 19 20 "github.com/secoba/wails/v2/pkg/menu" 21 "github.com/secoba/wails/v2/pkg/menu/keys" 22 ) 23 24 type NSMenu struct { 25 context unsafe.Pointer 26 nsmenu unsafe.Pointer 27 } 28 29 func NewNSMenu(context unsafe.Pointer, name string) *NSMenu { 30 c := NewCalloc() 31 defer c.Free() 32 title := c.String(name) 33 nsmenu := C.NewMenu(title) 34 return &NSMenu{ 35 context: context, 36 nsmenu: nsmenu, 37 } 38 } 39 40 func (m *NSMenu) AddSubMenu(label string) *NSMenu { 41 result := NewNSMenu(m.context, label) 42 C.AppendSubmenu(m.nsmenu, result.nsmenu) 43 return result 44 } 45 46 func (m *NSMenu) AppendRole(role menu.Role) { 47 C.AppendRole(m.context, m.nsmenu, C.int(role)) 48 } 49 50 type MenuItem struct { 51 id uint 52 nsmenuitem unsafe.Pointer 53 wailsMenuItem *menu.MenuItem 54 radioGroupMembers []*MenuItem 55 } 56 57 func (m *NSMenu) AddMenuItem(menuItem *menu.MenuItem) *MenuItem { 58 c := NewCalloc() 59 defer c.Free() 60 var modifier C.int 61 var key *C.char 62 if menuItem.Accelerator != nil { 63 modifier = C.int(keys.ToMacModifier(menuItem.Accelerator)) 64 key = c.String(menuItem.Accelerator.Key) 65 } 66 67 result := &MenuItem{ 68 wailsMenuItem: menuItem, 69 } 70 71 result.id = createMenuItemID(result) 72 result.nsmenuitem = C.AppendMenuItem(m.context, m.nsmenu, c.String(menuItem.Label), key, modifier, bool2Cint(menuItem.Disabled), bool2Cint(menuItem.Checked), C.int(result.id)) 73 return result 74 } 75 76 //func (w *Window) SetApplicationMenu(menu *menu.Menu) { 77 //w.applicationMenu = menu 78 //processMenu(w, menu) 79 //} 80 81 func processMenu(parent *NSMenu, wailsMenu *menu.Menu) { 82 var radioGroups []*MenuItem 83 84 for _, menuItem := range wailsMenu.Items { 85 if menuItem.SubMenu != nil { 86 if len(radioGroups) > 0 { 87 processRadioGroups(radioGroups) 88 radioGroups = []*MenuItem{} 89 } 90 submenu := parent.AddSubMenu(menuItem.Label) 91 processMenu(submenu, menuItem.SubMenu) 92 } else { 93 lastMenuItem := processMenuItem(parent, menuItem) 94 if menuItem.Type == menu.RadioType { 95 radioGroups = append(radioGroups, lastMenuItem) 96 } else { 97 if len(radioGroups) > 0 { 98 processRadioGroups(radioGroups) 99 radioGroups = []*MenuItem{} 100 } 101 } 102 } 103 } 104 } 105 106 func processRadioGroups(groups []*MenuItem) { 107 for _, item := range groups { 108 item.radioGroupMembers = groups 109 } 110 } 111 112 func processMenuItem(parent *NSMenu, menuItem *menu.MenuItem) *MenuItem { 113 if menuItem.Hidden { 114 return nil 115 } 116 if menuItem.Role != 0 { 117 parent.AppendRole(menuItem.Role) 118 return nil 119 } 120 if menuItem.Type == menu.SeparatorType { 121 C.AppendSeparator(parent.nsmenu) 122 return nil 123 } 124 125 return parent.AddMenuItem(menuItem) 126 } 127 128 func (f *Frontend) MenuSetApplicationMenu(menu *menu.Menu) { 129 f.mainWindow.SetApplicationMenu(menu) 130 } 131 132 func (f *Frontend) MenuUpdateApplicationMenu() { 133 f.mainWindow.UpdateApplicationMenu() 134 }