思澈科技软件开发工具包  2.20
图形应用框架

名词解释

App - 指一个应用程序的GUI部分,即MVC模型中的View部分,它是page的集合。支持内置App以及动态安装App。
Page - 指一个显示页面,允许用户在上面创建控件、注册输入设备处理、链接数据服务并显示,(注意这不是lv_page)。每个page拥有独立的lv_screen,状态处理回调函数,以及转场动画
lv_screen - littleVGL上的虚拟屏幕,一个物理LCD上同一时间只能显示一个lv_screen的内容,输入设备只能操作当前显示的lv_screen

功能

  • 提供App之间、App内部的显示界面的调度以及转场动画
  • 提供App打开顺序、App内部Page打开顺序的记录
  • 支持后台刷新App/page

限制

  • 一个App至少包含一个page
  • 一个page可以从属任意App
  • 同时只能有一个page处于active状态
  • 同时只能有一个App处于avtive状态

Page间的调度

AppA、AppB各有3个page,分别表示为A1~A3,B1~B3 下图显示了各种调度情况下各Page的最终状态(注意此处忽略了过渡态)

Figure 1: Page间的调度

Page状态机和各状态的实现规范

  • entryfunction() - 启动page函数, 如果不需要参数,此步骤可以并入on_start
    • 分配内存
    • 接收处理参数
  • on_start()
    • 创建/布局当前page内的lv控件
    • 订阅service
    • 向service request 数据
  • on_resume()
    • 运行app内部的lv_task/timer
  • on_pause()
    • 停止(或删除)app内部lv_task
  • on_stop()
    • 退订service
    • 释放内存
    • 创建的lv控件会自动删除,可以不用主动删除
Figure 2: Page内部状态机

图片示例中其他处理函数说明:

  • xxx_service_callback()
    Page内订阅服务的处理函数
    See also
    Data service interface
  • Page’s lv_task()
    Page内可选的lv_task处理函数
  • lv_obj_callback()
    littleVGL object的事件处理函数

常用API说明

GUI Application Framework

Application example

typedef struct
{
lv_obj_t *title_text;
lv_obj_t *img_arrow;
lv_img_dsc_t *p_img_arrow_dsc;
datac_handle_t srv_handle;
uint32_t last_degree;
} app_compass_t;
static app_compass_t *p_compass = NULL;
static void compass_request_data(void)
{
data_service_init_msg(&msg, MSG_SRV_COMPASS_CUR_VAL_GET_REQ, 0);
datac_send_msg(p_compass->srv_handle, &msg);
}
static int compass_data_callback(data_callback_arg_t *arg)
{
switch (arg->msg_id)
{
case MSG_SERVICE_SUBSCRIBE_RSP:
{
data_rsp_t *rsp;
rsp = (data_rsp_t *)arg->data;
RT_ASSERT(rsp);
/* Subscribe data error*/
if (rsp->result < 0)
{
p_compass->srv_handle = DATA_CONN_INVALID_ID;
}
else
{
/* Request compass degree*/
compass_request_data();
}
break;
}
case MSG_SRV_COMPASS_CUR_VAL_GET_RSP:
{
compass_data_t *data = (compass_data_t *)arg->data;
if(data)
{
/* Valid data*/
if(data->accuracy > 0)
{
uint32_t degree = (3600 - data->azimuth * 10);
/* Need update UI*/
if(degree != p_compass->last_degree)
{
char text_buf[20];
/* Update compass arrow angle*/
lv_img_set_angle(p_compass->img_arrow, degree);
/* Update compass angle label text*/
sprintf(text_buf, "%d d", degree);
lv_label_set_text(p_compass->title_text, text_buf);
p_compass->last_degree = degree;
}
}
}
/* Request compass degree again*/
compass_request_data();
}
break;
default:
break;
}
return 0;
}
static void on_start(void)
{
if (NULL != p_compass)
rt_free(p_compass);
/* Alloc app memory*/
p_compass = rt_malloc(sizeof(app_compass_t));
memset(p_compass, 0, sizeof(app_compass_t));
/* Create UI widgets*/
{
lv_obj_t *obj;
obj = lv_img_create(lv_scr_act(), NULL);
lv_img_set_src(obj, LV_EXT_IMG_GET(compass_bg));
lv_obj_align(obj, NULL, LV_ALIGN_CENTER, 0, 0);
obj = lv_img_create(lv_scr_act(), NULL);
p_compass->img_arrow = obj;
obj = lv_label_create(lv_scr_act(), NULL);
lv_label_set_text(obj, "230 d");
lv_obj_align(obj, NULL, LV_ALIGN_IN_TOP_LEFT, 10, 10);
p_compass->title_text = obj;
}
/* Subscribe service data*/
p_compass->srv_handle = ui_datac_subscribe("COMP",
compass_data_callback, 0);
}
static void on_pause(void)
{
/*Free SRAM image to save heap memory*/
lv_img_set_src(p_compass->img_arrow, NULL);
if(NULL != p_compass->p_img_arrow_dsc)
{
lv_img_buf_free(p_compass->p_img_arrow_dsc);
p_compass->p_img_arrow_dsc = NULL;
}
}
static void on_resume(void)
{
const lv_img_dsc_t *org_img;
org_img = LV_EXT_IMG_GET(compass_arrow);
/*Copy image to SRAM to speed up*/
p_compass->p_img_arrow_dsc = lv_img_buf_alloc(org_img->header.w,
org_img->header.h,
org_img->header.cf);
memcpy((void *)p_compass->p_img_arrow_dsc->data, org_img->data, org_img->data_size);
/* Update image's source and coordinates.*/
lv_img_set_src(p_compass->img_arrow, p_compass->p_img_arrow_dsc);
lv_obj_align(p_compass->img_arrow, NULL, LV_ALIGN_CENTER, 0, 0);
}
static void on_stop(void)
{
/*unsubscribe service before exit app*/
if (DATA_CONN_INVALID_ID != p_compass->srv_handle)
{
datac_unsubscribe(p_compass->srv_handle);
p_compass->srv_handle = DATA_CONN_INVALID_ID;
}
if (NULL != p_compass)
{
rt_free(p_compass);
p_compass = NULL;
}
}
static void msg_handler(gui_app_msg_type_t msg, void *param)
{
switch (msg)
{
on_start();
break;
on_resume();
break;
on_pause();
break;
on_stop();
break;
default:
break;
}
}
static int app_main(int argc, char *argv[])
{
/* Regist root page message handler */
gui_app_regist_msg_handler(argv[0], msg_handler);
return 0;
}
/* Regist compass app */
BUILTIN_APP_EXPORT("compass", LV_EXT_IMG_GET(img_compass), "compass", app_main);
ui_datac_subscribe
datac_handle_t ui_datac_subscribe(datac_handle_t handle, char *name, data_callback_t cbk, uint32_t user_data)
Subscribe data service in GUI thread context.
data_service_init_msg
uint8_t * data_service_init_msg(data_msg_t *msg, uint16_t msg_id, uint16_t body_len)
Initialize data service message.
GUI_APP_MSG_ONPAUSE
@ GUI_APP_MSG_ONPAUSE
Definition: gui_app_fwk2.h:44
GUI_APP_MSG_ONRESUME
@ GUI_APP_MSG_ONRESUME
Definition: gui_app_fwk2.h:37
data_msg_t
data service message structure type
Definition: data_service.h:179
data
uint8_t data[]
Definition: bf0_ble_ancs.h:227
data_callback_arg_tag::data
uint8_t * data
Definition: data_service.h:128
BUILTIN_APP_EXPORT
#define BUILTIN_APP_EXPORT(name, icon, id, entry)
Definition: gui_app_fwk.h:129
GUI_APP_MSG_ONSTOP
@ GUI_APP_MSG_ONSTOP
Definition: gui_app_fwk2.h:51
GUI_APP_MSG_ONSTART
@ GUI_APP_MSG_ONSTART
Definition: gui_app_fwk2.h:30
data_rsp_t
Parameter for response messages.
Definition: data_service.h:156
gui_app_msg_type_t
gui_app_msg_type_t
Page state notification messages.
Definition: gui_app_fwk2.h:25
data_callback_arg_tag
Definition: data_service.h:125
datac_send_msg
rt_err_t datac_send_msg(datac_handle_t handle, data_msg_t *msg)
Send message to service provider.
data_callback_arg_tag::msg_id
uint16_t msg_id
Definition: data_service.h:126
datac_unsubscribe
#define datac_unsubscribe(handle)
Unsubscribe to service.
Definition: data_service_subscriber.h:133