class BBS::Menubar
A horizontal strip at the top of the screen with named drop-down menus. Each menu has a label like &File (the letter after the & is the hotkey, so Alt-F opens it) and a list of MenuItem entries. F10 opens the first menu; the arrow keys, Enter, Esc, the item hotkeys and the mouse work inside an open one.
An Application fills it with its menu DSL (BBS::Application::MenubarBuilder#menu):
menubar do menu("&File") do item("&Open", shortcut: "F3") { |item| open_file } separator item("E&xit", shortcut: "Alt-X") { :halt } end end
The bar itself never takes the keyboard focus (focusable? is false); the application passes events to handle_event first.
Constants
- KEYS
-
The keys of an open menu and the method each one calls.
- Menu
-
One menu on the bar:
labelwith an optional&before the hotkey letter,itemsan Array ofMenuItem,xthe column it was last drawn at (nilbefore the first render). - MenuItem
-
One entry of a menu, built by the
Applicationmenu DSL:label(with an optional&before the hotkey letter),shortcut(text shown at the right edge, for display only),enabled(true,falseor a callable asked each time),on_select(the block called with the item when it is chosen),separator(a dividing line rather than an entry) andhint(a line about the entry that theApplicationshows on the statusbar while the entry is highlighted, ornil).
Attributes
A callable invoked with the MenuItem after any item is activated (after its own block), or nil.
Public Class Methods
Source
# File lib/bbs/menu.rb, line 42 def initialize(**kw) super @menus = [] @open_index = nil @item_index = 0 @on_activate = nil end
Creates an empty menu bar; kw (id, bounds, theme) go to Widget.new.
Public Instance Methods
Source
# File lib/bbs/menu.rb, line 74 def close @open_index = nil @item_index = 0 end
Closes the open menu, if any.
Source
# File lib/bbs/menu.rb, line 80 def focusable? = false
Returns false: the bar never takes the keyboard focus.
Source
# File lib/bbs/menu.rb, line 102 def handle_event(event) return press(event) if left_press?(event) return (open? ? :handled : nil) if event.mouse? return navigate(event.key) if open? open_by_key(event) end
Handles a keyboard or mouse event. Inside an open menu Left/Right switch menus, Up/Down move to the previous/next enabled item, Enter or an item’s hotkey letter activates it, Esc or F10 closes the menu, and a left click picks an item, switches menus or closes the menu when outside it. Otherwise F10 or an Alt-hotkey opens a menu and a left click on a label toggles it.
Activating an item closes the menu, calls its on_select block with the item, then on_activate. Returns :halt when the block returned :halt, :handled when the bar used the event, nil otherwise.
Source
# File lib/bbs/menu.rb, line 66 def open(index) return if @menus.empty? @open_index = index.clamp(0, @menus.size - 1) @item_index = opened_menu.items.find_index(&:enabled?) || 0 end
Drops down the menu at index (clamped to the existing menus) and highlights its first enabled item. Does nothing when there are no menus.
Source
# File lib/bbs/menu.rb, line 51 def open? = !@open_index.nil?
Returns whether a menu is dropped down.
Source
# File lib/bbs/menu.rb, line 85 def render(frame) frame.move(bounds.x, bounds.y) frame.write(' ' * bounds.width, sgr: style(:menubar)) @menus.each_with_index.reduce(bounds.x + 1) { |x, (menu, i)| render_label(frame, menu, i, x) } dropdown&.render(frame, @item_index) end
Draws the bar across its bounds into the BBS::FrameBuffer frame, with the hotkey letters highlighted, and the open menu’s drop-down box with its shadow under it. Records each menu’s column in Menu#x.
Source
# File lib/bbs/menu.rb, line 61 def selected_hint = open? ? selected_item&.hint : nil
Returns the hint of the highlighted item while a menu is open, or nil (no menu open, or the item has no hint).
Source
# File lib/bbs/menu.rb, line 57 def selected_item = opened_menu&.items&.[](@item_index)
Returns the highlighted MenuItem of the open menu, or nil.