* MIT License
* Copyright (c) 2021 - 2023 _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 following 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 "DataProc.h"
#include "Frameworks/PageManager/PageManager.h"
#include "UI/AppFactory.h"
#define IS_STR_EQ(STR1, STR2) (strcmp(STR1, STR2) == 0)
using namespace DataProc;
class DP_PageNavi {
public:
DP_PageNavi(DataNode* node);
private:
DataNode* _node;
const DataNode* _nodeGlobal;
Env_Helper _env;
PageManager* _manager;
bool _enable;
lv_style_t _pageStyle;
private:
int onEvent(DataNode::EventParam_t* param);
int onNotify(const PageNavi_Info_t* info);
int onGlobalEvent(const Global_Info_t* info);
int naviToPage(PAGE_NAVI_CMD cmd, const char* name = nullptr);
static PageManager::RES_TYPE onPageEvent(PageManager::EVENT* event);
};
DP_PageNavi::DP_PageNavi(DataNode* node)
: _node(node)
, _env(node)
{
_nodeGlobal = node->subscribe("Global");
node->setEventCallback(
[](DataNode* n, DataNode::EventParam_t* param) {
auto ctx = (DP_PageNavi*)n->getUserData();
return ctx->onEvent(param);
},
DataNode::EVENT_PUBLISH | DataNode::EVENT_NOTIFY);
APP_DESCRIPTOR_IMPORT(Dashboard);
APP_DESCRIPTOR_IMPORT(LiveMap);
APP_DESCRIPTOR_IMPORT(Shutdown);
APP_DESCRIPTOR_IMPORT(Startup);
APP_DESCRIPTOR_IMPORT(SystemInfos);
}
int DP_PageNavi::onEvent(DataNode::EventParam_t* param)
{
if (param->event == DataNode::EVENT_NOTIFY) {
if (param->size != sizeof(PageNavi_Info_t)) {
return DataNode::RES_SIZE_MISMATCH;
}
return onNotify((const PageNavi_Info_t*)param->data_p);
}
if (param->tran == _env) {
auto info = (const Env_Info_t*)param->data_p;
if (IS_STR_EQ(info->key, "pagenavi")) {
_enable = IS_STR_EQ(info->value, "enable");
}
}
if (param->tran == _nodeGlobal) {
return onGlobalEvent((const Global_Info_t*)param->data_p);
}
if (!_enable) {
return DataNode::RES_UNSUPPORTED_REQUEST;
}
return DataNode::RES_UNSUPPORTED_REQUEST;
}
int DP_PageNavi::onNotify(const PageNavi_Info_t* info)
{
auto retval = PageManager::RES_TYPE::ERR_UNKNOWN;
switch (info->cmd) {
case PAGE_NAVI_CMD::PUSH: {
retval = _manager->push(info->name);
} break;
case PAGE_NAVI_CMD::POP: {
retval = _manager->pop();
} break;
default:
break;
}
return retval == PageManager::RES_TYPE::OK ? DataNode::RES_OK : DataNode::RES_UNSUPPORTED_REQUEST;
}
int DP_PageNavi::onGlobalEvent(const Global_Info_t* info)
{
switch (info->event) {
case GLOBAL_EVENT::PAGE_MANAGER_INIT_FINISHED: {
_manager = (PageManager*)info->param;
#if defined(PAGE_HOR_RES) && PAGE_HOR_RES > 0 && defined(PAGE_VER_RES) && PAGE_VER_RES > 0
lv_obj_t* scr = lv_obj_create(lv_scr_act());
lv_obj_remove_style_all(scr);
lv_obj_set_size(scr, PAGE_HOR_RES, PAGE_VER_RES);
lv_obj_center(scr);
_manager->setRootParent(scr);
lv_obj_t* layer_top = lv_obj_create(lv_layer_top());
lv_obj_remove_style_all(layer_top);
lv_obj_remove_flag(layer_top, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_remove_flag(layer_top, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_size(layer_top, PAGE_HOR_RES, PAGE_VER_RES);
lv_obj_center(layer_top);
_manager->setLayerTop(layer_top);
#endif
lv_obj_set_style_pad_all(_manager->getRootParent(), 0, 0);
lv_obj_clear_flag(_manager->getRootParent(), LV_OBJ_FLAG_SCROLLABLE);
lv_style_init(&_pageStyle);
lv_style_set_size(&_pageStyle, lv_pct(100), lv_pct(100));
lv_style_set_pad_all(&_pageStyle, 0);
lv_style_set_radius(&_pageStyle, 0);
lv_style_set_border_width(&_pageStyle, 0);
lv_style_set_text_font(&_pageStyle, lv_theme_get_font_normal(nullptr));
_manager->setRootDefaultStyle(&_pageStyle);
_manager->setEventCallback(onPageEvent, this);
} break;
case GLOBAL_EVENT::STATUS_BAR_INIT_FINISHED: {
lv_style_set_pad_top(&_pageStyle, _env.getInt("statusbar-padding-top"));
} break;
case GLOBAL_EVENT::APP_STARTED: {
_manager->push("Startup");
} break;
case GLOBAL_EVENT::APP_STOPPED: {
_manager->setRootDefaultStyle(nullptr);
lv_style_reset(&_pageStyle);
} break;
default:
break;
}
return DataNode::RES_OK;
}
int DP_PageNavi::naviToPage(PAGE_NAVI_CMD cmd, const char* name)
{
PageNavi_Info_t info;
info.cmd = cmd;
info.name = name;
return onNotify(&info);
}
PageManager::RES_TYPE DP_PageNavi::onPageEvent(PageManager::EVENT* event)
{
auto self = (DP_PageNavi*)event->userData;
switch (event->type) {
case PageManager::EVENT_TYPE::PAGE_STATE_CHANGED: {
auto state = *(const PageBase::STATE*)event->param;
if (state == PageBase::STATE::DID_APPEAR) {
self->_env.set("statusbar-opa", "cover");
self->_env.set("navibar", "enable");
self->_env.set("statusbar", "enable");
self->_env.set("pagenavi", "enable");
}
} break;
case PageManager::EVENT_TYPE::PAGE_PUSH:
case PageManager::EVENT_TYPE::PAGE_POP: {
PageNavi_Info_t info;
info.cmd = event->type == PageManager::EVENT_TYPE::PAGE_PUSH ? PAGE_NAVI_CMD::PUSH : PAGE_NAVI_CMD::POP;
info.name = (const char*)event->param;
auto res = self->_node->publish(&info, sizeof(info));
if (res == DataNode::RES_STOP_PROCESS) {
return PageManager::RES_TYPE::STOP_PROCESS;
}
return PageManager::RES_TYPE::OK;
} break;
default:
break;
}
return PageManager::RES_TYPE::OK;
}
DATA_PROC_DESCRIPTOR_DEF(PageNavi);