Menu System
This module wraps libDaisy's menu system for building hierarchical UI menus on small displays. It provides AbstractMenu as a base class and FullScreenItemMenu as a ready-to-use implementation for full-screen menus.
Features:
- Multiple menu item types (value, checkbox, callback, submenu, close)
- Custom item support for specialized rendering
- Flexible control schemes (buttons, encoders, potentiometers)
- Orientation control (horizontal/vertical navigation)
- Edit mode with step size control
- MappedValue system for parameterized editing
Wrapped Headers: ui/AbstractMenu.h, ui/FullScreenItemMenu.h, util/MappedValue.h
Example - Simple menu with callback:
import nimphea_menu import nimphea_ui_events proc onActionTriggered(ctx: pointer) {.cdecl.} = echo "Action triggered!" var items = [ createCallbackItem("Do Something", onActionTriggered, nil), createCloseItem("Close Menu") ] var menu: FullScreenItemMenu menu.init(items[0].addr, 2)
Example - Value editing menu:
var volume = createMappedFloatValue(0.0, 1.0, 0.5, lin, "dB", 2) var isMuted = false var items = [ createValueItem("Volume", addr volume), createCheckboxItem("Mute", addr isMuted) ] var menu: FullScreenItemMenu menu.init(items[0].addr, 2, leftRightSelectUpDownModify, true)
Example - Hierarchical menu:
var settingsPage: FullScreenItemMenu # ... configure settingsPage items ... var mainItems = [ createOpenPageItem("Settings", addr settingsPage), createCloseItem("Exit") ]Menu orientation - controls which buttons navigate vs modifyMenu item type enumerationArrow button type (from UI.h)Canvas descriptor for UI drawingBase class for UI pagesMapping function type for float valuesBase class for mapped values (abstract)Float value with mapping functionMenu item configuration (union type)Base class for custom menu itemsAbstract base class for menu pagesFull-screen menu implementation for small displays
Types
AbstractMenu {.importcpp: "daisy::AbstractMenu", header: "ui/AbstractMenu.h".} = object of UiPage
- Source Edit
ArrowButtonType {.importcpp: "daisy::ArrowButtonType", size: 4.} = enum left = 0, ## Right arrow button right, ## Up arrow button up, ## Down arrow button down
- Left arrow button Source Edit
CustomMenuItem {.importcpp: "daisy::AbstractMenu::CustomItem", header: "ui/AbstractMenu.h".} = object
- Source Edit
FullScreenItemMenu {.importcpp: "daisy::FullScreenItemMenu", header: "ui/FullScreenItemMenu.h".} = object of AbstractMenu
- Source Edit
MappedFloatValue {.importcpp: "daisy::MappedFloatValue", header: "util/MappedValue.h".} = object of MappedValue
- Source Edit
MappedValue {.importcpp: "daisy::MappedValue", header: "util/MappedValue.h", inheritable.} = object
- Source Edit
MappedValueMapping {.importcpp: "daisy::MappedFloatValue::Mapping", size: 4.} = enum lin, ## Logarithmic mapping (min/max/default must be > 0) log, ## Power-of-2 mapping pow2
- Linear mapping Source Edit
MenuItemConfig {.importcpp: "daisy::AbstractMenu::ItemConfig", bycopy.} = object text* {.importc.}: cstring
- Item type Source Edit
MenuItemType {.importcpp: "daisy::AbstractMenu::ItemType", size: 4.} = enum callbackFunctionItem, ## Displays checkbox, toggles boolean value checkboxItem, ## Displays name and editable value (MappedValue) valueItem, ## Opens another UiPage (submenu) openUiPageItem, ## Closes the menu when selected closeMenuItem, ## Custom user-defined item customItem
- Displays text and calls callback when activated Source Edit
MenuOrientation {.importcpp: "daisy::AbstractMenu::Orientation", size: 4.} = enum leftRightSelectUpDownModify, ## Up/Down buttons select items, Left/Right modify values upDownSelectLeftRightModify
- Left/Right buttons select items, Up/Down modify values Source Edit
UiCanvasDescriptor {.importcpp: "daisy::UiCanvasDescriptor", header: "ui/UI.h", bycopy.} = object id* {.importc: "id_".}: uint8 ## Pointer to canvas handle (display object) handle* {.importc: "handle_".}: pointer ## Update rate in milliseconds updateRateMs* {.importc: "updateRateMs_".}: uint32 ## Screen saver timeout (0 = disabled) screenSaverTimeOut* {.importc.}: uint32 ## Screen saver active flag screenSaverOn* {.importc.}: bool
- Canvas ID number Source Edit
Procs
proc createCallbackItem(text: cstring; callback: proc (ctx: pointer) {.cdecl.}; context: pointer = nil): MenuItemConfig {.importcpp: """ [&]() { daisy::AbstractMenu::ItemConfig item; item.type = daisy::AbstractMenu::ItemType::callbackFunctionItem; item.text = #; item.asCallbackFunctionItem.callbackFunction = #; item.asCallbackFunctionItem.context = #; return item; }() """, header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Create a callback function menu item Source Edit
proc createCheckboxItem(text: cstring; valuePtr: ptr bool): MenuItemConfig {.importcpp: """ [&]() { daisy::AbstractMenu::ItemConfig item; item.type = daisy::AbstractMenu::ItemType::checkboxItem; item.text = #; item.asCheckboxItem.valueToModify = #; return item; }() """, header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Create a checkbox menu item Source Edit
proc createCloseItem(text: cstring): MenuItemConfig {.importcpp: """ [&]() { daisy::AbstractMenu::ItemConfig item; item.type = daisy::AbstractMenu::ItemType::closeMenuItem; item.text = #; return item; }() """, header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Create a menu close item Source Edit
proc createMappedFloatValue(minVal, maxVal, defaultVal: float; mapping: MappedValueMapping = lin; unitStr: string = ""; numDecimals: int = 1; forceSign: bool = false): MappedFloatValue {. header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Create a MappedFloatValue with Nim-friendly types Source Edit
proc createOpenPageItem(text: cstring; pagePtr: UiPagePtr): MenuItemConfig {.importcpp: """ [&]() { daisy::AbstractMenu::ItemConfig item; item.type = daisy::AbstractMenu::ItemType::openUiPageItem; item.text = #; item.asOpenUiPageItem.pageToOpen = #; return item; }() """, header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Create a submenu/page opening item Source Edit
proc createValueItem(text: cstring; valuePtr: ptr MappedValue): MenuItemConfig {.importcpp: """ [&]() { daisy::AbstractMenu::ItemConfig item; item.type = daisy::AbstractMenu::ItemType::valueItem; item.text = #; item.asMappedValueItem.valueToModify = #; return item; }() """, header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Create a value editing menu item Source Edit
proc createValueItemFloat(text: string; valuePtr: ptr MappedFloatValue): MenuItemConfig {. ...raises: [], tags: [], forbids: [].}
- Nim-friendly wrapper for creating float value items Source Edit
proc draw(this: var FullScreenItemMenu; canvas: UiCanvasDescriptor) {. importcpp: "#.Draw(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Draw menu to canvas (called by UI system) Source Edit
proc get(this: var MappedFloatValue): cfloat {.importcpp: "#.Get()", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Get current value Source Edit
proc getAs0to1(this: var MappedFloatValue): cfloat {.importcpp: "#.GetAs0to1()", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Get normalized value (0.0-1.0) Source Edit
proc getItem(this: var AbstractMenu; itemIdx: uint16): MenuItemConfig {. importcpp: "#.GetItem(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Get item configuration by index Source Edit
proc getNumItems(this: var AbstractMenu): uint16 {.importcpp: "#.GetNumItems()", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Get total number of items in menu Source Edit
proc getSelectedItemIdx(this: var AbstractMenu): int16 {. importcpp: "#.GetSelectedItemIdx()", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Get currently selected item index (-1 if none) Source Edit
proc init(this: var FullScreenItemMenu; items: ptr MenuItemConfig; numItems: uint16; orientation: MenuOrientation = leftRightSelectUpDownModify; allowEntering: bool = true) {.importcpp: "#.Init(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
-
Initialize menu with items array
Parameters:
- items - Array of MenuItemConfig
- numItems - Number of items in array
- orientation - Button mapping (select vs modify)
- allowEntering - Allow OK button to enter edit mode
proc initFullScreenMenu(items: var openArray[MenuItemConfig]; orientation: MenuOrientation = leftRightSelectUpDownModify; allowEntering: bool = true): FullScreenItemMenu {. ...raises: [], tags: [], forbids: [].}
- Create and initialize a full-screen menu from array Source Edit
proc initMappedFloatValue(minVal, maxVal, defaultVal: cfloat; mapping: MappedValueMapping = lin; unitStr: cstring = ""; numDecimals: uint8 = 1; forceSign: bool = false): MappedFloatValue {. importcpp: "daisy::MappedFloatValue(@)", constructor, header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Source Edit
proc onArrowButton(this: var AbstractMenu; arrowType: ArrowButtonType; numPresses: uint8; isRetriggering: bool): bool {. importcpp: "#.OnArrowButton(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Handle arrow button press Source Edit
proc onCancelButton(this: var AbstractMenu; numPresses: uint8; isRetriggering: bool): bool {. importcpp: "#.OnCancelButton(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Handle cancel button press Source Edit
proc onFunctionButton(this: var AbstractMenu; numPresses: uint8; isRetriggering: bool): bool {. importcpp: "#.OnFunctionButton(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Handle function button press (for coarse stepping) Source Edit
proc onMenuEncoderTurned(this: var AbstractMenu; turns: int16; stepsPerRev: uint16): bool {. importcpp: "#.OnMenuEncoderTurned(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Handle menu encoder rotation Source Edit
proc onOkayButton(this: var AbstractMenu; numPresses: uint8; isRetriggering: bool): bool {.importcpp: "#.OnOkayButton(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Handle OK button press Source Edit
proc onShow(this: var AbstractMenu) {.importcpp: "#.OnShow()", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Called when page is shown Source Edit
proc onValueEncoderTurned(this: var AbstractMenu; turns: int16; stepsPerRev: uint16): bool {. importcpp: "#.OnValueEncoderTurned(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Handle value encoder rotation Source Edit
proc onValuePotMoved(this: var AbstractMenu; newPosition: cfloat): bool {. importcpp: "#.OnValuePotMoved(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Handle value potentiometer movement Source Edit
proc resetToDefault(this: var MappedFloatValue) {. importcpp: "#.ResetToDefault()", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Reset to default value Source Edit
proc selectItem(this: var AbstractMenu; itemIdx: uint16) {. importcpp: "#.SelectItem(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Select a specific item by index Source Edit
proc set(this: var MappedFloatValue; newValue: cfloat) {.importcpp: "#.Set(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Set value (clamped to valid range) Source Edit
proc setFrom0to1(this: var MappedFloatValue; normalizedValue: cfloat) {. importcpp: "#.SetFrom0to1(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Set from normalized value (0.0-1.0) Source Edit
proc setOneBitGraphicsDisplayToDrawTo(this: var FullScreenItemMenu; canvasId: uint16) {. importcpp: "#.SetOneBitGraphicsDisplayToDrawTo(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Set which canvas this menu draws to (default: primary display) Source Edit
proc step(this: var MappedFloatValue; numStepsUp: int16; useCoarseStep: bool) {. importcpp: "#.Step(@)", header: "ui/AbstractMenu.h", ...raises: [], tags: [], forbids: [].}
- Step value up/down by increments Source Edit