133 lines
4.3 KiB
C
133 lines
4.3 KiB
C
#include "menu.h"
|
|
#include "graphics.h"
|
|
#include "fonts/font.h"
|
|
#include "display.h"
|
|
|
|
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(255, 255, 255);
|
|
static const pixel_t disabled_text_color = MAKE_PIXEL(128, 128, 128);
|
|
static const pixel_t entry_bg_color = MAKE_PIXEL(0, 0, 0);
|
|
static const pixel_t highlighted_bg_color = MAKE_PIXEL(50, 50, 50);
|
|
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 y_pos = entry_idx * entry_height;
|
|
const graphical_menu_entry_t *entry = &menu->children[entry_idx];
|
|
const bool is_highlighted = (entry_idx == menu->highlighted_child_idx) && !entry->disabled;
|
|
|
|
// 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->disabled ? 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->num_children; i++)
|
|
{
|
|
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
|
|
if (menu->highlighted_child_idx >= menu->num_children)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const graphical_menu_entry_t *entry = &menu->children[menu->highlighted_child_idx];
|
|
|
|
// Only select if the entry is enabled
|
|
if (!entry->disabled && entry->selected_callback_function != NULL)
|
|
{
|
|
entry->selected_callback_function(entry->selected_callback_function_args);
|
|
}
|
|
}
|
|
|
|
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->highlighted_child_idx;
|
|
|
|
|
|
// Handle case where the last entry is disabled
|
|
if (idx == menu->num_children - 1)
|
|
{
|
|
while (!menu->children[idx].disabled)
|
|
{
|
|
idx--;
|
|
}
|
|
}
|
|
|
|
// Only allow selecting enabled entries
|
|
while (menu->children[idx].disabled)
|
|
{
|
|
if (idx > menu->highlighted_child_idx)
|
|
{
|
|
idx--;
|
|
}
|
|
else
|
|
{
|
|
idx++;
|
|
}
|
|
}
|
|
|
|
// Clamp the index to valid range
|
|
if (idx >= menu->num_children)
|
|
{
|
|
if (menu->num_children == 0) return;
|
|
idx = menu->num_children - 1;
|
|
}
|
|
|
|
menu->highlighted_child_idx = idx;
|
|
partial_redraw_menu(framebuffer, menu, old_highlighted_entry_idx, idx);
|
|
}
|
|
|
|
void decrement_selected_menu_entry_idx(volatile pixel_t *const framebuffer, graphical_menu_t *const menu)
|
|
{
|
|
if (menu->highlighted_child_idx == 0)
|
|
{
|
|
set_selected_menu_entry_idx(framebuffer, menu, menu->num_children - 1);
|
|
return;
|
|
}
|
|
set_selected_menu_entry_idx(framebuffer, menu, menu->highlighted_child_idx - 1);
|
|
}
|
|
|
|
void increment_selected_menu_entry_idx(volatile pixel_t *const framebuffer, graphical_menu_t *const menu)
|
|
{
|
|
if (menu->highlighted_child_idx == menu->num_children - 1)
|
|
{
|
|
set_selected_menu_entry_idx(framebuffer, menu, 0);
|
|
return;
|
|
}
|
|
set_selected_menu_entry_idx(framebuffer, menu, menu->highlighted_child_idx + 1);
|
|
} |