Files
templates/c/menu/README.md
Andrey Kruchinkin 1248a6551a feat(menu): экранное меню со стеком экранов и прокруткой
Перенесён из KONOR_ds18b20/lib/menu; в OpticalTester лежала такая же копия.

Содержимое экрана движок запрашивает обратными вызовами, поэтому один
экран описывает и статический список, и перечень датчиков переменной
длины. Рисует через Menu_Painter: от драйвера дисплея не зависит,
цвет передаётся как есть — подходит и RGB565, и монохром.
2026-08-23 01:15:12 +03:00

72 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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, и палитра монохромного индикатора:
```c
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);
```
## Быстрый старт
```c
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`](../st7789) и [`keypad`](../keypad).
Меню от них не зависит: связывает всё адаптер в приложении.