Menus Revisited
August 9, 2025
Now that we have a little framework for handling arguments, and have used it for our <input>
components, we should probably redesign the Menu
component. Let's get rid of the current Add
function:
Add←{
m←⍺
9=⎕NC'⍵':m AddSubmenu ⍵
v←⍵,(≢⍵)↓'' '' '' 0 1 0
cm←(5⊃v)/⎕UCS 10004
c←A.New¨{'span'⍵}¨cm(0⊃v)(1⊃v)''
i←m A.New'li'(A.New'div'c)
i.(Label Shortcut Function Separator Active Checked)←v
i.Function←1 A.FQP i.Function
i.Type←'Item'
i.tabindex←'0'
i.Selected←i=⊃m.Content
i.class←i.Selected/'sel-item'
i.class,←(~i.Active)/' inactive'
i.class,←i.Separator/' separator'
i
}
This function adds a menu item or a (sub)menu to a menu. Instead, let's just have an AddItem
function to add a menu item, essentially creating a MenuItem
component but keeping it all under the Menu
namespace:
NewItem←{
i←(⍺ A.New'li')⎕NS(
'Label' ''
'Shortcut' ''
'Function' ''
'Separator' 0
'Active' 1
'Checked' 0
)A.InitProps ⍵
cm←i.Checked/⎕UCS 10004
c←A.New¨{'span'⍵}¨cm i.Label i.Shortcut''
i.Content←A.New'div'c
i.Function←1 A.FQP i.Function
i.Type←'Item'
i.tabindex←'0'
i.Selected←i=⊃⍺.Content
i.class←i.Selected/'sel-item'
i.class,←(~i.Active)/' inactive'
i.class,←i.Separator/' separator'
i
}
Much nicer! Clearer to read and see the defaults, much more flexible to call. The Menu.New
function can take over adding a (sub)menu to a menu:
New←{
⍺←0
m←(A.New'menu')⎕NS(
'Label' ''
'Separator' 0
)A.InitProps ⍵
m.Content←m.Label
m.class←'menu'
m.popover←'auto'
m.Toggled←0
0=⍺:m ⍝ Top Level menu
b←'>'
c←A.New¨{'span'⍵}¨''(m.Content)''(⊂⊂b)
i←⍺ A.New'li'(A.New'div'(c,m))
i.Type←'Menu'
i.tabindex←0
i.class←m.Separator/'separator'
i.Selected←0
m.Content←''
m
}
~~~
Now we can build a menu like so:
BuildMenu←{
NewMenu←A.Menu.New
NewItem←A.Menu.NewItem
m←NewMenu''
s←m NewMenu⊂'File'
i←s NewItem'Open' 'Ctrl+O' 'OnFileOpen'
i←s NewItem'Save' 'Ctrl+S' 'OnFileSave'
i←s NewItem'Save As...' 'Ctrl+A' 'OnFileSaveAs'
s←m NewMenu⊂'Edit'
i←s NewItem'Cut' 'Ctrl+X' 'OnCut'
i←s NewItem'Copy' 'Ctrl+C' 'OnCopy'
i←s NewItem'Paste' 'Ctrl+V' 'OnPaste'
s←m NewMenu⊂'View'
i←s NewItem'List' 'Ctrl+Q' 'OnViewList'
s2←s NewMenu⊂'Icons'
i←s2 NewItem'Small' 'Ctrl+L' 'OnViewLarge'
i←s2 NewItem'Medium' 'Ctrl+M' 'OnViewMedium' ('Checked' 1)
i←s2 NewItem'Large' 'Ctrl+S' 'OnViewSmall' ('Active' 0)
m
}