More menu work
This commit is contained in:
@@ -16,8 +16,8 @@ extern lv_font_t roboto_bold_large_font;
|
|||||||
extern lv_font_t runescape_font;
|
extern lv_font_t runescape_font;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint16_t draw_character(pixel_t *framebuffer, const lv_font_t *font, const uint16_t x_loc, const uint16_t y_loc, const char character, pixel_t color);
|
uint16_t draw_character(volatile pixel_t *const framebuffer, const lv_font_t *font, const uint16_t x_loc, const uint16_t y_loc, const char character, pixel_t color);
|
||||||
|
|
||||||
void draw_string(pixel_t *framebuffer, const lv_font_t *font, const uint16_t x_loc, const uint16_t y_loc, const char *string, pixel_t color);
|
void draw_string(volatile pixel_t *const framebuffer, const lv_font_t *font, const uint16_t x_loc, const uint16_t y_loc, const char *string, pixel_t color);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
#include "stdbool.h"
|
#include "stdbool.h"
|
||||||
|
#include "display.h"
|
||||||
|
|
||||||
typedef void (*menu_callback_t)(void *args);
|
typedef void (*menu_callback_t)(void *args);
|
||||||
typedef struct _graphical_menu_layout_t graphical_menu_layout_t;
|
typedef struct _graphical_menu_layout_t graphical_menu_layout_t;
|
||||||
@@ -40,10 +41,10 @@ struct _graphical_menu_t {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void draw_menu(const graphical_menu_t *const menu);
|
void draw_menu(volatile pixel_t *const framebuffer, const graphical_menu_t *const menu);
|
||||||
|
void partial_redraw_menu(volatile pixel_t *const framebuffer, graphical_menu_t *const menu, uint8_t old_highlighted_entry_idx, uint8_t new_highlighted_entry_idx);
|
||||||
void select_menu_entry(graphical_menu_t *const menu);
|
void select_menu_entry(graphical_menu_t *const menu);
|
||||||
uint8_t get_selected_menu_entry_idx(void);
|
void set_selected_menu_entry_idx(volatile pixel_t *const framebuffer, graphical_menu_t *const menu, uint8_t idx);
|
||||||
void set_selected_menu_entry_idx(graphical_menu_t *const menu, int8_t idx);
|
|
||||||
void decrement_selected_menu_entry_idx(graphical_menu_t *const menu);
|
void decrement_selected_menu_entry_idx(graphical_menu_t *const menu);
|
||||||
void increment_selected_menu_entry_idx(graphical_menu_t *const menu);
|
void increment_selected_menu_entry_idx(graphical_menu_t *const menu);
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ const void * lv_font_get_bitmap_fmt_txt(lv_font_fmt_txt_glyph_dsc_t * g_dsc, lv_
|
|||||||
* @note If the character is not found in the font's character map, the function returns
|
* @note If the character is not found in the font's character map, the function returns
|
||||||
* 0 without drawing anything.
|
* 0 without drawing anything.
|
||||||
*/
|
*/
|
||||||
uint16_t draw_character(pixel_t *framebuffer, const lv_font_t *font, const uint16_t x_loc, const uint16_t y_loc, const char character, pixel_t color)
|
uint16_t draw_character(volatile pixel_t *const framebuffer, const lv_font_t *font, const uint16_t x_loc, const uint16_t y_loc, const char character, pixel_t color)
|
||||||
{
|
{
|
||||||
const lv_font_fmt_txt_dsc_t *font_dsc = (lv_font_fmt_txt_dsc_t *)font->dsc;
|
const lv_font_fmt_txt_dsc_t *font_dsc = (lv_font_fmt_txt_dsc_t *)font->dsc;
|
||||||
lv_font_fmt_txt_glyph_dsc_t glyph_dsc;
|
lv_font_fmt_txt_glyph_dsc_t glyph_dsc;
|
||||||
@@ -140,7 +140,7 @@ uint16_t draw_character(pixel_t *framebuffer, const lv_font_t *font, const uint1
|
|||||||
* @note All characters in the string are drawn on the same horizontal baseline (y_loc
|
* @note All characters in the string are drawn on the same horizontal baseline (y_loc
|
||||||
* remains constant for all characters).
|
* remains constant for all characters).
|
||||||
*/
|
*/
|
||||||
void draw_string(pixel_t *framebuffer, const lv_font_t *font, const uint16_t x_loc, const uint16_t y_loc, const char *string, pixel_t color)
|
void draw_string(volatile pixel_t *const framebuffer, const lv_font_t *font, const uint16_t x_loc, const uint16_t y_loc, const char *string, pixel_t color)
|
||||||
{
|
{
|
||||||
uint32_t current_x = x_loc << 4;
|
uint32_t current_x = x_loc << 4;
|
||||||
|
|
||||||
|
|||||||
@@ -2,50 +2,61 @@
|
|||||||
#include "graphics.h"
|
#include "graphics.h"
|
||||||
#include "fonts/font.h"
|
#include "fonts/font.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "ui.h"
|
|
||||||
|
|
||||||
void draw_menu(const graphical_menu_t *const menu)
|
static const uint16_t entry_height = 40;
|
||||||
|
static const uint16_t padding_x = 10;
|
||||||
|
static const uint16_t padding_y = 0;
|
||||||
|
static const pixel_t enabled_text_color = MAKE_PIXEL(0, 0, 0);
|
||||||
|
static const pixel_t disabled_text_color = MAKE_PIXEL(128, 128, 128);
|
||||||
|
static const pixel_t entry_bg_color = MAKE_PIXEL(255, 255, 255);
|
||||||
|
static const pixel_t highlighted_bg_color = MAKE_PIXEL(0, 0, 0);
|
||||||
|
static const pixel_t highlighted_text_color = MAKE_PIXEL(255, 255, 0);
|
||||||
|
|
||||||
|
void draw_menu_entry(volatile pixel_t *const framebuffer, const graphical_menu_t *const menu, uint8_t entry_idx)
|
||||||
{
|
{
|
||||||
const uint16_t entry_height = 40;
|
const uint16_t y_pos = entry_idx * entry_height;
|
||||||
const uint16_t padding_x = 10;
|
const graphical_menu_entry_t *entry = &menu->layout->entries[entry_idx];
|
||||||
const uint16_t padding_y = 0;
|
const bool is_highlighted = (entry_idx == menu->selected_entry_idx) && entry->enabled;
|
||||||
const pixel_t enabled_text_color = MAKE_PIXEL(0, 0, 0);
|
|
||||||
const pixel_t disabled_text_color = MAKE_PIXEL(128, 128, 128);
|
// Draw entry background - use highlighted color if this is the selected entry
|
||||||
const pixel_t entry_bg_color = MAKE_PIXEL(255, 255, 255);
|
pixel_t bg_color = is_highlighted ? highlighted_bg_color : entry_bg_color;
|
||||||
const pixel_t highlighted_bg_color = MAKE_PIXEL(0, 0, 0);
|
DrawBox(0, y_pos, DISPLAY_WIDTH, entry_height, bg_color);
|
||||||
const pixel_t highlighted_text_color = MAKE_PIXEL(255, 255, 0);
|
|
||||||
|
// Draw entry text - use highlighted color if selected, otherwise use enabled/disabled color
|
||||||
|
pixel_t text_color;
|
||||||
|
if (is_highlighted)
|
||||||
|
{
|
||||||
|
text_color = highlighted_text_color;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
text_color = entry->enabled ? enabled_text_color : disabled_text_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate baseline from top position: baseline = top + (line_height - base_line)
|
||||||
|
const uint16_t text_baseline_y = y_pos + padding_y + (roboto_bold_font.line_height - roboto_bold_font.base_line);
|
||||||
|
draw_string(framebuffer, &runescape_font,
|
||||||
|
padding_x, text_baseline_y,
|
||||||
|
entry->title, text_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_menu(volatile pixel_t *const framebuffer, const graphical_menu_t *const menu)
|
||||||
|
{
|
||||||
DrawBox(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, entry_bg_color);
|
DrawBox(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, entry_bg_color);
|
||||||
|
|
||||||
for (uint8_t i = 0; i < menu->layout->num_entries; i++)
|
for (uint8_t i = 0; i < menu->layout->num_entries; i++)
|
||||||
{
|
{
|
||||||
const uint16_t y_pos = i * entry_height;
|
draw_menu_entry(framebuffer, menu, i);
|
||||||
const graphical_menu_entry_t *entry = &menu->layout->entries[i];
|
|
||||||
const bool is_highlighted = (i == menu->selected_entry_idx) && entry->enabled;
|
|
||||||
|
|
||||||
// Draw entry background - use highlighted color if this is the selected entry
|
|
||||||
pixel_t bg_color = is_highlighted ? highlighted_bg_color : entry_bg_color;
|
|
||||||
DrawBox(0, y_pos, DISPLAY_WIDTH, entry_height, bg_color);
|
|
||||||
|
|
||||||
// Draw entry text - use highlighted color if selected, otherwise use enabled/disabled color
|
|
||||||
pixel_t text_color;
|
|
||||||
if (is_highlighted)
|
|
||||||
{
|
|
||||||
text_color = highlighted_text_color;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
text_color = entry->enabled ? enabled_text_color : disabled_text_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate baseline from top position: baseline = top + (line_height - base_line)
|
|
||||||
const uint16_t text_baseline_y = y_pos + padding_y + (roboto_bold_font.line_height - roboto_bold_font.base_line);
|
|
||||||
draw_string((pixel_t *)framebuffer, &runescape_font,
|
|
||||||
padding_x, text_baseline_y,
|
|
||||||
entry->title, text_color);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void partial_redraw_menu(volatile pixel_t *const framebuffer, graphical_menu_t *const menu, uint8_t old_highlighted_entry_idx, uint8_t new_highlighted_entry_idx)
|
||||||
|
{
|
||||||
|
draw_menu_entry(framebuffer, menu, old_highlighted_entry_idx);
|
||||||
|
draw_menu_entry(framebuffer, menu, new_highlighted_entry_idx);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void select_menu_entry(graphical_menu_t *const menu)
|
void select_menu_entry(graphical_menu_t *const menu)
|
||||||
{
|
{
|
||||||
// Ensure selected_entry_idx is within bounds
|
// Ensure selected_entry_idx is within bounds
|
||||||
@@ -63,12 +74,24 @@ void select_menu_entry(graphical_menu_t *const menu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_selected_menu_entry_idx(graphical_menu_t *const menu, int8_t idx)
|
void set_selected_menu_entry_idx(volatile pixel_t *const framebuffer, graphical_menu_t *const menu, uint8_t idx)
|
||||||
{
|
{
|
||||||
|
const uint16_t old_highlighted_entry_idx = menu->selected_entry_idx;
|
||||||
|
|
||||||
|
|
||||||
|
// Handle case where the last entry is disabled
|
||||||
|
if (idx == menu->layout->num_entries - 1)
|
||||||
|
{
|
||||||
|
while (!menu->layout->entries[idx].enabled)
|
||||||
|
{
|
||||||
|
idx--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only allow selecting enabled entries
|
// Only allow selecting enabled entries
|
||||||
while (!menu->layout->entries[idx].enabled)
|
while (!menu->layout->entries[idx].enabled)
|
||||||
{
|
{
|
||||||
if (idx >menu->selected_entry_idx)
|
if (idx > menu->selected_entry_idx)
|
||||||
{
|
{
|
||||||
idx--;
|
idx--;
|
||||||
}
|
}
|
||||||
@@ -79,21 +102,32 @@ void set_selected_menu_entry_idx(graphical_menu_t *const menu, int8_t idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clamp the index to valid range
|
// Clamp the index to valid range
|
||||||
if (idx < 0 || idx >= menu->layout->num_entries)
|
if (idx >= menu->layout->num_entries)
|
||||||
{
|
{
|
||||||
idx = menu->layout->num_entries > 0 ? menu->layout->num_entries - 1 : 0;
|
if (menu->layout->num_entries == 0) return;
|
||||||
|
idx = menu->layout->num_entries - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
menu->selected_entry_idx = idx;
|
menu->selected_entry_idx = idx;
|
||||||
ui_request_redraw();
|
partial_redraw_menu(framebuffer, menu, old_highlighted_entry_idx, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void decrement_selected_menu_entry_idx(graphical_menu_t *const menu)
|
void decrement_selected_menu_entry_idx(graphical_menu_t *const menu)
|
||||||
{
|
{
|
||||||
set_selected_menu_entry_idx(menu, menu->selected_entry_idx - 1);
|
if (menu->selected_entry_idx == 0)
|
||||||
|
{
|
||||||
|
set_selected_menu_entry_idx(framebuffer, menu, menu->layout->num_entries - 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set_selected_menu_entry_idx(framebuffer, menu, menu->selected_entry_idx - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void increment_selected_menu_entry_idx(graphical_menu_t *const menu)
|
void increment_selected_menu_entry_idx(graphical_menu_t *const menu)
|
||||||
{
|
{
|
||||||
set_selected_menu_entry_idx(menu, menu->selected_entry_idx + 1);
|
if (menu->selected_entry_idx == menu->layout->num_entries - 1)
|
||||||
|
{
|
||||||
|
set_selected_menu_entry_idx(framebuffer, menu, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set_selected_menu_entry_idx(framebuffer, menu, menu->selected_entry_idx + 1);
|
||||||
}
|
}
|
||||||
@@ -28,11 +28,10 @@ static const graphical_menu_layout_t main_menu_layout = {
|
|||||||
|
|
||||||
static const graphical_menu_layout_t runescape_memes_menu_layout = {
|
static const graphical_menu_layout_t runescape_memes_menu_layout = {
|
||||||
.parent_menu = &main_menu,
|
.parent_menu = &main_menu,
|
||||||
.num_entries = 8,
|
.num_entries = 7,
|
||||||
.entries = (graphical_menu_entry_t[]){
|
.entries = (graphical_menu_entry_t[]){
|
||||||
{.title = "where varock", .enabled = true, .highlighted_callback_function = 0, .highlighted_callback_function_args = 0, .selected_callback_function = 0, .selected_callback_function_args = 0},
|
{.title = "where varock", .enabled = true, .highlighted_callback_function = 0, .highlighted_callback_function_args = 0, .selected_callback_function = 0, .selected_callback_function_args = 0},
|
||||||
{.title = "buying gf", .enabled = true, .highlighted_callback_function = 0, .highlighted_callback_function_args = 0, .selected_callback_function = 0, .selected_callback_function_args = 0},
|
{.title = "buying gf", .enabled = true, .highlighted_callback_function = 0, .highlighted_callback_function_args = 0, .selected_callback_function = 0, .selected_callback_function_args = 0},
|
||||||
{.title = "le goblin", .enabled = true, .highlighted_callback_function = 0, .highlighted_callback_function_args = 0, .selected_callback_function = 0, .selected_callback_function_args = 0},
|
|
||||||
{.title = "you chop the tree", .enabled = true, .highlighted_callback_function = 0, .highlighted_callback_function_args = 0, .selected_callback_function = 0, .selected_callback_function_args = 0},
|
{.title = "you chop the tree", .enabled = true, .highlighted_callback_function = 0, .highlighted_callback_function_args = 0, .selected_callback_function = 0, .selected_callback_function_args = 0},
|
||||||
{.title = "you chop the tree", .enabled = true, .highlighted_callback_function = 0, .highlighted_callback_function_args = 0, .selected_callback_function = 0, .selected_callback_function_args = 0},
|
{.title = "you chop the tree", .enabled = true, .highlighted_callback_function = 0, .highlighted_callback_function_args = 0, .selected_callback_function = 0, .selected_callback_function_args = 0},
|
||||||
{.title = "you chop the tree", .enabled = true, .highlighted_callback_function = 0, .highlighted_callback_function_args = 0, .selected_callback_function = 0, .selected_callback_function_args = 0},
|
{.title = "you chop the tree", .enabled = true, .highlighted_callback_function = 0, .highlighted_callback_function_args = 0, .selected_callback_function = 0, .selected_callback_function_args = 0},
|
||||||
@@ -121,6 +120,6 @@ void ui_task(void)
|
|||||||
if (redraw_requested)
|
if (redraw_requested)
|
||||||
{
|
{
|
||||||
redraw_requested = false;
|
redraw_requested = false;
|
||||||
draw_menu(current_menu);
|
draw_menu(framebuffer, current_menu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user