diff --git a/Core/Inc/graphics/fonts/font.h b/Core/Inc/graphics/fonts/font.h index 0ab32fc..f7e022b 100644 --- a/Core/Inc/graphics/fonts/font.h +++ b/Core/Inc/graphics/fonts/font.h @@ -16,8 +16,8 @@ extern lv_font_t roboto_bold_large_font; extern lv_font_t runescape_font; #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 \ No newline at end of file diff --git a/Core/Inc/graphics/menu.h b/Core/Inc/graphics/menu.h index efecafe..932e7ed 100644 --- a/Core/Inc/graphics/menu.h +++ b/Core/Inc/graphics/menu.h @@ -3,6 +3,7 @@ #include "stdint.h" #include "stdbool.h" +#include "display.h" typedef void (*menu_callback_t)(void *args); 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); -uint8_t get_selected_menu_entry_idx(void); -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); void decrement_selected_menu_entry_idx(graphical_menu_t *const menu); void increment_selected_menu_entry_idx(graphical_menu_t *const menu); diff --git a/Core/Src/graphics/fonts/font.c b/Core/Src/graphics/fonts/font.c index 132360b..b4741b5 100644 --- a/Core/Src/graphics/fonts/font.c +++ b/Core/Src/graphics/fonts/font.c @@ -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 * 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; 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 * 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; diff --git a/Core/Src/graphics/menu.c b/Core/Src/graphics/menu.c index f054152..ceddff7 100644 --- a/Core/Src/graphics/menu.c +++ b/Core/Src/graphics/menu.c @@ -2,50 +2,61 @@ #include "graphics.h" #include "fonts/font.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 padding_x = 10; - const uint16_t padding_y = 0; - const pixel_t enabled_text_color = MAKE_PIXEL(0, 0, 0); - const pixel_t disabled_text_color = MAKE_PIXEL(128, 128, 128); - const pixel_t entry_bg_color = MAKE_PIXEL(255, 255, 255); - const pixel_t highlighted_bg_color = MAKE_PIXEL(0, 0, 0); - const pixel_t highlighted_text_color = MAKE_PIXEL(255, 255, 0); + const uint16_t y_pos = entry_idx * entry_height; + const graphical_menu_entry_t *entry = &menu->layout->entries[entry_idx]; + const bool is_highlighted = (entry_idx == 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(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); for (uint8_t i = 0; i < menu->layout->num_entries; i++) { - const uint16_t y_pos = i * entry_height; - 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); + draw_menu_entry(framebuffer, menu, i); } } +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) { // 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 while (!menu->layout->entries[idx].enabled) { - if (idx >menu->selected_entry_idx) + if (idx > menu->selected_entry_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 - 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; - ui_request_redraw(); + partial_redraw_menu(framebuffer, menu, old_highlighted_entry_idx, idx); } 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) { - 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); } \ No newline at end of file diff --git a/Core/Src/ui.c b/Core/Src/ui.c index bd35592..93f1b19 100644 --- a/Core/Src/ui.c +++ b/Core/Src/ui.c @@ -28,11 +28,10 @@ static const graphical_menu_layout_t main_menu_layout = { static const graphical_menu_layout_t runescape_memes_menu_layout = { .parent_menu = &main_menu, - .num_entries = 8, + .num_entries = 7, .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 = "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}, @@ -121,6 +120,6 @@ void ui_task(void) if (redraw_requested) { redraw_requested = false; - draw_menu(current_menu); + draw_menu(framebuffer, current_menu); } } \ No newline at end of file