Files
menu/api/menu_api.c
2025-12-19 17:01:27 +08:00

261 lines
7.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
**********************************************************************************************************************
* @file menu_api.c
* @brief 菜单组件对外API接口实现
* @author menu_component
* @date 2025-12-19
**********************************************************************************************************************
*/
/* Includes ----------------------------------------------------------------------------------------------------------*/
#include "menu_api.h"
#include "../src/core/menu_core.h"
#include "../src/core/menu_event.h"
#include "../src/core/menu_hash.h"
/* 函数实现 ---------------------------------------------------------------------------------------------------------*/
/* 菜单初始化与反初始化 ---------------------------------------------------------------------------------------------*/
MenuErrCode menu_init(void)
{
return menu_core_init();
}
MenuErrCode menu_deinit(void)
{
return menu_core_deinit();
}
/* 菜单节点管理 -----------------------------------------------------------------------------------------------------*/
MenuNodeId menu_register_node(MenuNodeId node_id, MenuNodeId parent_id, const char* name, MenuCallback enter_cb, MenuCallback exit_cb)
{
// 参数验证
if (name == NULL) {
return 0; // 保持原有API兼容0表示注册失败
}
// 调用核心层的节点注册功能
return menu_core_register_node(node_id, parent_id, name, enter_cb, exit_cb);
}
MenuErrCode menu_register_nodes(const struct MenuNode* nodes, uint16_t count)
{
// 暂未实现批量注册功能
(void)nodes;
(void)count;
return MENU_ERR_OPERATION_FAILED;
}
MenuErrCode menu_unregister_node(MenuNodeId node_id)
{
// 调用核心层的节点注销功能
return menu_core_unregister_node(node_id);
}
MenuErrCode menu_update_node(MenuNodeId node_id, const char* name, MenuCallback enter_cb, MenuCallback exit_cb)
{
MenuCoreCtx* core_ctx = menu_get_core_ctx();
MenuNode* node = menu_hash_find(core_ctx, node_id);
if (node == NULL || !node->flags.is_registered) {
return MENU_ERR_NODE_NOT_FOUND;
}
// 更新节点信息
if (name != NULL) {
node->name = name;
}
if (enter_cb != NULL) {
node->enter_cb = enter_cb;
}
if (exit_cb != NULL) {
node->exit_cb = exit_cb;
}
return MENU_ERR_OK;
}
const struct MenuNode* menu_find_node(MenuNodeId node_id)
{
MenuCoreCtx* core_ctx = menu_get_core_ctx();
return menu_hash_find(core_ctx, node_id);
}
/* 菜单事件处理 -----------------------------------------------------------------------------------------------------*/
MenuErrCode menu_post_event(MenuEventType event_type, uint8_t priority)
{
MenuCoreCtx* core_ctx = menu_get_core_ctx();
MenuEvent event;
event.type = event_type;
event.priority = priority;
event.target_node_id = core_ctx->current_node_id;
event.data = NULL;
event.timestamp = core_ctx->last_refresh_tick;
return menu_event_queue_push(&core_ctx->event_queue, &event);
}
MenuErrCode menu_post_event_with_data(MenuEventType event_type, uint8_t priority, void* data)
{
MenuCoreCtx* core_ctx = menu_get_core_ctx();
MenuEvent event;
event.type = event_type;
event.priority = priority;
event.target_node_id = core_ctx->current_node_id;
event.data = data;
event.timestamp = core_ctx->last_refresh_tick;
return menu_event_queue_push(&core_ctx->event_queue, &event);
}
/* 菜单导航操作 -----------------------------------------------------------------------------------------------------*/
MenuErrCode menu_main_loop(uint32_t tick)
{
// 调用核心层的主循环功能
return menu_core_main_loop(tick);
}
MenuErrCode menu_enter(void)
{
return menu_post_event(MENU_EVENT_KEY_ENTER, 1);
}
MenuErrCode menu_exit(void)
{
return menu_post_event(MENU_EVENT_KEY_ESC, 1);
}
MenuErrCode menu_up(void)
{
return menu_post_event(MENU_EVENT_KEY_UP, 1);
}
MenuErrCode menu_down(void)
{
return menu_post_event(MENU_EVENT_KEY_DOWN, 1);
}
MenuErrCode menu_select(MenuNodeId node_id)
{
// 暂未实现直接选择指定节点功能
(void)node_id;
return MENU_ERR_OPERATION_FAILED;
}
MenuErrCode menu_reset(void)
{
// 暂未实现重置功能
return MENU_ERR_OPERATION_FAILED;
}
/* 菜单状态查询 -----------------------------------------------------------------------------------------------------*/
MenuState menu_get_state(void)
{
return menu_get_current_state();
}
MenuNodeId menu_get_current_node(void)
{
return menu_get_current_node_id();
}
uint8_t menu_get_nav_depth(void)
{
MenuCoreCtx* core_ctx = menu_get_core_ctx();
return core_ctx->nav_path.depth;
}
uint8_t menu_get_nav_path(MenuNodeId* path, uint8_t max_depth)
{
MenuCoreCtx* core_ctx = menu_get_core_ctx();
uint8_t actual_depth = core_ctx->nav_path.depth;
if (actual_depth > max_depth) {
actual_depth = max_depth;
}
for (uint8_t i = 0; i < actual_depth; i++) {
path[i] = core_ctx->nav_path.path[i];
}
return actual_depth;
}
/* 状态机扩展接口 ---------------------------------------------------------------------------------------------------*/
#if MENU_CONFIG_ENABLE_STATE_MACHINE_EXT
MenuErrCode menu_state_register_transition(const MenuStateTransition* transition)
{
MenuCoreCtx* core_ctx = menu_get_core_ctx();
if (core_ctx->custom_transition_count >= MENU_CONFIG_MAX_STATE_TRANSITIONS) {
return MENU_ERR_OUT_OF_MEMORY;
}
core_ctx->custom_transitions[core_ctx->custom_transition_count] = *transition;
core_ctx->custom_transition_count++;
return MENU_ERR_OK;
}
MenuErrCode menu_state_unregister_transition(MenuState current_state, MenuEventType event)
{
MenuCoreCtx* core_ctx = menu_get_core_ctx();
bool found = false;
// 查找并删除匹配的状态转换规则
for (uint16_t i = 0; i < core_ctx->custom_transition_count; i++) {
if (core_ctx->custom_transitions[i].current_state == current_state &&
core_ctx->custom_transitions[i].event == event) {
// 找到匹配的规则,将后续规则前移
for (uint16_t j = i; j < core_ctx->custom_transition_count - 1; j++) {
core_ctx->custom_transitions[j] = core_ctx->custom_transitions[j + 1];
}
core_ctx->custom_transition_count--;
found = true;
break;
}
}
return found ? MENU_ERR_OK : MENU_ERR_INVALID_STATE;
}
MenuErrCode menu_state_switch(MenuState state)
{
MenuCoreCtx* core_ctx = menu_get_core_ctx();
core_ctx->current_state = state;
return MENU_ERR_OK;
}
#endif
/* 内存监控接口 -----------------------------------------------------------------------------------------------------*/
#if MENU_CONFIG_ENABLE_MEM_MONITOR
uint16_t menu_mem_get_used_nodes(void)
{
MenuCoreCtx* core_ctx = menu_get_core_ctx();
return core_ctx->node_count;
}
uint16_t menu_mem_get_free_nodes(void)
{
MenuCoreCtx* core_ctx = menu_get_core_ctx();
return core_ctx->free_node_count;
}
uint16_t menu_mem_get_max_nodes(void)
{
return MENU_CONFIG_MAX_NODES;
}
#endif