Перенесён из KONOR_ds18b20/lib/menu; в OpticalTester лежала такая же копия. Содержимое экрана движок запрашивает обратными вызовами, поэтому один экран описывает и статический список, и перечень датчиков переменной длины. Рисует через Menu_Painter: от драйвера дисплея не зависит, цвет передаётся как есть — подходит и RGB565, и монохром.
72 lines
3.3 KiB
Markdown
72 lines
3.3 KiB
Markdown
# 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).
|
|
Меню от них не зависит: связывает всё адаптер в приложении.
|