HCoreBase/include/HUIPageManage.h
coffee 8631a84333 1. 更新命令行
2. 更新页面管理
2025-06-04 15:50:21 +08:00

163 lines
6.6 KiB
C

/**
* 日期: 2025-04-02
* 作者: coffee
* 描述: ui页面管理, 独立模块, 用于管理页面切换和跳转
*/
#ifndef __H_UI_PAGE_MANAGE_H__
#define __H_UI_PAGE_MANAGE_H__
#include <stdint.h>
#ifndef __COUNT_ARGS_IMPL
#define __COUNT_ARGS_IMPL(_, _1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N
#endif
#ifndef __COUNT_ARGS
#define __COUNT_ARGS(...) __COUNT_ARGS_IMPL(dummy, ##__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#endif
#define USE_UI_PAGE
/** ================================================================= */
// 注册页面函数辅助宏
#define UIPAGE_FUNC(func) uint8_t func##PageCall(uint16_t cmd, void *data, uint16_t len)
#define UIPAGE_DATA data
#define UIPAGE_LEN len
#define UIPAGE_CMD cmd
#if 1
#define UIPAGE_CASE(page, func) case page: { LogD("current page[%d], event[%s]", page, #page); func(); LogD("event End"); } break
#define UIPAGE_CASE_RET(page, func) case page: { LogD("current page[%d], event[%s]", page, #page); return func(); LogD("event End"); } break
#else
#define UIPAGE_CASE(page, func) case page: { func(); } break
#define UIPAGE_CASE_RET(page, func) case page: { return func(); } break
#endif
#define UIPAGE_INIT_FUNC(func) UIPAGE_CASE(kCallInitPage, func)
#define UIPAGE_FREE_FUNC(func) UIPAGE_CASE(kCallFreePage, func)
#define UIPAGE_SHOW_FUNC(func) UIPAGE_CASE(kCallShowPage, func)
#define UIPAGE_HIDE_FUNC(func) UIPAGE_CASE(kCallHidePage, func)
#define UIPAGE_SWITCH_FUNC(func) UIPAGE_CASE_RET(kCallSwitchPage, func)
#define UIPAGE_INDEX_FUNC(func) UIPAGE_CASE(kCallIndexSave, func)
#define UIPAGE_INIT_SHOW_FUNC(init, show) UIPAGE_INIT_FUNC(init); UIPAGE_SHOW_FUNC(show)
#define UIPAGE_DEINIT_HIDE_FUNC(deinit, hide) UIPAGE_FREE_FUNC(deinit); UIPAGE_HIDE_FUNC(hide)
#define UIPAGE_INIT_DEINIT_FUNC(init, deinit) UIPAGE_INIT_FUNC(init); UIPAGE_FREE_FUNC(deinit)
#define UIPAGE_SHOW_HIDE_FUNC(show, hide) UIPAGE_SHOW_FUNC(show); UIPAGE_HIDE_FUNC(hide)
// 对应事件的data转换具体类型宏
#define UI_CALL_INDEX_TYPE(value) ((HUiPageIndex_t *)value)
/** ================================================================= */
typedef uint8_t HUiPageIndex_t;
// hide -> free -> update Page -> init -> show
// 或者非返回时如下, 此时的hide和index事件都可存储该页面索引:
// hide -> index -> free -> update Page -> init -> show
enum eCallCmd
{
kCallInitPage, ///< 构建页面, 对应页面自己内部创建数据(非释放页面不调用, 但如未构建则会触发)
kCallFreePage, ///< 释放页面, 对应页面自己内部释放数据(非释放页面不调用)
kCallShowPage, ///< 显示页面
kCallHidePage, ///< 退出页面, 此事件如果是返回触发的可以存储索引数据
kCallSwitchPage, ///< 切换页面, 对应页面返回false时则不切换, 所有切换都会触发这个事件
kCallIndexSave, ///< 存储当前索引事件, 通知此事件说明当前不是返回事件(cmd, HUiPageIndex_t *nextPage, 1);
};
// 每个页面占用一个枚举, 根据枚举切换页面, kUIPageMax最大页面值, 要求格式统一 kUIPage + 页面名, 可以任意调整位置
typedef enum eUIPage
{
kUIPageMax = 4, ///< ui最大个数, 不超过254个页面, 如超过则需要修改字节栈类型
} eUIPage;
///< cmd命令, data数据, len数据长度
typedef uint8_t (*pageCallType_t)(uint16_t cmd, void *data, uint16_t len);
typedef void (*initPageType_t)(pageCallType_t *call);
// 初始化页面管理, 当为NULL时内部初始化, 否则回调初始化, 请需要先设置好主页, 初始化会默认显示主页
void HUIPageInit(initPageType_t initPage);
// 设置主页, 切换到主页清空返回栈, 如果返回栈为空时, 当前页面不是主页, 则切换到主页
void HUIPageSetHome(HUiPageIndex_t page);
// 切换页面, 当前页面入栈, 相同页面不操作, 需要检查栈, 栈存在就回栈清空之后的, 不存在就压栈
// 因为有些页面可能不用HUIPageBack来返回, 所以需要兼容这种情况
void HUIPageSwitch(HUiPageIndex_t page);
// 切换到主页
void HUIPageSwitchHome();
// 返回上一个页面
void HUIPageBack();
// 清空返回栈, 不允许切换时, 将显示该页面, 而无法继续回栈, 成功返回1, 否则返回0
uint8_t HUIPageClear();
/**
* @brief
* 添加关联页面到返回栈, 用于一些按键跳转到指定页面, 或者一些不想逐个进入, 而是直接跳转, 然后返回时逐个返回的功能使用
* 如正常是 主页->菜单->该页面, 但快捷跳转是主页->该页面, 需要将菜单页面添加到返回栈
* 则需要调用 清空返回栈, 然后添加 主页->菜单, 最后再切换到该页面(内部会判断首个页面是否存在返回栈, 自动清空首个页面前的返回栈)
* HUIPageClear(); HUIPageAddStack(主页, 菜单, 该页面); // 栈2个, 显示该页面
* 注: 调用这个时, 当前页面将不会入栈, 最大参数长度9个
* 如: 当前页面是菜单, 设置 主页->菜单, 则菜单页面不会入栈
* 因此, 此方法用于绝对顺序跳转
*/
void _HUIPageAddStack(int len, ...);
#define HUIPageAddStack(...) _HUIPageAddStack(__COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__)
// 当前自身页面不释放内存, 用于某些暂不想释放页面, 等返回后再考虑释放
void HUIPageSetCurrNotFree();
// 恢复当前页面默认释放内存
void HUIPageResetCurrFree();
// 获取当前页面是否不释放
uint8_t HUIPageGetCurrNotFree();
// 设置指定页面不释放内存
void HUIPageSetNotFree(HUiPageIndex_t page);
// 恢复指定页面默认释放内存
void HUIPageResetFree(HUiPageIndex_t page);
// 获取指定页面是否不释放, 是返回1, 否则返回0
uint8_t HUIPageGetNotFree(HUiPageIndex_t page);
// 设置用户数据, 在 kCallShowPage 和 kCallHidePage 都可调用, 但每次切换这些事件后都会重置数据为0
void HUIPageSetUserData(long userData);
// 获取用户数据
long HUIPageGetUserData();
// 保存当前页面索引, 仅在 kCallHidePage 和 kCallIndexSave 有效, 成功返回1, 否则返回0
uint8_t HUIPageSaveIndex(uint8_t value);
// 获取当前页面索引, 仅在 HUIPageIsBack() 返回1时有效, 否则返回0
uint8_t HUIPageGetIndex();
// 获取当前页面
HUiPageIndex_t HUIPageGetCurrPage();
// 获取上一个页面
HUiPageIndex_t HUIPageGetPrevPage();
// 获取返回栈使用长度
uint8_t HUIPageGetStackLen();
// 获取索引栈使用长度
uint8_t HUIPageGetIndexStackLen();
// 检查当前是否是返回
uint8_t HUIPageIsBack();
// 检查该页面是否在返回栈, 是返回1, 否则返回0
uint8_t HUIPageFindStack(HUiPageIndex_t page);
#endif //__H_UI_PAGE_MANAGE_H__