feat(menu): экранное меню со стеком экранов и прокруткой
Перенесён из KONOR_ds18b20/lib/menu; в OpticalTester лежала такая же копия. Содержимое экрана движок запрашивает обратными вызовами, поэтому один экран описывает и статический список, и перечень датчиков переменной длины. Рисует через Menu_Painter: от драйвера дисплея не зависит, цвет передаётся как есть — подходит и RGB565, и монохром.
This commit is contained in:
71
c/menu/README.md
Normal file
71
c/menu/README.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# 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).
|
||||
Меню от них не зависит: связывает всё адаптер в приложении.
|
||||
Reference in New Issue
Block a user