You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
toaster-oven-bluepill/Core/Src/Gui/screen_menu.c

97 lines
3.1 KiB

//
// Created by MightyPork on 2023/04/09.
//
#include <stdbool.h>
#include "screen_menu.h"
#include "app_gui.h"
#include "FreeRTOS.h"
#include "task.h"
#include "ufb/utf8.h"
#include "ufb/framebuffer_config.h"
#include "ufb/framebuffer.h"
#include "ufb/fb_text.h"
void screen_menu(GuiEvent event, const char **options, menu_callback_t cb) {
bool menu_changed = false;
const uint32_t tickNow = xTaskGetTickCount();
struct menu_state *menu = &s_app.page.menu;
switch (event) {
case GUI_EVENT_SCREEN_INIT:
menu->pos = 0;
menu->len = 0;
menu->change_time = tickNow;
menu->text_slide = 0;
const char **opt = options;
while (*opt) {
menu->len++;
opt++;
}
break;
case GUI_EVENT_SCREEN_TICK:
// long text sliding animation
if (tickNow - menu->change_time >= pdMS_TO_TICKS(500)) {
const uint32_t textlen = utf8_strlen(options[menu->pos]) * 6;
if (textlen >= FBW - 2) {
if (textlen - menu->text_slide > FBW - 1) {
menu->text_slide += 1;
if (textlen - menu->text_slide >= FBW - 1) {
menu->slide_end_time = tickNow;
}
} else if (tickNow - menu->slide_end_time >= pdMS_TO_TICKS(500)) {
menu->change_time = tickNow;
menu->slide_end_time = 0;
menu->text_slide = 0;
}
request_paint();
}
}
break;
case GUI_EVENT_PAINT:
for (int i = 0; i < menu->len; i++) {
// is the row currently rendered the selected row?
const bool is_selected = menu->pos == i;
const fbcolor_t color = !is_selected; // text color - black if selected, because it's inverted
const fbpos_t y = 27 + i * 10;
fb_rect(0, y, FBW, 10, !color);
fb_text(1 - (is_selected ? menu->text_slide : 0), y + 1, options[i], FONT_5X7, color);
// ensure the text doesn't touch the edge (looks ugly)
fb_vline(FBW - 1, y, 10, !color);
fb_vline(0, y, 10, !color);
}
break;
// the button is held! release is what activates the button
case GUI_EVENT_KNOB_RELEASE:
input_sound_effect();
cb(menu->pos);
break;
case GUI_EVENT_KNOB_PLUS:
if (menu->pos < menu->len - 1) {
menu->pos++;
menu_changed = true;
}
break;
case GUI_EVENT_KNOB_MINUS:
if (menu->pos > 0) {
menu->pos--;
menu_changed = true;
}
break;
}
if (menu_changed) {
menu->change_time = tickNow;
menu->text_slide = 0;
menu->slide_end_time = 0;
input_sound_effect();
request_paint();
}
}