github.com/AlpineAIO/wails/v2@v2.0.0-beta.32.0.20240505041856-1047a8fa5fef/internal/menumanager/processedMenu.go (about) 1 package menumanager 2 3 import ( 4 "encoding/json" 5 6 "github.com/AlpineAIO/wails/v2/pkg/menu" 7 "github.com/AlpineAIO/wails/v2/pkg/menu/keys" 8 ) 9 10 type ProcessedMenuItem struct { 11 ID string 12 // Label is what appears as the menu text 13 Label string `json:",omitempty"` 14 // Role is a predefined menu type 15 // Role menu.Role `json:",omitempty"` 16 // Accelerator holds a representation of a key binding 17 Accelerator *keys.Accelerator `json:",omitempty"` 18 // Type of MenuItem, EG: Checkbox, Text, Separator, Radio, Submenu 19 Type menu.Type 20 // Disabled makes the item unselectable 21 Disabled bool `json:",omitempty"` 22 // Hidden ensures that the item is not shown in the menu 23 Hidden bool `json:",omitempty"` 24 // Checked indicates if the item is selected (used by Checkbox and Radio types only) 25 Checked bool `json:",omitempty"` 26 // Submenu contains a list of menu items that will be shown as a submenu 27 // SubMenu []*MenuItem `json:"SubMenu,omitempty"` 28 SubMenu *ProcessedMenu `json:",omitempty"` 29 /* 30 // Colour 31 RGBA string `json:",omitempty"` 32 33 // Font 34 FontSize int `json:",omitempty"` 35 FontName string `json:",omitempty"` 36 37 // Image - base64 image data 38 Image string `json:",omitempty"` 39 MacTemplateImage bool `json:", omitempty"` 40 MacAlternate bool `json:", omitempty"` 41 42 // Tooltip 43 Tooltip string `json:",omitempty"` 44 45 // Styled label 46 StyledLabel []*ansi.StyledText `json:",omitempty"` 47 */ 48 } 49 50 func NewProcessedMenuItem(menuItemMap *MenuItemMap, menuItem *menu.MenuItem) *ProcessedMenuItem { 51 ID := menuItemMap.menuItemToIDMap[menuItem] 52 53 // Parse ANSI text 54 //var styledLabel []*ansi.StyledText 55 //tempLabel := menuItem.Label 56 //if strings.Contains(tempLabel, "\033[") { 57 // parsedLabel, err := ansi.Parse(menuItem.Label) 58 // if err == nil { 59 // styledLabel = parsedLabel 60 // } 61 //} 62 63 result := &ProcessedMenuItem{ 64 ID: ID, 65 Label: menuItem.Label, 66 // Role: menuItem.Role, 67 Accelerator: menuItem.Accelerator, 68 Type: menuItem.Type, 69 Disabled: menuItem.Disabled, 70 Hidden: menuItem.Hidden, 71 Checked: menuItem.Checked, 72 SubMenu: nil, 73 // BackgroundColour: menuItem.BackgroundColour, 74 // FontSize: menuItem.FontSize, 75 // FontName: menuItem.FontName, 76 // Image: menuItem.Image, 77 // MacTemplateImage: menuItem.MacTemplateImage, 78 // MacAlternate: menuItem.MacAlternate, 79 // Tooltip: menuItem.Tooltip, 80 // StyledLabel: styledLabel, 81 } 82 83 if menuItem.SubMenu != nil { 84 result.SubMenu = NewProcessedMenu(menuItemMap, menuItem.SubMenu) 85 } 86 87 return result 88 } 89 90 type ProcessedMenu struct { 91 Items []*ProcessedMenuItem 92 } 93 94 func NewProcessedMenu(menuItemMap *MenuItemMap, menu *menu.Menu) *ProcessedMenu { 95 result := &ProcessedMenu{} 96 if menu != nil { 97 for _, item := range menu.Items { 98 processedMenuItem := NewProcessedMenuItem(menuItemMap, item) 99 result.Items = append(result.Items, processedMenuItem) 100 } 101 } 102 103 return result 104 } 105 106 // WailsMenu is the original menu with the addition 107 // of radio groups extracted from the menu data 108 type WailsMenu struct { 109 Menu *ProcessedMenu 110 RadioGroups []*RadioGroup 111 currentRadioGroup []string 112 } 113 114 // RadioGroup holds all the members of the same radio group 115 type RadioGroup struct { 116 Members []string 117 Length int 118 } 119 120 func NewWailsMenu(menuItemMap *MenuItemMap, menu *menu.Menu) *WailsMenu { 121 result := &WailsMenu{} 122 123 // Process the menus 124 result.Menu = NewProcessedMenu(menuItemMap, menu) 125 126 // Process the radio groups 127 result.processRadioGroups() 128 129 return result 130 } 131 132 func (w *WailsMenu) AsJSON() (string, error) { 133 menuAsJSON, err := json.Marshal(w) 134 if err != nil { 135 return "", err 136 } 137 return string(menuAsJSON), nil 138 } 139 140 func (w *WailsMenu) processRadioGroups() { 141 // Loop over top level menus 142 for _, item := range w.Menu.Items { 143 // Process MenuItem 144 w.processMenuItem(item) 145 } 146 147 w.finaliseRadioGroup() 148 } 149 150 func (w *WailsMenu) processMenuItem(item *ProcessedMenuItem) { 151 switch item.Type { 152 153 // We need to recurse submenus 154 case menu.SubmenuType: 155 156 // Finalise any current radio groups as they don't trickle down to submenus 157 w.finaliseRadioGroup() 158 159 // Process each submenu item 160 for _, subitem := range item.SubMenu.Items { 161 w.processMenuItem(subitem) 162 } 163 case menu.RadioType: 164 // Add the item to the radio group 165 w.currentRadioGroup = append(w.currentRadioGroup, item.ID) 166 default: 167 w.finaliseRadioGroup() 168 } 169 } 170 171 func (w *WailsMenu) finaliseRadioGroup() { 172 // If we were processing a radio group, fix up the references 173 if len(w.currentRadioGroup) > 0 { 174 175 // Create new radiogroup 176 group := &RadioGroup{ 177 Members: w.currentRadioGroup, 178 Length: len(w.currentRadioGroup), 179 } 180 w.RadioGroups = append(w.RadioGroups, group) 181 182 // Empty the radio group 183 w.currentRadioGroup = []string{} 184 } 185 }