#include "menu_api.h" #include "../src/core/menu_core.h" #include "../src/core/menu_event.h" #include "../src/core/menu_stack.h" #include static MenuCoreCtx g_menu_ctx; MenuErrCode menu_init(void) { return menu_core_init(&g_menu_ctx); } void menu_deinit(void) { // Cleanup if needed } void menu_main_loop(uint32_t tick) { menu_core_loop(&g_menu_ctx, tick); } MenuNodeId menu_register_node( MenuNodeId id, MenuNodeId parent_id, const char* name, MenuCallback enter_cb, MenuCallback exit_cb ) { return menu_register_node_ex(id, parent_id, name, enter_cb, exit_cb, NULL, NULL); } MenuNodeId menu_register_node_ex( MenuNodeId id, MenuNodeId parent_id, const char* name, MenuCallback enter_cb, MenuCallback exit_cb, MenuCallback render_cb, void* user_data ) { MenuNode node = {0}; node.id = id; node.parent_id = parent_id; node.name = name; node.enter_cb = enter_cb; node.exit_cb = exit_cb; node.render_cb = render_cb; node.user_data = user_data; node.flags.is_enabled = true; node.flags.is_visible = true; node.flags.is_registered = false; // Will be set by core node.param_id = 0; node.permission_level = 0; MenuNodeId new_id = 0; if (menu_core_register_node(&g_menu_ctx, &node, &new_id) == MENU_ERR_OK) { return new_id; } return 0; } MenuErrCode menu_register_nodes( const MenuNode* nodes, size_t count, MenuNodeId* out_ids ) { if (!nodes || count == 0) return MENU_ERR_INVALID_PARAM; for (size_t i = 0; i < count; i++) { MenuNode node = nodes[i]; MenuNodeId new_id = 0; node.flags.is_enabled = true; node.flags.is_visible = true; node.flags.is_registered = false; node.param_id = node.param_id ? node.param_id : 0; node.permission_level = node.permission_level ? node.permission_level : 0; MenuErrCode err = menu_core_register_node(&g_menu_ctx, &node, &new_id); if (err != MENU_ERR_OK) { return err; } if (out_ids) { out_ids[i] = new_id; } } return MENU_ERR_OK; } MenuErrCode menu_post_event(MenuEventType type, uint32_t param) { return menu_event_post(&g_menu_ctx.event_queue, type, param); } MenuErrCode menu_enter(void) { // We try to enter the first available root node. // We can trigger an event or just let the loop handle it. // If we rely on handle_event to enter root on NULL current, // we just need to ensure loop is called. // But explicitly: if (g_menu_ctx.current_node_id == 0) { // Force finding a root // Since we don't have public access to ctx nodes from here easily without exposing everything, // we can just call handle_event with a dummy event or NONE event if handle_event checks NULL current. // But handle_event checks event type. // We can add MENU_EVENT_NONE handling in handle_event to check entry? // Or just manually find root here. // We have access to g_menu_ctx. for(int i=0; iparam_id = param_id; return MENU_ERR_OK; } // Permission management functions MenuErrCode menu_permission_register_role(uint8_t role_id, const char* name, MenuPermissionLevel level) { if (!name) return MENU_ERR_INVALID_PARAM; if (g_menu_ctx.permission.role_count >= 8) return MENU_ERR_NO_MEM; for (uint8_t i = 0; i < g_menu_ctx.permission.role_count; i++) { if (g_menu_ctx.permission.roles[i].id == role_id) { return MENU_ERR_FAIL; } } MenuRole* role = &g_menu_ctx.permission.roles[g_menu_ctx.permission.role_count]; role->id = role_id; role->name = name; role->level = level; g_menu_ctx.permission.role_count++; return MENU_ERR_OK; } MenuErrCode menu_permission_set_current_role(uint8_t role_id) { g_menu_ctx.permission.current_role_id = role_id; return MENU_ERR_OK; } MenuErrCode menu_permission_update_node_level(MenuNodeId node_id, MenuPermissionLevel level) { MenuNode* node = menu_core_get_node(&g_menu_ctx, node_id); if (!node) return MENU_ERR_NOT_FOUND; node->permission_level = level; return MENU_ERR_OK; } bool menu_permission_check_node_access(MenuNodeId node_id) { MenuNode* node = menu_core_get_node(&g_menu_ctx, node_id); if (!node) return false; #if MENU_CONFIG_ENABLE_PERMISSION MenuRole* role_node = NULL; for (uint8_t i = 0; i < g_menu_ctx.permission.role_count; i++) { if (g_menu_ctx.permission.roles[i].id == g_menu_ctx.permission.current_role_id) { role_node = &g_menu_ctx.permission.roles[i]; break; } } if (!role_node || role_node->level < node->permission_level) { return false; } #endif return true; } // Persistence functions MenuErrCode menu_persistence_save(void) { return menu_core_save_state(&g_menu_ctx); } MenuErrCode menu_persistence_load(void) { return menu_core_load_state(&g_menu_ctx); } MenuErrCode menu_refresh(void) { MenuErrCode err = menu_post_event(MENU_EVENT_RENDER, 0); if (err != MENU_ERR_OK) { return err; } return MENU_ERR_OK; }