161 lines
6.6 KiB
C
161 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>
|
|
|
|
// 外部需要定义该宏, 用于说明页面数量, 如果不定义, 默认搜索 kUIPageMax 枚举
|
|
#ifndef HUI_PAGE_MAX_NUM
|
|
#define HUI_PAGE_MAX_NUM kUIPageMax
|
|
#endif
|
|
|
|
#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(__VA_ARGS__); LogD("event End"); } break
|
|
#define UIPAGE_CASE_RET(page, func, ...) case page: { LogD("current page[%d], event[%s]", page, #page); return func(__VA_ARGS__); LogD("event End"); } break
|
|
#else
|
|
#define UIPAGE_CASE(page, func, ...) case page: { func(__VA_ARGS__); } break
|
|
#define UIPAGE_CASE_RET(page, func, ...) case page: { return func(__VA_ARGS__); } break
|
|
#endif
|
|
|
|
#define UIPAGE_INIT_FUNC(func, ...) UIPAGE_CASE(kCallInitPage, func, __VA_ARGS__)
|
|
#define UIPAGE_FREE_FUNC(func, ...) UIPAGE_CASE(kCallFreePage, func, __VA_ARGS__)
|
|
#define UIPAGE_SHOW_FUNC(func, ...) UIPAGE_CASE(kCallShowPage, func, __VA_ARGS__)
|
|
#define UIPAGE_HIDE_FUNC(func, ...) UIPAGE_CASE(kCallHidePage, func, __VA_ARGS__)
|
|
|
|
#define UIPAGE_SWITCH_FUNC(func, ...) UIPAGE_CASE_RET(kCallSwitchPage, func, __VA_ARGS__)
|
|
#define UIPAGE_INDEX_FUNC(func, ...) UIPAGE_CASE(kCallIndexSave, func, __VA_ARGS__)
|
|
|
|
#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)
|
|
/** ================================================================= */
|
|
|
|
|
|
// 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);
|
|
};
|
|
|
|
typedef uint8_t HUiPageIndex_t;
|
|
|
|
///< 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__
|