Transition to hekate bdk layout
This commit is contained in:
parent
4425e81085
commit
4ffd4ce7f0
317 changed files with 60891 additions and 1003 deletions
12
bdk/libs/lvgl/lv_core/lv_core.mk
Normal file
12
bdk/libs/lvgl/lv_core/lv_core.mk
Normal file
|
@ -0,0 +1,12 @@
|
|||
CSRCS += lv_group.c
|
||||
CSRCS += lv_indev.c
|
||||
CSRCS += lv_obj.c
|
||||
CSRCS += lv_refr.c
|
||||
CSRCS += lv_style.c
|
||||
CSRCS += lv_vdb.c
|
||||
CSRCS += lv_lang.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/lvgl/lv_core
|
||||
VPATH += :$(LVGL_DIR)/lvgl/lv_core
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/lvgl/lv_core"
|
554
bdk/libs/lvgl/lv_core/lv_group.c
Normal file
554
bdk/libs/lvgl/lv_core/lv_group.c
Normal file
|
@ -0,0 +1,554 @@
|
|||
/**
|
||||
* @file lv_group.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_group.h"
|
||||
#if USE_LV_GROUP != 0
|
||||
#include <stddef.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void style_mod_def(lv_style_t * style);
|
||||
static void style_mod_edit_def(lv_style_t * style);
|
||||
static void lv_group_refocus(lv_group_t *g);
|
||||
static void obj_to_foreground(lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a new object group
|
||||
* @return pointer to the new object group
|
||||
*/
|
||||
lv_group_t * lv_group_create(void)
|
||||
{
|
||||
lv_group_t * group = lv_mem_alloc(sizeof(lv_group_t));
|
||||
lv_mem_assert(group);
|
||||
if(group == NULL) return NULL;
|
||||
lv_ll_init(&group->obj_ll, sizeof(lv_obj_t *));
|
||||
|
||||
group->style_mod = style_mod_def;
|
||||
group->style_mod_edit = style_mod_edit_def;
|
||||
group->obj_focus = NULL;
|
||||
group->frozen = 0;
|
||||
group->focus_cb = NULL;
|
||||
group->click_focus = 1;
|
||||
group->editing = 0;
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a group object
|
||||
* @param group pointer to a group
|
||||
*/
|
||||
void lv_group_del(lv_group_t * group)
|
||||
{
|
||||
/*Defocus the the currently focused object*/
|
||||
if(group->obj_focus != NULL) {
|
||||
(*group->obj_focus)->signal_func(*group->obj_focus, LV_SIGNAL_DEFOCUS, NULL);
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
}
|
||||
|
||||
/*Remove the objects from the group*/
|
||||
lv_obj_t ** obj;
|
||||
LL_READ(group->obj_ll, obj) {
|
||||
(*obj)->group_p = NULL;
|
||||
}
|
||||
|
||||
lv_ll_clear(&(group->obj_ll));
|
||||
lv_mem_free(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an object to a group
|
||||
* @param group pointer to a group
|
||||
* @param obj pointer to an object to add
|
||||
*/
|
||||
void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj)
|
||||
{
|
||||
if(group == NULL) return;
|
||||
|
||||
/*If the object is already in a group and focused then defocus it*/
|
||||
if(obj->group_p) {
|
||||
if(lv_obj_is_focused(obj)) {
|
||||
lv_group_refocus(obj->group_p);
|
||||
|
||||
LV_LOG_INFO("group: assign object to an other group");
|
||||
}
|
||||
}
|
||||
|
||||
obj->group_p = group;
|
||||
lv_obj_t ** next = lv_ll_ins_tail(&group->obj_ll);
|
||||
lv_mem_assert(next);
|
||||
if(next == NULL) return;
|
||||
*next = obj;
|
||||
|
||||
/* If the head and the tail is equal then there is only one object in the linked list.
|
||||
* In this case automatically activate it*/
|
||||
if(lv_ll_get_head(&group->obj_ll) == next) {
|
||||
lv_group_refocus(group);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an object from its group
|
||||
* @param obj pointer to an object to remove
|
||||
*/
|
||||
void lv_group_remove_obj(lv_obj_t * obj)
|
||||
{
|
||||
lv_group_t * g = obj->group_p;
|
||||
if(g == NULL) return;
|
||||
if(g->obj_focus == NULL) return; /*Just to be sure (Not possible if there is at least one object in the group)*/
|
||||
|
||||
/*Focus on the next object*/
|
||||
if(*g->obj_focus == obj) {
|
||||
/*If this is the only object in the group then focus to nothing.*/
|
||||
if(lv_ll_get_head(&g->obj_ll) == g->obj_focus && lv_ll_get_tail(&g->obj_ll) == g->obj_focus) {
|
||||
(*g->obj_focus)->signal_func(*g->obj_focus, LV_SIGNAL_DEFOCUS, NULL);
|
||||
}
|
||||
/*If there more objects in the group then focus to the next/prev object*/
|
||||
else {
|
||||
lv_group_refocus(g);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the focuses object is still the same then it was the only object in the group but it will be deleted.
|
||||
* Set the `obj_focus` to NULL to get back to the initial state of the group with zero objects*/
|
||||
if(*g->obj_focus == obj) {
|
||||
g->obj_focus = NULL;
|
||||
}
|
||||
|
||||
/*Search the object and remove it from its group */
|
||||
lv_obj_t ** i;
|
||||
LL_READ(g->obj_ll, i) {
|
||||
if(*i == obj) {
|
||||
lv_ll_rem(&g->obj_ll, i);
|
||||
lv_mem_free(i);
|
||||
obj->group_p = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus on an object (defocus the current)
|
||||
* @param obj pointer to an object to focus on
|
||||
*/
|
||||
void lv_group_focus_obj(lv_obj_t * obj)
|
||||
{
|
||||
lv_group_t * g = obj->group_p;
|
||||
if(g == NULL) return;
|
||||
|
||||
if(g->frozen != 0) return;
|
||||
|
||||
/*On defocus edit mode must be leaved*/
|
||||
lv_group_set_editing(g, false);
|
||||
|
||||
lv_obj_t ** i;
|
||||
LL_READ(g->obj_ll, i) {
|
||||
if(*i == obj) {
|
||||
if(g->obj_focus == i) return; /*Don't focus the already focused object again*/
|
||||
if(g->obj_focus != NULL) {
|
||||
(*g->obj_focus)->signal_func(*g->obj_focus, LV_SIGNAL_DEFOCUS, NULL);
|
||||
lv_obj_invalidate(*g->obj_focus);
|
||||
}
|
||||
|
||||
g->obj_focus = i;
|
||||
|
||||
if(g->obj_focus != NULL) {
|
||||
(*g->obj_focus)->signal_func(*g->obj_focus, LV_SIGNAL_FOCUS, NULL);
|
||||
if(g->focus_cb) g->focus_cb(g);
|
||||
lv_obj_invalidate(*g->obj_focus);
|
||||
|
||||
/*If the object or its parent has `top == true` bring it to the foregorund*/
|
||||
obj_to_foreground(*g->obj_focus);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus the next object in a group (defocus the current)
|
||||
* @param group pointer to a group
|
||||
*/
|
||||
void lv_group_focus_next(lv_group_t * group)
|
||||
{
|
||||
if(group->frozen) return;
|
||||
|
||||
if(group->obj_focus) {
|
||||
(*group->obj_focus)->signal_func(*group->obj_focus, LV_SIGNAL_DEFOCUS, NULL);
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
}
|
||||
|
||||
lv_obj_t ** obj_next;
|
||||
if(group->obj_focus == NULL) obj_next = lv_ll_get_head(&group->obj_ll);
|
||||
else obj_next = lv_ll_get_next(&group->obj_ll, group->obj_focus);
|
||||
|
||||
if(obj_next == NULL) {
|
||||
if(group->wrap) obj_next = lv_ll_get_head(&group->obj_ll);
|
||||
else obj_next = lv_ll_get_tail(&group->obj_ll);
|
||||
}
|
||||
group->obj_focus = obj_next;
|
||||
|
||||
if(group->obj_focus) {
|
||||
(*group->obj_focus)->signal_func(*group->obj_focus, LV_SIGNAL_FOCUS, NULL);
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
|
||||
if(group->focus_cb) group->focus_cb(group);
|
||||
|
||||
/*If the object or its parent has `top == true` bring it to the foregorund*/
|
||||
obj_to_foreground(*group->obj_focus);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus the previous object in a group (defocus the current)
|
||||
* @param group pointer to a group
|
||||
*/
|
||||
void lv_group_focus_prev(lv_group_t * group)
|
||||
{
|
||||
if(group->frozen) return;
|
||||
|
||||
if(group->obj_focus) {
|
||||
(*group->obj_focus)->signal_func(*group->obj_focus, LV_SIGNAL_DEFOCUS, NULL);
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
}
|
||||
|
||||
lv_obj_t ** obj_next;
|
||||
if(group->obj_focus == NULL) obj_next = lv_ll_get_tail(&group->obj_ll);
|
||||
else obj_next = lv_ll_get_prev(&group->obj_ll, group->obj_focus);
|
||||
|
||||
if(obj_next == NULL) {
|
||||
if(group->wrap) obj_next = lv_ll_get_tail(&group->obj_ll);
|
||||
else obj_next = lv_ll_get_head(&group->obj_ll);
|
||||
}
|
||||
group->obj_focus = obj_next;
|
||||
|
||||
if(group->obj_focus != NULL) {
|
||||
(*group->obj_focus)->signal_func(*group->obj_focus, LV_SIGNAL_FOCUS, NULL);
|
||||
lv_obj_invalidate(*group->obj_focus);
|
||||
|
||||
if(group->focus_cb) group->focus_cb(group);
|
||||
|
||||
/*If the object or its parent has `top == true` bring it to the foregorund*/
|
||||
obj_to_foreground(*group->obj_focus);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not let to change the focus from the current object
|
||||
* @param group pointer to a group
|
||||
* @param en true: freeze, false: release freezing (normal mode)
|
||||
*/
|
||||
void lv_group_focus_freeze(lv_group_t * group, bool en)
|
||||
{
|
||||
if(en == false) group->frozen = 0;
|
||||
else group->frozen = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a control character to the focuses object of a group
|
||||
* @param group pointer to a group
|
||||
* @param c a character (use LV_GROUP_KEY_.. to navigate)
|
||||
* @return result of focused object in group.
|
||||
*/
|
||||
lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c)
|
||||
{
|
||||
lv_obj_t * act = lv_group_get_focused(group);
|
||||
if(act == NULL) return LV_RES_OK;
|
||||
|
||||
return act->signal_func(act, LV_SIGNAL_CONTROLL, &c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a function for a group which will modify the object's style if it is in focus
|
||||
* @param group pointer to a group
|
||||
* @param style_mod_func the style modifier function pointer
|
||||
*/
|
||||
void lv_group_set_style_mod_cb(lv_group_t * group, lv_group_style_mod_func_t style_mod_func)
|
||||
{
|
||||
group->style_mod = style_mod_func;
|
||||
if(group->obj_focus != NULL) lv_obj_invalidate(*group->obj_focus);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a function for a group which will modify the object's style if it is in focus in edit mode
|
||||
* @param group pointer to a group
|
||||
* @param style_mod_func the style modifier function pointer
|
||||
*/
|
||||
void lv_group_set_style_mod_edit_cb(lv_group_t * group, lv_group_style_mod_func_t style_mod_func)
|
||||
{
|
||||
group->style_mod_edit = style_mod_func;
|
||||
if(group->obj_focus != NULL) lv_obj_invalidate(*group->obj_focus);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a function for a group which will be called when a new object is focused
|
||||
* @param group pointer to a group
|
||||
* @param focus_cb the call back function or NULL if unused
|
||||
*/
|
||||
void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb)
|
||||
{
|
||||
group->focus_cb = focus_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually set the current mode (edit or navigate).
|
||||
* @param group pointer to group
|
||||
* @param edit: true: edit mode; false: navigate mode
|
||||
*/
|
||||
void lv_group_set_editing(lv_group_t * group, bool edit)
|
||||
{
|
||||
uint8_t en_val = edit ? 1 : 0;
|
||||
|
||||
if(en_val == group->editing) return; /*Do not set the same mode again*/
|
||||
|
||||
group->editing = en_val;
|
||||
lv_obj_t * focused = lv_group_get_focused(group);
|
||||
|
||||
if(focused) focused->signal_func(focused, LV_SIGNAL_FOCUS, NULL); /*Focus again to properly leave edit mode*/
|
||||
|
||||
lv_obj_invalidate(focused);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the `click_focus` attribute. If enabled then the object will be focused then it is clicked.
|
||||
* @param group pointer to group
|
||||
* @param en: true: enable `click_focus`
|
||||
*/
|
||||
void lv_group_set_click_focus(lv_group_t * group, bool en)
|
||||
{
|
||||
group->click_focus = en ? 1 : 0;
|
||||
}
|
||||
|
||||
void lv_group_set_refocus_policy(lv_group_t * group, lv_group_refocus_policy_t policy) {
|
||||
group->refocus_policy = policy & 0x01;
|
||||
}
|
||||
|
||||
static void lv_group_refocus(lv_group_t *g) {
|
||||
/*Refocus must temporarily allow wrapping to work correctly*/
|
||||
uint8_t temp_wrap = g->wrap;
|
||||
g->wrap = 1;
|
||||
|
||||
if(g->refocus_policy == LV_GROUP_REFOCUS_POLICY_NEXT)
|
||||
lv_group_focus_next(g);
|
||||
else if(g->refocus_policy == LV_GROUP_REFOCUS_POLICY_PREV)
|
||||
lv_group_focus_prev(g);
|
||||
/*Restore wrap property*/
|
||||
g->wrap = temp_wrap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether focus next/prev will allow wrapping from first->last or last->first.
|
||||
* @param group pointer to group
|
||||
* @param en: true: enable `click_focus`
|
||||
*/
|
||||
void lv_group_set_wrap(lv_group_t * group, bool en)
|
||||
{
|
||||
group->wrap = en ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify a style with the set 'style_mod' function. The input style remains unchanged.
|
||||
* @param group pointer to group
|
||||
* @param style pointer to a style to modify
|
||||
* @return a copy of the input style but modified with the 'style_mod' function
|
||||
*/
|
||||
lv_style_t * lv_group_mod_style(lv_group_t * group, const lv_style_t * style)
|
||||
{
|
||||
lv_style_copy(&group->style_tmp, style);
|
||||
|
||||
if(group->editing) {
|
||||
if(group->style_mod_edit) group->style_mod_edit(&group->style_tmp);
|
||||
} else {
|
||||
if(group->style_mod) group->style_mod(&group->style_tmp);
|
||||
}
|
||||
return &group->style_tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the focused object or NULL if there isn't one
|
||||
* @param group pointer to a group
|
||||
* @return pointer to the focused object
|
||||
*/
|
||||
lv_obj_t * lv_group_get_focused(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return NULL;
|
||||
if(group->obj_focus == NULL) return NULL;
|
||||
|
||||
return *group->obj_focus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a the style modifier function of a group
|
||||
* @param group pointer to a group
|
||||
* @return pointer to the style modifier function
|
||||
*/
|
||||
lv_group_style_mod_func_t lv_group_get_style_mod_cb(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return false;
|
||||
return group->style_mod ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a the style modifier function of a group in edit mode
|
||||
* @param group pointer to a group
|
||||
* @return pointer to the style modifier function
|
||||
*/
|
||||
lv_group_style_mod_func_t lv_group_get_style_mod_edit_cb(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return false;
|
||||
return group->style_mod_edit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the focus callback function of a group
|
||||
* @param group pointer to a group
|
||||
* @return the call back function or NULL if not set
|
||||
*/
|
||||
lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return false;
|
||||
return group->focus_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current mode (edit or navigate).
|
||||
* @param group pointer to group
|
||||
* @return true: edit mode; false: navigate mode
|
||||
*/
|
||||
bool lv_group_get_editing(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return false;
|
||||
return group->editing ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `click_focus` attribute.
|
||||
* @param group pointer to group
|
||||
* @return true: `click_focus` is enabled; false: disabled
|
||||
*/
|
||||
bool lv_group_get_click_focus(const lv_group_t * group)
|
||||
{
|
||||
if(!group) return false;
|
||||
return group->click_focus ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether focus next/prev will allow wrapping from first->last or last->first object.
|
||||
* @param group pointer to group
|
||||
* @param en: true: wrapping enabled; false: wrapping disabled
|
||||
*/
|
||||
bool lv_group_get_wrap(lv_group_t * group)
|
||||
{
|
||||
if(!group) return false;
|
||||
return group->wrap ? true : false;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Default style modifier function
|
||||
* @param style pointer to a style to modify. (Typically group.style_tmp) It will be OVERWRITTEN.
|
||||
*/
|
||||
static void style_mod_def(lv_style_t * style)
|
||||
{
|
||||
#if LV_COLOR_DEPTH != 1
|
||||
|
||||
/*Make the style to be a little bit orange*/
|
||||
style->body.border.opa = LV_OPA_COVER;
|
||||
style->body.border.color = LV_COLOR_ORANGE;
|
||||
|
||||
/*If not empty or has border then emphasis the border*/
|
||||
if(style->body.empty == 0 || style->body.border.width != 0) style->body.border.width = LV_DPI / 20;
|
||||
|
||||
style->body.main_color = lv_color_mix(style->body.main_color, LV_COLOR_ORANGE, LV_OPA_70);
|
||||
style->body.grad_color = lv_color_mix(style->body.grad_color, LV_COLOR_ORANGE, LV_OPA_70);
|
||||
style->body.shadow.color = lv_color_mix(style->body.shadow.color, LV_COLOR_ORANGE, LV_OPA_60);
|
||||
|
||||
style->text.color = lv_color_mix(style->text.color, LV_COLOR_ORANGE, LV_OPA_70);
|
||||
#else
|
||||
style->body.border.opa = LV_OPA_COVER;
|
||||
style->body.border.color = LV_COLOR_BLACK;
|
||||
style->body.border.width = 2;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Default style modifier function
|
||||
* @param style pointer to a style to modify. (Typically group.style_tmp) It will be OVERWRITTEN.
|
||||
*/
|
||||
static void style_mod_edit_def(lv_style_t * style)
|
||||
{
|
||||
#if LV_COLOR_DEPTH != 1
|
||||
|
||||
/*Make the style to be a little bit orange*/
|
||||
style->body.border.opa = LV_OPA_COVER;
|
||||
style->body.border.color = LV_COLOR_GREEN;
|
||||
|
||||
/*If not empty or has border then emphasis the border*/
|
||||
if(style->body.empty == 0 || style->body.border.width != 0) style->body.border.width = LV_DPI / 20;
|
||||
|
||||
style->body.main_color = lv_color_mix(style->body.main_color, LV_COLOR_GREEN, LV_OPA_70);
|
||||
style->body.grad_color = lv_color_mix(style->body.grad_color, LV_COLOR_GREEN, LV_OPA_70);
|
||||
style->body.shadow.color = lv_color_mix(style->body.shadow.color, LV_COLOR_GREEN, LV_OPA_60);
|
||||
|
||||
style->text.color = lv_color_mix(style->text.color, LV_COLOR_GREEN, LV_OPA_70);
|
||||
#else
|
||||
style->body.border.opa = LV_OPA_COVER;
|
||||
style->body.border.color = LV_COLOR_BLACK;
|
||||
style->body.border.width = 3;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void obj_to_foreground(lv_obj_t * obj)
|
||||
{
|
||||
/*Search for 'top' attribute*/
|
||||
lv_obj_t * i = obj;
|
||||
lv_obj_t * last_top = NULL;
|
||||
while(i != NULL) {
|
||||
if(i->top != 0) last_top = i;
|
||||
i = lv_obj_get_parent(i);
|
||||
}
|
||||
|
||||
if(last_top != NULL) {
|
||||
/*Move the last_top object to the foreground*/
|
||||
lv_obj_t * par = lv_obj_get_parent(last_top);
|
||||
/*After list change it will be the new head*/
|
||||
lv_ll_chg_list(&par->child_ll, &par->child_ll, last_top);
|
||||
lv_obj_invalidate(last_top);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*USE_LV_GROUP != 0*/
|
247
bdk/libs/lvgl/lv_core/lv_group.h
Normal file
247
bdk/libs/lvgl/lv_core/lv_group.h
Normal file
|
@ -0,0 +1,247 @@
|
|||
/**
|
||||
* @file lv_group.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GROUP_H
|
||||
#define LV_GROUP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
#include "lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*Predefined keys to control the focused object via lv_group_send(group, c)*/
|
||||
/*For compatibility in signal function define the keys regardless to LV_GROUP*/
|
||||
#define LV_GROUP_KEY_UP 17 /*0x11*/
|
||||
#define LV_GROUP_KEY_DOWN 18 /*0x12*/
|
||||
#define LV_GROUP_KEY_RIGHT 19 /*0x13*/
|
||||
#define LV_GROUP_KEY_LEFT 20 /*0x14*/
|
||||
#define LV_GROUP_KEY_ESC 27 /*0x1B*/
|
||||
#define LV_GROUP_KEY_DEL 127 /*0x7F*/
|
||||
#define LV_GROUP_KEY_BACKSPACE 8 /*0x08*/
|
||||
#define LV_GROUP_KEY_ENTER 10 /*0x0A, '\n'*/
|
||||
#define LV_GROUP_KEY_NEXT 9 /*0x09, '\t'*/
|
||||
#define LV_GROUP_KEY_PREV 11 /*0x0B, '*/
|
||||
|
||||
#if USE_LV_GROUP != 0
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
struct _lv_group_t;
|
||||
|
||||
typedef void (*lv_group_style_mod_func_t)(lv_style_t *);
|
||||
typedef void (*lv_group_focus_cb_t)(struct _lv_group_t *);
|
||||
|
||||
typedef struct _lv_group_t
|
||||
{
|
||||
lv_ll_t obj_ll; /*Linked list to store the objects in the group */
|
||||
lv_obj_t ** obj_focus; /*The object in focus*/
|
||||
lv_group_style_mod_func_t style_mod; /*A function which modifies the style of the focused object*/
|
||||
lv_group_style_mod_func_t style_mod_edit;/*A function which modifies the style of the focused object*/
|
||||
lv_group_focus_cb_t focus_cb; /*A function to call when a new object is focused (optional)*/
|
||||
lv_style_t style_tmp; /*Stores the modified style of the focused object */
|
||||
uint8_t frozen :1; /*1: can't focus to new object*/
|
||||
uint8_t editing :1; /*1: Edit mode, 0: Navigate mode*/
|
||||
uint8_t click_focus :1; /*1: If an object in a group is clicked by an indev then it will be focused */
|
||||
uint8_t refocus_policy :1; /*1: Focus prev if focused on deletion. 0: Focus prev if focused on deletion.*/
|
||||
uint8_t wrap :1; /*1: Focus next/prev can wrap at end of list. 0: Focus next/prev stops at end of list.*/
|
||||
} lv_group_t;
|
||||
|
||||
typedef enum _lv_group_refocus_policy_t {
|
||||
LV_GROUP_REFOCUS_POLICY_NEXT = 0,
|
||||
LV_GROUP_REFOCUS_POLICY_PREV = 1
|
||||
} lv_group_refocus_policy_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a new object group
|
||||
* @return pointer to the new object group
|
||||
*/
|
||||
lv_group_t * lv_group_create(void);
|
||||
|
||||
/**
|
||||
* Delete a group object
|
||||
* @param group pointer to a group
|
||||
*/
|
||||
void lv_group_del(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Add an object to a group
|
||||
* @param group pointer to a group
|
||||
* @param obj pointer to an object to add
|
||||
*/
|
||||
void lv_group_add_obj(lv_group_t * group, lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Remove an object from its group
|
||||
* @param obj pointer to an object to remove
|
||||
*/
|
||||
void lv_group_remove_obj(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Focus on an object (defocus the current)
|
||||
* @param obj pointer to an object to focus on
|
||||
*/
|
||||
void lv_group_focus_obj(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Focus the next object in a group (defocus the current)
|
||||
* @param group pointer to a group
|
||||
*/
|
||||
void lv_group_focus_next(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Focus the previous object in a group (defocus the current)
|
||||
* @param group pointer to a group
|
||||
*/
|
||||
void lv_group_focus_prev(lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Do not let to change the focus from the current object
|
||||
* @param group pointer to a group
|
||||
* @param en true: freeze, false: release freezing (normal mode)
|
||||
*/
|
||||
void lv_group_focus_freeze(lv_group_t * group, bool en);
|
||||
|
||||
/**
|
||||
* Send a control character to the focuses object of a group
|
||||
* @param group pointer to a group
|
||||
* @param c a character (use LV_GROUP_KEY_.. to navigate)
|
||||
* @return result of focused object in group.
|
||||
*/
|
||||
lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c);
|
||||
|
||||
/**
|
||||
* Set a function for a group which will modify the object's style if it is in focus
|
||||
* @param group pointer to a group
|
||||
* @param style_mod_func the style modifier function pointer
|
||||
*/
|
||||
void lv_group_set_style_mod_cb(lv_group_t * group, lv_group_style_mod_func_t style_mod_func);
|
||||
|
||||
/**
|
||||
* Set a function for a group which will modify the object's style if it is in focus in edit mode
|
||||
* @param group pointer to a group
|
||||
* @param style_mod_func the style modifier function pointer
|
||||
*/
|
||||
void lv_group_set_style_mod_edit_cb(lv_group_t * group, lv_group_style_mod_func_t style_mod_func);
|
||||
|
||||
/**
|
||||
* Set a function for a group which will be called when a new object is focused
|
||||
* @param group pointer to a group
|
||||
* @param focus_cb the call back function or NULL if unused
|
||||
*/
|
||||
void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb);
|
||||
|
||||
/**
|
||||
* Set whether the next or previous item in a group is focused if the currently focussed obj is deleted.
|
||||
* @param group pointer to a group
|
||||
* @param new refocus policy enum
|
||||
*/
|
||||
void lv_group_set_refocus_policy(lv_group_t * group, lv_group_refocus_policy_t policy);
|
||||
|
||||
/**
|
||||
* Manually set the current mode (edit or navigate).
|
||||
* @param group pointer to group
|
||||
* @param edit: true: edit mode; false: navigate mode
|
||||
*/
|
||||
void lv_group_set_editing(lv_group_t * group, bool edit);
|
||||
|
||||
/**
|
||||
* Set the `click_focus` attribute. If enabled then the object will be focused then it is clicked.
|
||||
* @param group pointer to group
|
||||
* @param en: true: enable `click_focus`
|
||||
*/
|
||||
void lv_group_set_click_focus(lv_group_t * group, bool en);
|
||||
|
||||
/**
|
||||
* Set whether focus next/prev will allow wrapping from first->last or last->first object.
|
||||
* @param group pointer to group
|
||||
* @param en: true: wrapping enabled; false: wrapping disabled
|
||||
*/
|
||||
void lv_group_set_wrap(lv_group_t * group, bool en);
|
||||
|
||||
/**
|
||||
* Modify a style with the set 'style_mod' function. The input style remains unchanged.
|
||||
* @param group pointer to group
|
||||
* @param style pointer to a style to modify
|
||||
* @return a copy of the input style but modified with the 'style_mod' function
|
||||
*/
|
||||
lv_style_t * lv_group_mod_style(lv_group_t * group, const lv_style_t * style);
|
||||
|
||||
/**
|
||||
* Get the focused object or NULL if there isn't one
|
||||
* @param group pointer to a group
|
||||
* @return pointer to the focused object
|
||||
*/
|
||||
lv_obj_t * lv_group_get_focused(const lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get a the style modifier function of a group
|
||||
* @param group pointer to a group
|
||||
* @return pointer to the style modifier function
|
||||
*/
|
||||
lv_group_style_mod_func_t lv_group_get_style_mod_cb(const lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get a the style modifier function of a group in edit mode
|
||||
* @param group pointer to a group
|
||||
* @return pointer to the style modifier function
|
||||
*/
|
||||
lv_group_style_mod_func_t lv_group_get_style_mod_edit_cb(const lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get the focus callback function of a group
|
||||
* @param group pointer to a group
|
||||
* @return the call back function or NULL if not set
|
||||
*/
|
||||
lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get the current mode (edit or navigate).
|
||||
* @param group pointer to group
|
||||
* @return true: edit mode; false: navigate mode
|
||||
*/
|
||||
bool lv_group_get_editing(const lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get the `click_focus` attribute.
|
||||
* @param group pointer to group
|
||||
* @return true: `click_focus` is enabled; false: disabled
|
||||
*/
|
||||
bool lv_group_get_click_focus(const lv_group_t * group);
|
||||
|
||||
/**
|
||||
* Get whether focus next/prev will allow wrapping from first->last or last->first object.
|
||||
* @param group pointer to group
|
||||
* @param en: true: wrapping enabled; false: wrapping disabled
|
||||
*/
|
||||
bool lv_group_get_wrap(lv_group_t * group);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_GROUP != 0*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_GROUP_H*/
|
971
bdk/libs/lvgl/lv_core/lv_indev.c
Normal file
971
bdk/libs/lvgl/lv_core/lv_indev.c
Normal file
|
@ -0,0 +1,971 @@
|
|||
/**
|
||||
* @file lv_indev_proc.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
********************/
|
||||
#include "lv_indev.h"
|
||||
|
||||
#include "../lv_hal/lv_hal_tick.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_core/lv_refr.h"
|
||||
#include "../lv_misc/lv_task.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_draw/lv_draw_rbasic.h"
|
||||
#include "lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if LV_INDEV_DRAG_THROW <= 0
|
||||
#warning "LV_INDEV_DRAG_THROW must be greater than 0"
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
#if LV_INDEV_READ_PERIOD != 0
|
||||
static void indev_proc_task(void * param);
|
||||
static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data);
|
||||
static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data);
|
||||
static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data);
|
||||
static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data);
|
||||
static void indev_proc_press(lv_indev_proc_t * proc);
|
||||
static void indev_proc_release(lv_indev_proc_t * proc);
|
||||
static void indev_proc_reset_query_handler(lv_indev_t * indev);
|
||||
static lv_obj_t * indev_search_obj(const lv_indev_proc_t * proc, lv_obj_t * obj);
|
||||
static void indev_drag(lv_indev_proc_t * state);
|
||||
static void indev_drag_throw(lv_indev_proc_t * state);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_indev_t * indev_act;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the display input device subsystem
|
||||
*/
|
||||
void lv_indev_init(void)
|
||||
{
|
||||
#if LV_INDEV_READ_PERIOD != 0
|
||||
lv_task_create(indev_proc_task, LV_INDEV_READ_PERIOD, LV_TASK_PRIO_MID, NULL);
|
||||
#endif
|
||||
|
||||
lv_indev_reset(NULL); /*Reset all input devices*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently processed input device. Can be used in action functions too.
|
||||
* @return pointer to the currently processed input device or NULL if no input device processing right now
|
||||
*/
|
||||
lv_indev_t * lv_indev_get_act(void)
|
||||
{
|
||||
return indev_act;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of an input device
|
||||
* @param indev pointer to an input device
|
||||
* @return the type of the input device from `lv_hal_indev_type_t` (`LV_INDEV_TYPE_...`)
|
||||
*/
|
||||
lv_hal_indev_type_t lv_indev_get_type(const lv_indev_t * indev)
|
||||
{
|
||||
if(indev == NULL) return LV_INDEV_TYPE_NONE;
|
||||
|
||||
return indev->driver.type;
|
||||
}
|
||||
/**
|
||||
* Reset one or all input devices
|
||||
* @param indev pointer to an input device to reset or NULL to reset all of them
|
||||
*/
|
||||
void lv_indev_reset(lv_indev_t * indev)
|
||||
{
|
||||
if(indev) indev->proc.reset_query = 1;
|
||||
else {
|
||||
lv_indev_t * i = lv_indev_next(NULL);
|
||||
while(i) {
|
||||
i->proc.reset_query = 1;
|
||||
i = lv_indev_next(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the long press state of an input device
|
||||
* @param indev pointer to an input device
|
||||
*/
|
||||
void lv_indev_reset_lpr(lv_indev_t * indev)
|
||||
{
|
||||
indev->proc.long_pr_sent = 0;
|
||||
indev->proc.longpr_rep_timestamp = lv_tick_get();
|
||||
indev->proc.pr_timestamp = lv_tick_get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable input devices device by type
|
||||
* @param type Input device type
|
||||
* @param enable true: enable this type; false: disable this type
|
||||
*/
|
||||
void lv_indev_enable(lv_hal_indev_type_t type, bool enable)
|
||||
{
|
||||
lv_indev_t * i = lv_indev_next(NULL);
|
||||
|
||||
while(i) {
|
||||
if(i->driver.type == type) i->proc.disabled = enable == false ? 1 : 0;
|
||||
i = lv_indev_next(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cursor for a pointer input device (for LV_INPUT_TYPE_POINTER and LV_INPUT_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @param cur_obj pointer to an object to be used as cursor
|
||||
*/
|
||||
void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj)
|
||||
{
|
||||
if(indev->driver.type != LV_INDEV_TYPE_POINTER) return;
|
||||
|
||||
indev->cursor = cur_obj;
|
||||
if (indev->cursor)
|
||||
{
|
||||
lv_obj_set_parent(indev->cursor, lv_layer_sys());
|
||||
lv_obj_set_pos(indev->cursor, indev->proc.act_point.x, indev->proc.act_point.y);
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_LV_GROUP
|
||||
/**
|
||||
* Set a destination group for a keypad input device (for LV_INDEV_TYPE_KEYPAD)
|
||||
* @param indev pointer to an input device
|
||||
* @param group point to a group
|
||||
*/
|
||||
void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group)
|
||||
{
|
||||
if(indev->driver.type == LV_INDEV_TYPE_KEYPAD || indev->driver.type == LV_INDEV_TYPE_ENCODER) indev->group = group;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set the an array of points for LV_INDEV_TYPE_BUTTON.
|
||||
* These points will be assigned to the buttons to press a specific point on the screen
|
||||
* @param indev pointer to an input device
|
||||
* @param group point to a group
|
||||
*/
|
||||
void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t * points)
|
||||
{
|
||||
if(indev->driver.type == LV_INDEV_TYPE_BUTTON) indev->btn_points = points;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set feedback callback for indev.
|
||||
* @param indev pointer to an input device
|
||||
* @param feedback feedback callback
|
||||
*/
|
||||
void lv_indev_set_feedback(lv_indev_t *indev, lv_indev_feedback_t feedback)
|
||||
{
|
||||
indev->feedback = feedback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last point of an input device (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @param point pointer to a point to store the result
|
||||
*/
|
||||
void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point)
|
||||
{
|
||||
if(indev->driver.type != LV_INDEV_TYPE_POINTER && indev->driver.type != LV_INDEV_TYPE_BUTTON) {
|
||||
point->x = -1;
|
||||
point->y = -1;
|
||||
} else {
|
||||
point->x = indev->proc.act_point.x;
|
||||
point->y = indev->proc.act_point.y;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last key of an input device (for LV_INDEV_TYPE_KEYPAD)
|
||||
* @param indev pointer to an input device
|
||||
* @return the last pressed key (0 on error)
|
||||
*/
|
||||
uint32_t lv_indev_get_key(const lv_indev_t * indev)
|
||||
{
|
||||
if(indev->driver.type != LV_INDEV_TYPE_KEYPAD) return 0;
|
||||
else return indev->proc.last_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is dragging with an input device or not (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @return true: drag is in progress
|
||||
*/
|
||||
bool lv_indev_is_dragging(const lv_indev_t * indev)
|
||||
{
|
||||
if(indev == NULL) return false;
|
||||
if(indev->driver.type != LV_INDEV_TYPE_POINTER && indev->driver.type != LV_INDEV_TYPE_BUTTON) return false;
|
||||
return indev->proc.drag_in_prog == 0 ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the vector of dragging of an input device (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @param point pointer to a point to store the vector
|
||||
*/
|
||||
void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point)
|
||||
{
|
||||
if(indev == NULL) {
|
||||
point->x = 0;
|
||||
point->y = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(indev->driver.type != LV_INDEV_TYPE_POINTER && indev->driver.type != LV_INDEV_TYPE_BUTTON) {
|
||||
point->x = 0;
|
||||
point->y = 0;
|
||||
} else {
|
||||
point->x = indev->proc.vect.x;
|
||||
point->y = indev->proc.vect.y;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get elapsed time since last press
|
||||
* @param indev pointer to an input device (NULL to get the overall smallest inactivity)
|
||||
* @return Elapsed ticks (milliseconds) since last press
|
||||
*/
|
||||
uint32_t lv_indev_get_inactive_time(const lv_indev_t * indev)
|
||||
{
|
||||
uint32_t t;
|
||||
|
||||
if(indev) return t = lv_tick_elaps(indev->last_activity_time);
|
||||
|
||||
lv_indev_t * i;
|
||||
t = UINT16_MAX;
|
||||
i = lv_indev_next(NULL);
|
||||
while(i) {
|
||||
t = LV_MATH_MIN(t, lv_tick_elaps(i->last_activity_time));
|
||||
i = lv_indev_next(i);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get feedback callback for indev.
|
||||
* @param indev pointer to an input device
|
||||
* @return feedback callback
|
||||
*/
|
||||
lv_indev_feedback_t lv_indev_get_feedback(const lv_indev_t *indev)
|
||||
{
|
||||
return indev->feedback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing until the next release
|
||||
* @param indev pointer to an input device
|
||||
*/
|
||||
void lv_indev_wait_release(lv_indev_t * indev)
|
||||
{
|
||||
indev->proc.wait_unil_release = 1;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#if LV_INDEV_READ_PERIOD != 0
|
||||
/**
|
||||
* Called periodically to handle the input devices
|
||||
* @param param unused
|
||||
*/
|
||||
static void indev_proc_task(void * param)
|
||||
{
|
||||
(void)param;
|
||||
|
||||
|
||||
LV_LOG_TRACE("indev task started");
|
||||
|
||||
lv_indev_data_t data;
|
||||
lv_indev_t * i;
|
||||
i = lv_indev_next(NULL);
|
||||
|
||||
/*Read and process all indevs*/
|
||||
while(i) {
|
||||
indev_act = i;
|
||||
|
||||
/*Handle reset query before processing the point*/
|
||||
indev_proc_reset_query_handler(i);
|
||||
|
||||
if(i->proc.disabled == 0) {
|
||||
bool more_to_read;
|
||||
do {
|
||||
/*Read the data*/
|
||||
more_to_read = lv_indev_read(i, &data);
|
||||
indev_proc_reset_query_handler(i); /*The active object might deleted even in the read function*/
|
||||
i->proc.state = data.state;
|
||||
|
||||
if(i->proc.state == LV_INDEV_STATE_PR) {
|
||||
i->last_activity_time = lv_tick_get();
|
||||
}
|
||||
|
||||
if(i->driver.type == LV_INDEV_TYPE_POINTER) {
|
||||
indev_pointer_proc(i, &data);
|
||||
} else if(i->driver.type == LV_INDEV_TYPE_KEYPAD) {
|
||||
indev_keypad_proc(i, &data);
|
||||
} else if(i->driver.type == LV_INDEV_TYPE_ENCODER) {
|
||||
indev_encoder_proc(i, &data);
|
||||
} else if(i->driver.type == LV_INDEV_TYPE_BUTTON) {
|
||||
indev_button_proc(i, &data);
|
||||
}
|
||||
/*Handle reset query if it happened in during processing*/
|
||||
indev_proc_reset_query_handler(i);
|
||||
} while(more_to_read);
|
||||
}
|
||||
i = lv_indev_next(i); /*Go to the next indev*/
|
||||
}
|
||||
|
||||
indev_act = NULL; /*End of indev processing, so no act indev*/
|
||||
|
||||
LV_LOG_TRACE("indev task finished");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process a new point from LV_INDEV_TYPE_POINTER input device
|
||||
* @param i pointer to an input device
|
||||
* @param data pointer to the data read from the input device
|
||||
*/
|
||||
static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data)
|
||||
{
|
||||
/*Move the cursor if set and moved*/
|
||||
if(i->cursor != NULL &&
|
||||
(i->proc.last_point.x != data->point.x ||
|
||||
i->proc.last_point.y != data->point.y)) {
|
||||
/*Use cursor's center as pointer*/
|
||||
uint32_t off_x = lv_obj_get_width(i->cursor) >> 1;
|
||||
uint32_t off_y = lv_obj_get_height(i->cursor) >> 1;
|
||||
lv_obj_set_pos(i->cursor, data->point.x - off_x, data->point.y - off_y);
|
||||
}
|
||||
|
||||
i->proc.act_point.x = data->point.x;
|
||||
i->proc.act_point.y = data->point.y;
|
||||
|
||||
if(i->proc.state == LV_INDEV_STATE_PR) {
|
||||
#if LV_INDEV_POINT_MARKER != 0
|
||||
lv_area_t area;
|
||||
area.x1 = i->proc.act_point.x - (LV_INDEV_POINT_MARKER >> 1);
|
||||
area.y1 = i->proc.act_point.y - (LV_INDEV_POINT_MARKER >> 1);
|
||||
area.x2 = i->proc.act_point.x + ((LV_INDEV_POINT_MARKER >> 1) | 0x1);
|
||||
area.y2 = i->proc.act_point.y + ((LV_INDEV_POINT_MARKER >> 1) | 0x1);
|
||||
lv_rfill(&area, NULL, LV_COLOR_MAKE(0xFF, 0, 0), LV_OPA_COVER);
|
||||
#endif
|
||||
indev_proc_press(&i->proc);
|
||||
} else {
|
||||
indev_proc_release(&i->proc);
|
||||
}
|
||||
|
||||
i->proc.last_point.x = i->proc.act_point.x;
|
||||
i->proc.last_point.y = i->proc.act_point.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a new point from LV_INDEV_TYPE_KEYPAD input device
|
||||
* @param i pointer to an input device
|
||||
* @param data pointer to the data read from the input device
|
||||
*/
|
||||
static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data)
|
||||
{
|
||||
#if USE_LV_GROUP
|
||||
if(i->group == NULL) return;
|
||||
|
||||
/*Key press happened*/
|
||||
if(data->state == LV_INDEV_STATE_PR &&
|
||||
i->proc.last_state == LV_INDEV_STATE_REL) {
|
||||
i->proc.pr_timestamp = lv_tick_get();
|
||||
lv_obj_t * focused = lv_group_get_focused(i->group);
|
||||
if(focused && data->key == LV_GROUP_KEY_ENTER) {
|
||||
focused->signal_func(focused, LV_SIGNAL_PRESSED, indev_act);
|
||||
}
|
||||
}
|
||||
/*Pressing*/
|
||||
else if(data->state == LV_INDEV_STATE_PR && i->proc.last_state == LV_INDEV_STATE_PR) {
|
||||
if(data->key == LV_GROUP_KEY_ENTER &&
|
||||
i->proc.long_pr_sent == 0 &&
|
||||
lv_tick_elaps(i->proc.pr_timestamp) > LV_INDEV_LONG_PRESS_TIME) {
|
||||
/*On enter long press leave edit mode.*/
|
||||
lv_obj_t * focused = lv_group_get_focused(i->group);
|
||||
if(focused) {
|
||||
focused->signal_func(focused, LV_SIGNAL_LONG_PRESS, indev_act);
|
||||
i->proc.long_pr_sent = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*Release happened*/
|
||||
else if(data->state == LV_INDEV_STATE_REL && i->proc.last_state == LV_INDEV_STATE_PR) {
|
||||
/*The user might clear the key when it was released. Always release the pressed key*/
|
||||
data->key = i->proc.last_key;
|
||||
|
||||
/* Edit mode is not used by KEYPAD devices.
|
||||
* So leave edit mode if we are in it before focusing on the next/prev object*/
|
||||
if(data->key == LV_GROUP_KEY_NEXT || data->key == LV_GROUP_KEY_PREV) {
|
||||
lv_group_set_editing(i->group, false);
|
||||
}
|
||||
|
||||
if(data->key == LV_GROUP_KEY_NEXT) {
|
||||
lv_group_focus_next(i->group);
|
||||
} else if(data->key == LV_GROUP_KEY_PREV) {
|
||||
lv_group_focus_prev(i->group);
|
||||
} else if(data->key == LV_GROUP_KEY_ENTER) {
|
||||
if(!i->proc.long_pr_sent) {
|
||||
lv_group_send_data(i->group, data->key);
|
||||
}
|
||||
} else {
|
||||
lv_group_send_data(i->group, data->key);
|
||||
}
|
||||
|
||||
if(i->proc.reset_query) return; /*The object might be deleted in `focus_cb` or due to any other user event*/
|
||||
|
||||
i->proc.pr_timestamp = 0;
|
||||
i->proc.long_pr_sent = 0;
|
||||
}
|
||||
|
||||
i->proc.last_state = data->state;
|
||||
i->proc.last_key = data->key;
|
||||
#else
|
||||
(void)data; /*Unused*/
|
||||
(void)i; /*Unused*/
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a new point from LV_INDEV_TYPE_ENCODER input device
|
||||
* @param i pointer to an input device
|
||||
* @param data pointer to the data read from the input device
|
||||
*/
|
||||
static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data)
|
||||
{
|
||||
#if USE_LV_GROUP
|
||||
if(i->group == NULL) return;
|
||||
|
||||
/*Process the steps first. They are valid only with released button*/
|
||||
if(data->state == LV_INDEV_STATE_REL) {
|
||||
/*In edit mode send LEFT/RIGHT keys*/
|
||||
if(lv_group_get_editing(i->group)) {
|
||||
int32_t s;
|
||||
if(data->enc_diff < 0) {
|
||||
for(s = 0; s < -data->enc_diff; s++) lv_group_send_data(i->group, LV_GROUP_KEY_LEFT);
|
||||
} else if(data->enc_diff > 0) {
|
||||
for(s = 0; s < data->enc_diff; s++) lv_group_send_data(i->group, LV_GROUP_KEY_RIGHT);
|
||||
}
|
||||
}
|
||||
/*In navigate mode focus on the next/prev objects*/
|
||||
else {
|
||||
int32_t s;
|
||||
if(data->enc_diff < 0) {
|
||||
for(s = 0; s < -data->enc_diff; s++) lv_group_focus_prev(i->group);
|
||||
} else if(data->enc_diff > 0) {
|
||||
for(s = 0; s < data->enc_diff; s++) lv_group_focus_next(i->group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*Key press happened*/
|
||||
if(data->state == LV_INDEV_STATE_PR &&
|
||||
i->proc.last_state == LV_INDEV_STATE_REL) {
|
||||
i->proc.pr_timestamp = lv_tick_get();
|
||||
}
|
||||
/*Pressing*/
|
||||
else if(data->state == LV_INDEV_STATE_PR && i->proc.last_state == LV_INDEV_STATE_PR) {
|
||||
if(i->proc.long_pr_sent == 0 &&
|
||||
lv_tick_elaps(i->proc.pr_timestamp) > LV_INDEV_LONG_PRESS_TIME) {
|
||||
/*On enter long press leave edit mode.*/
|
||||
lv_obj_t * focused = lv_group_get_focused(i->group);
|
||||
|
||||
bool editable = false;
|
||||
if(focused) focused->signal_func(focused, LV_SIGNAL_GET_EDITABLE, &editable);
|
||||
|
||||
if(editable) {
|
||||
if(i->group->obj_ll.head != i->group->obj_ll.tail)
|
||||
lv_group_set_editing(i->group, lv_group_get_editing(i->group) ? false : true); /*Toggle edit mode on long press*/
|
||||
else if(focused)
|
||||
focused->signal_func(focused, LV_SIGNAL_LONG_PRESS, indev_act);
|
||||
}
|
||||
/*If not editable then just send a long press signal*/
|
||||
else {
|
||||
if(focused)
|
||||
focused->signal_func(focused, LV_SIGNAL_LONG_PRESS, indev_act);
|
||||
}
|
||||
i->proc.long_pr_sent = 1;
|
||||
}
|
||||
}
|
||||
/*Release happened*/
|
||||
else if(data->state == LV_INDEV_STATE_REL && i->proc.last_state == LV_INDEV_STATE_PR) {
|
||||
lv_obj_t * focused = lv_group_get_focused(i->group);
|
||||
bool editable = false;
|
||||
if(focused) focused->signal_func(focused, LV_SIGNAL_GET_EDITABLE, &editable);
|
||||
|
||||
/*The button was released on a non-editable object. Just send enter*/
|
||||
if(!editable) {
|
||||
lv_group_send_data(i->group, LV_GROUP_KEY_ENTER);
|
||||
}
|
||||
/*An object is being edited and the button is releases. Just send enter */
|
||||
else if(i->group->editing) {
|
||||
if(!i->proc.long_pr_sent || i->group->obj_ll.head == i->group->obj_ll.tail)
|
||||
lv_group_send_data(i->group, LV_GROUP_KEY_ENTER); /*Ignore long pressed enter release because it comes from mode switch*/
|
||||
}
|
||||
/*If the focused object is editable and now in navigate mode then enter edit mode*/
|
||||
else if(editable && !i->group->editing && !i->proc.long_pr_sent) {
|
||||
lv_group_set_editing(i->group, lv_group_get_editing(i->group) ? false : true); /*Toggle edit mode on long press*/
|
||||
}
|
||||
|
||||
if(i->proc.reset_query) return; /*The object might be deleted in `focus_cb` or due to any other user event*/
|
||||
|
||||
i->proc.pr_timestamp = 0;
|
||||
i->proc.long_pr_sent = 0;
|
||||
}
|
||||
|
||||
i->proc.last_state = data->state;
|
||||
i->proc.last_key = data->key;
|
||||
#else
|
||||
(void)data; /*Unused*/
|
||||
(void)i; /*Unused*/
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Process new points from a input device. indev->state.pressed has to be set
|
||||
* @param indev pointer to an input device state
|
||||
* @param x x coordinate of the next point
|
||||
* @param y y coordinate of the next point
|
||||
*/
|
||||
static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data)
|
||||
{
|
||||
i->proc.act_point.x = i->btn_points[data->btn].x;
|
||||
i->proc.act_point.y = i->btn_points[data->btn].y;
|
||||
|
||||
/*Still the same point is pressed*/
|
||||
if(i->proc.last_point.x == i->proc.act_point.x &&
|
||||
i->proc.last_point.y == i->proc.act_point.y &&
|
||||
data->state == LV_INDEV_STATE_PR) {
|
||||
#if LV_INDEV_POINT_MARKER != 0
|
||||
lv_area_t area;
|
||||
area.x1 = i->proc.act_point.x - (LV_INDEV_POINT_MARKER >> 1);
|
||||
area.y1 = i->proc.act_point.y - (LV_INDEV_POINT_MARKER >> 1);
|
||||
area.x2 = i->proc.act_point.x + ((LV_INDEV_POINT_MARKER >> 1) | 0x1);
|
||||
area.y2 = i->proc.act_point.y + ((LV_INDEV_POINT_MARKER >> 1) | 0x1);
|
||||
lv_rfill(&area, NULL, LV_COLOR_MAKE(0xFF, 0, 0), LV_OPA_COVER);
|
||||
#endif
|
||||
indev_proc_press(&i->proc);
|
||||
} else {
|
||||
/*If a new point comes always make a release*/
|
||||
indev_proc_release(&i->proc);
|
||||
}
|
||||
|
||||
i->proc.last_point.x = i->proc.act_point.x;
|
||||
i->proc.last_point.y = i->proc.act_point.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the pressed state of LV_INDEV_TYPE_POINER input devices
|
||||
* @param indev pointer to an input device 'proc'
|
||||
*/
|
||||
static void indev_proc_press(lv_indev_proc_t * proc)
|
||||
{
|
||||
lv_obj_t * pr_obj = proc->act_obj;
|
||||
|
||||
if(proc->wait_unil_release != 0) return;
|
||||
|
||||
/*If there is no last object then search*/
|
||||
if(proc->act_obj == NULL) {
|
||||
pr_obj = indev_search_obj(proc, lv_layer_top());
|
||||
if(pr_obj == NULL) pr_obj = indev_search_obj(proc, lv_scr_act());
|
||||
}
|
||||
/*If there is last object but it is not dragged and not protected also search*/
|
||||
else if(proc->drag_in_prog == 0 &&
|
||||
lv_obj_is_protected(proc->act_obj, LV_PROTECT_PRESS_LOST) == false) {/*Now act_obj != NULL*/
|
||||
pr_obj = indev_search_obj(proc, lv_layer_top());
|
||||
if(pr_obj == NULL) pr_obj = indev_search_obj(proc, lv_scr_act());
|
||||
}
|
||||
/*If a dragable or a protected object was the last then keep it*/
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
/*If a new object was found reset some variables and send a pressed signal*/
|
||||
if(pr_obj != proc->act_obj) {
|
||||
|
||||
proc->last_point.x = proc->act_point.x;
|
||||
proc->last_point.y = proc->act_point.y;
|
||||
|
||||
/*If a new object found the previous was lost, so send a signal*/
|
||||
if(proc->act_obj != NULL) {
|
||||
proc->act_obj->signal_func(proc->act_obj, LV_SIGNAL_PRESS_LOST, indev_act);
|
||||
if(proc->reset_query != 0) return;
|
||||
}
|
||||
|
||||
proc->act_obj = pr_obj; /*Save the pressed object*/
|
||||
proc->last_obj = proc->act_obj; /*Refresh the last_obj*/
|
||||
|
||||
if(proc->act_obj != NULL) {
|
||||
/* Save the time when the obj pressed.
|
||||
* It is necessary to count the long press time.*/
|
||||
proc->pr_timestamp = lv_tick_get();
|
||||
proc->long_pr_sent = 0;
|
||||
proc->drag_range_out = 0;
|
||||
proc->drag_in_prog = 0;
|
||||
proc->drag_sum.x = 0;
|
||||
proc->drag_sum.y = 0;
|
||||
proc->vect.x = 0;
|
||||
proc->vect.y = 0;
|
||||
|
||||
/*Search for 'top' attribute*/
|
||||
lv_obj_t * i = proc->act_obj;
|
||||
lv_obj_t * last_top = NULL;
|
||||
while(i != NULL) {
|
||||
if(i->top != 0) last_top = i;
|
||||
i = lv_obj_get_parent(i);
|
||||
}
|
||||
|
||||
if(last_top != NULL) {
|
||||
/*Move the last_top object to the foreground*/
|
||||
lv_obj_t * par = lv_obj_get_parent(last_top);
|
||||
/*After list change it will be the new head*/
|
||||
lv_ll_chg_list(&par->child_ll, &par->child_ll, last_top);
|
||||
lv_obj_invalidate(last_top);
|
||||
}
|
||||
|
||||
/*Send a signal about the press*/
|
||||
proc->act_obj->signal_func(proc->act_obj, LV_SIGNAL_PRESSED, indev_act);
|
||||
if(proc->reset_query != 0) return;
|
||||
}
|
||||
}
|
||||
|
||||
/*Calculate the vector*/
|
||||
proc->vect.x = proc->act_point.x - proc->last_point.x;
|
||||
proc->vect.y = proc->act_point.y - proc->last_point.y;
|
||||
|
||||
/*If there is active object and it can be dragged run the drag*/
|
||||
if(proc->act_obj != NULL) {
|
||||
proc->act_obj->signal_func(proc->act_obj, LV_SIGNAL_PRESSING, indev_act);
|
||||
if(proc->reset_query != 0) return;
|
||||
|
||||
indev_drag(proc);
|
||||
if(proc->reset_query != 0) return;
|
||||
|
||||
/*If there is no drag then check for long press time*/
|
||||
if(proc->drag_in_prog == 0 && proc->long_pr_sent == 0) {
|
||||
/*Send a signal about the long press if enough time elapsed*/
|
||||
if(lv_tick_elaps(proc->pr_timestamp) > LV_INDEV_LONG_PRESS_TIME) {
|
||||
pr_obj->signal_func(pr_obj, LV_SIGNAL_LONG_PRESS, indev_act);
|
||||
if(proc->reset_query != 0) return;
|
||||
|
||||
/*Mark the signal sending to do not send it again*/
|
||||
proc->long_pr_sent = 1;
|
||||
|
||||
/*Save the long press time stamp for the long press repeat handler*/
|
||||
proc->longpr_rep_timestamp = lv_tick_get();
|
||||
}
|
||||
}
|
||||
/*Send long press repeated signal*/
|
||||
if(proc->drag_in_prog == 0 && proc->long_pr_sent == 1) {
|
||||
/*Send a signal about the long press repeate if enough time elapsed*/
|
||||
if(lv_tick_elaps(proc->longpr_rep_timestamp) > LV_INDEV_LONG_PRESS_REP_TIME) {
|
||||
pr_obj->signal_func(pr_obj, LV_SIGNAL_LONG_PRESS_REP, indev_act);
|
||||
if(proc->reset_query != 0) return;
|
||||
proc->longpr_rep_timestamp = lv_tick_get();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the released state of LV_INDEV_TYPE_POINER input devices
|
||||
* @param proc pointer to an input device 'proc'
|
||||
*/
|
||||
static void indev_proc_release(lv_indev_proc_t * proc)
|
||||
{
|
||||
if(proc->wait_unil_release != 0) {
|
||||
proc->act_obj = NULL;
|
||||
proc->last_obj = NULL;
|
||||
proc->pr_timestamp = 0;
|
||||
proc->longpr_rep_timestamp = 0;
|
||||
proc->wait_unil_release = 0;
|
||||
}
|
||||
|
||||
/*Forgot the act obj and send a released signal */
|
||||
if(proc->act_obj != NULL) {
|
||||
/* If the object was protected against press lost then it possible that
|
||||
* the object is already not pressed but still it is the `act_obj`.
|
||||
* In this case send the `LV_SIGNAL_RELEASED` if the indev is ON the `act_obj` */
|
||||
if(lv_obj_is_protected(proc->act_obj, LV_PROTECT_PRESS_LOST)) {
|
||||
/* Search the object on the current current coordinates.
|
||||
* The start object is the object itself. If not ON it the the result will be NULL*/
|
||||
lv_obj_t * obj_on = indev_search_obj(proc, proc->act_obj);
|
||||
if(obj_on == proc->act_obj) proc->act_obj->signal_func(proc->act_obj, LV_SIGNAL_RELEASED, indev_act);
|
||||
else proc->act_obj->signal_func(proc->act_obj, LV_SIGNAL_PRESS_LOST, indev_act);
|
||||
|
||||
}
|
||||
/* The simple case: `act_obj` was not protected against press lost.
|
||||
* If it is already not pressed then was handled in `indev_proc_press`*/
|
||||
else {
|
||||
proc->act_obj->signal_func(proc->act_obj, LV_SIGNAL_RELEASED, indev_act);
|
||||
}
|
||||
|
||||
if(proc->reset_query != 0) return;
|
||||
|
||||
/*Handle click focus*/
|
||||
#if USE_LV_GROUP
|
||||
/*Edit mode is not used by POINTER devices. So leave edit mode if we are in it*/
|
||||
lv_group_t * act_g = lv_obj_get_group(proc->act_obj);
|
||||
if(lv_group_get_editing(act_g)) {
|
||||
lv_group_set_editing(act_g, false);
|
||||
}
|
||||
|
||||
/*Check, if the parent is in a group focus on it.*/
|
||||
if(lv_obj_is_protected(proc->act_obj, LV_PROTECT_CLICK_FOCUS) == false) { /*Respect the click protection*/
|
||||
lv_group_t * g = lv_obj_get_group(proc->act_obj);
|
||||
lv_obj_t * parent = proc->act_obj;
|
||||
|
||||
while(g == NULL) {
|
||||
parent = lv_obj_get_parent(parent);
|
||||
if(parent == NULL) break;
|
||||
if(lv_obj_is_protected(parent, LV_PROTECT_CLICK_FOCUS)) { /*Ignore is the protected against click focus*/
|
||||
parent = NULL;
|
||||
break;
|
||||
}
|
||||
g = lv_obj_get_group(parent);
|
||||
}
|
||||
|
||||
if(g != NULL && parent != NULL)
|
||||
if(lv_group_get_click_focus(g)) {
|
||||
lv_group_focus_obj(parent);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(proc->reset_query != 0) return;
|
||||
proc->act_obj = NULL;
|
||||
proc->pr_timestamp = 0;
|
||||
proc->longpr_rep_timestamp = 0;
|
||||
}
|
||||
|
||||
/*The reset can be set in the signal function.
|
||||
* In case of reset query ignore the remaining parts.*/
|
||||
if(proc->last_obj != NULL && proc->reset_query == 0) {
|
||||
indev_drag_throw(proc);
|
||||
if(proc->reset_query != 0) return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a new point from LV_INDEV_TYPE_BUTTON input device
|
||||
* @param i pointer to an input device
|
||||
* @param data pointer to the data read from the input device
|
||||
* Reset input device if a reset query has been sent to it
|
||||
* @param indev pointer to an input device
|
||||
*/
|
||||
static void indev_proc_reset_query_handler(lv_indev_t * indev)
|
||||
{
|
||||
if(indev->proc.reset_query) {
|
||||
indev->proc.act_obj = NULL;
|
||||
indev->proc.last_obj = NULL;
|
||||
indev->proc.drag_range_out = 0;
|
||||
indev->proc.drag_in_prog = 0;
|
||||
indev->proc.long_pr_sent = 0;
|
||||
indev->proc.pr_timestamp = 0;
|
||||
indev->proc.longpr_rep_timestamp = 0;
|
||||
indev->proc.drag_sum.x = 0;
|
||||
indev->proc.drag_sum.y = 0;
|
||||
indev->proc.reset_query = 0;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Search the most top, clickable object on the last point of an input device
|
||||
* @param proc pointer to the `lv_indev_proc_t` part of the input device
|
||||
* @param obj pointer to a start object, typically the screen
|
||||
* @return pointer to the found object or NULL if there was no suitable object
|
||||
*/
|
||||
static lv_obj_t * indev_search_obj(const lv_indev_proc_t * proc, lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_t * found_p = NULL;
|
||||
|
||||
/*If the point is on this object*/
|
||||
/*Check its children too*/
|
||||
if(lv_area_is_point_on(&obj->coords, &proc->act_point)) {
|
||||
lv_obj_t * i;
|
||||
|
||||
LL_READ(obj->child_ll, i) {
|
||||
found_p = indev_search_obj(proc, i);
|
||||
|
||||
/*If a child was found then break*/
|
||||
if(found_p != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*If then the children was not ok, and this obj is clickable
|
||||
* and it or its parent is not hidden then save this object*/
|
||||
if(found_p == NULL && lv_obj_get_click(obj) != false) {
|
||||
lv_obj_t * hidden_i = obj;
|
||||
while(hidden_i != NULL) {
|
||||
if(lv_obj_get_hidden(hidden_i) == true) break;
|
||||
hidden_i = lv_obj_get_parent(hidden_i);
|
||||
}
|
||||
/*No parent found with hidden == true*/
|
||||
if(hidden_i == NULL) found_p = obj;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return found_p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the dragging of indev_proc_p->act_obj
|
||||
* @param indev pointer to a input device state
|
||||
*/
|
||||
static void indev_drag(lv_indev_proc_t * state)
|
||||
{
|
||||
lv_obj_t * drag_obj = state->act_obj;
|
||||
|
||||
/*If drag parent is active check recursively the drag_parent attribute*/
|
||||
while(lv_obj_get_drag_parent(drag_obj) != false &&
|
||||
drag_obj != NULL) {
|
||||
drag_obj = lv_obj_get_parent(drag_obj);
|
||||
}
|
||||
|
||||
if(drag_obj == NULL) return;
|
||||
|
||||
if(lv_obj_get_drag(drag_obj) == false) return;
|
||||
|
||||
/*Count the movement by drag*/
|
||||
state->drag_sum.x += state->vect.x;
|
||||
state->drag_sum.y += state->vect.y;
|
||||
|
||||
/*Enough move?*/
|
||||
if(state->drag_range_out == 0) {
|
||||
/*If a move is greater then LV_DRAG_LIMIT then begin the drag*/
|
||||
if(LV_MATH_ABS(state->drag_sum.x) >= LV_INDEV_DRAG_LIMIT ||
|
||||
LV_MATH_ABS(state->drag_sum.y) >= LV_INDEV_DRAG_LIMIT) {
|
||||
state->drag_range_out = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*If the drag limit is stepped over then handle the dragging*/
|
||||
if(state->drag_range_out != 0) {
|
||||
/*Set new position if the vector is not zero*/
|
||||
if(state->vect.x != 0 ||
|
||||
state->vect.y != 0) {
|
||||
/*Get the coordinates of the object and modify them*/
|
||||
lv_coord_t act_x = lv_obj_get_x(drag_obj);
|
||||
lv_coord_t act_y = lv_obj_get_y(drag_obj);
|
||||
uint16_t inv_buf_size = lv_refr_get_buf_size(); /*Get the number of currently invalidated areas*/
|
||||
|
||||
lv_coord_t prev_x = drag_obj->coords.x1;
|
||||
lv_coord_t prev_y = drag_obj->coords.y1;
|
||||
lv_coord_t prev_par_w = lv_obj_get_width(lv_obj_get_parent(drag_obj));
|
||||
lv_coord_t prev_par_h = lv_obj_get_height(lv_obj_get_parent(drag_obj));
|
||||
|
||||
lv_obj_set_pos(drag_obj, act_x + state->vect.x, act_y + state->vect.y);
|
||||
|
||||
/*Set the drag in progress flag if the object is really moved*/
|
||||
|
||||
if(drag_obj->coords.x1 != prev_x || drag_obj->coords.y1 != prev_y) {
|
||||
if(state->drag_range_out != 0) { /*Send the drag begin signal on first move*/
|
||||
drag_obj->signal_func(drag_obj, LV_SIGNAL_DRAG_BEGIN, indev_act);
|
||||
if(state->reset_query != 0) return;
|
||||
}
|
||||
state->drag_in_prog = 1;
|
||||
}
|
||||
/*If the object didn't moved then clear the invalidated areas*/
|
||||
else {
|
||||
/*In a special case if the object is moved on a page and
|
||||
* the scrollable has fit == true and the object is dragged of the page then
|
||||
* while its coordinate is not changing only the parent's size is reduced */
|
||||
lv_coord_t act_par_w = lv_obj_get_width(lv_obj_get_parent(drag_obj));
|
||||
lv_coord_t act_par_h = lv_obj_get_height(lv_obj_get_parent(drag_obj));
|
||||
if(act_par_w == prev_par_w && act_par_h == prev_par_h) {
|
||||
uint16_t new_inv_buf_size = lv_refr_get_buf_size();
|
||||
lv_refr_pop_from_buf(new_inv_buf_size - inv_buf_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle throwing by drag if the drag is ended
|
||||
* @param indev pointer to an input device state
|
||||
*/
|
||||
static void indev_drag_throw(lv_indev_proc_t * state)
|
||||
{
|
||||
if(state->drag_in_prog == 0) return;
|
||||
|
||||
/*Set new position if the vector is not zero*/
|
||||
lv_obj_t * drag_obj = state->last_obj;
|
||||
|
||||
/*If drag parent is active check recursively the drag_parent attribute*/
|
||||
while(lv_obj_get_drag_parent(drag_obj) != false &&
|
||||
drag_obj != NULL) {
|
||||
drag_obj = lv_obj_get_parent(drag_obj);
|
||||
}
|
||||
|
||||
if(drag_obj == NULL) return;
|
||||
|
||||
/*Return if the drag throw is not enabled*/
|
||||
if(lv_obj_get_drag_throw(drag_obj) == false) {
|
||||
state->drag_in_prog = 0;
|
||||
drag_obj->signal_func(drag_obj, LV_SIGNAL_DRAG_END, indev_act);
|
||||
return;
|
||||
}
|
||||
|
||||
/*Reduce the vectors*/
|
||||
state->vect.x = state->vect.x * (100 - LV_INDEV_DRAG_THROW) / 100;
|
||||
state->vect.y = state->vect.y * (100 - LV_INDEV_DRAG_THROW) / 100;
|
||||
|
||||
if(state->vect.x != 0 ||
|
||||
state->vect.y != 0) {
|
||||
/*Get the coordinates and modify them*/
|
||||
lv_area_t coords_ori;
|
||||
lv_obj_get_coords(drag_obj, &coords_ori);
|
||||
lv_coord_t act_x = lv_obj_get_x(drag_obj) + state->vect.x;
|
||||
lv_coord_t act_y = lv_obj_get_y(drag_obj) + state->vect.y;
|
||||
lv_obj_set_pos(drag_obj, act_x, act_y);
|
||||
|
||||
lv_area_t coord_new;
|
||||
lv_obj_get_coords(drag_obj, &coord_new);
|
||||
|
||||
/*If non of the coordinates are changed then do not continue throwing*/
|
||||
if((coords_ori.x1 == coord_new.x1 || state->vect.x == 0) &&
|
||||
(coords_ori.y1 == coord_new.y1 || state->vect.y == 0)) {
|
||||
state->drag_in_prog = 0;
|
||||
state->vect.x = 0;
|
||||
state->vect.y = 0;
|
||||
drag_obj->signal_func(drag_obj, LV_SIGNAL_DRAG_END, indev_act);
|
||||
|
||||
}
|
||||
}
|
||||
/*If the vectors become 0 -> drag_in_prog = 0 and send a drag end signal*/
|
||||
else {
|
||||
state->drag_in_prog = 0;
|
||||
drag_obj->signal_func(drag_obj, LV_SIGNAL_DRAG_END, indev_act);
|
||||
}
|
||||
}
|
||||
#endif
|
157
bdk/libs/lvgl/lv_core/lv_indev.h
Normal file
157
bdk/libs/lvgl/lv_core/lv_indev.h
Normal file
|
@ -0,0 +1,157 @@
|
|||
/**
|
||||
* @file lv_indev_proc.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_INDEV_H
|
||||
#define LV_INDEV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "../lv_hal/lv_hal_indev.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the display input device subsystem
|
||||
*/
|
||||
void lv_indev_init(void);
|
||||
|
||||
/**
|
||||
* Get the currently processed input device. Can be used in action functions too.
|
||||
* @return pointer to the currently processed input device or NULL if no input device processing right now
|
||||
*/
|
||||
lv_indev_t * lv_indev_get_act(void);
|
||||
|
||||
|
||||
/**
|
||||
* Get the type of an input device
|
||||
* @param indev pointer to an input device
|
||||
* @return the type of the input device from `lv_hal_indev_type_t` (`LV_INDEV_TYPE_...`)
|
||||
*/
|
||||
lv_hal_indev_type_t lv_indev_get_type(const lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Reset one or all input devices
|
||||
* @param indev pointer to an input device to reset or NULL to reset all of them
|
||||
*/
|
||||
void lv_indev_reset(lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Reset the long press state of an input device
|
||||
* @param indev_proc pointer to an input device
|
||||
*/
|
||||
void lv_indev_reset_lpr(lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Enable input devices device by type
|
||||
* @param type Input device type
|
||||
* @param enable true: enable this type; false: disable this type
|
||||
*/
|
||||
void lv_indev_enable(lv_hal_indev_type_t type, bool enable);
|
||||
|
||||
/**
|
||||
* Set a cursor for a pointer input device (for LV_INPUT_TYPE_POINTER and LV_INPUT_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @param cur_obj pointer to an object to be used as cursor
|
||||
*/
|
||||
void lv_indev_set_cursor(lv_indev_t *indev, lv_obj_t *cur_obj);
|
||||
|
||||
#if USE_LV_GROUP
|
||||
/**
|
||||
* Set a destination group for a keypad input device (for LV_INDEV_TYPE_KEYPAD)
|
||||
* @param indev pointer to an input device
|
||||
* @param group point to a group
|
||||
*/
|
||||
void lv_indev_set_group(lv_indev_t *indev, lv_group_t *group);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set the an array of points for LV_INDEV_TYPE_BUTTON.
|
||||
* These points will be assigned to the buttons to press a specific point on the screen
|
||||
* @param indev pointer to an input device
|
||||
* @param group point to a group
|
||||
*/
|
||||
void lv_indev_set_button_points(lv_indev_t *indev, const lv_point_t *points);
|
||||
|
||||
/**
|
||||
* Set feedback callback for indev.
|
||||
* @param indev pointer to an input device
|
||||
* @param feedback feedback callback
|
||||
*/
|
||||
void lv_indev_set_feedback(lv_indev_t *indev, lv_indev_feedback_t feedback);
|
||||
|
||||
/**
|
||||
* Get the last point of an input device (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @param point pointer to a point to store the result
|
||||
*/
|
||||
void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point);
|
||||
|
||||
/**
|
||||
* Get the last key of an input device (for LV_INDEV_TYPE_KEYPAD)
|
||||
* @param indev pointer to an input device
|
||||
* @return the last pressed key (0 on error)
|
||||
*/
|
||||
uint32_t lv_indev_get_key(const lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Check if there is dragging with an input device or not (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @return true: drag is in progress
|
||||
*/
|
||||
bool lv_indev_is_dragging(const lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Get the vector of dragging of an input device (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
|
||||
* @param indev pointer to an input device
|
||||
* @param point pointer to a point to store the vector
|
||||
*/
|
||||
void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point);
|
||||
/**
|
||||
* Get elapsed time since last press
|
||||
* @param indev pointer to an input device (NULL to get the overall smallest inactivity)
|
||||
* @return Elapsed ticks (milliseconds) since last press
|
||||
*/
|
||||
uint32_t lv_indev_get_inactive_time(const lv_indev_t * indev);
|
||||
|
||||
/**
|
||||
* Get feedback callback for indev.
|
||||
* @param indev pointer to an input device
|
||||
* @return feedback callback
|
||||
*/
|
||||
lv_indev_feedback_t lv_indev_get_feedback(const lv_indev_t *indev);
|
||||
|
||||
/**
|
||||
* Do nothing until the next release
|
||||
* @param indev pointer to an input device
|
||||
*/
|
||||
void lv_indev_wait_release(lv_indev_t * indev);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_INDEV_H*/
|
117
bdk/libs/lvgl/lv_core/lv_lang.c
Normal file
117
bdk/libs/lvgl/lv_core/lv_lang.c
Normal file
|
@ -0,0 +1,117 @@
|
|||
/**
|
||||
* @file lv_lang.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_lang.h"
|
||||
#if USE_LV_MULTI_LANG
|
||||
|
||||
#include "lv_obj.h"
|
||||
#include "../lv_misc/lv_gc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lang_set_core(lv_obj_t * obj);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static uint8_t lang_act = 0;
|
||||
static const void * (*get_txt)(uint16_t);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Change the language
|
||||
* @param lang_id the id of the
|
||||
*/
|
||||
void lv_lang_set(uint8_t lang_id)
|
||||
{
|
||||
lang_act = lang_id;
|
||||
|
||||
lv_obj_t * i;
|
||||
LL_READ(LV_GC_ROOT(_lv_scr_ll), i) {
|
||||
i->signal_func(i, LV_SIGNAL_LANG_CHG, NULL);
|
||||
|
||||
lang_set_core(i);
|
||||
}
|
||||
|
||||
lang_set_core(lv_scr_act());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a function to get the texts of the set languages from a `txt_id`
|
||||
* @param fp a function pointer to get the texts
|
||||
*/
|
||||
void lv_lang_set_text_func(const void * (*fp)(uint16_t))
|
||||
{
|
||||
get_txt = fp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the function set by `lv_lang_set_text_func` to get the `txt_id` text in the set language
|
||||
* @param txt_id an ID of the text to get
|
||||
* @return the `txt_id` txt on the set language
|
||||
*/
|
||||
const void * lv_lang_get_text(uint16_t txt_id)
|
||||
{
|
||||
if(get_txt == NULL) {
|
||||
LV_LOG_WARN("lv_lang_get_text: text_func is not specified");
|
||||
return NULL; /*No text_get function specified */
|
||||
}
|
||||
if(txt_id == LV_LANG_TXT_ID_NONE) {
|
||||
LV_LOG_WARN("lv_lang_get_text: attempts to get invalid text ID");
|
||||
return NULL; /*Invalid txt_id*/
|
||||
}
|
||||
|
||||
return get_txt(txt_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return with ID of the currently selected language
|
||||
* @return pointer to the active screen object (loaded by 'lv_scr_load()')
|
||||
*/
|
||||
uint8_t lv_lang_act(void)
|
||||
{
|
||||
return lang_act;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Change the language of the children. (Called recursively)
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
static void lang_set_core(lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_t * i;
|
||||
LL_READ(obj->child_ll, i) {
|
||||
i->signal_func(i, LV_SIGNAL_LANG_CHG, NULL);
|
||||
|
||||
lang_set_core(i);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*USE_LV_MULTI_LANG*/
|
74
bdk/libs/lvgl/lv_core/lv_lang.h
Normal file
74
bdk/libs/lvgl/lv_core/lv_lang.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* @file lv_lang.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_LANG_H
|
||||
#define LV_LANG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
#if USE_LV_MULTI_LANG
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_LANG_TXT_ID_NONE 0xFFFF /*Used to not assign any text IDs for a multi-language object.*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Change the language
|
||||
* @param lang_id the id of the
|
||||
*/
|
||||
void lv_lang_set(uint8_t lang_id);
|
||||
|
||||
/**
|
||||
* Set a function to get the texts of the set languages from a `txt_id`
|
||||
* @param fp a function pointer to get the texts
|
||||
*/
|
||||
void lv_lang_set_text_func(const void * (*fp)(uint16_t));
|
||||
|
||||
/**
|
||||
* Use the function set by `lv_lang_set_text_func` to get the `txt_id` text in the set language
|
||||
* @param txt_id an ID of the text to get
|
||||
* @return the `txt_id` txt on the set language
|
||||
*/
|
||||
const void * lv_lang_get_text(uint16_t txt_id);
|
||||
|
||||
/**
|
||||
* Return with ID of the currently selected language
|
||||
* @return pointer to the active screen object (loaded by 'lv_scr_load()')
|
||||
*/
|
||||
uint8_t lv_lang_act(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_MULTI_LANG*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_LANG_H*/
|
1986
bdk/libs/lvgl/lv_core/lv_obj.c
Normal file
1986
bdk/libs/lvgl/lv_core/lv_obj.c
Normal file
File diff suppressed because it is too large
Load diff
840
bdk/libs/lvgl/lv_core/lv_obj.h
Normal file
840
bdk/libs/lvgl/lv_core/lv_obj.h
Normal file
|
@ -0,0 +1,840 @@
|
|||
/**
|
||||
* @file lv_obj.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_OBJ_H
|
||||
#define LV_OBJ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include "lv_style.h"
|
||||
#include "../lv_misc/lv_area.h"
|
||||
#include "../lv_misc/lv_mem.h"
|
||||
#include "../lv_misc/lv_ll.h"
|
||||
#include "../lv_misc/lv_color.h"
|
||||
#include "../lv_misc/lv_log.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/*Error check of lv_conf.h*/
|
||||
#if LV_HOR_RES == 0 || LV_VER_RES == 0
|
||||
#error "LittlevGL: LV_HOR_RES and LV_VER_RES must be greater than 0"
|
||||
#endif
|
||||
|
||||
#if LV_ANTIALIAS > 1
|
||||
#error "LittlevGL: LV_ANTIALIAS can be only 0 or 1"
|
||||
#endif
|
||||
|
||||
#if LV_VDB_SIZE == 0 && LV_ANTIALIAS != 0
|
||||
#error "LittlevGL: If LV_VDB_SIZE == 0 the anti-aliasing must be disabled"
|
||||
#endif
|
||||
|
||||
#if LV_VDB_SIZE > 0 && LV_VDB_SIZE < LV_HOR_RES
|
||||
#error "LittlevGL: Small Virtual Display Buffer (lv_conf.h: LV_VDB_SIZE >= LV_HOR_RES)"
|
||||
#endif
|
||||
|
||||
#if LV_VDB_SIZE == 0 && USE_LV_REAL_DRAW == 0
|
||||
#error "LittlevGL: If LV_VDB_SIZE = 0 Real drawing function are required (lv_conf.h: USE_LV_REAL_DRAW 1)"
|
||||
#endif
|
||||
|
||||
|
||||
#define LV_ANIM_IN 0x00 /*Animation to show an object. 'OR' it with lv_anim_builtin_t*/
|
||||
#define LV_ANIM_OUT 0x80 /*Animation to hide an object. 'OR' it with lv_anim_builtin_t*/
|
||||
#define LV_ANIM_DIR_MASK 0x80 /*ANIM_IN/ANIM_OUT mask*/
|
||||
|
||||
#define LV_MAX_ANCESTOR_NUM 8
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_obj_t;
|
||||
|
||||
enum
|
||||
{
|
||||
LV_DESIGN_DRAW_MAIN,
|
||||
LV_DESIGN_DRAW_POST,
|
||||
LV_DESIGN_COVER_CHK,
|
||||
};
|
||||
typedef uint8_t lv_design_mode_t;
|
||||
|
||||
typedef bool (* lv_design_func_t) (struct _lv_obj_t * obj, const lv_area_t * mask_p, lv_design_mode_t mode);
|
||||
|
||||
enum
|
||||
{
|
||||
LV_RES_INV = 0, /*Typically indicates that the object is deleted (become invalid) in the action function or an operation was failed*/
|
||||
LV_RES_OK, /*The object is valid (no deleted) after the action*/
|
||||
};
|
||||
typedef uint8_t lv_res_t;
|
||||
|
||||
enum
|
||||
{
|
||||
/*General signals*/
|
||||
LV_SIGNAL_CLEANUP,
|
||||
LV_SIGNAL_CHILD_CHG,
|
||||
LV_SIGNAL_CORD_CHG,
|
||||
LV_SIGNAL_STYLE_CHG,
|
||||
LV_SIGNAL_REFR_EXT_SIZE,
|
||||
LV_SIGNAL_LANG_CHG,
|
||||
LV_SIGNAL_GET_TYPE,
|
||||
|
||||
_LV_SIGNAL_FEEDBACK_SECTION_START,
|
||||
/*Input device related*/
|
||||
LV_SIGNAL_PRESSED,
|
||||
LV_SIGNAL_PRESSING,
|
||||
LV_SIGNAL_PRESS_LOST,
|
||||
LV_SIGNAL_RELEASED,
|
||||
LV_SIGNAL_LONG_PRESS,
|
||||
LV_SIGNAL_LONG_PRESS_REP,
|
||||
LV_SIGNAL_DRAG_BEGIN,
|
||||
LV_SIGNAL_DRAG_END,
|
||||
|
||||
/*Group related*/
|
||||
LV_SIGNAL_FOCUS,
|
||||
LV_SIGNAL_DEFOCUS,
|
||||
LV_SIGNAL_CONTROLL,
|
||||
_LV_SIGNAL_FEEDBACK_SECTION_END,
|
||||
LV_SIGNAL_GET_EDITABLE,
|
||||
};
|
||||
typedef uint8_t lv_signal_t;
|
||||
|
||||
typedef lv_res_t (* lv_signal_func_t) (struct _lv_obj_t * obj, lv_signal_t sign, void * param);
|
||||
|
||||
enum
|
||||
{
|
||||
LV_ALIGN_CENTER = 0,
|
||||
LV_ALIGN_IN_TOP_LEFT,
|
||||
LV_ALIGN_IN_TOP_MID,
|
||||
LV_ALIGN_IN_TOP_RIGHT,
|
||||
LV_ALIGN_IN_BOTTOM_LEFT,
|
||||
LV_ALIGN_IN_BOTTOM_MID,
|
||||
LV_ALIGN_IN_BOTTOM_RIGHT,
|
||||
LV_ALIGN_IN_LEFT_MID,
|
||||
LV_ALIGN_IN_RIGHT_MID,
|
||||
LV_ALIGN_OUT_TOP_LEFT,
|
||||
LV_ALIGN_OUT_TOP_MID,
|
||||
LV_ALIGN_OUT_TOP_RIGHT,
|
||||
LV_ALIGN_OUT_BOTTOM_LEFT,
|
||||
LV_ALIGN_OUT_BOTTOM_MID,
|
||||
LV_ALIGN_OUT_BOTTOM_RIGHT,
|
||||
LV_ALIGN_OUT_LEFT_TOP,
|
||||
LV_ALIGN_OUT_LEFT_MID,
|
||||
LV_ALIGN_OUT_LEFT_BOTTOM,
|
||||
LV_ALIGN_OUT_RIGHT_TOP,
|
||||
LV_ALIGN_OUT_RIGHT_MID,
|
||||
LV_ALIGN_OUT_RIGHT_BOTTOM,
|
||||
};
|
||||
typedef uint8_t lv_align_t;
|
||||
|
||||
#if LV_OBJ_REALIGN
|
||||
typedef struct {
|
||||
const struct _lv_obj_t * base;
|
||||
lv_coord_t xofs;
|
||||
lv_coord_t yofs;
|
||||
lv_align_t align;
|
||||
uint8_t auto_realign :1;
|
||||
uint8_t origo_align :1; /*1: the oigo (center of the object) was aligned with `lv_obj_align_origo`*/
|
||||
}lv_reailgn_t;
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct _lv_obj_t
|
||||
{
|
||||
struct _lv_obj_t * par; /*Pointer to the parent object*/
|
||||
lv_ll_t child_ll; /*Linked list to store the children objects*/
|
||||
|
||||
lv_area_t coords; /*Coordinates of the object (x1, y1, x2, y2)*/
|
||||
|
||||
lv_signal_func_t signal_func; /*Object type specific signal function*/
|
||||
lv_design_func_t design_func; /*Object type specific design function*/
|
||||
|
||||
void * ext_attr; /*Object type specific extended data*/
|
||||
lv_style_t * style_p; /*Pointer to the object's style*/
|
||||
|
||||
#if LV_OBJ_FREE_PTR != 0
|
||||
void * free_ptr; /*Application specific pointer (set it freely)*/
|
||||
#endif
|
||||
|
||||
#if USE_LV_GROUP != 0
|
||||
void * group_p; /*Pointer to the group of the object*/
|
||||
#endif
|
||||
/*Attributes and states*/
|
||||
uint8_t click :1; /*1: Can be pressed by an input device*/
|
||||
uint8_t drag :1; /*1: Enable the dragging*/
|
||||
uint8_t drag_throw :1; /*1: Enable throwing with drag*/
|
||||
uint8_t drag_parent :1; /*1: Parent will be dragged instead*/
|
||||
uint8_t hidden :1; /*1: Object is hidden*/
|
||||
uint8_t top :1; /*1: If the object or its children is clicked it goes to the foreground*/
|
||||
uint8_t opa_scale_en :1; /*1: opa_scale is set*/
|
||||
uint8_t protect; /*Automatically happening actions can be prevented. 'OR'ed values from `lv_protect_t`*/
|
||||
lv_opa_t opa_scale; /*Scale down the opacity by this factor. Effects all children as well*/
|
||||
|
||||
lv_coord_t ext_size; /*EXTtend the size of the object in every direction. E.g. for shadow drawing*/
|
||||
#if LV_OBJ_REALIGN
|
||||
lv_reailgn_t realign;
|
||||
#endif
|
||||
|
||||
#ifdef LV_OBJ_FREE_NUM_TYPE
|
||||
LV_OBJ_FREE_NUM_TYPE free_num; /*Application specific identifier (set it freely)*/
|
||||
#endif
|
||||
} lv_obj_t;
|
||||
|
||||
typedef lv_res_t (*lv_action_t) (struct _lv_obj_t * obj);
|
||||
|
||||
/*Protect some attributes (max. 8 bit)*/
|
||||
enum
|
||||
{
|
||||
LV_PROTECT_NONE = 0x00,
|
||||
LV_PROTECT_CHILD_CHG = 0x01, /*Disable the child change signal. Used by the library*/
|
||||
LV_PROTECT_PARENT = 0x02, /*Prevent automatic parent change (e.g. in lv_page)*/
|
||||
LV_PROTECT_POS = 0x04, /*Prevent automatic positioning (e.g. in lv_cont layout)*/
|
||||
LV_PROTECT_FOLLOW = 0x08, /*Prevent the object be followed in automatic ordering (e.g. in lv_cont PRETTY layout)*/
|
||||
LV_PROTECT_PRESS_LOST= 0x10, /*If the `indev` was pressing this object but swiped out while pressing do not search other object.*/
|
||||
LV_PROTECT_CLICK_FOCUS= 0x20,/*Prevent focusing the object by clicking on it*/
|
||||
};
|
||||
typedef uint8_t lv_protect_t;
|
||||
|
||||
|
||||
/*Used by `lv_obj_get_type()`. The object's and its ancestor types are stored here*/
|
||||
typedef struct {
|
||||
const char * type[LV_MAX_ANCESTOR_NUM]; /*[0]: the actual type, [1]: ancestor, [2] #1's ancestor ... [x]: "lv_obj" */
|
||||
} lv_obj_type_t;
|
||||
|
||||
enum
|
||||
{
|
||||
LV_ANIM_NONE = 0,
|
||||
LV_ANIM_FLOAT_TOP, /*Float from/to the top*/
|
||||
LV_ANIM_FLOAT_LEFT, /*Float from/to the left*/
|
||||
LV_ANIM_FLOAT_BOTTOM, /*Float from/to the bottom*/
|
||||
LV_ANIM_FLOAT_RIGHT, /*Float from/to the right*/
|
||||
LV_ANIM_GROW_H, /*Grow/shrink horizontally*/
|
||||
LV_ANIM_GROW_V, /*Grow/shrink vertically*/
|
||||
};
|
||||
typedef uint8_t lv_anim_builtin_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Init. the 'lv' library.
|
||||
*/
|
||||
void lv_init(void);
|
||||
|
||||
/*--------------------
|
||||
* Create and delete
|
||||
*-------------------*/
|
||||
|
||||
/**
|
||||
* Create a basic object
|
||||
* @param parent pointer to a parent object.
|
||||
* If NULL then a screen will be created
|
||||
* @param copy pointer to a base object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the new object
|
||||
*/
|
||||
lv_obj_t * lv_obj_create(lv_obj_t * parent,const lv_obj_t * copy);
|
||||
|
||||
/**
|
||||
* Delete 'obj' and all of its children
|
||||
* @param obj pointer to an object to delete
|
||||
* @return LV_RES_INV because the object is deleted
|
||||
*/
|
||||
lv_res_t lv_obj_del(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Delete all children of an object
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_clean(lv_obj_t *obj);
|
||||
|
||||
/**
|
||||
* Mark the object as invalid therefore its current position will be redrawn by 'lv_refr_task'
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_invalidate(const lv_obj_t * obj);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/*--------------
|
||||
* Screen set
|
||||
*--------------*/
|
||||
|
||||
/**
|
||||
* Load a new screen
|
||||
* @param scr pointer to a screen
|
||||
*/
|
||||
void lv_scr_load(lv_obj_t * scr);
|
||||
|
||||
/*--------------------
|
||||
* Parent/children set
|
||||
*--------------------*/
|
||||
|
||||
/**
|
||||
* Set a new parent for an object. Its relative position will be the same.
|
||||
* @param obj pointer to an object. Can't be a screen.
|
||||
* @param parent pointer to the new parent object. (Can't be NULL)
|
||||
*/
|
||||
void lv_obj_set_parent(lv_obj_t * obj, lv_obj_t * parent);
|
||||
|
||||
/*--------------------
|
||||
* Coordinate set
|
||||
* ------------------*/
|
||||
|
||||
/**
|
||||
* Set relative the position of an object (relative to the parent)
|
||||
* @param obj pointer to an object
|
||||
* @param x new distance from the left side of the parent
|
||||
* @param y new distance from the top of the parent
|
||||
*/
|
||||
void lv_obj_set_pos(lv_obj_t * obj, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
/**
|
||||
* Set the x coordinate of a object
|
||||
* @param obj pointer to an object
|
||||
* @param x new distance from the left side from the parent
|
||||
*/
|
||||
void lv_obj_set_x(lv_obj_t * obj, lv_coord_t x);
|
||||
|
||||
/**
|
||||
* Set the y coordinate of a object
|
||||
* @param obj pointer to an object
|
||||
* @param y new distance from the top of the parent
|
||||
*/
|
||||
void lv_obj_set_y(lv_obj_t * obj, lv_coord_t y);
|
||||
|
||||
/**
|
||||
* Set the size of an object
|
||||
* @param obj pointer to an object
|
||||
* @param w new width
|
||||
* @param h new height
|
||||
*/
|
||||
void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h);
|
||||
|
||||
/**
|
||||
* Set the width of an object
|
||||
* @param obj pointer to an object
|
||||
* @param w new width
|
||||
*/
|
||||
void lv_obj_set_width(lv_obj_t * obj, lv_coord_t w);
|
||||
|
||||
/**
|
||||
* Set the height of an object
|
||||
* @param obj pointer to an object
|
||||
* @param h new height
|
||||
*/
|
||||
void lv_obj_set_height(lv_obj_t * obj, lv_coord_t h);
|
||||
|
||||
/**
|
||||
* Align an object to an other object.
|
||||
* @param obj pointer to an object to align
|
||||
* @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it.
|
||||
* @param align type of alignment (see 'lv_align_t' enum)
|
||||
* @param x_mod x coordinate shift after alignment
|
||||
* @param y_mod y coordinate shift after alignment
|
||||
*/
|
||||
void lv_obj_align(lv_obj_t * obj,const lv_obj_t * base, lv_align_t align, lv_coord_t x_mod, lv_coord_t y_mod);
|
||||
|
||||
/**
|
||||
* Align an object to an other object.
|
||||
* @param obj pointer to an object to align
|
||||
* @param base pointer to an object (if NULL the parent is used). 'obj' will be aligned to it.
|
||||
* @param align type of alignment (see 'lv_align_t' enum)
|
||||
* @param x_mod x coordinate shift after alignment
|
||||
* @param y_mod y coordinate shift after alignment
|
||||
*/
|
||||
void lv_obj_align_origo(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_mod, lv_coord_t y_mod);
|
||||
|
||||
/**
|
||||
* Realign the object based on the last `lv_obj_align` parameters.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_realign(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Enable the automatic realign of the object when its size has changed based on the last `lv_obj_align` parameters.
|
||||
* @param obj pointer to an object
|
||||
* @param en true: enable auto realign; false: disable auto realign
|
||||
*/
|
||||
void lv_obj_set_auto_realign(lv_obj_t * obj, bool en);
|
||||
|
||||
/*---------------------
|
||||
* Appearance set
|
||||
*--------------------*/
|
||||
|
||||
/**
|
||||
* Set a new style for an object
|
||||
* @param obj pointer to an object
|
||||
* @param style_p pointer to the new style
|
||||
*/
|
||||
void lv_obj_set_style(lv_obj_t * obj, lv_style_t * style);
|
||||
|
||||
/**
|
||||
* Notify an object about its style is modified
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_refresh_style(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Notify all object if a style is modified
|
||||
* @param style pointer to a style. Only the objects with this style will be notified
|
||||
* (NULL to notify all objects)
|
||||
*/
|
||||
void lv_obj_report_style_mod(lv_style_t * style);
|
||||
|
||||
/*-----------------
|
||||
* Attribute set
|
||||
*----------------*/
|
||||
|
||||
/**
|
||||
* Hide an object. It won't be visible and clickable.
|
||||
* @param obj pointer to an object
|
||||
* @param en true: hide the object
|
||||
*/
|
||||
void lv_obj_set_hidden(lv_obj_t * obj, bool en);
|
||||
|
||||
/**
|
||||
* Enable or disable the clicking of an object
|
||||
* @param obj pointer to an object
|
||||
* @param en true: make the object clickable
|
||||
*/
|
||||
void lv_obj_set_click(lv_obj_t * obj, bool en);
|
||||
|
||||
/**
|
||||
* Enable to bring this object to the foreground if it
|
||||
* or any of its children is clicked
|
||||
* @param obj pointer to an object
|
||||
* @param en true: enable the auto top feature
|
||||
*/
|
||||
void lv_obj_set_top(lv_obj_t * obj, bool en);
|
||||
|
||||
/**
|
||||
* Enable the dragging of an object
|
||||
* @param obj pointer to an object
|
||||
* @param en true: make the object dragable
|
||||
*/
|
||||
void lv_obj_set_drag(lv_obj_t * obj, bool en);
|
||||
|
||||
/**
|
||||
* Enable the throwing of an object after is is dragged
|
||||
* @param obj pointer to an object
|
||||
* @param en true: enable the drag throw
|
||||
*/
|
||||
void lv_obj_set_drag_throw(lv_obj_t * obj, bool en);
|
||||
|
||||
/**
|
||||
* Enable to use parent for drag related operations.
|
||||
* If trying to drag the object the parent will be moved instead
|
||||
* @param obj pointer to an object
|
||||
* @param en true: enable the 'drag parent' for the object
|
||||
*/
|
||||
void lv_obj_set_drag_parent(lv_obj_t * obj, bool en);
|
||||
|
||||
/**
|
||||
* Set editable parameter Used by groups and keyboard/encoder control.
|
||||
* Editable object has something inside to choose (the elements of a list)
|
||||
* @param obj pointer to an object
|
||||
* @param en true: enable editing
|
||||
*/
|
||||
//void lv_obj_set_editable(lv_obj_t * obj, bool en);
|
||||
|
||||
/**
|
||||
* Set the opa scale enable parameter (required to set opa_scale with `lv_obj_set_opa_scale()`)
|
||||
* @param obj pointer to an object
|
||||
* @param en true: opa scaling is enabled for this object and all children; false: no opa scaling
|
||||
*/
|
||||
void lv_obj_set_opa_scale_enable(lv_obj_t * obj, bool en);
|
||||
|
||||
/**
|
||||
* Set the opa scale of an object
|
||||
* @param obj pointer to an object
|
||||
* @param opa_scale a factor to scale down opacity [0..255]
|
||||
*/
|
||||
void lv_obj_set_opa_scale(lv_obj_t * obj, lv_opa_t opa_scale);
|
||||
|
||||
/**
|
||||
* Set a bit or bits in the protect filed
|
||||
* @param obj pointer to an object
|
||||
* @param prot 'OR'-ed values from `lv_protect_t`
|
||||
*/
|
||||
void lv_obj_set_protect(lv_obj_t * obj, uint8_t prot);
|
||||
|
||||
/**
|
||||
* Clear a bit or bits in the protect filed
|
||||
* @param obj pointer to an object
|
||||
* @param prot 'OR'-ed values from `lv_protect_t`
|
||||
*/
|
||||
void lv_obj_clear_protect(lv_obj_t * obj, uint8_t prot);
|
||||
|
||||
/**
|
||||
* Set the signal function of an object.
|
||||
* Always call the previous signal function in the new.
|
||||
* @param obj pointer to an object
|
||||
* @param fp the new signal function
|
||||
*/
|
||||
void lv_obj_set_signal_func(lv_obj_t * obj, lv_signal_func_t fp);
|
||||
|
||||
/**
|
||||
* Set a new design function for an object
|
||||
* @param obj pointer to an object
|
||||
* @param fp the new design function
|
||||
*/
|
||||
void lv_obj_set_design_func(lv_obj_t * obj, lv_design_func_t fp);
|
||||
|
||||
/*----------------
|
||||
* Other set
|
||||
*--------------*/
|
||||
|
||||
/**
|
||||
* Allocate a new ext. data for an object
|
||||
* @param obj pointer to an object
|
||||
* @param ext_size the size of the new ext. data
|
||||
* @return pointer to the allocated ext
|
||||
*/
|
||||
void * lv_obj_allocate_ext_attr(lv_obj_t * obj, uint16_t ext_size);
|
||||
|
||||
/**
|
||||
* Send a 'LV_SIGNAL_REFR_EXT_SIZE' signal to the object
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_obj_refresh_ext_size(lv_obj_t * obj);
|
||||
|
||||
#ifdef LV_OBJ_FREE_NUM_TYPE
|
||||
/**
|
||||
* Set an application specific number for an object.
|
||||
* It can help to identify objects in the application.
|
||||
* @param obj pointer to an object
|
||||
* @param free_num the new free number
|
||||
*/
|
||||
void lv_obj_set_free_num(lv_obj_t * obj, LV_OBJ_FREE_NUM_TYPE free_num);
|
||||
#endif
|
||||
|
||||
#if LV_OBJ_FREE_PTR != 0
|
||||
/**
|
||||
* Set an application specific pointer for an object.
|
||||
* It can help to identify objects in the application.
|
||||
* @param obj pointer to an object
|
||||
* @param free_p the new free pinter
|
||||
*/
|
||||
void lv_obj_set_free_ptr(lv_obj_t * obj, void * free_p);
|
||||
#endif
|
||||
|
||||
#if USE_LV_ANIMATION
|
||||
/**
|
||||
* Animate an object
|
||||
* @param obj pointer to an object to animate
|
||||
* @param type type of animation from 'lv_anim_builtin_t'. 'OR' it with ANIM_IN or ANIM_OUT
|
||||
* @param time time of animation in milliseconds
|
||||
* @param delay delay before the animation in milliseconds
|
||||
* @param cb a function to call when the animation is ready
|
||||
*/
|
||||
void lv_obj_animate(lv_obj_t * obj, lv_anim_builtin_t type, uint16_t time, uint16_t delay, void (*cb) (lv_obj_t *));
|
||||
#endif
|
||||
|
||||
/*=======================
|
||||
* Getter functions
|
||||
*======================*/
|
||||
|
||||
/*------------------
|
||||
* Screen get
|
||||
*-----------------*/
|
||||
|
||||
/**
|
||||
* Return with a pointer to the active screen
|
||||
* @return pointer to the active screen object (loaded by 'lv_scr_load()')
|
||||
*/
|
||||
lv_obj_t * lv_scr_act(void);
|
||||
|
||||
/**
|
||||
* Return with the top layer. (Same on every screen and it is above the normal screen layer)
|
||||
* @return pointer to the top layer object (transparent screen sized lv_obj)
|
||||
*/
|
||||
lv_obj_t * lv_layer_top(void);
|
||||
|
||||
/**
|
||||
* Return with the system layer. (Same on every screen and it is above the all other layers)
|
||||
* It is used for example by the cursor
|
||||
* @return pointer to the system layer object (transparent screen sized lv_obj)
|
||||
*/
|
||||
lv_obj_t * lv_layer_sys(void);
|
||||
|
||||
/**
|
||||
* Return with the screen of an object
|
||||
* @param obj pointer to an object
|
||||
* @return pointer to a screen
|
||||
*/
|
||||
lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj);
|
||||
|
||||
/*---------------------
|
||||
* Parent/children get
|
||||
*--------------------*/
|
||||
|
||||
/**
|
||||
* Returns with the parent of an object
|
||||
* @param obj pointer to an object
|
||||
* @return pointer to the parent of 'obj'
|
||||
*/
|
||||
lv_obj_t * lv_obj_get_parent(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Iterate through the children of an object (start from the "youngest, lastly created")
|
||||
* @param obj pointer to an object
|
||||
* @param child NULL at first call to get the next children
|
||||
* and the previous return value later
|
||||
* @return the child after 'act_child' or NULL if no more child
|
||||
*/
|
||||
lv_obj_t * lv_obj_get_child(const lv_obj_t * obj, const lv_obj_t * child);
|
||||
|
||||
/**
|
||||
* Iterate through the children of an object (start from the "oldest", firstly created)
|
||||
* @param obj pointer to an object
|
||||
* @param child NULL at first call to get the next children
|
||||
* and the previous return value later
|
||||
* @return the child after 'act_child' or NULL if no more child
|
||||
*/
|
||||
lv_obj_t * lv_obj_get_child_back(const lv_obj_t * obj, const lv_obj_t * child);
|
||||
|
||||
/**
|
||||
* Count the children of an object (only children directly on 'obj')
|
||||
* @param obj pointer to an object
|
||||
* @return children number of 'obj'
|
||||
*/
|
||||
uint16_t lv_obj_count_children(const lv_obj_t * obj);
|
||||
|
||||
/*---------------------
|
||||
* Coordinate get
|
||||
*--------------------*/
|
||||
|
||||
/**
|
||||
* Copy the coordinates of an object to an area
|
||||
* @param obj pointer to an object
|
||||
* @param cords_p pointer to an area to store the coordinates
|
||||
*/
|
||||
void lv_obj_get_coords(const lv_obj_t * obj, lv_area_t * cords_p);
|
||||
|
||||
/**
|
||||
* Get the x coordinate of object
|
||||
* @param obj pointer to an object
|
||||
* @return distance of 'obj' from the left side of its parent
|
||||
*/
|
||||
lv_coord_t lv_obj_get_x(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the y coordinate of object
|
||||
* @param obj pointer to an object
|
||||
* @return distance of 'obj' from the top of its parent
|
||||
*/
|
||||
lv_coord_t lv_obj_get_y(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the width of an object
|
||||
* @param obj pointer to an object
|
||||
* @return the width
|
||||
*/
|
||||
lv_coord_t lv_obj_get_width(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the height of an object
|
||||
* @param obj pointer to an object
|
||||
* @return the height
|
||||
*/
|
||||
lv_coord_t lv_obj_get_height(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the extended size attribute of an object
|
||||
* @param obj pointer to an object
|
||||
* @return the extended size attribute
|
||||
*/
|
||||
lv_coord_t lv_obj_get_ext_size(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the automatic realign property of the object.
|
||||
* @param obj pointer to an object
|
||||
* @return true: auto realign is enabled; false: auto realign is disabled
|
||||
*/
|
||||
bool lv_obj_get_auto_realign(lv_obj_t * obj);
|
||||
|
||||
/*-----------------
|
||||
* Appearance get
|
||||
*---------------*/
|
||||
|
||||
/**
|
||||
* Get the style pointer of an object (if NULL get style of the parent)
|
||||
* @param obj pointer to an object
|
||||
* @return pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_obj_get_style(const lv_obj_t * obj);
|
||||
|
||||
/*-----------------
|
||||
* Attribute get
|
||||
*----------------*/
|
||||
|
||||
/**
|
||||
* Get the hidden attribute of an object
|
||||
* @param obj pointer to an object
|
||||
* @return true: the object is hidden
|
||||
*/
|
||||
bool lv_obj_get_hidden(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the click enable attribute of an object
|
||||
* @param obj pointer to an object
|
||||
* @return true: the object is clickable
|
||||
*/
|
||||
bool lv_obj_get_click(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the top enable attribute of an object
|
||||
* @param obj pointer to an object
|
||||
* @return true: the auto top feature is enabled
|
||||
*/
|
||||
bool lv_obj_get_top(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the drag enable attribute of an object
|
||||
* @param obj pointer to an object
|
||||
* @return true: the object is dragable
|
||||
*/
|
||||
bool lv_obj_get_drag(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the drag throw enable attribute of an object
|
||||
* @param obj pointer to an object
|
||||
* @return true: drag throw is enabled
|
||||
*/
|
||||
bool lv_obj_get_drag_throw(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the drag parent attribute of an object
|
||||
* @param obj pointer to an object
|
||||
* @return true: drag parent is enabled
|
||||
*/
|
||||
bool lv_obj_get_drag_parent(const lv_obj_t * obj);
|
||||
|
||||
|
||||
/**
|
||||
* Get the opa scale enable parameter
|
||||
* @param obj pointer to an object
|
||||
* @return true: opa scaling is enabled for this object and all children; false: no opa scaling
|
||||
*/
|
||||
lv_opa_t lv_obj_get_opa_scale_enable(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the opa scale parameter of an object
|
||||
* @param obj pointer to an object
|
||||
* @return opa scale [0..255]
|
||||
*/
|
||||
lv_opa_t lv_obj_get_opa_scale(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the protect field of an object
|
||||
* @param obj pointer to an object
|
||||
* @return protect field ('OR'ed values of `lv_protect_t`)
|
||||
*/
|
||||
uint8_t lv_obj_get_protect(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Check at least one bit of a given protect bitfield is set
|
||||
* @param obj pointer to an object
|
||||
* @param prot protect bits to test ('OR'ed values of `lv_protect_t`)
|
||||
* @return false: none of the given bits are set, true: at least one bit is set
|
||||
*/
|
||||
bool lv_obj_is_protected(const lv_obj_t * obj, uint8_t prot);
|
||||
|
||||
/**
|
||||
* Get the signal function of an object
|
||||
* @param obj pointer to an object
|
||||
* @return the signal function
|
||||
*/
|
||||
lv_signal_func_t lv_obj_get_signal_func(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the design function of an object
|
||||
* @param obj pointer to an object
|
||||
* @return the design function
|
||||
*/
|
||||
lv_design_func_t lv_obj_get_design_func(const lv_obj_t * obj);
|
||||
|
||||
/*------------------
|
||||
* Other get
|
||||
*-----------------*/
|
||||
|
||||
/**
|
||||
* Get the ext pointer
|
||||
* @param obj pointer to an object
|
||||
* @return the ext pointer but not the dynamic version
|
||||
* Use it as ext->data1, and NOT da(ext)->data1
|
||||
*/
|
||||
void * lv_obj_get_ext_attr(const lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get object's and its ancestors type. Put their name in `type_buf` starting with the current type.
|
||||
* E.g. buf.type[0]="lv_btn", buf.type[1]="lv_cont", buf.type[2]="lv_obj"
|
||||
* @param obj pointer to an object which type should be get
|
||||
* @param buf pointer to an `lv_obj_type_t` buffer to store the types
|
||||
*/
|
||||
void lv_obj_get_type(lv_obj_t * obj, lv_obj_type_t * buf);
|
||||
|
||||
#ifdef LV_OBJ_FREE_NUM_TYPE
|
||||
/**
|
||||
* Get the free number
|
||||
* @param obj pointer to an object
|
||||
* @return the free number
|
||||
*/
|
||||
LV_OBJ_FREE_NUM_TYPE lv_obj_get_free_num(const lv_obj_t * obj);
|
||||
#endif
|
||||
|
||||
#if LV_OBJ_FREE_PTR != 0
|
||||
/**
|
||||
* Get the free pointer
|
||||
* @param obj pointer to an object
|
||||
* @return the free pointer
|
||||
*/
|
||||
void * lv_obj_get_free_ptr(const lv_obj_t * obj);
|
||||
#endif
|
||||
|
||||
#if USE_LV_GROUP
|
||||
/**
|
||||
* Get the group of the object
|
||||
* @param obj pointer to an object
|
||||
* @return the pointer to group of the object
|
||||
*/
|
||||
void * lv_obj_get_group(const lv_obj_t * obj);
|
||||
|
||||
|
||||
/**
|
||||
* Tell whether the object is the focused object of a group or not.
|
||||
* @param obj pointer to an object
|
||||
* @return true: the object is focused, false: the object is not focused or not in a group
|
||||
*/
|
||||
bool lv_obj_is_focused(const lv_obj_t * obj);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_OBJ_H*/
|
614
bdk/libs/lvgl/lv_core/lv_refr.c
Normal file
614
bdk/libs/lvgl/lv_core/lv_refr.c
Normal file
|
@ -0,0 +1,614 @@
|
|||
/**
|
||||
* @file lv_refr.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
#include "lv_refr.h"
|
||||
#include "lv_vdb.h"
|
||||
#include "../lv_hal/lv_hal_tick.h"
|
||||
#include "../lv_hal/lv_hal_disp.h"
|
||||
#include "../lv_misc/lv_task.h"
|
||||
#include "../lv_misc/lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#ifndef LV_INV_FIFO_SIZE
|
||||
#define LV_INV_FIFO_SIZE 32 /*The average count of objects on a screen */
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
lv_area_t area;
|
||||
uint8_t joined;
|
||||
} lv_join_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_refr_task(void * param);
|
||||
static void lv_refr_join_area(void);
|
||||
static void lv_refr_areas(void);
|
||||
#if LV_VDB_SIZE == 0
|
||||
static void lv_refr_area_no_vdb(const lv_area_t * area_p);
|
||||
#else
|
||||
static void lv_refr_area_with_vdb(const lv_area_t * area_p);
|
||||
static void lv_refr_area_part_vdb(const lv_area_t * area_p);
|
||||
#endif
|
||||
static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj);
|
||||
static void lv_refr_obj_and_children(lv_obj_t * top_p, const lv_area_t * mask_p);
|
||||
static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_join_t inv_buf[LV_INV_FIFO_SIZE];
|
||||
static uint16_t inv_buf_p;
|
||||
static void (*monitor_cb)(uint32_t, uint32_t); /*Monitor the rendering time*/
|
||||
static void (*round_cb)(lv_area_t *); /*If set then called to modify invalidated areas for special display controllers*/
|
||||
static uint32_t px_num;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the screen refresh subsystem
|
||||
*/
|
||||
void lv_refr_init(void)
|
||||
{
|
||||
inv_buf_p = 0;
|
||||
memset(inv_buf, 0, sizeof(inv_buf));
|
||||
|
||||
lv_task_t * task;
|
||||
task = lv_task_create(lv_refr_task, LV_REFR_PERIOD, LV_TASK_PRIO_MID, NULL);
|
||||
lv_task_ready(task); /*Be sure the screen will be refreshed immediately on start up*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Redraw the invalidated areas now.
|
||||
* Normally the redrawing is periodically executed in `lv_task_handler` but a long blocking process can
|
||||
* prevent the call of `lv_task_handler`. In this case if the the GUI is updated in the process (e.g. progress bar)
|
||||
* this function can be called when the screen should be updated.
|
||||
*/
|
||||
void lv_refr_now(void)
|
||||
{
|
||||
lv_refr_task(NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invalidate an area
|
||||
* @param area_p pointer to area which should be invalidated
|
||||
*/
|
||||
void lv_inv_area(const lv_area_t * area_p)
|
||||
{
|
||||
/*Clear the invalidate buffer if the parameter is NULL*/
|
||||
if(area_p == NULL) {
|
||||
inv_buf_p = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
lv_area_t scr_area;
|
||||
scr_area.x1 = 0;
|
||||
scr_area.y1 = 0;
|
||||
scr_area.x2 = LV_HOR_RES - 1;
|
||||
scr_area.y2 = LV_VER_RES - 1;
|
||||
|
||||
lv_area_t com_area;
|
||||
bool suc;
|
||||
|
||||
suc = lv_area_intersect(&com_area, area_p, &scr_area);
|
||||
|
||||
/*The area is truncated to the screen*/
|
||||
if(suc != false) {
|
||||
if(round_cb) round_cb(&com_area);
|
||||
|
||||
/*Save only if this area is not in one of the saved areas*/
|
||||
uint16_t i;
|
||||
for(i = 0; i < inv_buf_p; i++) {
|
||||
if(lv_area_is_in(&com_area, &inv_buf[i].area) != false) return;
|
||||
}
|
||||
|
||||
/*Save the area*/
|
||||
if(inv_buf_p < LV_INV_FIFO_SIZE) {
|
||||
lv_area_copy(&inv_buf[inv_buf_p].area, &com_area);
|
||||
} else {/*If no place for the area add the screen*/
|
||||
inv_buf_p = 0;
|
||||
lv_area_copy(&inv_buf[inv_buf_p].area, &scr_area);
|
||||
}
|
||||
inv_buf_p ++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a function to call after every refresh to announce the refresh time and the number of refreshed pixels
|
||||
* @param cb pointer to a callback function (void my_refr_cb(uint32_t time_ms, uint32_t px_num))
|
||||
* time_ms: refresh time in [ms]
|
||||
* px_num: not the drawn pixels but the number of affected pixels of the screen
|
||||
* (more pixels are drawn because of overlapping objects)
|
||||
*/
|
||||
void lv_refr_set_monitor_cb(void (*cb)(uint32_t, uint32_t))
|
||||
{
|
||||
monitor_cb = cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an area is invalidated to modify the coordinates of the area.
|
||||
* Special display controllers may require special coordinate rounding
|
||||
* @param cb pointer to the a function which will modify the area
|
||||
*/
|
||||
void lv_refr_set_round_cb(void(*cb)(lv_area_t *))
|
||||
{
|
||||
round_cb = cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of areas in the buffer
|
||||
* @return number of invalid areas
|
||||
*/
|
||||
uint16_t lv_refr_get_buf_size(void)
|
||||
{
|
||||
return inv_buf_p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop (delete) the last 'num' invalidated areas from the buffer
|
||||
* @param num number of areas to delete
|
||||
*/
|
||||
void lv_refr_pop_from_buf(uint16_t num)
|
||||
{
|
||||
if(inv_buf_p < num) inv_buf_p = 0;
|
||||
else inv_buf_p -= num;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Called periodically to handle the refreshing
|
||||
* @param param unused
|
||||
*/
|
||||
static void lv_refr_task(void * param)
|
||||
{
|
||||
(void)param;
|
||||
|
||||
LV_LOG_TRACE("display refresh task started");
|
||||
|
||||
uint32_t start = lv_tick_get();
|
||||
|
||||
if(lv_disp_get_active() == NULL) {
|
||||
LV_LOG_TRACE("No display is registered");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_refr_join_area();
|
||||
|
||||
lv_refr_areas();
|
||||
|
||||
/*If refresh happened ...*/
|
||||
if(inv_buf_p != 0) {
|
||||
|
||||
/*In true double buffered mode copy the refreshed areas to the new VDB to keep it up to date*/
|
||||
#if LV_VDB_TRUE_DOUBLE_BUFFERED
|
||||
lv_vdb_t * vdb_p = lv_vdb_get();
|
||||
vdb_p->area.x1 = 0;
|
||||
vdb_p->area.x2 = LV_HOR_RES-1;
|
||||
vdb_p->area.y1 = 0;
|
||||
vdb_p->area.y2 = LV_VER_RES - 1;
|
||||
|
||||
/*Flush the content of the VDB*/
|
||||
lv_vdb_flush();
|
||||
|
||||
/* With true double buffering the flushing should be only the address change of the current frame buffer
|
||||
* Wait until the address change is ready and copy the active content to the other frame buffer (new active VDB)
|
||||
* The changes will be written to the new VDB.*/
|
||||
lv_vdb_t * vdb_act = lv_vdb_get_active();
|
||||
lv_vdb_t * vdb_ina = lv_vdb_get_inactive();
|
||||
|
||||
uint8_t * buf_act = (uint8_t *) vdb_act->buf;
|
||||
uint8_t * buf_ina = (uint8_t *) vdb_ina->buf;
|
||||
|
||||
uint16_t a;
|
||||
for(a = 0; a < inv_buf_p; a++) {
|
||||
if(inv_buf[a].joined == 0) {
|
||||
lv_coord_t y;
|
||||
uint32_t start_offs = ((LV_HOR_RES * inv_buf[a].area.y1 + inv_buf[a].area.x1) * LV_VDB_PX_BPP) >> 3;
|
||||
uint32_t line_length = (lv_area_get_width(&inv_buf[a].area) * LV_VDB_PX_BPP) >> 3;
|
||||
|
||||
for(y = inv_buf[a].area.y1; y <= inv_buf[a].area.y2; y++) {
|
||||
memcpy(buf_act + start_offs, buf_ina + start_offs, line_length);
|
||||
start_offs += (LV_HOR_RES * LV_VDB_PX_BPP) >> 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*Clean up*/
|
||||
memset(inv_buf, 0, sizeof(inv_buf));
|
||||
inv_buf_p = 0;
|
||||
|
||||
/*Call monitor cb if present*/
|
||||
if(monitor_cb != NULL) {
|
||||
monitor_cb(lv_tick_elaps(start), px_num);
|
||||
}
|
||||
}
|
||||
|
||||
LV_LOG_TRACE("display refresh task finished");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Join the areas which has got common parts
|
||||
*/
|
||||
static void lv_refr_join_area(void)
|
||||
{
|
||||
uint32_t join_from;
|
||||
uint32_t join_in;
|
||||
lv_area_t joined_area;
|
||||
for(join_in = 0; join_in < inv_buf_p; join_in++) {
|
||||
if(inv_buf[join_in].joined != 0) continue;
|
||||
|
||||
/*Check all areas to join them in 'join_in'*/
|
||||
for(join_from = 0; join_from < inv_buf_p; join_from++) {
|
||||
/*Handle only unjoined areas and ignore itself*/
|
||||
if(inv_buf[join_from].joined != 0 || join_in == join_from) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*Check if the areas are on each other*/
|
||||
if(lv_area_is_on(&inv_buf[join_in].area,
|
||||
&inv_buf[join_from].area) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
lv_area_join(&joined_area, &inv_buf[join_in].area,
|
||||
&inv_buf[join_from].area);
|
||||
|
||||
/*Join two area only if the joined area size is smaller*/
|
||||
if(lv_area_get_size(&joined_area) <
|
||||
(lv_area_get_size(&inv_buf[join_in].area) + lv_area_get_size(&inv_buf[join_from].area))) {
|
||||
lv_area_copy(&inv_buf[join_in].area, &joined_area);
|
||||
|
||||
/*Mark 'join_form' is joined into 'join_in'*/
|
||||
inv_buf[join_from].joined = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the joined areas
|
||||
*/
|
||||
static void lv_refr_areas(void)
|
||||
{
|
||||
px_num = 0;
|
||||
uint32_t i;
|
||||
|
||||
for(i = 0; i < inv_buf_p; i++) {
|
||||
/*Refresh the unjoined areas*/
|
||||
if(inv_buf[i].joined == 0) {
|
||||
/*If there is no VDB do simple drawing*/
|
||||
#if LV_VDB_SIZE == 0
|
||||
lv_refr_area_no_vdb(&inv_buf[i].area);
|
||||
#else
|
||||
/*If VDB is used...*/
|
||||
lv_refr_area_with_vdb(&inv_buf[i].area);
|
||||
#endif
|
||||
if(monitor_cb != NULL) px_num += lv_area_get_size(&inv_buf[i].area);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if LV_VDB_SIZE == 0
|
||||
/**
|
||||
* Refresh an area if there is no Virtual Display Buffer
|
||||
* @param area_p pointer to an area to refresh
|
||||
*/
|
||||
static void lv_refr_area_no_vdb(const lv_area_t * area_p)
|
||||
{
|
||||
lv_obj_t * top_p;
|
||||
|
||||
/*Get top object which is not covered by others*/
|
||||
top_p = lv_refr_get_top_obj(area_p, lv_scr_act());
|
||||
|
||||
/*Do the refreshing*/
|
||||
lv_refr_obj_and_children(top_p, area_p);
|
||||
|
||||
/*Also refresh top and sys layer unconditionally*/
|
||||
lv_refr_obj_and_children(lv_layer_top(), area_p);
|
||||
lv_refr_obj_and_children(lv_layer_sys(), area_p);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* Refresh an area if there is Virtual Display Buffer
|
||||
* @param area_p pointer to an area to refresh
|
||||
*/
|
||||
static void lv_refr_area_with_vdb(const lv_area_t * area_p)
|
||||
{
|
||||
|
||||
#if LV_VDB_TRUE_DOUBLE_BUFFERED == 0
|
||||
/*Calculate the max row num*/
|
||||
lv_coord_t w = lv_area_get_width(area_p);
|
||||
lv_coord_t h = lv_area_get_height(area_p);
|
||||
lv_coord_t y2 = area_p->y2 >= LV_VER_RES ? y2 = LV_VER_RES - 1 : area_p->y2;
|
||||
|
||||
int32_t max_row = (uint32_t) LV_VDB_SIZE / w;
|
||||
|
||||
if(max_row > h) max_row = h;
|
||||
|
||||
|
||||
/*Round down the lines of VDB if rounding is added*/
|
||||
if(round_cb) {
|
||||
lv_area_t tmp;
|
||||
tmp.x1 = 0;
|
||||
tmp.x2 = 0;
|
||||
tmp.y1 = 0;
|
||||
|
||||
lv_coord_t y_tmp = max_row - 1;
|
||||
do {
|
||||
tmp.y2 = y_tmp;
|
||||
round_cb(&tmp);
|
||||
|
||||
/*If this height fits into `max_row` then fine*/
|
||||
if(lv_area_get_height(&tmp) <= max_row) break;
|
||||
|
||||
/*Decrement the height of the area until it fits into `max_row` after rounding*/
|
||||
y_tmp --;
|
||||
} while(y_tmp != 0);
|
||||
|
||||
if(y_tmp == 0) {
|
||||
LV_LOG_WARN("Can't set VDB height using the round function. (Wrong round_cb or to small VDB)");
|
||||
return;
|
||||
} else {
|
||||
max_row = tmp.y2 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*Always use the full row*/
|
||||
lv_coord_t row;
|
||||
lv_coord_t row_last = 0;
|
||||
for(row = area_p->y1; row + max_row - 1 <= y2; row += max_row) {
|
||||
lv_vdb_t * vdb_p = lv_vdb_get();
|
||||
if(!vdb_p) {
|
||||
LV_LOG_WARN("Invalid VDB pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
/*Calc. the next y coordinates of VDB*/
|
||||
vdb_p->area.x1 = area_p->x1;
|
||||
vdb_p->area.x2 = area_p->x2;
|
||||
vdb_p->area.y1 = row;
|
||||
vdb_p->area.y2 = row + max_row - 1;
|
||||
if(vdb_p->area.y2 > y2) vdb_p->area.y2 = y2;
|
||||
row_last = vdb_p->area.y2;
|
||||
lv_refr_area_part_vdb(area_p);
|
||||
}
|
||||
|
||||
/*If the last y coordinates are not handled yet ...*/
|
||||
if(y2 != row_last) {
|
||||
lv_vdb_t * vdb_p = lv_vdb_get();
|
||||
if(!vdb_p) {
|
||||
LV_LOG_WARN("Invalid VDB pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
/*Calc. the next y coordinates of VDB*/
|
||||
vdb_p->area.x1 = area_p->x1;
|
||||
vdb_p->area.x2 = area_p->x2;
|
||||
vdb_p->area.y1 = row;
|
||||
vdb_p->area.y2 = y2;
|
||||
|
||||
/*Refresh this part too*/
|
||||
lv_refr_area_part_vdb(area_p);
|
||||
}
|
||||
#else
|
||||
lv_vdb_t * vdb_p = lv_vdb_get();
|
||||
vdb_p->area.x1 = 0;
|
||||
vdb_p->area.x2 = LV_HOR_RES-1;
|
||||
vdb_p->area.y1 = 0;
|
||||
vdb_p->area.y2 = LV_VER_RES - 1;
|
||||
lv_refr_area_part_vdb(area_p);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh a part of an area which is on the actual Virtual Display Buffer
|
||||
* @param area_p pointer to an area to refresh
|
||||
*/
|
||||
static void lv_refr_area_part_vdb(const lv_area_t * area_p)
|
||||
{
|
||||
lv_vdb_t * vdb_p = lv_vdb_get();
|
||||
if(!vdb_p) {
|
||||
LV_LOG_WARN("Invalid VDB pointer");
|
||||
return;
|
||||
}
|
||||
lv_obj_t * top_p;
|
||||
|
||||
/*Get the new mask from the original area and the act. VDB
|
||||
It will be a part of 'area_p'*/
|
||||
lv_area_t start_mask;
|
||||
lv_area_intersect(&start_mask, area_p, &vdb_p->area);
|
||||
|
||||
/*Get the most top object which is not covered by others*/
|
||||
top_p = lv_refr_get_top_obj(&start_mask, lv_scr_act());
|
||||
|
||||
/*Do the refreshing from the top object*/
|
||||
lv_refr_obj_and_children(top_p, &start_mask);
|
||||
|
||||
/*Also refresh top and sys layer unconditionally*/
|
||||
lv_refr_obj_and_children(lv_layer_top(), &start_mask);
|
||||
lv_refr_obj_and_children(lv_layer_sys(), &start_mask);
|
||||
|
||||
/* In true double buffered mode flush only once when all areas were rendered.
|
||||
* In normal mode flush after every area */
|
||||
#if LV_VDB_TRUE_DOUBLE_BUFFERED == 0
|
||||
/*Flush the content of the VDB*/
|
||||
lv_vdb_flush();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /*LV_VDB_SIZE == 0*/
|
||||
|
||||
/**
|
||||
* Search the most top object which fully covers an area
|
||||
* @param area_p pointer to an area
|
||||
* @param obj the first object to start the searching (typically a screen)
|
||||
* @return
|
||||
*/
|
||||
static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_t * i;
|
||||
lv_obj_t * found_p = NULL;
|
||||
|
||||
/*If this object is fully cover the draw area check the children too */
|
||||
if(lv_area_is_in(area_p, &obj->coords) && obj->hidden == 0) {
|
||||
LL_READ(obj->child_ll, i) {
|
||||
found_p = lv_refr_get_top_obj(area_p, i);
|
||||
|
||||
/*If a children is ok then break*/
|
||||
if(found_p != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*If no better children check this object*/
|
||||
if(found_p == NULL) {
|
||||
lv_style_t * style = lv_obj_get_style(obj);
|
||||
if(style->body.opa == LV_OPA_COVER &&
|
||||
obj->design_func(obj, area_p, LV_DESIGN_COVER_CHK) != false &&
|
||||
lv_obj_get_opa_scale(obj) == LV_OPA_COVER) {
|
||||
found_p = obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found_p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the refreshing from an object. Draw all its children and the youngers too.
|
||||
* @param top_p pointer to an objects. Start the drawing from it.
|
||||
* @param mask_p pointer to an area, the objects will be drawn only here
|
||||
*/
|
||||
static void lv_refr_obj_and_children(lv_obj_t * top_p, const lv_area_t * mask_p)
|
||||
{
|
||||
/* Normally always will be a top_obj (at least the screen)
|
||||
* but in special cases (e.g. if the screen has alpha) it won't.
|
||||
* In this case use the screen directly */
|
||||
if(top_p == NULL) top_p = lv_scr_act();
|
||||
|
||||
/*Refresh the top object and its children*/
|
||||
lv_refr_obj(top_p, mask_p);
|
||||
|
||||
/*Draw the 'younger' sibling objects because they can be on top_obj */
|
||||
lv_obj_t * par;
|
||||
lv_obj_t * i;
|
||||
lv_obj_t * border_p = top_p;
|
||||
|
||||
par = lv_obj_get_parent(top_p);
|
||||
|
||||
/*Do until not reach the screen*/
|
||||
while(par != NULL) {
|
||||
/*object before border_p has to be redrawn*/
|
||||
i = lv_ll_get_prev(&(par->child_ll), border_p);
|
||||
|
||||
while(i != NULL) {
|
||||
/*Refresh the objects*/
|
||||
lv_refr_obj(i, mask_p);
|
||||
i = lv_ll_get_prev(&(par->child_ll), i);
|
||||
}
|
||||
|
||||
/*The new border will be there last parents,
|
||||
*so the 'younger' brothers of parent will be refreshed*/
|
||||
border_p = par;
|
||||
/*Go a level deeper*/
|
||||
par = lv_obj_get_parent(par);
|
||||
}
|
||||
|
||||
/*Call the post draw design function of the parents of the to object*/
|
||||
par = lv_obj_get_parent(top_p);
|
||||
while(par != NULL) {
|
||||
par->design_func(par, mask_p, LV_DESIGN_DRAW_POST);
|
||||
par = lv_obj_get_parent(par);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh an object an all of its children. (Called recursively)
|
||||
* @param obj pointer to an object to refresh
|
||||
* @param mask_ori_p pointer to an area, the objects will be drawn only here
|
||||
*/
|
||||
static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p)
|
||||
{
|
||||
/*Do not refresh hidden objects*/
|
||||
if(obj->hidden != 0) return;
|
||||
|
||||
bool union_ok; /* Store the return value of area_union */
|
||||
/* Truncate the original mask to the coordinates of the parent
|
||||
* because the parent and its children are visible only here */
|
||||
lv_area_t obj_mask;
|
||||
lv_area_t obj_ext_mask;
|
||||
lv_area_t obj_area;
|
||||
lv_coord_t ext_size = obj->ext_size;
|
||||
lv_obj_get_coords(obj, &obj_area);
|
||||
obj_area.x1 -= ext_size;
|
||||
obj_area.y1 -= ext_size;
|
||||
obj_area.x2 += ext_size;
|
||||
obj_area.y2 += ext_size;
|
||||
union_ok = lv_area_intersect(&obj_ext_mask, mask_ori_p, &obj_area);
|
||||
|
||||
/*Draw the parent and its children only if they ore on 'mask_parent'*/
|
||||
if(union_ok != false) {
|
||||
|
||||
/* Redraw the object */
|
||||
obj->design_func(obj, &obj_ext_mask, LV_DESIGN_DRAW_MAIN);
|
||||
//usleep(5 * 1000); /*DEBUG: Wait after every object draw to see the order of drawing*/
|
||||
|
||||
|
||||
/*Create a new 'obj_mask' without 'ext_size' because the children can't be visible there*/
|
||||
lv_obj_get_coords(obj, &obj_area);
|
||||
union_ok = lv_area_intersect(&obj_mask, mask_ori_p, &obj_area);
|
||||
if(union_ok != false) {
|
||||
lv_area_t mask_child; /*Mask from obj and its child*/
|
||||
lv_obj_t * child_p;
|
||||
lv_area_t child_area;
|
||||
LL_READ_BACK(obj->child_ll, child_p) {
|
||||
lv_obj_get_coords(child_p, &child_area);
|
||||
ext_size = child_p->ext_size;
|
||||
child_area.x1 -= ext_size;
|
||||
child_area.y1 -= ext_size;
|
||||
child_area.x2 += ext_size;
|
||||
child_area.y2 += ext_size;
|
||||
/* Get the union (common parts) of original mask (from obj)
|
||||
* and its child */
|
||||
union_ok = lv_area_intersect(&mask_child, &obj_mask, &child_area);
|
||||
|
||||
/*If the parent and the child has common area then refresh the child */
|
||||
if(union_ok) {
|
||||
/*Refresh the next children*/
|
||||
lv_refr_obj(child_p, &mask_child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If all the children are redrawn make 'post draw' design */
|
||||
obj->design_func(obj, &obj_ext_mask, LV_DESIGN_DRAW_POST);
|
||||
|
||||
}
|
||||
}
|
94
bdk/libs/lvgl/lv_core/lv_refr.h
Normal file
94
bdk/libs/lvgl/lv_core/lv_refr.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* @file lv_refr.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_REFR_H
|
||||
#define LV_REFR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize the screen refresh subsystem
|
||||
*/
|
||||
void lv_refr_init(void);
|
||||
|
||||
/**
|
||||
* Redraw the invalidated areas now.
|
||||
* Normally the redrawing is periodically executed in `lv_task_handler` but a long blocking process can
|
||||
* prevent the call of `lv_task_handler`. In this case if the the GUI is updated in the process (e.g. progress bar)
|
||||
* this function can be called when the screen should be updated.
|
||||
*/
|
||||
void lv_refr_now(void);
|
||||
|
||||
/**
|
||||
* Invalidate an area
|
||||
* @param area_p pointer to area which should be invalidated
|
||||
*/
|
||||
void lv_inv_area(const lv_area_t * area_p);
|
||||
|
||||
/**
|
||||
* Set a function to call after every refresh to announce the refresh time and the number of refreshed pixels
|
||||
* @param cb pointer to a callback function (void my_refr_cb(uint32_t time_ms, uint32_t px_num))
|
||||
*/
|
||||
void lv_refr_set_monitor_cb(void (*cb)(uint32_t, uint32_t));
|
||||
|
||||
/**
|
||||
* Called when an area is invalidated to modify the coordinates of the area.
|
||||
* Special display controllers may require special coordinate rounding
|
||||
* @param cb pointer to the a function which will modify the area
|
||||
*/
|
||||
void lv_refr_set_round_cb(void(*cb)(lv_area_t*));
|
||||
|
||||
/**
|
||||
* Get the number of areas in the buffer
|
||||
* @return number of invalid areas
|
||||
*/
|
||||
uint16_t lv_refr_get_buf_size(void);
|
||||
|
||||
/**
|
||||
* Pop (delete) the last 'num' invalidated areas from the buffer
|
||||
* @param num number of areas to delete
|
||||
*/
|
||||
void lv_refr_pop_from_buf(uint16_t num);
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_REFR_H*/
|
357
bdk/libs/lvgl/lv_core/lv_style.c
Normal file
357
bdk/libs/lvgl/lv_core/lv_style.c
Normal file
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
* Copyright (c) 2018 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_obj.h"
|
||||
#include "../lv_misc/lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define STYLE_MIX_MAX 256
|
||||
#define STYLE_MIX_SHIFT 8 /*log2(STYLE_MIX_MAX)*/
|
||||
|
||||
#define VAL_PROP(v1, v2, r) v1 + (((v2-v1) * r) >> STYLE_MIX_SHIFT)
|
||||
#define STYLE_ATTR_MIX(attr, r) if(start->attr != end->attr) {res->attr = VAL_PROP(start->attr, end->attr, r);} else {res->attr = start->attr;}
|
||||
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
#if USE_LV_ANIMATION
|
||||
typedef struct {
|
||||
lv_style_t style_start; /*Save not only pointers because can be same as 'style_anim' then it will be modified too*/
|
||||
lv_style_t style_end;
|
||||
lv_style_t * style_anim;
|
||||
void (*end_cb)(void *);
|
||||
} lv_style_anim_dsc_t;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
#if USE_LV_ANIMATION
|
||||
static void style_animator(lv_style_anim_dsc_t * dsc, int32_t val);
|
||||
static void style_animation_common_end_cb(void * ptr);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
lv_style_t lv_style_scr;
|
||||
lv_style_t lv_style_transp;
|
||||
lv_style_t lv_style_transp_fit;
|
||||
lv_style_t lv_style_transp_tight;
|
||||
lv_style_t lv_style_plain;
|
||||
lv_style_t lv_style_plain_color;
|
||||
lv_style_t lv_style_pretty;
|
||||
lv_style_t lv_style_pretty_color;
|
||||
lv_style_t lv_style_btn_rel;
|
||||
lv_style_t lv_style_btn_pr;
|
||||
lv_style_t lv_style_btn_tgl_rel;
|
||||
lv_style_t lv_style_btn_tgl_pr;
|
||||
lv_style_t lv_style_btn_ina;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Init the basic styles
|
||||
*/
|
||||
void lv_style_init(void)
|
||||
{
|
||||
/* Not White/Black/Gray colors are created by HSV model with
|
||||
* HUE = 210*/
|
||||
|
||||
/*Screen style*/
|
||||
lv_style_scr.glass = 0;
|
||||
lv_style_scr.body.opa = LV_OPA_COVER;
|
||||
lv_style_scr.body.main_color = LV_COLOR_BLACK;
|
||||
lv_style_scr.body.grad_color = LV_COLOR_BLACK;
|
||||
lv_style_scr.body.radius = 0;
|
||||
lv_style_scr.body.padding.ver = LV_DPI / 12;
|
||||
lv_style_scr.body.padding.hor = LV_DPI / 12;
|
||||
lv_style_scr.body.padding.inner = LV_DPI / 12;
|
||||
|
||||
lv_style_scr.body.border.color = LV_COLOR_WHITE;
|
||||
lv_style_scr.body.border.opa = LV_OPA_COVER;
|
||||
lv_style_scr.body.border.width = 0;
|
||||
lv_style_scr.body.border.part = LV_BORDER_FULL;
|
||||
|
||||
lv_style_scr.body.shadow.color = LV_COLOR_GRAY;
|
||||
lv_style_scr.body.shadow.type = LV_SHADOW_FULL;
|
||||
lv_style_scr.body.shadow.width = 0;
|
||||
|
||||
lv_style_scr.text.opa = LV_OPA_COVER;
|
||||
lv_style_scr.text.color = LV_COLOR_HEX(0xFBFBFB);
|
||||
lv_style_scr.text.font = LV_FONT_DEFAULT;
|
||||
lv_style_scr.text.letter_space = 3; // Important
|
||||
lv_style_scr.text.line_space = 2;
|
||||
|
||||
lv_style_scr.image.opa = LV_OPA_COVER;
|
||||
lv_style_scr.image.color = LV_COLOR_MAKE(0x20, 0x20, 0x20);
|
||||
lv_style_scr.image.intense = LV_OPA_TRANSP;
|
||||
|
||||
lv_style_scr.line.opa = LV_OPA_COVER;
|
||||
lv_style_scr.line.color = LV_COLOR_MAKE(0x20, 0x20, 0x20);
|
||||
lv_style_scr.line.width = 2;
|
||||
lv_style_scr.line.rounded = 0;
|
||||
|
||||
/*Plain style (by default near the same as the screen style)*/
|
||||
memcpy(&lv_style_plain, &lv_style_scr, sizeof(lv_style_t));
|
||||
|
||||
/*Plain color style*/
|
||||
memcpy(&lv_style_plain_color, &lv_style_plain, sizeof(lv_style_t));
|
||||
lv_style_plain_color.text.color = LV_COLOR_MAKE(0xf0, 0xf0, 0xf0);
|
||||
lv_style_plain_color.image.color = LV_COLOR_MAKE(0xf0, 0xf0, 0xf0);
|
||||
lv_style_plain_color.line.color = LV_COLOR_MAKE(0xf0, 0xf0, 0xf0);
|
||||
lv_style_plain_color.body.main_color = LV_COLOR_MAKE(0x55, 0x96, 0xd8);
|
||||
lv_style_plain_color.body.grad_color = lv_style_plain_color.body.main_color;
|
||||
|
||||
/*Pretty style */
|
||||
memcpy(&lv_style_pretty, &lv_style_plain, sizeof(lv_style_t));
|
||||
lv_style_pretty.text.color = LV_COLOR_MAKE(0x20, 0x20, 0x20);
|
||||
lv_style_pretty.image.color = LV_COLOR_MAKE(0x20, 0x20, 0x20);
|
||||
lv_style_pretty.line.color = LV_COLOR_MAKE(0x20, 0x20, 0x20);
|
||||
lv_style_pretty.body.main_color = LV_COLOR_WHITE;
|
||||
lv_style_pretty.body.grad_color = LV_COLOR_SILVER;
|
||||
lv_style_pretty.body.radius = LV_DPI / 15;
|
||||
lv_style_pretty.body.border.color = LV_COLOR_MAKE(0x40, 0x40, 0x40);
|
||||
lv_style_pretty.body.border.width = LV_DPI / 50 >= 1 ? LV_DPI / 50 : 1;
|
||||
lv_style_pretty.body.border.opa = LV_OPA_30;
|
||||
|
||||
/*Pretty color style*/
|
||||
memcpy(&lv_style_pretty_color, &lv_style_pretty, sizeof(lv_style_t));
|
||||
lv_style_pretty_color.text.color = LV_COLOR_MAKE(0xe0, 0xe0, 0xe0);
|
||||
lv_style_pretty_color.image.color = LV_COLOR_MAKE(0xe0, 0xe0, 0xe0);
|
||||
lv_style_pretty_color.line.color = LV_COLOR_MAKE(0xc0, 0xc0, 0xc0);
|
||||
lv_style_pretty_color.body.main_color = LV_COLOR_MAKE(0x6b, 0x9a, 0xc7);
|
||||
lv_style_pretty_color.body.grad_color = LV_COLOR_MAKE(0x2b, 0x59, 0x8b);
|
||||
lv_style_pretty_color.body.border.color = LV_COLOR_MAKE(0x15, 0x2c, 0x42);
|
||||
|
||||
/*Transparent style*/
|
||||
memcpy(&lv_style_transp, &lv_style_plain, sizeof(lv_style_t));
|
||||
lv_style_transp.body.empty = 1;
|
||||
lv_style_transp.glass = 1;
|
||||
lv_style_transp.body.border.width = 0;
|
||||
|
||||
/*Transparent fitting size*/
|
||||
memcpy(&lv_style_transp_fit, &lv_style_transp, sizeof(lv_style_t));
|
||||
lv_style_transp_fit.body.padding.hor = 0;
|
||||
lv_style_transp_fit.body.padding.ver = 0;
|
||||
|
||||
/*Transparent tight style*/
|
||||
memcpy(&lv_style_transp_tight, &lv_style_transp_fit, sizeof(lv_style_t));
|
||||
lv_style_transp_tight.body.padding.inner = 0;
|
||||
|
||||
/*Button released style*/
|
||||
memcpy(&lv_style_btn_rel, &lv_style_plain, sizeof(lv_style_t));
|
||||
lv_style_btn_rel.body.main_color = LV_COLOR_MAKE(0x76, 0xa2, 0xd0);
|
||||
lv_style_btn_rel.body.grad_color = LV_COLOR_MAKE(0x19, 0x3a, 0x5d);
|
||||
lv_style_btn_rel.body.radius = LV_DPI / 15;
|
||||
lv_style_btn_rel.body.padding.hor = LV_DPI / 4;
|
||||
lv_style_btn_rel.body.padding.ver = LV_DPI / 6;
|
||||
lv_style_btn_rel.body.padding.inner = LV_DPI / 10;
|
||||
lv_style_btn_rel.body.border.color = LV_COLOR_MAKE(0x0b, 0x19, 0x28);
|
||||
lv_style_btn_rel.body.border.width = LV_DPI / 50 >= 1 ? LV_DPI / 50 : 1;
|
||||
lv_style_btn_rel.body.border.opa = LV_OPA_70;
|
||||
lv_style_btn_rel.body.shadow.color = LV_COLOR_GRAY;
|
||||
lv_style_btn_rel.body.shadow.width = 0;
|
||||
lv_style_btn_rel.text.color = LV_COLOR_MAKE(0xff, 0xff, 0xff);
|
||||
lv_style_btn_rel.image.color = LV_COLOR_MAKE(0xff, 0xff, 0xff);
|
||||
|
||||
/*Button pressed style*/
|
||||
memcpy(&lv_style_btn_pr, &lv_style_btn_rel, sizeof(lv_style_t));
|
||||
lv_style_btn_pr.body.main_color = LV_COLOR_MAKE(0x33, 0x62, 0x94);
|
||||
lv_style_btn_pr.body.grad_color = LV_COLOR_MAKE(0x10, 0x26, 0x3c);
|
||||
lv_style_btn_pr.text.color = LV_COLOR_MAKE(0xa4, 0xb5, 0xc6);
|
||||
lv_style_btn_pr.image.color = LV_COLOR_MAKE(0xa4, 0xb5, 0xc6);
|
||||
lv_style_btn_pr.line.color = LV_COLOR_MAKE(0xa4, 0xb5, 0xc6);
|
||||
|
||||
/*Button toggle released style*/
|
||||
memcpy(&lv_style_btn_tgl_rel, &lv_style_btn_rel, sizeof(lv_style_t));
|
||||
lv_style_btn_tgl_rel.body.main_color = LV_COLOR_MAKE(0x0a, 0x11, 0x22);
|
||||
lv_style_btn_tgl_rel.body.grad_color = LV_COLOR_MAKE(0x37, 0x62, 0x90);
|
||||
lv_style_btn_tgl_rel.body.border.color = LV_COLOR_MAKE(0x01, 0x07, 0x0d);
|
||||
lv_style_btn_tgl_rel.text.color = LV_COLOR_MAKE(0xc8, 0xdd, 0xf4);
|
||||
lv_style_btn_tgl_rel.image.color = LV_COLOR_MAKE(0xc8, 0xdd, 0xf4);
|
||||
lv_style_btn_tgl_rel.line.color = LV_COLOR_MAKE(0xc8, 0xdd, 0xf4);
|
||||
|
||||
/*Button toggle pressed style*/
|
||||
memcpy(&lv_style_btn_tgl_pr, &lv_style_btn_tgl_rel, sizeof(lv_style_t));
|
||||
lv_style_btn_tgl_pr.body.main_color = LV_COLOR_MAKE(0x02, 0x14, 0x27);
|
||||
lv_style_btn_tgl_pr.body.grad_color = LV_COLOR_MAKE(0x2b, 0x4c, 0x70);
|
||||
lv_style_btn_tgl_pr.text.color = LV_COLOR_MAKE(0xa4, 0xb5, 0xc6);
|
||||
lv_style_btn_tgl_pr.image.color = LV_COLOR_MAKE(0xa4, 0xb5, 0xc6);
|
||||
lv_style_btn_tgl_pr.line.color = LV_COLOR_MAKE(0xa4, 0xb5, 0xc6);
|
||||
|
||||
/*Button inactive style*/
|
||||
memcpy(&lv_style_btn_ina, &lv_style_btn_rel, sizeof(lv_style_t));
|
||||
lv_style_btn_ina.body.main_color = LV_COLOR_MAKE(0xd8, 0xd8, 0xd8);
|
||||
lv_style_btn_ina.body.grad_color = LV_COLOR_MAKE(0xd8, 0xd8, 0xd8);
|
||||
lv_style_btn_ina.body.border.color = LV_COLOR_MAKE(0x90, 0x90, 0x90);
|
||||
lv_style_btn_ina.text.color = LV_COLOR_MAKE(0x70, 0x70, 0x70);
|
||||
lv_style_btn_ina.image.color = LV_COLOR_MAKE(0x70, 0x70, 0x70);
|
||||
lv_style_btn_ina.line.color = LV_COLOR_MAKE(0x70, 0x70, 0x70);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy a style to an other
|
||||
* @param dest pointer to the destination style
|
||||
* @param src pointer to the source style
|
||||
*/
|
||||
void lv_style_copy(lv_style_t * dest, const lv_style_t * src)
|
||||
{
|
||||
memcpy(dest, src, sizeof(lv_style_t));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mix two styles according to a given ratio
|
||||
* @param start start style
|
||||
* @param end end style
|
||||
* @param res store the result style here
|
||||
* @param ratio the ratio of mix [0..256]; 0: `start` style; 256: `end` style
|
||||
*/
|
||||
void lv_style_mix(const lv_style_t * start, const lv_style_t * end, lv_style_t * res, uint16_t ratio)
|
||||
{
|
||||
STYLE_ATTR_MIX(body.opa, ratio);
|
||||
STYLE_ATTR_MIX(body.radius, ratio);
|
||||
STYLE_ATTR_MIX(body.border.width, ratio);
|
||||
STYLE_ATTR_MIX(body.border.opa, ratio);
|
||||
STYLE_ATTR_MIX(body.shadow.width, ratio);
|
||||
STYLE_ATTR_MIX(body.padding.hor, ratio);
|
||||
STYLE_ATTR_MIX(body.padding.ver, ratio);
|
||||
STYLE_ATTR_MIX(body.padding.inner, ratio);
|
||||
STYLE_ATTR_MIX(text.line_space, ratio);
|
||||
STYLE_ATTR_MIX(text.letter_space, ratio);
|
||||
STYLE_ATTR_MIX(text.opa, ratio);
|
||||
STYLE_ATTR_MIX(line.width, ratio);
|
||||
STYLE_ATTR_MIX(line.opa, ratio);
|
||||
STYLE_ATTR_MIX(image.intense, ratio);
|
||||
STYLE_ATTR_MIX(image.opa, ratio);
|
||||
|
||||
lv_opa_t opa = ratio == STYLE_MIX_MAX ? LV_OPA_COVER : ratio;
|
||||
|
||||
res->body.main_color = lv_color_mix(end->body.main_color, start->body.main_color, opa);
|
||||
res->body.grad_color = lv_color_mix(end->body.grad_color, start->body.grad_color, opa);
|
||||
res->body.border.color = lv_color_mix(end->body.border.color, start->body.border.color, opa);
|
||||
res->body.shadow.color = lv_color_mix(end->body.shadow.color, start->body.shadow.color, opa);
|
||||
res->text.color = lv_color_mix(end->text.color, start->text.color, opa);
|
||||
res->image.color = lv_color_mix(end->image.color, start->image.color, opa);
|
||||
res->line.color = lv_color_mix(end->line.color, start->line.color, opa);
|
||||
|
||||
if(ratio < (STYLE_MIX_MAX >> 1)) {
|
||||
res->body.empty = start->body.empty;
|
||||
res->body.border.part = start->body.border.part;
|
||||
res->glass = start->glass;
|
||||
res->text.font = start->text.font;
|
||||
res->body.shadow.type = start->body.shadow.type;
|
||||
res->line.rounded = start->line.rounded;
|
||||
} else {
|
||||
res->body.empty = end->body.empty;
|
||||
res->body.border.part = end->body.border.part;
|
||||
res->glass = end->glass;
|
||||
res->text.font = end->text.font;
|
||||
res->body.shadow.type = end->body.shadow.type;
|
||||
res->line.rounded = end->line.rounded;
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_LV_ANIMATION
|
||||
|
||||
/**
|
||||
* Create an animation from a pre-configured 'lv_style_anim_t' variable
|
||||
* @param anim pointer to a pre-configured 'lv_style_anim_t' variable (will be copied)
|
||||
* @return pointer to a descriptor. Really this variable will be animated. (Can be used in `lv_anim_del(dsc, NULL)`)
|
||||
*/
|
||||
void * lv_style_anim_create(lv_style_anim_t * anim)
|
||||
{
|
||||
lv_style_anim_dsc_t * dsc;
|
||||
dsc = lv_mem_alloc(sizeof(lv_style_anim_dsc_t));
|
||||
lv_mem_assert(dsc);
|
||||
if(dsc == NULL) return NULL;
|
||||
|
||||
dsc->style_anim = anim->style_anim;
|
||||
memcpy(&dsc->style_start, anim->style_start, sizeof(lv_style_t));
|
||||
memcpy(&dsc->style_end, anim->style_end, sizeof(lv_style_t));
|
||||
memcpy(dsc->style_anim, anim->style_start, sizeof(lv_style_t));
|
||||
dsc->end_cb = anim->end_cb;
|
||||
|
||||
|
||||
lv_anim_t a;
|
||||
a.var = (void *)dsc;
|
||||
a.start = 0;
|
||||
a.end = STYLE_MIX_MAX;
|
||||
a.fp = (lv_anim_fp_t)style_animator;
|
||||
a.path = lv_anim_path_linear;
|
||||
a.end_cb = style_animation_common_end_cb;
|
||||
a.act_time = anim->act_time;
|
||||
a.time = anim->time;
|
||||
a.playback = anim->playback;
|
||||
a.playback_pause = anim->playback_pause;
|
||||
a.repeat = anim->repeat;
|
||||
a.repeat_pause = anim->repeat_pause;
|
||||
|
||||
lv_anim_create(&a);
|
||||
|
||||
return dsc;
|
||||
}
|
||||
|
||||
#endif
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
#if USE_LV_ANIMATION
|
||||
/**
|
||||
* Used by the style animations to set the values of a style according to start and end style.
|
||||
* @param dsc the 'animated variable' set by lv_style_anim_create()
|
||||
* @param val the current state of the animation between 0 and LV_STYLE_ANIM_RES
|
||||
*/
|
||||
static void style_animator(lv_style_anim_dsc_t * dsc, int32_t val)
|
||||
{
|
||||
const lv_style_t * start = &dsc->style_start;
|
||||
const lv_style_t * end = &dsc->style_end;
|
||||
lv_style_t * act = dsc->style_anim;
|
||||
|
||||
lv_style_mix(start, end, act, val);
|
||||
|
||||
lv_obj_report_style_mod(dsc->style_anim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a style animation is ready
|
||||
* It called the user defined call back and free the allocated memories
|
||||
* @param ptr the 'animated variable' set by lv_style_anim_create()
|
||||
*/
|
||||
static void style_animation_common_end_cb(void * ptr)
|
||||
{
|
||||
lv_style_anim_dsc_t * dsc = ptr; /*To avoid casting*/
|
||||
|
||||
if(dsc->end_cb) dsc->end_cb(dsc);
|
||||
|
||||
lv_mem_free(dsc);
|
||||
}
|
||||
|
||||
#endif
|
198
bdk/libs/lvgl/lv_core/lv_style.h
Normal file
198
bdk/libs/lvgl/lv_core/lv_style.h
Normal file
|
@ -0,0 +1,198 @@
|
|||
/**
|
||||
* @file lv_style.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_STYLE_H
|
||||
#define LV_STYLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_misc/lv_color.h"
|
||||
#include "../lv_misc/lv_area.h"
|
||||
#include "../lv_misc/lv_font.h"
|
||||
#include "../lv_misc/lv_anim.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_RADIUS_CIRCLE (LV_COORD_MAX) /*A very big radius to always draw as circle*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Border types (Use 'OR'ed values)*/
|
||||
enum
|
||||
{
|
||||
LV_BORDER_NONE = 0x00,
|
||||
LV_BORDER_BOTTOM = 0x01,
|
||||
LV_BORDER_TOP = 0x02,
|
||||
LV_BORDER_LEFT = 0x04,
|
||||
LV_BORDER_RIGHT = 0x08,
|
||||
LV_BORDER_FULL = 0x0F,
|
||||
LV_BORDER_INTERNAL = 0x10, /*FOR matrix-like objects (e.g. Button matrix)*/
|
||||
};
|
||||
typedef uint8_t lv_border_part_t;
|
||||
|
||||
/*Shadow types*/
|
||||
enum
|
||||
{
|
||||
LV_SHADOW_BOTTOM = 0,
|
||||
LV_SHADOW_FULL,
|
||||
};
|
||||
typedef uint8_t lv_shadow_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t glass :1; /*1: Do not inherit this style*/
|
||||
|
||||
struct {
|
||||
lv_color_t main_color;
|
||||
lv_color_t grad_color; /*`grad_color` will be removed in v6.0, use `aux_color` instead*/
|
||||
lv_coord_t radius;
|
||||
lv_opa_t opa;
|
||||
|
||||
struct {
|
||||
lv_color_t color;
|
||||
lv_coord_t width;
|
||||
lv_border_part_t part;
|
||||
lv_opa_t opa;
|
||||
} border;
|
||||
|
||||
struct {
|
||||
lv_color_t color;
|
||||
lv_coord_t width;
|
||||
lv_shadow_type_t type;
|
||||
} shadow;
|
||||
|
||||
struct {
|
||||
lv_coord_t ver;
|
||||
lv_coord_t hor;
|
||||
lv_coord_t inner;
|
||||
} padding;
|
||||
|
||||
uint8_t empty :1; /*Transparent background (border still drawn)*/
|
||||
} body;
|
||||
|
||||
|
||||
struct {
|
||||
lv_color_t color;
|
||||
const lv_font_t * font;
|
||||
lv_coord_t letter_space;
|
||||
lv_coord_t line_space;
|
||||
lv_opa_t opa;
|
||||
} text;
|
||||
|
||||
struct {
|
||||
lv_color_t color;
|
||||
lv_opa_t intense;
|
||||
lv_opa_t opa;
|
||||
} image;
|
||||
|
||||
struct {
|
||||
lv_color_t color;
|
||||
lv_coord_t width;
|
||||
lv_opa_t opa;
|
||||
uint8_t rounded :1; /*1: rounded line endings*/
|
||||
} line;
|
||||
} lv_style_t;
|
||||
|
||||
#if USE_LV_ANIMATION
|
||||
typedef struct {
|
||||
const lv_style_t * style_start; /*Pointer to the starting style*/
|
||||
const lv_style_t * style_end; /*Pointer to the destination style*/
|
||||
lv_style_t * style_anim; /*Pointer to a style to animate*/
|
||||
lv_anim_cb_t end_cb; /*Call it when the animation is ready (NULL if unused)*/
|
||||
int16_t time; /*Animation time in ms*/
|
||||
int16_t act_time; /*Current time in animation. Set to negative to make delay.*/
|
||||
uint16_t playback_pause; /*Wait before play back*/
|
||||
uint16_t repeat_pause; /*Wait before repeat*/
|
||||
uint8_t playback :1; /*When the animation is ready play it back*/
|
||||
uint8_t repeat :1; /*Repeat the animation infinitely*/
|
||||
} lv_style_anim_t;
|
||||
|
||||
/* Example initialization
|
||||
lv_style_anim_t a;
|
||||
a.style_anim = &style_to_anim;
|
||||
a.style_start = &style_1;
|
||||
a.style_end = &style_2;
|
||||
a.act_time = 0;
|
||||
a.time = 1000;
|
||||
a.playback = 0;
|
||||
a.playback_pause = 0;
|
||||
a.repeat = 0;
|
||||
a.repeat_pause = 0;
|
||||
a.end_cb = NULL;
|
||||
lv_style_anim_create(&a);
|
||||
*/
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Init the basic styles
|
||||
*/
|
||||
void lv_style_init (void);
|
||||
|
||||
/**
|
||||
* Copy a style to an other
|
||||
* @param dest pointer to the destination style
|
||||
* @param src pointer to the source style
|
||||
*/
|
||||
void lv_style_copy(lv_style_t * dest, const lv_style_t * src);
|
||||
|
||||
|
||||
/**
|
||||
* Mix two styles according to a given ratio
|
||||
* @param start start style
|
||||
* @param end end style
|
||||
* @param res store the result style here
|
||||
* @param ratio the ratio of mix [0..256]; 0: `start` style; 256: `end` style
|
||||
*/
|
||||
void lv_style_mix(const lv_style_t * start, const lv_style_t * end, lv_style_t * res, uint16_t ratio);
|
||||
|
||||
#if USE_LV_ANIMATION
|
||||
|
||||
/**
|
||||
* Create an animation from a pre-configured 'lv_style_anim_t' variable
|
||||
* @param anim pointer to a pre-configured 'lv_style_anim_t' variable (will be copied)
|
||||
* @return pointer to a descriptor. Really this variable will be animated. (Can be used in `lv_anim_del(dsc, NULL)`)
|
||||
*/
|
||||
void * lv_style_anim_create(lv_style_anim_t * anim);
|
||||
#endif
|
||||
|
||||
/*************************
|
||||
* GLOBAL VARIABLES
|
||||
*************************/
|
||||
extern lv_style_t lv_style_scr;
|
||||
extern lv_style_t lv_style_transp;
|
||||
extern lv_style_t lv_style_transp_fit;
|
||||
extern lv_style_t lv_style_transp_tight;
|
||||
extern lv_style_t lv_style_plain;
|
||||
extern lv_style_t lv_style_plain_color;
|
||||
extern lv_style_t lv_style_pretty;
|
||||
extern lv_style_t lv_style_pretty_color;
|
||||
extern lv_style_t lv_style_btn_rel;
|
||||
extern lv_style_t lv_style_btn_pr;
|
||||
extern lv_style_t lv_style_btn_tgl_rel;
|
||||
extern lv_style_t lv_style_btn_tgl_pr;
|
||||
extern lv_style_t lv_style_btn_ina;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_STYLE_H*/
|
207
bdk/libs/lvgl/lv_core/lv_vdb.c
Normal file
207
bdk/libs/lvgl/lv_core/lv_vdb.c
Normal file
|
@ -0,0 +1,207 @@
|
|||
/**
|
||||
* @file lv_vdb.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_vdb.h"
|
||||
#if LV_VDB_SIZE != 0
|
||||
|
||||
#include "../lv_hal/lv_hal_disp.h"
|
||||
#include "../lv_misc/lv_log.h"
|
||||
#include <stddef.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#ifndef LV_ATTRIBUTE_FLUSH_READY
|
||||
#define LV_ATTRIBUTE_FLUSH_READY
|
||||
#endif
|
||||
|
||||
#ifndef LV_ATTRIBUTE_MEM_ALIGN
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/*Simple VDB*/
|
||||
#if LV_VDB_DOUBLE == 0
|
||||
# if LV_VDB_ADR == 0
|
||||
/*If the buffer address is not specified simply allocate it*/
|
||||
static LV_ATTRIBUTE_MEM_ALIGN uint8_t vdb_buf[LV_VDB_SIZE_IN_BYTES];
|
||||
static lv_vdb_t vdb = {.buf = (lv_color_t *)vdb_buf};
|
||||
# else /*LV_VDB_ADR != 0*/
|
||||
/*If the buffer address is specified use that address*/
|
||||
static lv_vdb_t vdb = {.buf = (lv_color_t *)LV_VDB_ADR};
|
||||
# endif
|
||||
|
||||
/*LV_VDB_DOUBLE != 0*/
|
||||
#else
|
||||
/*Double VDB*/
|
||||
static uint8_t vdb_active = 0;
|
||||
# if LV_VDB_ADR == 0
|
||||
/*If the buffer address is not specified simply allocate it*/
|
||||
static LV_ATTRIBUTE_MEM_ALIGN uint8_t vdb_buf1[LV_VDB_SIZE_IN_BYTES];
|
||||
static LV_ATTRIBUTE_MEM_ALIGN uint8_t vdb_buf2[LV_VDB_SIZE_IN_BYTES];
|
||||
static lv_vdb_t vdb[2] = {{.buf = (lv_color_t *) vdb_buf1}, {.buf = (lv_color_t *) vdb_buf2}};
|
||||
# else /*LV_VDB_ADR != 0*/
|
||||
/*If the buffer address is specified use that address*/
|
||||
static lv_vdb_t vdb[2] = {{.buf = (lv_color_t *)LV_VDB_ADR}, {.buf = (lv_color_t *)LV_VDB2_ADR}};
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static volatile bool vdb_flushing = false;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get the 'vdb' variable or allocate one in LV_VDB_DOUBLE mode
|
||||
* @return pointer to a 'vdb' variable
|
||||
*/
|
||||
lv_vdb_t * lv_vdb_get(void)
|
||||
{
|
||||
#if LV_VDB_DOUBLE == 0
|
||||
/* Wait until VDB is flushing.
|
||||
* (Until this user calls of 'lv_flush_ready()' in the display drivers's flush function*/
|
||||
while(vdb_flushing);
|
||||
|
||||
return &vdb;
|
||||
#else
|
||||
/*If already there is an active do nothing*/
|
||||
return &vdb[vdb_active];
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the content of the VDB
|
||||
*/
|
||||
void lv_vdb_flush(void)
|
||||
{
|
||||
lv_vdb_t * vdb_act = lv_vdb_get();
|
||||
if(!vdb_act) {
|
||||
LV_LOG_WARN("Invalid VDB pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
/*Don't start a new flush while the previous is not finished*/
|
||||
#if LV_VDB_DOUBLE
|
||||
while(vdb_flushing);
|
||||
#endif /*LV_VDB_DOUBLE*/
|
||||
|
||||
vdb_flushing = true;
|
||||
|
||||
/*Flush the rendered content to the display*/
|
||||
lv_disp_flush(vdb_act->area.x1, vdb_act->area.y1, vdb_act->area.x2, vdb_act->area.y2, vdb_act->buf);
|
||||
|
||||
|
||||
#if LV_VDB_DOUBLE
|
||||
/*Make the other VDB active. The content of the current will be kept until the next flush*/
|
||||
vdb_active++;
|
||||
vdb_active &= 0x1;
|
||||
|
||||
/*If the screen is transparent initialize it when the new VDB is selected*/
|
||||
# if LV_COLOR_SCREEN_TRANSP
|
||||
memset(vdb[vdb_active].buf, 0x00, LV_VDB_SIZE_IN_BYTES);
|
||||
# endif /*LV_COLOR_SCREEN_TRANSP*/
|
||||
|
||||
#endif /*#if LV_VDB_DOUBLE*/
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the address of VDB buffer(s) manually. To use this set `LV_VDB_ADR` (and `LV_VDB2_ADR`) to `LV_VDB_ADR_INV` in `lv_conf.h`.
|
||||
* It should be called before `lv_init()`. The size of the buffer should be: `LV_VDB_SIZE_IN_BYTES`
|
||||
* @param buf1 address of the VDB.
|
||||
* @param buf2 address of the second buffer. `NULL` if `LV_VDB_DOUBLE 0`
|
||||
*/
|
||||
void lv_vdb_set_adr(void * buf1, void * buf2)
|
||||
{
|
||||
#if LV_VDB_DOUBLE == 0
|
||||
(void) buf2; /*unused*/
|
||||
vdb.buf = buf1;
|
||||
#else
|
||||
vdb[0].buf = buf1;
|
||||
vdb[1].buf = buf2;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Call in the display driver's 'disp_flush' function when the flushing is finished
|
||||
*/
|
||||
LV_ATTRIBUTE_FLUSH_READY void lv_flush_ready(void)
|
||||
{
|
||||
vdb_flushing = false;
|
||||
|
||||
/*If the screen is transparent initialize it when the flushing is ready*/
|
||||
#if LV_VDB_DOUBLE == 0 && LV_COLOR_SCREEN_TRANSP
|
||||
memset(vdb_buf, 0x00, LV_VDB_SIZE_IN_BYTES);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get currently active VDB, where the drawing happens. Used with `LV_VDB_DOUBLE 1`
|
||||
* @return pointer to the active VDB. If `LV_VDB_DOUBLE 0` give the single VDB
|
||||
*/
|
||||
lv_vdb_t * lv_vdb_get_active(void)
|
||||
{
|
||||
#if LV_VDB_DOUBLE == 0
|
||||
return &vdb;
|
||||
#else
|
||||
return &vdb[vdb_active];
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get currently inactive VDB, which is being displayed or being flushed. Used with `LV_VDB_DOUBLE 1`
|
||||
* @return pointer to the inactive VDB. If `LV_VDB_DOUBLE 0` give the single VDB
|
||||
*/
|
||||
lv_vdb_t * lv_vdb_get_inactive(void)
|
||||
{
|
||||
#if LV_VDB_DOUBLE == 0
|
||||
return &vdb;
|
||||
#else
|
||||
return &vdb[(vdb_active + 1) & 0x1];
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the flushing is in progress or not
|
||||
* @return true: flushing is in progress; false: flushing ready
|
||||
*/
|
||||
bool lv_vdb_is_flushing(void)
|
||||
{
|
||||
return vdb_flushing;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* Just for compatibility
|
||||
*/
|
||||
void lv_flush_ready(void)
|
||||
{
|
||||
/*Do nothing. It is used only for VDB*/
|
||||
}
|
||||
#endif
|
119
bdk/libs/lvgl/lv_core/lv_vdb.h
Normal file
119
bdk/libs/lvgl/lv_core/lv_vdb.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
/**
|
||||
* @file lv_vdb.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_VDB_H
|
||||
#define LV_VDB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#ifdef LV_CONF_INCLUDE_SIMPLE
|
||||
#include "lv_conf.h"
|
||||
#else
|
||||
#include "../../lv_conf.h"
|
||||
#endif
|
||||
|
||||
#if LV_VDB_SIZE != 0
|
||||
|
||||
#include "../lv_misc/lv_color.h"
|
||||
#include "../lv_misc/lv_area.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*Can be used in `lv_conf.h` the set an invalid address for the VDB. It should be replaced later by a valid address using `lv_vdb_set_adr()`*/
|
||||
#define LV_VDB_ADR_INV 8 /*8 is still too small to be valid but it's aligned on 64 bit machines as well*/
|
||||
|
||||
#ifndef LV_VDB_PX_BPP
|
||||
#define LV_VDB_PX_BPP LV_COLOR_SIZE /* Default is LV_COLOR_SIZE */
|
||||
#endif
|
||||
|
||||
|
||||
#if LV_VDB_TRUE_DOUBLE_BUFFERED && (LV_VDB_SIZE != LV_HOR_RES * LV_VER_RES || LV_VDB_DOUBLE == 0)
|
||||
#error "With LV_VDB_TRUE_DOUBLE_BUFFERED: (LV_VDB_SIZE = LV_HOR_RES * LV_VER_RES and LV_VDB_DOUBLE = 1 is required"
|
||||
#endif
|
||||
|
||||
|
||||
/* The size of VDB in bytes.
|
||||
* (LV_VDB_SIZE * LV_VDB_PX_BPP) >> 3): just divide by 8 to convert bits to bytes
|
||||
* (((LV_VDB_SIZE * LV_VDB_PX_BPP) & 0x7) ? 1 : 0): add an extra byte to round up.
|
||||
* E.g. if LV_VDB_SIZE = 10 and LV_VDB_PX_BPP = 1 -> 10 bits -> 2 bytes*/
|
||||
#define LV_VDB_SIZE_IN_BYTES ((LV_VDB_SIZE * LV_VDB_PX_BPP) >> 3) + (((LV_VDB_SIZE * LV_VDB_PX_BPP) & 0x7) ? 1 : 0)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
lv_area_t area;
|
||||
lv_color_t *buf;
|
||||
} lv_vdb_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get the 'vdb' variable or allocate one in LV_VDB_DOUBLE mode
|
||||
* @return pointer to a 'vdb' variable
|
||||
*/
|
||||
lv_vdb_t * lv_vdb_get(void);
|
||||
|
||||
/**
|
||||
* Flush the content of the vdb
|
||||
*/
|
||||
void lv_vdb_flush(void);
|
||||
|
||||
/**
|
||||
* Set the address of VDB buffer(s) manually. To use this set `LV_VDB_ADR` (and `LV_VDB2_ADR`) to `LV_VDB_ADR_INV` in `lv_conf.h`.
|
||||
* It should be called before `lv_init()`. The size of the buffer should be: `LV_VDB_SIZE_IN_BYTES`
|
||||
* @param buf1 address of the VDB.
|
||||
* @param buf2 address of the second buffer. `NULL` if `LV_VDB_DOUBLE 0`
|
||||
*/
|
||||
void lv_vdb_set_adr(void * buf1, void * buf2);
|
||||
|
||||
/**
|
||||
* Call in the display driver's 'disp_flush' function when the flushing is finished
|
||||
*/
|
||||
void lv_flush_ready(void);
|
||||
|
||||
/**
|
||||
* Get currently active VDB, where the drawing happens. Used with `LV_VDB_DOUBLE 1`
|
||||
* @return pointer to the active VDB. If `LV_VDB_DOUBLE 0` give the single VDB
|
||||
*/
|
||||
lv_vdb_t * lv_vdb_get_active(void);
|
||||
|
||||
/**
|
||||
* Get currently inactive VDB, which is being displayed or being flushed. Used with `LV_VDB_DOUBLE 1`
|
||||
* @return pointer to the inactive VDB. If `LV_VDB_DOUBLE 0` give the single VDB
|
||||
*/
|
||||
lv_vdb_t * lv_vdb_get_inactive(void);
|
||||
|
||||
/**
|
||||
* Whether the flushing is in progress or not
|
||||
* @return true: flushing is in progress; false: flushing ready
|
||||
*/
|
||||
bool lv_vdb_is_flushing(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#else /*LV_VDB_SIZE != 0*/
|
||||
|
||||
/*Just for compatibility*/
|
||||
void lv_flush_ready(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_VDB_H*/
|
Loading…
Add table
Add a link
Reference in a new issue