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  }