feat: initial
This commit is contained in:
1 parent
53b3a102d0
commit
3522c5b950
9 files changed
+622
-3
No files matched your search
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* @file zh_menu.h
|
||||
*
|
||||
* @brief Hierarchical menu component for ESP-IDF.
|
||||
*
|
||||
* This header provides types and functions for building a multi-level
|
||||
* menu with navigation, selection handling and user callback support.
|
||||
* The component is independent of any particular input method (buttons,
|
||||
* encoder, interface commands) and operates with abstract navigation
|
||||
* commands.
|
||||
*
|
||||
* This component is a derivative work based on the original project
|
||||
* "menu_manager" by Marcio Bulla, available at:
|
||||
* https://github.com/MarcioBulla/menu_manager
|
||||
* The original project is distributed under the Apache License,
|
||||
* Version 2.0. The original code was adapted, modified and extended
|
||||
* for use with ESP-IDF as the zh_menu component.
|
||||
*
|
||||
* Key features:
|
||||
* - Support for nested submenus with a depth limit
|
||||
* - Configurable callbacks for position change, enter and exit
|
||||
* - Cyclic navigation mode over menu items
|
||||
* - Flexible handling of selectable and non-selectable items
|
||||
* - Low memory footprint due to dynamic allocation of the handle
|
||||
*
|
||||
* @note The component functions are thread-safe only to the extent
|
||||
* provided by the caller. External synchronization is required
|
||||
* when accessed from multiple tasks.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Opaque menu handle.
|
||||
*
|
||||
* The internal structure is hidden from the user and is defined
|
||||
* in the implementation file. All operations are performed through
|
||||
* a pointer to this type.
|
||||
*/
|
||||
typedef struct _zh_menu_handle_t zh_menu_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Menu navigation commands.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ZH_MENU_ENTER, /*!< Activate the menu and go to the root level */
|
||||
ZH_MENU_SHOW, /*!< Force refresh of the current state via callback */
|
||||
ZH_MENU_UP, /*!< Move selection to the previous item */
|
||||
ZH_MENU_DOWN, /*!< Move selection to the next item */
|
||||
ZH_MENU_SELECT, /*!< Select the current item or enter a submenu */
|
||||
ZH_MENU_BACK, /*!< Return to the previous level or exit the menu */
|
||||
ZH_MENU_MAX /*!< Upper bound of valid commands, not a command itself */
|
||||
} zh_menu_navigate_t;
|
||||
|
||||
/**
|
||||
* @brief Menu tree node.
|
||||
*
|
||||
* Describes a single menu item: its displayed label, nested submenu,
|
||||
* number of items in the submenu, user callback and selectable flag.
|
||||
*
|
||||
* @warning The submenu array must exist during the entire lifetime
|
||||
* of the menu. The component does not copy nodes.
|
||||
*/
|
||||
typedef struct zh_menu_node_t
|
||||
{
|
||||
const char *label; /*!< Displayed label of the menu item */
|
||||
struct zh_menu_node_t *submenu; /*!< Pointer to an array of nested items or NULL */
|
||||
uint8_t item_numbers; /*!< Number of items in the nested submenu array */
|
||||
void (*item_cb)(void *args); /*!< Callback invoked when the item is selected */
|
||||
bool selectable; /*!< Flag indicating that the item can be selected */
|
||||
} zh_menu_node_t;
|
||||
|
||||
/**
|
||||
* @brief Current menu state.
|
||||
*
|
||||
* Used to pass activity and selection status to external code
|
||||
* through the zh_menu_get() function.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool is_active; /*!< Flag indicating that the menu is activated */
|
||||
bool is_selected; /*!< Flag indicating that the current item is in the selection state */
|
||||
} zh_menu_status_t;
|
||||
|
||||
/**
|
||||
* @brief Menu initialization configuration.
|
||||
*
|
||||
* Contains the root node, a set of user callbacks and the cyclic navigation flag.
|
||||
*
|
||||
* @note The change_cb, enter_cb and exit_cb callbacks may be NULL
|
||||
* if the corresponding handling is not required.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
zh_menu_node_t *root; /*!< Root node of the menu tree */
|
||||
void (*change_cb)(zh_menu_node_t *current_path, uint8_t current_index); /*!< Callback for the current position change */
|
||||
void (*enter_cb)(void *args); /*!< Callback for entering the menu */
|
||||
void (*exit_cb)(void *args); /*!< Callback for exiting the menu */
|
||||
bool loop; /*!< Cyclic navigation flag over items */
|
||||
} zh_menu_init_config_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the menu.
|
||||
*
|
||||
* Creates the menu handle, stores the configuration and prepares
|
||||
* the internal state. After a successful call, the menu is in
|
||||
* an inactive state until the ZH_MENU_ENTER command.
|
||||
*
|
||||
* @param[in] config Initialization configuration (must not be NULL)
|
||||
* @param[out] handle Pointer to the handle pointer (must be NULL)
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return ESP_ERR_INVALID_ARG if config, config->root or handle is NULL
|
||||
* @return ESP_ERR_INVALID_STATE if *handle is already initialized
|
||||
* @return ESP_ERR_NO_MEM if memory allocation for the handle failed
|
||||
*/
|
||||
esp_err_t zh_menu_init(const zh_menu_init_config_t *config, zh_menu_handle_t **handle);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the menu.
|
||||
*
|
||||
* Frees the dynamic memory occupied by the handle and resets the pointer to it.
|
||||
*
|
||||
* @param[in,out] handle Pointer to the handle pointer (must not be NULL)
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return ESP_ERR_INVALID_ARG if handle or *handle is NULL
|
||||
*/
|
||||
esp_err_t zh_menu_deinit(zh_menu_handle_t **handle);
|
||||
|
||||
/**
|
||||
* @brief Execute a menu navigation command.
|
||||
*
|
||||
* Processes one of the zh_menu_navigate_t commands, changing
|
||||
* the internal menu state and invoking the corresponding callbacks.
|
||||
* The exact behavior depends on the current activity and selection state.
|
||||
*
|
||||
* @param[in,out] handle Pointer to the handle pointer (must not be NULL)
|
||||
* @param[in] command Navigation command. Must be less than ZH_MENU_MAX
|
||||
* @param[in] arg Arbitrary argument passed to the user callbacks (enter_cb, exit_cb, item_cb) (may be NULL)
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return ESP_ERR_INVALID_ARG if handle, *handle is NULL or command >= ZH_MENU_MAX
|
||||
*
|
||||
* @note Commands that are invalid in the current state are ignored and do not cause an error.
|
||||
*/
|
||||
esp_err_t zh_menu_set(zh_menu_handle_t **handle, zh_menu_navigate_t command, void *arg);
|
||||
|
||||
/**
|
||||
* @brief Get the current menu state.
|
||||
*
|
||||
* Fills the status structure with the activity and selection flags.
|
||||
*
|
||||
* @param[in] handle Pointer to the handle pointer (must not be NULL)
|
||||
* @param[out] status Pointer to the status structure to be filled (must not be NULL)
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return ESP_ERR_INVALID_ARG if handle, *handle or status is NULL
|
||||
*/
|
||||
esp_err_t zh_menu_get(zh_menu_handle_t **handle, zh_menu_status_t *status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in new issue
Block a user