应用对接
一、说明
应用的构成分为三个部分:应用主体,应用子页,应用弹窗页。
二、应用主体
相关文件:
《app_tool_app.c》
《app_tool_app.h》
1.应用的创建和删除
1.1 创建
void sfat_app_register(void *data)
{
sfat_manager_node_t *node = (sfat_manager_node_t *)data;
builtin_app_desc_t *desc = (builtin_app_desc_t *)app_malloc(sizeof(builtin_app_desc_t));
rt_memcpy((void *)&desc->name, (const void *)&node, sizeof(sfat_manager_node_t *));
rt_memcpy(desc->id, node->binary.header.st->id, GUI_APP_ID_MAX_LEN);
desc->entry = app_main;
desc->type = GUI_APP_TOOLS;
desc->icon = (const void *)node;
node->app_node = (void *)desc;
}
在解析工具应用文件的时候,会调用此函数进行应用注册。此时需要申请一个应用的节点,并且填写应用相关信息。
desc->entry:进入应用的回调函数接口。
desc->type: 应用的来源类型,标注为GUI工具。
desc->icon: 应用图标,在此填写了整个节点,需要在显示应用图标的地方再次解析。
node->app_node: 将应用节点记录到工具节点中,以供后续查找使用。
1.2 删除
void sfat_app_unregister(void *data)
{
sfat_manager_node_t *node = (sfat_manager_node_t *)data;
if (node->app_node)
{
app_free(node->app_node);
node->app_node = NULL;
}
}
在删除工具应用文件的时候,会调用此函数进行应用注销。此时需要将注册时申请的应用节点释放。
2.应用列表的添加与显示
2.1 添加到应用菜单
相关文件:
《gui_app_fwk.c》\
static void app_load(const char *id, app_entity_info *p_app_info)
{
const builtin_app_desc_t *item = NULL;
#ifdef APP_TOOL_SUPPORT
if (item == NULL)
{
item = (const builtin_app_desc_t *)sfat_manager_get_app_next((void *)item);
while (item != NULL)
{
if (0 == strcmp(item->id, id))
{
break;
}
item = (const builtin_app_desc_t *)sfat_manager_get_app_next((void *)item);
}
}
#endif
}
app_load这个函数用于实现从各个途径获取应用信息,示例代码段为获取GUI工具应用的信息。
2.2 显示应用图标
每个菜单样式都有自己的显示图片的函数,我们需要在对应的函数中去添加GUI工具应用图标显示流程.在此我们以蜂窝菜单为例:
void mainmenu_cell_item_create(builtin_app_desc_t *app_desc, mainmenu_ext_icons_t *table_elem, uint16_t index, void *user_data)
{
if (app_desc && app_desc->type == GUI_APP_TOOLS)
{
#ifdef APP_TOOL_SUPPORT
sfat_manager_node_t *node = (sfat_manager_node_t *)img;
lv_obj_t *menu_icon = lv_img_create(icon_btn);
sfat_set_header_src(menu_icon, node->file_path, &node->binary);
lv_obj_align(menu_icon, LV_ALIGN_CENTER, 0, 0);
lv_obj_add_flag(menu_icon, LV_OBJ_FLAG_SCROLL_CHAIN | LV_OBJ_FLAG_EVENT_BUBBLE);
lv_obj_refr_size(menu_icon);
#endif
}
else
{
lv_obj_t *menu_icon = lv_img_create(icon_btn);
lv_img_set_src(menu_icon, img);
lv_obj_align(menu_icon, LV_ALIGN_CENTER, 0, 0);
lv_obj_add_flag(menu_icon, LV_OBJ_FLAG_SCROLL_CHAIN | LV_OBJ_FLAG_EVENT_BUBBLE);
lv_obj_refr_size(menu_icon);
}
}
通过type判断此应用信息是否为工具类型,并添加相应的处理流程。
根据第二章第一节的节点创建中的内容,我们给应用信息的icon赋值为GUI工具的节点信息。所以在此我们将icon强制转换为工具节点类型,然后根据工具的库函数sfat_set_header_src为图片控件设置图片源。即可完成GUI工具应用的菜单图标显示。
3.应用的运行
3.1 应用运行的准备
static int app_main(intent_t i)
{
p_intent tmp = (intent_t)app_malloc(sizeof(_intent));
rt_memcpy(tmp, i, sizeof(_intent));
sfat_manager_set_active_by_id(&tmp->content[0], SFAT_MANAGER_TYPE_APP);
app_free(tmp);
sfat_manager_node_t *node = sfat_manager_get_active_node(SFAT_MANAGER_TYPE_APP);
gui_app_regist_msg_handler_ext((const char *)node->binary.header.st->id, msg_handler, (void *)node, 0);
return 0;
}
app_main是应用运行的入口函数,每当应用创建准备开始运行的时候,会执行此函数。、 在此我们可以提前获取到即将要运行的应用的ID,并通过ID获取到工具应用的节点。然后将其传递给后续流程使用。
3.2 应用运行与退出
static void on_start(void)
{
sfat_gui_sys_init(p_sfat_node); //app tool system init
}
static void on_stop(void)
{
sfat_gui_sys_deinit(p_sfat_node); //app tool system deinit
p_sfat_node = NULL;
}
当应用开始运行的时候,需要对GUI工具的系统进行初始化,其中包括设置脚本运行环境,读取字体信息,控制命令管理。
相应的在应用退出的时候,需要进行反初始化,将之前的配置移除。
三、应用子页
相关文件:
《app_tool_page.c》
《app_tool_page.h》
1.子页的创建
void sfat_page_main(char *theme_id)
{
/*创建的页面一定是在当前活动的应用上*/
sfat_manager_node_t *node = sfat_manager_get_active_node(SFAT_MANAGER_TYPE_APP);
/*检查theme id的有效性*/
if (false == sfat_set_active_theme(node, theme_id))
{
rt_kprintf("%s, not find:%s in file:%s!!!
", __func__, theme_id, node->binary.header.st->id);
RT_ASSERT(0);
}
if (RT_EOK == gui_app_goback_to_page(theme_id)) return;
gui_app_create_page_ext(theme_id, msg_handler, sfat_get_theme_by_id(node, theme_id));
}
static void msg_handler(gui_app_msg_type_t msg, void *param)
{
p_sfat_node = sfat_manager_get_node_by_id((char *)param, SFAT_MANAGER_TYPE_APP);
p_sfat_theme = gui_app_this_page_userdata();
}
在页面创建的时候,需要把当前活动页的信息设置到页面框架中,方便后续读取使用。
四、应用页的弹窗
相关文件:
《app_tool_pop.c》
《app_tool_pop.h》
1.弹窗注册
void sfat_pop_register(void *data)
{
sfat_manager_node_t *node = (sfat_manager_node_t *)data;
for (uint8_t i = 0; i < node->binary.header.st->theme_count; i++)
{
if (node->binary.theme_table[i].sta.flag.type == SFAT_THEME_TYPE_APP_WINDOW)
{
sfat_theme_t *theme = sfat_read_theme(node->file_path, &node->binary, i, false);
popup_register_for_app(node->binary.header.st->id, theme->sta.id, theme->dynamic.pop_data->prio, theme->dynamic.pop_data->time, msg_handler, 0, POPUP_APP_TOOLS);
}
}
}
在应用文件的解析过程中,会遍历此应用的所有页面,所有的弹窗页面都会在此处统一进行注册。
2.弹窗注销
void sfat_pop_unregister(void *data)
{
sfat_manager_node_t *node = (sfat_manager_node_t *)data;
popup_unregister_for_app(node->binary.header.st->id);
}
在卸载应用的过程中,会调用此函数将此应用所包含的所有弹窗移除。
3.弹窗使用
int popup_run(const char *id, void *user_data);
工具使用弹窗是在《app_tool_event.c》中由事件触发进行使用。
但是由于弹窗是注册到系统的弹窗框架中的,所有在用户自己的代码中也可以使用这些弹窗。