Перенесён из KONOR_ds18b20/lib/menu; в OpticalTester лежала такая же копия. Содержимое экрана движок запрашивает обратными вызовами, поэтому один экран описывает и статический список, и перечень датчиков переменной длины. Рисует через Menu_Painter: от драйвера дисплея не зависит, цвет передаётся как есть — подходит и RGB565, и монохром.
menu
Экранное меню для дисплея и шести кнопок навигации.
Движок хранит стек открытых экранов, курсор и окно прокрутки, а содержимое запрашивает у приложения обратными вызовами: так один и тот же экран описывает и статический список, и перечень датчиков, число которых меняется на ходу.
Рисует движок через таблицу Menu_Painter, поэтому от драйвера дисплея он не
зависит: для ST7789V адаптер занимает несколько строк, для знакосинтезирующего
ЖКИ или SSD1306 — столько же.
приложение
count/text/enter/adjust ← чем наполнен экран
│
menu.c стек экранов, курсор, прокрутка, перерисовка
│
Menu_Painter fill_rect, draw_text
│
драйвер дисплея
Состав
| Файл | Что делает | Зависимости |
|---|---|---|
menu.h, menu.c |
стек экранов до 4 уровней, курсор, прокрутка, тема оформления, строка состояния | stdint.h |
Вспомогательное: Menu_TextCopy() и Menu_TextInt() — форматирование строк
пунктов без snprintf. Menu_GetSnapshot() отдаёт состояние без отрисовки,
что удобно для хостовых тестов.
Что нужно от платформы
Только два вызова отрисовки — цвет передаётся как есть, поэтому в него укладывается и RGB565, и палитра монохромного индикатора:
void fill_rect(void *ctx, int16_t x, int16_t y, uint16_t w, uint16_t h, uint32_t color);
void draw_text(void *ctx, int16_t x, int16_t y, const char *text,
uint32_t color, uint32_t background, uint8_t scale);
Быстрый старт
static const Menu_Screen screen_root = {
.title = "Главное меню",
.count = root_count, /* сколько пунктов сейчас */
.text = root_text, /* текст пункта по индексу */
.enter = root_enter, /* вернуть вложенный экран или 0 */
.context = &app,
};
Menu menu;
Menu_Theme theme;
Menu_ThemeDefault(&theme);
Menu_Init(&menu, &painter, &theme, &screen_root);
Menu_HandleKey(&menu, MENU_KEY_DOWN);
Menu_Render(&menu, 0); /* перерисует только если что-то изменилось */
Данные, меняющиеся сами по себе (температура, состояние связи), обновляются
вызовом Menu_Invalidate() — движок перерисует экран на ближайшем Menu_Render().
Проверено в проектах
KONOR_ds18b20, OpticalTester — поверх st7789 и keypad.
Меню от них не зависит: связывает всё адаптер в приложении.