界面
其实关于业务逻辑这方面并没有什么好说的,有一个大概的想法去做就行,但这部分也是最费时间的地方,还有有原U主的代码作为参考,这次其实也只是在UP的基础上去修改一点东西,毕竟UI这个东西没个好的审美,做出来也费力不讨好,简称,我杀我自己…
关于界面的实现,我使用PC端先仿真一些纯逻辑和界面的内容,涉及到硬件的先使用其他方法跳过,然后做完一个移植一个,直至全部完成.
页面框架
整个GUI是由8个页面构成的,每个页面都是一个大小等同于屏幕大小的容器,在上电后,各个硬件模块初始化完毕后,就开始了8个容器的初始化.后续的管理由一个页面管理模块管理.该页面管理模块单独占用一个系统线程.
页面管理里面简单的认为所有的页面一共划分为3级,如下.
- 表盘页面
- 菜单页面
- 各个功能页面
界面管理
依旧延续up主思路,每个页面由四个主要函数实现一切逻辑,分别是初始化,循环,触发,退出四个事件.然后将每个页面注册到页面管理器中,通过页面管理器进行统一的页面调度.
界面管理器原代码是C++写的(MIT许可),里面模拟了一些压栈入栈的操作,我根据个人需求该了一下这个文件,删除了一些内容.
现在只有基本的页面切换管理,事件传递调度.
具体代码如下.(临时改的,有需要的可以根据自己的命名规范修改)
/*
* MIT License
* Copyright (c) 2018-2020 _VIFEXTech
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the follo18wing conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "PageManager.h"
#include <string.h>
#include "lv_obj_test.h"
#define MALLOC malloc
#define FREE free
#define IS_PAGE(page) ((page)<(page_manager.max_page))
typedef struct
{
uint8_t new_page;
uint8_t old_page;
uint8_t max_page;
PageList_TypeDef* page_list;
}page_manager_data_t;
static page_manager_data_t page_manager;
static bool push(uint8_t _id);
static bool pop(void);
static void enent_transmit(void* _obj, int _event);
static void run(void);
static void init(uint8_t _max);
static void delte(void);
static bool creat( uint8_t _id,
CallbackFunction_t ,
CallbackFunction_t ,
CallbackFunction_t ,
EventFunction_t );
page_manager_t page =
{
init,
delte,
creat,
push,
pop,
enent_transmit,
run
};
/**
* @brief 清除一个页面
* @param pageID: 页面编号
* @retval true:成功 false:失败
*/
static bool PageClear(uint8_t pageID)
{
if(!IS_PAGE(pageID))
return false;
page_manager.page_list[pageID].SetupCallback = NULL;
page_manager.page_list[pageID].LoopCallback = NULL;
page_manager.page_list[pageID].ExitCallback = NULL;
page_manager.page_list[pageID].EventCallback = NULL;
return true;
}
/**
* @brief 初始化页面调度器
* @param pageMax: 页面最大数量
* @param eventMax: 事件最大数量
* @retval 无
*/
static void init(uint8_t pageMax)
{
page_manager.max_page = pageMax;
page_manager.new_page = E_PAGE_MAX;
page_manager.old_page = E_PAGE_MAX;
/* 申请内存,清空列表 */
page_manager.page_list = (PageList_TypeDef*)MALLOC(sizeof(PageList_TypeDef)*page_manager.max_page);
if(page_manager.page_list != NULL)
{
for(uint8_t page = 0; page < page_manager.max_page; page++)
{
PageClear(page);
}
}
else FREE(page_manager.page_list);
}
/**
* @brief 页面调度器析构
* @param 无
* @retval 无
*/
static void delte()
{
FREE(page_manager.page_list);
}
/**
* @brief 注册一个基本页面,包含一个初始化函数,循环函数,退出函数,事件函数
* @param pageID: 页面编号
* @param setupCallback: 初始化函数回调
* @param loopCallback: 循环函数回调
* @param exitCallback: 退出函数回调
* @param eventCallback: 事件函数回调
* @retval true:成功 false:失败
*/
static bool creat(
uint8_t pageID,
CallbackFunction_t setupCallback,
CallbackFunction_t loopCallback,
CallbackFunction_t exitCallback,
EventFunction_t eventCallback
)
{
if(!IS_PAGE(pageID))
return false;
page_manager.page_list[pageID].SetupCallback = setupCallback;
page_manager.page_list[pageID].LoopCallback = loopCallback;
page_manager.page_list[pageID].ExitCallback = exitCallback;
page_manager.page_list[pageID].EventCallback = eventCallback;
return true;
}
/**
* @brief 页面事件传递
* @param obj: 发生事件的对象
* @param event: 事件编号
* @retval 无
*/
static void enent_transmit(void* obj, int event)
{
/*将事件传递到当前页面*/
if(page_manager.page_list[page_manager.new_page].EventCallback != NULL)
page_manager.page_list[page_manager.new_page].EventCallback(obj, event);
}
/**
* @brief 页面压栈,跳转至该页面
* @param pageID: 页面编号
* @retval true:成功 false:失败
*/
static bool push(uint8_t pageID)
{
if(!IS_PAGE(pageID))
return false;
page_manager.old_page = page_manager.new_page;
page_manager.new_page = pageID;
return true;
}
/**
* @brief 页面弹栈,跳转至上一个页面
* @param 无
* @retval true:成功 false:失败
*/
static bool pop()
{
page_manager.old_page = page_manager.new_page;
if(page_manager.new_page == PAGE_MainMenu) //在第二级菜单 跳转到第一级菜单
{
page_manager.new_page = PAGE_DialPlate;
}
else if(page_manager.new_page > PAGE_MainMenu) //在第三级菜单 跳转到第二级菜单
{
page_manager.new_page = PAGE_MainMenu;
}
else if(page_manager.new_page < PAGE_MainMenu) //在第一级菜单
{
page_manager.new_page = PAGE_DialPlate;
}
return true;
}
/**
* @brief 页面调度器状态机
* @param 无
* @retval 无
*/
static void run()
{
/*页面切换事件*/
if(page_manager.new_page != page_manager.old_page)
{
/*触发旧页面退出事件*/
if(page_manager.page_list[page_manager.old_page].ExitCallback != NULL && IS_PAGE(page_manager.old_page))
page_manager.page_list[page_manager.old_page].ExitCallback();
/*触发新页面初始化事件*/
if(page_manager.page_list[page_manager.new_page].SetupCallback != NULL && IS_PAGE(page_manager.new_page))
page_manager.page_list[page_manager.new_page].SetupCallback();
/*标记新页面为当前页面*/
page_manager.old_page = page_manager.new_page;
}
else
{
/*页面循环事件*/
if(page_manager.page_list[page_manager.new_page].LoopCallback != NULL && IS_PAGE(page_manager.new_page))
page_manager.page_list[page_manager.new_page].LoopCallback();
}
}
/*
* MIT License
* Copyright (c) 2018-2020 _VIFEXTech
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the follo18wing conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __PAGEMANAGER_H
#define __PAGEMANAGER_H
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
typedef void(*CallbackFunction_t)(void);
typedef void(*EventFunction_t)(void*,int);
typedef struct
{
CallbackFunction_t SetupCallback;
CallbackFunction_t LoopCallback;
CallbackFunction_t ExitCallback;
EventFunction_t EventCallback;
} PageList_TypeDef;
typedef struct
{
void(*init)(uint8_t);
void(*delte)(void);
bool(*creat)(uint8_t,CallbackFunction_t,CallbackFunction_t,CallbackFunction_t,EventFunction_t);
bool(*push)(uint8_t);
bool(*pop)(void);
void(*event_transmit)(void*,int);
void(*running)(void);
}page_manager_t;
extern page_manager_t page;
#endif
简单的将所有的页面划分为三个阶段的页面,初始页面为一级菜单,主页面为二级菜单,后续的所有功能页面为三级菜单,这样的好处就是逻辑足够简单,坏处就是通用性比较差.看个人取舍吧.