Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/The-Young-Maker/OpenMenuOS/llms.txt

Use this file to discover all available pages before exploring further.

Every user interface in OpenMenuOS is built from screens. A screen is the fundamental unit of display: it knows how to draw itself and how to respond to user input. OpenMenuOS ships three concrete screen types, each suited to a different purpose, all of which inherit from the abstract Screen base class. The ScreenManager keeps track of which screen is active and maintains a history stack so users can navigate forward and back through the interface.

The Screen base class

All screen types derive from Screen, which defines two pure-virtual methods every subclass must implement:
  • draw() — renders the screen onto the TFT canvas
  • handleInput() — processes button or encoder events for the current frame
The base class also provides shared utilities such as scrollbar drawing and horizontal text scrolling, and exposes the global ScreenConfig& config that controls appearance across the entire menu system.
Screen is abstract and cannot be instantiated directly. Always use one of the three concrete subclasses.

The three screen types

MenuScreen

A scrollable list of labelled items. Each item can link to another screen, trigger a callback, or display an icon. Use this as the primary navigation surface.

SettingsScreen

A structured list of configurable settings — boolean toggles, numeric ranges, option lists, and links to sub-screens. Values are automatically persisted to EEPROM or Preferences.

CustomScreen

A blank canvas with a customDraw function pointer. Assign any std::function<void()> to draw arbitrary graphics, sensor readouts, or status pages.

MenuScreen is the workhorse of most interfaces. It renders a vertically scrollable list and handles navigation to linked screens or invokes an ActionCallback when the user selects an item.
// With an explicit title
MenuScreen mainMenu("Main Menu");

// Without a title (title defaults to "Untitled Screen")
MenuScreen mainMenu;
Add items with addItem(). The overload that accepts a Screen* without a label uses the target screen’s own title automatically:
// Label + linked screen
mainMenu.addItem("Settings", &settingsScreen);

// Label + callback action
mainMenu.addItem("About", nullptr, showAbout);

// Label + screen + icon image
mainMenu.addItem("Settings", &settingsScreen, nullptr, (const uint16_t *)Menu_icon_1);

// Auto-use the target screen's title as the label
mainMenu.addItem(&testScreen);

SettingsScreen

SettingsScreen presents typed settings and persists their values automatically. Each setting is added via a dedicated helper method.
// With an explicit title
SettingsScreen settingsScreen("Settings");

// Without a title
SettingsScreen settingsScreen;
settingsScreen.addBooleanSetting("Animations", true);
settingsScreen.addRangeSetting("Brightness", 0, 100, 75, "%");

const char *themes[] = {"Dark", "Light", "Auto"};
settingsScreen.addOptionSetting("Theme", themes, 3, 0);

settingsScreen.addSubscreenSetting("Speaker Settings", &speakerScreen);
SettingsScreen enforces a maximum of MAX_ITEMS = 10 settings per screen. Use addSubscreenSetting() to link to a secondary SettingsScreen when you need more.

CustomScreen

CustomScreen gives you complete control over what is drawn. Assign a lambda or function to customDraw; it is called every time the screen needs to render.
CustomScreen aboutScreen("About");

aboutScreen.customDraw = []() {
    canvas.fillScreen(TFT_BLACK);
    canvas.setTextColor(TFT_WHITE);
    canvas.drawString("OpenMenuOS v3.1.0", 10, 30);
    canvas.drawString("Press SELECT to return", 10, 60);
};
Drawing is performed on the global canvas sprite (a TFT_eSprite), which is then flushed to the display by the library after draw() returns.

ScreenManager

The ScreenManager class owns the navigation stack. You typically do not interact with it directly — OpenMenuOS wraps its interface — but understanding it helps when using redirectToScreen() and navigateBack().
// Navigate forward (push onto stack)
menu.redirectToScreen(&myScreen);

// Navigate backward (pop from stack)
menu.navigateBack();
Internally, pushScreen() saves the currently active screen to screenHistory before activating the new one, and popScreen() restores it. The global currentScreen pointer always points to the active screen.
// ScreenManager's key methods (used internally):
void pushScreen(Screen *newScreen);   // forward navigation
bool popScreen();                     // back navigation
bool canGoBack() const;               // returns false at root
size_t getDepth() const;              // history stack depth
Use canGoBack() to conditionally show a “back” button or indicator in a CustomScreen.

Choosing the right screen type

ScenarioScreen type
Top-level navigation hubMenuScreen
Sub-menu or category listMenuScreen
User-configurable optionsSettingsScreen
Dashboard, sensor readout, or about pageCustomScreen
Any screen requiring free-form graphicsCustomScreen

Build docs developers (and LLMs) love