NCInput demo
NCInput is a C++ input helper for gint apps. It gives you ready-made dialogs for text input, number input, lists, date pickers, time pickers, and confirmations.
This tutorial is based on the NCInput demo app.
Step 1: Include gint and NCInput
Section titled “Step 1: Include gint and NCInput”The demo uses gint for drawing and events, then includes the NCInput headers:
#include <gint/display.h>#include <gint/keyboard.h>#include <gint/rtc.h>#include <gint/clock.h>#include <string>#include <vector>#include <cstdio>#include "cinput.hpp"#include "cdateinput.hpp"cinput.hpp provides menus, text input, numeric input, list picking, and confirmations. cdateinput.hpp provides date and time pickers.
Step 2: Draw a simple shell
Section titled “Step 2: Draw a simple shell”The demo has a header bar and a menu icon:
void draw_header(const std::string& theme_name, const std::string& title = "Demo App") { const Theme& t = get_theme(theme_name); drect(0, 0, SCREEN_W, HEADER_H, t.accent); dtext_opt(SCREEN_W/2, HEADER_H/2, t.txt_acc, (int)C_NONE, DTEXT_CENTER, DTEXT_MIDDLE, title.c_str(), -1);}The rest of the screen tells the user to tap the menu or press MENU.
Step 3: Track theme and layout
Section titled “Step 3: Track theme and layout”NCInput supports different themes and keyboard layouts:
std::vector<std::string> themes = {"light", "dark", "grey"};std::vector<std::string> layouts = {"qwerty", "azerty", "qwertz", "abc"};
int curr_theme_idx = 0;int curr_layout_idx = 0;The demo lets the user switch these from the menu.
Step 4: Open the menu
Section titled “Step 4: Open the menu”The menu opens when the user presses EXE or taps the header icon:
if (keypressed(KEY_EXE)) { open_menu = true;}For touch, the demo reads events with pollevent() and checks the touch coordinates.
Step 5: Show a picker
Section titled “Step 5: Show a picker”The main menu is a call to pick():
PickResult choice_res = pick(opts, "App Menu", current_theme_name);If the picker succeeds, choice_res.values[0] is the selected item.
Step 6: Use text and number inputs
Section titled “Step 6: Use text and number inputs”Text input:
InputResult res = input("Enter text:", "text", current_theme_name, current_layout_name);Integer input:
InputResult res = input("Enter Integer:", "numeric_int negative", current_theme_name);Float input:
InputResult res = input("Enter Float:", "numeric_float", current_theme_name);Step 7: Use date and time pickers
Section titled “Step 7: Use date and time pickers”Date picker:
cdateinput::Date* res = cdateinput::datepick("Select Date", 2026, 5, 15, current_theme_name);Time picker:
cdateinput::Time* res = cdateinput::timepick("Select Time", 12, 30, current_theme_name);The demo deletes the returned pointer after using it.
Step 8: Use confirmations
Section titled “Step 8: Use confirmations”Confirmations return a boolean:
bool res = ask("Confirmation", "Are you sure?", "Yes", "No", current_theme_name);This is useful for delete actions, saving changes, or leaving a screen.
Final Code
Section titled “Final Code”This is the demo entry point. It expects the NCInput shared files to be part of your project.
#include <gint/display.h>#include <gint/keyboard.h>#include <gint/rtc.h>#include <gint/clock.h>#include <string>#include <vector>#include <cstdio>#include "cinput.hpp"#include "cdateinput.hpp"
using namespace cinput;
const int HEADER_H = 40;
void draw_header(const std::string& theme_name, const std::string& title = "Demo App") { const Theme& t = get_theme(theme_name); drect(0, 0, SCREEN_W, HEADER_H, t.accent); dtext_opt(SCREEN_W/2, HEADER_H/2, t.txt_acc, (int)C_NONE, DTEXT_CENTER, DTEXT_MIDDLE, title.c_str(), -1);
color_t col = t.txt_acc; int x = 10, y = 10; for (int i = 0; i < 3; ++i) { drect(x, y + 4 + i*5, x + 18, y + 5 + i*5, col); }}
#if defined(SIMULATOR_NATIVE) || defined(SIMULATOR_WEB)extern "C" void simulator_init();#endif
int main() {#if defined(SIMULATOR_NATIVE) || defined(SIMULATOR_WEB) simulator_init();#endif
std::vector<std::string> themes = {"light", "dark", "grey"}; std::vector<std::string> layouts = {"qwerty", "azerty", "qwertz", "abc"};
int curr_theme_idx = 0; int curr_layout_idx = 0;
bool running = true; bool touch_latched = false;
while (running) { std::string current_theme_name = themes[curr_theme_idx]; std::string current_layout_name = layouts[curr_layout_idx]; const Theme& t = get_theme(current_theme_name);
dclear(t.modal_bg); draw_header(current_theme_name);
const char* msg = "Tap Menu or press [EXE]"; dtext_opt(SCREEN_W/2, SCREEN_H/2, t.txt, (int)C_NONE, DTEXT_CENTER, DTEXT_MIDDLE, msg, -1); std::string theme_msg = "Theme: " + current_theme_name; dtext_opt(SCREEN_W/2, SCREEN_H/2 + 20, t.key_spec, (int)C_NONE, DTEXT_CENTER, DTEXT_MIDDLE, theme_msg.c_str(), -1);
dupdate();
cleareventflips();
bool open_menu = false;
if (keypressed(KEY_EXE)) { open_menu = true; } if (keypressed(KEY_EXIT)) { running = false; }
key_event_t e = pollevent(); std::vector<key_event_t> events; while (e.type != KEYEV_NONE) { events.push_back(e); e = pollevent(); }
for (const auto& ev : events) { if (ev.type == KEYEV_TOUCH_UP) { touch_latched = false; } else if (ev.type == KEYEV_TOUCH_DOWN && !touch_latched) { touch_latched = true; if (ev.y < HEADER_H && ev.x < 50) { open_menu = true; } } }
if (open_menu) { cleareventflips(); std::vector<std::string> opts = { "Text Input Demo", "Integer Input Demo", "Float Input Demo", "List Picker Demo", "Date Picker Demo", "Time Picker Demo", "French Date Picker", "Confirmation Demo", "Switch Theme (" + themes[(curr_theme_idx+1)%themes.size()] + ")", "Switch Layout (" + layouts[(curr_layout_idx+1)%layouts.size()] + ")", "Quit" };
PickResult choice_res = pick(opts, "App Menu", current_theme_name);
if (choice_res.success && !choice_res.values.empty()) { std::string choice = choice_res.values[0];
if (choice == "Quit") { running = false; } else if (choice.find("Switch Theme") != std::string::npos) { curr_theme_idx = (curr_theme_idx + 1) % themes.size(); } else if (choice.find("Switch Layout") != std::string::npos) { curr_layout_idx = (curr_layout_idx + 1) % layouts.size(); } else if (choice == "Text Input Demo") { InputResult res = input("Enter text (" + current_layout_name + "):", "text", current_theme_name, current_layout_name); if (res.success) { dclear(t.modal_bg); std::string typed = "You typed: " + res.value; dtext_opt(SCREEN_W/2, SCREEN_H/2, t.txt, (int)C_NONE, DTEXT_CENTER, DTEXT_MIDDLE, typed.c_str(), -1); dupdate(); sleep_ms(2000); } } else if (choice == "Integer Input Demo") { InputResult res = input("Enter Integer:", "numeric_int negative", current_theme_name); if (res.success) { dclear(t.modal_bg); std::string val = "Value: " + res.value; dtext_opt(SCREEN_W/2, SCREEN_H/2, t.txt, (int)C_NONE, DTEXT_CENTER, DTEXT_MIDDLE, val.c_str(), -1); dupdate(); sleep_ms(2000); } } else if (choice == "Float Input Demo") { InputResult res = input("Enter Float:", "numeric_float", current_theme_name); if (res.success) { dclear(t.modal_bg); std::string val = "Value: " + res.value; dtext_opt(SCREEN_W/2, SCREEN_H/2, t.txt, (int)C_NONE, DTEXT_CENTER, DTEXT_MIDDLE, val.c_str(), -1); dupdate(); sleep_ms(2000); } } else if (choice == "List Picker Demo") { std::vector<std::string> demo_opts; for (int i = 1; i <= 20; ++i) demo_opts.push_back("Item " + std::to_string(i)); PickResult res = pick(demo_opts, "Multi Select Demo", current_theme_name, true); if (res.success) { dclear(t.modal_bg); std::string res_str = "Selected: "; for (size_t i = 0; i < res.values.size(); ++i) { res_str += res.values[i] + (i == res.values.size() - 1 ? "" : ", "); } dtext_opt(10, SCREEN_H/2, t.txt, (int)C_NONE, DTEXT_LEFT, DTEXT_MIDDLE, res_str.c_str(), SCREEN_W-20); dupdate(); sleep_ms(2000); } } else if (choice == "Date Picker Demo") { cdateinput::Date* res = cdateinput::datepick("Select Date", 2026, 5, 15, current_theme_name); if (res) { dclear(t.modal_bg); char buf[64]; sprintf(buf, "Selected: %04d-%02d-%02d", res->year, res->month, res->day); dtext_opt(SCREEN_W/2, SCREEN_H/2, t.txt, (int)C_NONE, DTEXT_CENTER, DTEXT_MIDDLE, buf, -1); dupdate(); delete res; sleep_ms(2000); } } else if (choice == "Time Picker Demo") { cdateinput::Time* res = cdateinput::timepick("Select Time", 12, 30, current_theme_name); if (res) { dclear(t.modal_bg); char buf[64]; sprintf(buf, "Selected: %02d:%02d", res->hour, res->minute); dtext_opt(SCREEN_W/2, SCREEN_H/2, t.txt, (int)C_NONE, DTEXT_CENTER, DTEXT_MIDDLE, buf, -1); dupdate(); delete res; sleep_ms(2000); } } else if (choice == "Confirmation Demo") { bool res = ask("Confirmation", "Are you sure?", "Yes", "No", current_theme_name); dclear(t.modal_bg); const char* res_txt = res ? "You clicked Yes" : "You clicked No"; dtext_opt(SCREEN_W/2, SCREEN_H/2, t.txt, (int)C_NONE, DTEXT_CENTER, DTEXT_MIDDLE, res_txt, -1); dupdate(); sleep_ms(2000); } } }
sleep_ms(10); }
return 0;}