nimphea/nimphea_menu

Search:
Group by:
Source   Edit  

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  
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  
UiPage {.importcpp: "daisy::UiPage", header: "ui/UI.h", inheritable.} = object
Source   Edit  
UiPagePtr = ptr UiPage
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
Source   Edit  
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