#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(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 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++) { 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->selected_entry_idx >= menu->layout->num_entries) { return; } const graphical_menu_entry_t *entry = &menu->layout->entries[menu->selected_entry_idx]; // Only select if the entry is enabled if (entry->enabled && 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->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) { idx--; } else { idx++; } } // Clamp the index to valid range if (idx >= menu->layout->num_entries) { if (menu->layout->num_entries == 0) return; idx = menu->layout->num_entries - 1; } menu->selected_entry_idx = idx; partial_redraw_menu(framebuffer, menu, old_highlighted_entry_idx, idx); } void decrement_selected_menu_entry_idx(graphical_menu_t *const menu) { 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) { 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); }