Transition to hekate bdk layout
This commit is contained in:
parent
4425e81085
commit
4ffd4ce7f0
317 changed files with 60891 additions and 1003 deletions
310
bdk/libs/lvgl/lv_objx/lv_arc.c
Normal file
310
bdk/libs/lvgl/lv_objx/lv_arc.c
Normal file
|
@ -0,0 +1,310 @@
|
|||
/**
|
||||
* @file lv_arc.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_arc.h"
|
||||
#if USE_LV_ARC != 0
|
||||
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_draw/lv_draw_arc.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_arc_design(lv_obj_t * arc, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_arc_signal(lv_obj_t * arc, lv_signal_t sign, void * param);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
static lv_design_func_t ancestor_design;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a arc object
|
||||
* @param par pointer to an object, it will be the parent of the new arc
|
||||
* @param copy pointer to a arc object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created arc
|
||||
*/
|
||||
lv_obj_t * lv_arc_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
|
||||
LV_LOG_TRACE("arc create started");
|
||||
|
||||
/*Create the ancestor of arc*/
|
||||
lv_obj_t * new_arc = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_arc);
|
||||
if(new_arc == NULL) return NULL;
|
||||
|
||||
/*Allocate the arc type specific extended data*/
|
||||
lv_arc_ext_t * ext = lv_obj_allocate_ext_attr(new_arc, sizeof(lv_arc_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_arc);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_arc);
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->angle_start = 45;
|
||||
ext->angle_end = 315;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_arc, lv_arc_signal);
|
||||
lv_obj_set_design_func(new_arc, lv_arc_design);
|
||||
|
||||
/*Init the new arc arc*/
|
||||
if(copy == NULL) {
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_arc_set_style(new_arc, LV_ARC_STYLE_MAIN, th->arc);
|
||||
} else {
|
||||
lv_arc_set_style(new_arc, LV_ARC_STYLE_MAIN, &lv_style_plain_color);
|
||||
}
|
||||
|
||||
}
|
||||
/*Copy an existing arc*/
|
||||
else {
|
||||
lv_arc_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->angle_start = copy_ext->angle_start;
|
||||
ext->angle_end = copy_ext->angle_end;
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_arc);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("arc created");
|
||||
|
||||
return new_arc;
|
||||
}
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/*
|
||||
* New object specific "add" or "remove" functions come here
|
||||
*/
|
||||
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the start and end angles of an arc. 0 deg: bottom, 90 deg: right etc.
|
||||
* @param arc pointer to an arc object
|
||||
* @param start the start angle [0..360]
|
||||
* @param end the end angle [0..360]
|
||||
*/
|
||||
void lv_arc_set_angles(lv_obj_t * arc, uint16_t start, uint16_t end)
|
||||
{
|
||||
lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc);
|
||||
|
||||
if(start > 360) start = 360;
|
||||
if(end > 360) end = 360;
|
||||
|
||||
ext->angle_start = start;
|
||||
ext->angle_end = end;
|
||||
|
||||
lv_obj_invalidate(arc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a arc.
|
||||
* @param arc pointer to arc object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
* */
|
||||
void lv_arc_set_style(lv_obj_t * arc, lv_arc_style_t type, lv_style_t * style)
|
||||
{
|
||||
switch(type) {
|
||||
case LV_ARC_STYLE_MAIN:
|
||||
lv_obj_set_style(arc, style);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the start angle of an arc.
|
||||
* @param arc pointer to an arc object
|
||||
* @return the start angle [0..360]
|
||||
*/
|
||||
uint16_t lv_arc_get_angle_start(lv_obj_t * arc)
|
||||
{
|
||||
lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc);
|
||||
|
||||
return ext->angle_start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end angle of an arc.
|
||||
* @param arc pointer to an arc object
|
||||
* @return the end angle [0..360]
|
||||
*/
|
||||
uint16_t lv_arc_get_angle_end(lv_obj_t * arc)
|
||||
{
|
||||
lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc);
|
||||
|
||||
return ext->angle_end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get style of a arc.
|
||||
* @param arc pointer to arc object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
* */
|
||||
lv_style_t * lv_arc_get_style(const lv_obj_t * arc, lv_arc_style_t type)
|
||||
{
|
||||
lv_style_t * style = NULL;
|
||||
|
||||
switch(type) {
|
||||
case LV_ARC_STYLE_MAIN:
|
||||
style = lv_obj_get_style(arc);
|
||||
break;
|
||||
default:
|
||||
style = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/*
|
||||
* New object specific "other" functions come here
|
||||
*/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the arcs
|
||||
* @param arc pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_arc_design(lv_obj_t * arc, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return false;
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
lv_arc_ext_t * ext = lv_obj_get_ext_attr(arc);
|
||||
lv_style_t * style = lv_arc_get_style(arc, LV_ARC_STYLE_MAIN);
|
||||
|
||||
lv_coord_t r = (LV_MATH_MIN(lv_obj_get_width(arc), lv_obj_get_height(arc))) / 2;
|
||||
lv_coord_t x = arc->coords.x1 + lv_obj_get_width(arc) / 2;
|
||||
lv_coord_t y = arc->coords.y1 + lv_obj_get_height(arc) / 2;
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(arc);
|
||||
lv_draw_arc(x, y, r, mask, ext->angle_start, ext->angle_end, style, opa_scale);
|
||||
|
||||
|
||||
/*Draw circle on the ends if enabled */
|
||||
if(style->line.rounded) {
|
||||
lv_coord_t thick_half = style->line.width / 2;
|
||||
lv_coord_t cir_x = ((r - thick_half) * lv_trigo_sin(ext->angle_start) >> LV_TRIGO_SHIFT);
|
||||
lv_coord_t cir_y = ((r - thick_half) * lv_trigo_sin(ext->angle_start + 90) >> LV_TRIGO_SHIFT);
|
||||
|
||||
lv_style_t cir_style;
|
||||
lv_style_copy(&cir_style, &lv_style_plain);
|
||||
cir_style.body.grad_color = style->line.color;
|
||||
cir_style.body.main_color = cir_style.body.grad_color;
|
||||
cir_style.body.radius = LV_RADIUS_CIRCLE;
|
||||
lv_area_t cir_area;
|
||||
cir_area.x1 = cir_x + x - thick_half;
|
||||
cir_area.y1 = cir_y + y - thick_half;
|
||||
cir_area.x2 = cir_x + x + thick_half;
|
||||
cir_area.y2 = cir_y + y + thick_half;
|
||||
|
||||
lv_draw_rect(&cir_area, mask, &cir_style, opa_scale);
|
||||
|
||||
cir_x = ((r - thick_half) * lv_trigo_sin(ext->angle_end) >> LV_TRIGO_SHIFT);
|
||||
cir_y = ((r - thick_half) * lv_trigo_sin(ext->angle_end + 90) >> LV_TRIGO_SHIFT);
|
||||
|
||||
cir_area.x1 = cir_x + x - thick_half;
|
||||
cir_area.y1 = cir_y + y - thick_half;
|
||||
cir_area.x2 = cir_x + x + thick_half;
|
||||
cir_area.y2 = cir_y + y + thick_half;
|
||||
|
||||
lv_draw_rect(&cir_area, mask, &cir_style, opa_scale);
|
||||
}
|
||||
|
||||
}
|
||||
/*Post draw when the children are drawn*/
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the arc
|
||||
* @param arc pointer to a arc object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_arc_signal(lv_obj_t * arc, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(arc, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_arc";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
127
bdk/libs/lvgl/lv_objx/lv_arc.h
Normal file
127
bdk/libs/lvgl/lv_objx/lv_arc.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
/**
|
||||
* @file lv_arc.h
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_ARC_H
|
||||
#define LV_ARC_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_ARC != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Data of arc*/
|
||||
typedef struct {
|
||||
/*New data for this type */
|
||||
lv_coord_t angle_start;
|
||||
lv_coord_t angle_end;
|
||||
} lv_arc_ext_t;
|
||||
|
||||
|
||||
/*Styles*/
|
||||
enum {
|
||||
LV_ARC_STYLE_MAIN,
|
||||
};
|
||||
typedef uint8_t lv_arc_style_t;
|
||||
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a arc objects
|
||||
* @param par pointer to an object, it will be the parent of the new arc
|
||||
* @param copy pointer to a arc object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created arc
|
||||
*/
|
||||
lv_obj_t * lv_arc_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the start and end angles of an arc. 0 deg: bottom, 90 deg: right etc.
|
||||
* @param arc pointer to an arc object
|
||||
* @param start the start angle [0..360]
|
||||
* @param end the end angle [0..360]
|
||||
*/
|
||||
void lv_arc_set_angles(lv_obj_t * arc, uint16_t start, uint16_t end);
|
||||
|
||||
/**
|
||||
* Set a style of a arc.
|
||||
* @param arc pointer to arc object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
* */
|
||||
void lv_arc_set_style(lv_obj_t * arc, lv_arc_style_t type, lv_style_t *style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the start angle of an arc.
|
||||
* @param arc pointer to an arc object
|
||||
* @return the start angle [0..360]
|
||||
*/
|
||||
uint16_t lv_arc_get_angle_start(lv_obj_t * arc);
|
||||
|
||||
/**
|
||||
* Get the end angle of an arc.
|
||||
* @param arc pointer to an arc object
|
||||
* @return the end angle [0..360]
|
||||
*/
|
||||
uint16_t lv_arc_get_angle_end(lv_obj_t * arc);
|
||||
|
||||
/**
|
||||
* Get style of a arc.
|
||||
* @param arc pointer to arc object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
* */
|
||||
lv_style_t * lv_arc_get_style(const lv_obj_t * arc, lv_arc_style_t type);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_ARC*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_ARC_H*/
|
429
bdk/libs/lvgl/lv_objx/lv_bar.c
Normal file
429
bdk/libs/lvgl/lv_objx/lv_bar.c
Normal file
|
@ -0,0 +1,429 @@
|
|||
|
||||
|
||||
/**
|
||||
* @file lv_bar.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_bar.h"
|
||||
#if USE_LV_BAR != 0
|
||||
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_anim.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_bar_design(lv_obj_t * bar, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_bar_signal(lv_obj_t * bar, lv_signal_t sign, void * param);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_design_func_t ancestor_design_f;
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a bar objects
|
||||
* @param par pointer to an object, it will be the parent of the new bar
|
||||
* @param copy pointer to a bar object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created bar
|
||||
*/
|
||||
lv_obj_t * lv_bar_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("lv_bar create started");
|
||||
|
||||
/*Create the ancestor basic object*/
|
||||
lv_obj_t * new_bar = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_bar);
|
||||
if(new_bar == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_bar);
|
||||
if(ancestor_design_f == NULL) ancestor_design_f = lv_obj_get_design_func(new_bar);
|
||||
|
||||
/*Allocate the object type specific extended data*/
|
||||
lv_bar_ext_t * ext = lv_obj_allocate_ext_attr(new_bar, sizeof(lv_bar_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->min_value = 0;
|
||||
ext->max_value = 100;
|
||||
ext->cur_value = 0;
|
||||
ext->sym = 0;
|
||||
ext->style_indic = &lv_style_pretty_color;
|
||||
|
||||
lv_obj_set_signal_func(new_bar, lv_bar_signal);
|
||||
lv_obj_set_design_func(new_bar, lv_bar_design);
|
||||
|
||||
/*Init the new bar object*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_click(new_bar, false);
|
||||
lv_obj_set_size(new_bar, LV_DPI * 2, LV_DPI / 3);
|
||||
lv_bar_set_value(new_bar, ext->cur_value);
|
||||
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_bar_set_style(new_bar, LV_BAR_STYLE_BG, th->bar.bg);
|
||||
lv_bar_set_style(new_bar, LV_BAR_STYLE_INDIC, th->bar.indic);
|
||||
} else {
|
||||
lv_obj_set_style(new_bar, &lv_style_pretty);
|
||||
}
|
||||
} else {
|
||||
lv_bar_ext_t * ext_copy = lv_obj_get_ext_attr(copy);
|
||||
ext->min_value = ext_copy->min_value;
|
||||
ext->max_value = ext_copy->max_value;
|
||||
ext->cur_value = ext_copy->cur_value;
|
||||
ext->style_indic = ext_copy->style_indic;
|
||||
ext->sym = ext_copy->sym;
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_bar);
|
||||
|
||||
lv_bar_set_value(new_bar, ext->cur_value);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("bar created");
|
||||
|
||||
return new_bar;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new value on the bar
|
||||
* @param bar pointer to a bar object
|
||||
* @param value new value
|
||||
*/
|
||||
void lv_bar_set_value(lv_obj_t * bar, int16_t value)
|
||||
{
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
if(ext->cur_value == value) return;
|
||||
|
||||
ext->cur_value = value > ext->max_value ? ext->max_value : value;
|
||||
ext->cur_value = ext->cur_value < ext->min_value ? ext->min_value : ext->cur_value;
|
||||
lv_obj_invalidate(bar);
|
||||
}
|
||||
|
||||
#if USE_LV_ANIMATION
|
||||
/**
|
||||
* Set a new value with animation on the bar
|
||||
* @param bar pointer to a bar object
|
||||
* @param value new value
|
||||
* @param anim_time animation time in milliseconds
|
||||
*/
|
||||
void lv_bar_set_value_anim(lv_obj_t * bar, int16_t value, uint16_t anim_time)
|
||||
{
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
if(ext->cur_value == value) return;
|
||||
|
||||
int16_t new_value;
|
||||
new_value = value > ext->max_value ? ext->max_value : value;
|
||||
new_value = new_value < ext->min_value ? ext->min_value : new_value;
|
||||
|
||||
lv_anim_t a;
|
||||
a.var = bar;
|
||||
a.start = ext->cur_value;
|
||||
a.end = new_value;
|
||||
a.fp = (lv_anim_fp_t)lv_bar_set_value;
|
||||
a.path = lv_anim_path_linear;
|
||||
a.end_cb = NULL;
|
||||
a.act_time = 0;
|
||||
a.time = anim_time;
|
||||
a.playback = 0;
|
||||
a.playback_pause = 0;
|
||||
a.repeat = 0;
|
||||
a.repeat_pause = 0;
|
||||
|
||||
lv_anim_create(&a);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Set minimum and the maximum values of a bar
|
||||
* @param bar pointer to the bar object
|
||||
* @param min minimum value
|
||||
* @param max maximum value
|
||||
*/
|
||||
void lv_bar_set_range(lv_obj_t * bar, int16_t min, int16_t max)
|
||||
{
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
if(ext->min_value == min && ext->max_value == max) return;
|
||||
|
||||
ext->max_value = max;
|
||||
ext->min_value = min;
|
||||
if(ext->cur_value > max) {
|
||||
ext->cur_value = max;
|
||||
lv_bar_set_value(bar, ext->cur_value);
|
||||
}
|
||||
if(ext->cur_value < min) {
|
||||
ext->cur_value = min;
|
||||
lv_bar_set_value(bar, ext->cur_value);
|
||||
}
|
||||
lv_obj_invalidate(bar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the bar symmetric to zero. The indicator will grow from zero instead of the minimum position.
|
||||
* @param bar pointer to a bar object
|
||||
* @param en true: enable disable symmetric behavior; false: disable
|
||||
*/
|
||||
void lv_bar_set_sym(lv_obj_t * bar, bool en)
|
||||
{
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
ext->sym = en ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a bar
|
||||
* @param bar pointer to a bar object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_bar_set_style(lv_obj_t * bar, lv_bar_style_t type, lv_style_t * style)
|
||||
{
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
|
||||
switch(type) {
|
||||
case LV_BAR_STYLE_BG:
|
||||
lv_obj_set_style(bar, style);
|
||||
break;
|
||||
case LV_BAR_STYLE_INDIC:
|
||||
ext->style_indic = style;
|
||||
lv_obj_refresh_ext_size(bar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the value of a bar
|
||||
* @param bar pointer to a bar object
|
||||
* @return the value of the bar
|
||||
*/
|
||||
int16_t lv_bar_get_value(const lv_obj_t * bar)
|
||||
{
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
return ext->cur_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minimum value of a bar
|
||||
* @param bar pointer to a bar object
|
||||
* @return the minimum value of the bar
|
||||
*/
|
||||
int16_t lv_bar_get_min_value(const lv_obj_t * bar)
|
||||
{
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
return ext->min_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum value of a bar
|
||||
* @param bar pointer to a bar object
|
||||
* @return the maximum value of the bar
|
||||
*/
|
||||
int16_t lv_bar_get_max_value(const lv_obj_t * bar)
|
||||
{
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
return ext->max_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether the bar is symmetric or not.
|
||||
* @param bar pointer to a bar object
|
||||
* @return true: symmetric is enabled; false: disable
|
||||
*/
|
||||
bool lv_bar_get_sym(lv_obj_t * bar)
|
||||
{
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
return ext->sym ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a bar
|
||||
* @param bar pointer to a bar object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_bar_get_style(const lv_obj_t * bar, lv_bar_style_t type)
|
||||
{
|
||||
lv_style_t * style = NULL;
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
|
||||
switch(type) {
|
||||
case LV_BAR_STYLE_BG:
|
||||
style = lv_obj_get_style(bar);
|
||||
break;
|
||||
case LV_BAR_STYLE_INDIC:
|
||||
style = ext->style_indic;
|
||||
break;
|
||||
default:
|
||||
style = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the bars
|
||||
* @param bar pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_bar_design(lv_obj_t * bar, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
/*Return false if the object is not covers the mask area*/
|
||||
return ancestor_design_f(bar, mask, mode);
|
||||
} else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(bar);
|
||||
|
||||
#if USE_LV_GROUP == 0
|
||||
ancestor_design_f(bar, mask, mode);
|
||||
#else
|
||||
/* Draw the borders later if the bar is focused.
|
||||
* At value = 100% the indicator can cover to whole background and the focused style won't be visible*/
|
||||
if(lv_obj_is_focused(bar)) {
|
||||
lv_style_t * style_bg = lv_bar_get_style(bar, LV_BAR_STYLE_BG);
|
||||
lv_style_t style_tmp;
|
||||
lv_style_copy(&style_tmp, style_bg);
|
||||
style_tmp.body.border.width = 0;
|
||||
lv_draw_rect(&bar->coords, mask, &style_tmp, opa_scale);
|
||||
} else {
|
||||
ancestor_design_f(bar, mask, mode);
|
||||
}
|
||||
#endif
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
|
||||
if(ext->cur_value != ext->min_value || ext->sym) {
|
||||
lv_style_t * style_indic = lv_bar_get_style(bar, LV_BAR_STYLE_INDIC);
|
||||
lv_area_t indic_area;
|
||||
lv_area_copy(&indic_area, &bar->coords);
|
||||
indic_area.x1 += style_indic->body.padding.hor;
|
||||
indic_area.x2 -= style_indic->body.padding.hor;
|
||||
indic_area.y1 += style_indic->body.padding.ver;
|
||||
indic_area.y2 -= style_indic->body.padding.ver;
|
||||
|
||||
lv_coord_t w = lv_area_get_width(&indic_area);
|
||||
lv_coord_t h = lv_area_get_height(&indic_area);
|
||||
|
||||
if(w >= h) {
|
||||
/*Horizontal*/
|
||||
indic_area.x2 = (int32_t)((int32_t)w * (ext->cur_value - ext->min_value)) / (ext->max_value - ext->min_value);
|
||||
indic_area.x2 = indic_area.x1 + indic_area.x2 - 1;
|
||||
|
||||
if(ext->sym && ext->min_value < 0 && ext->max_value > 0) {
|
||||
/*Calculate the coordinate of the zero point*/
|
||||
lv_coord_t zero;
|
||||
zero = indic_area.x1 + (-ext->min_value * w) / (ext->max_value - ext->min_value);
|
||||
if(indic_area.x2 > zero) indic_area.x1 = zero;
|
||||
else {
|
||||
indic_area.x1 = indic_area.x2;
|
||||
indic_area.x2 = zero;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
indic_area.y1 = (int32_t)((int32_t)h * (ext->cur_value - ext->min_value)) / (ext->max_value - ext->min_value);
|
||||
indic_area.y1 = indic_area.y2 - indic_area.y1 + 1;
|
||||
|
||||
if(ext->sym && ext->min_value < 0 && ext->max_value > 0) {
|
||||
/*Calculate the coordinate of the zero point*/
|
||||
lv_coord_t zero;
|
||||
zero = indic_area.y2 - (-ext->min_value * h) / (ext->max_value - ext->min_value);
|
||||
if(indic_area.y1 < zero) indic_area.y2 = zero;
|
||||
else {
|
||||
indic_area.y2 = indic_area.y1;
|
||||
indic_area.y1 = zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*Draw the indicator*/
|
||||
lv_draw_rect(&indic_area, mask, style_indic, opa_scale);
|
||||
}
|
||||
} else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
#if USE_LV_GROUP
|
||||
/*Draw the border*/
|
||||
if(lv_obj_is_focused(bar)) {
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(bar);
|
||||
lv_style_t * style_bg = lv_bar_get_style(bar, LV_BAR_STYLE_BG);
|
||||
lv_style_t style_tmp;
|
||||
lv_style_copy(&style_tmp, style_bg);
|
||||
style_tmp.body.empty = 1;
|
||||
style_tmp.body.shadow.width = 0;
|
||||
lv_draw_rect(&bar->coords, mask, &style_tmp, opa_scale);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the bar
|
||||
* @param bar pointer to a bar object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_bar_signal(lv_obj_t * bar, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(bar, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
if(sign == LV_SIGNAL_REFR_EXT_SIZE) {
|
||||
lv_style_t * style_indic = lv_bar_get_style(bar, LV_BAR_STYLE_INDIC);
|
||||
if(style_indic->body.shadow.width > bar->ext_size) bar->ext_size = style_indic->body.shadow.width;
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_bar";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
160
bdk/libs/lvgl/lv_objx/lv_bar.h
Normal file
160
bdk/libs/lvgl/lv_objx/lv_bar.h
Normal file
|
@ -0,0 +1,160 @@
|
|||
/**
|
||||
* @file lv_bar.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_BAR_H
|
||||
#define LV_BAR_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_BAR != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_cont.h"
|
||||
#include "lv_btn.h"
|
||||
#include "lv_label.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Data of bar*/
|
||||
typedef struct
|
||||
{
|
||||
/*No inherited ext*/ /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
int16_t cur_value; /*Current value of the bar*/
|
||||
int16_t min_value; /*Minimum value of the bar*/
|
||||
int16_t max_value; /*Maximum value of the bar*/
|
||||
uint8_t sym :1; /*Symmetric: means the center is around zero value*/
|
||||
lv_style_t *style_indic; /*Style of the indicator*/
|
||||
} lv_bar_ext_t;
|
||||
|
||||
enum {
|
||||
LV_BAR_STYLE_BG,
|
||||
LV_BAR_STYLE_INDIC,
|
||||
};
|
||||
typedef uint8_t lv_bar_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a bar objects
|
||||
* @param par pointer to an object, it will be the parent of the new bar
|
||||
* @param copy pointer to a bar object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created bar
|
||||
*/
|
||||
lv_obj_t * lv_bar_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new value on the bar
|
||||
* @param bar pointer to a bar object
|
||||
* @param value new value
|
||||
*/
|
||||
void lv_bar_set_value(lv_obj_t * bar, int16_t value);
|
||||
|
||||
/**
|
||||
* Set a new value with animation on the bar
|
||||
* @param bar pointer to a bar object
|
||||
* @param value new value
|
||||
* @param anim_time animation time in milliseconds
|
||||
*/
|
||||
void lv_bar_set_value_anim(lv_obj_t * bar, int16_t value, uint16_t anim_time);
|
||||
|
||||
|
||||
/**
|
||||
* Set minimum and the maximum values of a bar
|
||||
* @param bar pointer to the bar object
|
||||
* @param min minimum value
|
||||
* @param max maximum value
|
||||
*/
|
||||
void lv_bar_set_range(lv_obj_t * bar, int16_t min, int16_t max);
|
||||
|
||||
/**
|
||||
* Make the bar symmetric to zero. The indicator will grow from zero instead of the minimum position.
|
||||
* @param bar pointer to a bar object
|
||||
* @param en true: enable disable symmetric behavior; false: disable
|
||||
*/
|
||||
void lv_bar_set_sym(lv_obj_t * bar, bool en);
|
||||
|
||||
/**
|
||||
* Set a style of a bar
|
||||
* @param bar pointer to a bar object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_bar_set_style(lv_obj_t *bar, lv_bar_style_t type, lv_style_t *style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the value of a bar
|
||||
* @param bar pointer to a bar object
|
||||
* @return the value of the bar
|
||||
*/
|
||||
int16_t lv_bar_get_value(const lv_obj_t * bar);
|
||||
|
||||
/**
|
||||
* Get the minimum value of a bar
|
||||
* @param bar pointer to a bar object
|
||||
* @return the minimum value of the bar
|
||||
*/
|
||||
int16_t lv_bar_get_min_value(const lv_obj_t * bar);
|
||||
|
||||
/**
|
||||
* Get the maximum value of a bar
|
||||
* @param bar pointer to a bar object
|
||||
* @return the maximum value of the bar
|
||||
*/
|
||||
int16_t lv_bar_get_max_value(const lv_obj_t * bar);
|
||||
|
||||
/**
|
||||
* Get whether the bar is symmetric or not.
|
||||
* @param bar pointer to a bar object
|
||||
* @return true: symmetric is enabled; false: disable
|
||||
*/
|
||||
bool lv_bar_get_sym(lv_obj_t * bar);
|
||||
|
||||
/**
|
||||
* Get a style of a bar
|
||||
* @param bar pointer to a bar object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_bar_get_style(const lv_obj_t *bar, lv_bar_style_t type);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_BAR*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_BAR_H*/
|
763
bdk/libs/lvgl/lv_objx/lv_btn.c
Normal file
763
bdk/libs/lvgl/lv_objx/lv_btn.c
Normal file
|
@ -0,0 +1,763 @@
|
|||
/**
|
||||
* @file lv_btn.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_btn.h"
|
||||
#if USE_LV_BTN != 0
|
||||
|
||||
#include <string.h>
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_area.h"
|
||||
#include "../lv_misc/lv_color.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_BTN_INK_VALUE_MAX 256
|
||||
#define LV_BTN_INK_VALUE_MAX_SHIFT 8
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_btn_design(lv_obj_t * btn, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param);
|
||||
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
static void lv_btn_ink_effect_anim(lv_obj_t * btn, int32_t val);
|
||||
static void lv_btn_ink_effect_anim_ready(void * p);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
static lv_design_func_t ancestor_design;
|
||||
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
static lv_coord_t ink_act_value;
|
||||
static lv_obj_t * ink_obj;
|
||||
static lv_btn_state_t ink_bg_state;
|
||||
static lv_btn_state_t ink_top_state;
|
||||
static bool ink_ready;
|
||||
static bool ink_playback;
|
||||
static lv_point_t ink_point;
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a button objects
|
||||
* @param par pointer to an object, it will be the parent of the new button
|
||||
* @param copy pointer to a button object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created button
|
||||
*/
|
||||
lv_obj_t * lv_btn_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("button create started");
|
||||
|
||||
lv_obj_t * new_btn;
|
||||
|
||||
new_btn = lv_cont_create(par, copy);
|
||||
lv_mem_assert(new_btn);
|
||||
if(new_btn == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_btn);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_btn);
|
||||
|
||||
/*Allocate the extended data*/
|
||||
lv_btn_ext_t * ext = lv_obj_allocate_ext_attr(new_btn, sizeof(lv_btn_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->state = LV_BTN_STATE_REL;
|
||||
|
||||
ext->actions[LV_BTN_ACTION_PR] = NULL;
|
||||
ext->actions[LV_BTN_ACTION_CLICK] = NULL;
|
||||
ext->actions[LV_BTN_ACTION_LONG_PR] = NULL;
|
||||
ext->actions[LV_BTN_ACTION_LONG_PR_REPEAT] = NULL;
|
||||
|
||||
ext->styles[LV_BTN_STATE_REL] = &lv_style_btn_rel;
|
||||
ext->styles[LV_BTN_STATE_PR] = &lv_style_btn_pr;
|
||||
ext->styles[LV_BTN_STATE_TGL_REL] = &lv_style_btn_tgl_rel;
|
||||
ext->styles[LV_BTN_STATE_TGL_PR] = &lv_style_btn_tgl_pr;
|
||||
ext->styles[LV_BTN_STATE_INA] = &lv_style_btn_ina;
|
||||
|
||||
ext->long_pr_action_executed = 0;
|
||||
ext->toggle = 0;
|
||||
ext->idx = 0;
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
ext->ink_in_time = 0;
|
||||
ext->ink_wait_time = 0;
|
||||
ext->ink_out_time = 0;
|
||||
#endif
|
||||
|
||||
lv_obj_set_signal_func(new_btn, lv_btn_signal);
|
||||
lv_obj_set_design_func(new_btn, lv_btn_design);
|
||||
|
||||
/*If no copy do the basic initialization*/
|
||||
if(copy == NULL) {
|
||||
/*Set layout if the button is not a screen*/
|
||||
if(par != NULL) {
|
||||
lv_btn_set_layout(new_btn, LV_LAYOUT_CENTER);
|
||||
}
|
||||
|
||||
lv_obj_set_click(new_btn, true); /*Be sure the button is clickable*/
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_btn_set_style(new_btn, LV_BTN_STYLE_REL, th->btn.rel);
|
||||
lv_btn_set_style(new_btn, LV_BTN_STYLE_PR, th->btn.pr);
|
||||
lv_btn_set_style(new_btn, LV_BTN_STYLE_TGL_REL, th->btn.tgl_rel);
|
||||
lv_btn_set_style(new_btn, LV_BTN_STYLE_TGL_PR, th->btn.tgl_pr);
|
||||
lv_btn_set_style(new_btn, LV_BTN_STYLE_INA, th->btn.ina);
|
||||
} else {
|
||||
lv_obj_set_style(new_btn, ext->styles[LV_BTN_STATE_REL]);
|
||||
}
|
||||
}
|
||||
/*Copy 'copy'*/
|
||||
else {
|
||||
lv_btn_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->state = copy_ext->state;
|
||||
ext->toggle = copy_ext->toggle;
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
ext->ink_in_time = copy_ext->ink_in_time;
|
||||
ext->ink_wait_time = copy_ext->ink_wait_time;
|
||||
ext->ink_out_time = copy_ext->ink_out_time;
|
||||
#endif
|
||||
memcpy(ext->actions, copy_ext->actions, sizeof(ext->actions));
|
||||
memcpy(ext->styles, copy_ext->styles, sizeof(ext->styles));
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_btn);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("button created");
|
||||
|
||||
return new_btn;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Enable the toggled states
|
||||
* @param btn pointer to a button object
|
||||
* @param tgl true: enable toggled states, false: disable
|
||||
*/
|
||||
void lv_btn_set_toggle(lv_obj_t * btn, bool tgl)
|
||||
{
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
|
||||
ext->toggle = tgl != false ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state of the button
|
||||
* @param btn pointer to a button object
|
||||
* @param state the new state of the button (from lv_btn_state_t enum)
|
||||
*/
|
||||
void lv_btn_set_state(lv_obj_t * btn, lv_btn_state_t state)
|
||||
{
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
if(ext->state != state) {
|
||||
ext->state = state;
|
||||
lv_obj_set_style(btn, ext->styles[state]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the state of the button (ON->OFF, OFF->ON)
|
||||
* @param btn pointer to a button object
|
||||
*/
|
||||
void lv_btn_toggle(lv_obj_t * btn)
|
||||
{
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
switch(ext->state) {
|
||||
case LV_BTN_STATE_REL:
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
|
||||
break;
|
||||
case LV_BTN_STATE_PR:
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_TGL_PR);
|
||||
break;
|
||||
case LV_BTN_STATE_TGL_REL:
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_REL);
|
||||
break;
|
||||
case LV_BTN_STATE_TGL_PR:
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_PR);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a function to call when a button event happens
|
||||
* @param btn pointer to a button object
|
||||
* @param action type of event form 'lv_action_t' (press, release, long press, long press repeat)
|
||||
*/
|
||||
void lv_btn_set_action(lv_obj_t * btn, lv_btn_action_t type, lv_action_t action)
|
||||
{
|
||||
if(type >= LV_BTN_ACTION_NUM) return;
|
||||
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
ext->actions[type] = action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set time of the ink effect (draw a circle on click to animate in the new state)
|
||||
* @param btn pointer to a button object
|
||||
* @param time the time of the ink animation
|
||||
*/
|
||||
void lv_btn_set_ink_in_time(lv_obj_t * btn, uint16_t time)
|
||||
{
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
ext->ink_in_time = time;
|
||||
#else
|
||||
(void)btn; /*Unused*/
|
||||
(void)time; /*Unused*/
|
||||
LV_LOG_WARN("`lv_btn_set_ink_ink_time` has no effect if LV_BTN_INK_EFEFCT or USE_LV_ANIMATION is disabled")
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the wait time before the ink disappears
|
||||
* @param btn pointer to a button object
|
||||
* @param time the time of the ink animation
|
||||
*/
|
||||
void lv_btn_set_ink_wait_time(lv_obj_t * btn, uint16_t time)
|
||||
{
|
||||
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
ext->ink_wait_time = time;
|
||||
#else
|
||||
(void)btn; /*Unused*/
|
||||
(void)time; /*Unused*/
|
||||
LV_LOG_WARN("`lv_btn_set_ink_wait_time` has no effect if LV_BTN_INK_EFEFCT or USE_LV_ANIMATION is disabled")
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Set time of the ink out effect (animate to the released state)
|
||||
* @param btn pointer to a button object
|
||||
* @param time the time of the ink animation
|
||||
*/
|
||||
void lv_btn_set_ink_out_time(lv_obj_t * btn, uint16_t time)
|
||||
{
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
ext->ink_out_time = time;
|
||||
#else
|
||||
(void)btn; /*Unused*/
|
||||
(void)time; /*Unused*/
|
||||
LV_LOG_WARN("`lv_btn_set_ink_out_time` has no effect if LV_BTN_INK_EFEFCT or USE_LV_ANIMATION is disabled")
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a button
|
||||
* @param btn pointer to a button object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_btn_set_style(lv_obj_t * btn, lv_btn_style_t type, lv_style_t * style)
|
||||
{
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
|
||||
switch(type) {
|
||||
case LV_BTN_STYLE_REL:
|
||||
ext->styles[LV_BTN_STATE_REL] = style;
|
||||
break;
|
||||
case LV_BTN_STYLE_PR:
|
||||
ext->styles[LV_BTN_STATE_PR] = style;
|
||||
break;
|
||||
case LV_BTN_STYLE_TGL_REL:
|
||||
ext->styles[LV_BTN_STATE_TGL_REL] = style;
|
||||
break;
|
||||
case LV_BTN_STYLE_TGL_PR:
|
||||
ext->styles[LV_BTN_STATE_TGL_PR] = style;
|
||||
break;
|
||||
case LV_BTN_STYLE_INA:
|
||||
ext->styles[LV_BTN_STATE_INA] = style;
|
||||
break;
|
||||
}
|
||||
|
||||
/*Refresh the object with the new style*/
|
||||
lv_obj_set_style(btn, ext->styles[ext->state]);
|
||||
}
|
||||
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the current state of the button
|
||||
* @param btn pointer to a button object
|
||||
* @return the state of the button (from lv_btn_state_t enum)
|
||||
*/
|
||||
lv_btn_state_t lv_btn_get_state(const lv_obj_t * btn)
|
||||
{
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
return ext->state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the toggle enable attribute of the button
|
||||
* @param btn pointer to a button object
|
||||
* @return ture: toggle enabled, false: disabled
|
||||
*/
|
||||
bool lv_btn_get_toggle(const lv_obj_t * btn)
|
||||
{
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
|
||||
return ext->toggle != 0 ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the release action of a button
|
||||
* @param btn pointer to a button object
|
||||
* @return pointer to the release action function
|
||||
*/
|
||||
lv_action_t lv_btn_get_action(const lv_obj_t * btn, lv_btn_action_t type)
|
||||
{
|
||||
if(type >= LV_BTN_ACTION_NUM) return NULL;
|
||||
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
return ext->actions[type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get time of the ink in effect (draw a circle on click to animate in the new state)
|
||||
* @param btn pointer to a button object
|
||||
* @return the time of the ink animation
|
||||
*/
|
||||
uint16_t lv_btn_get_ink_in_time(const lv_obj_t * btn)
|
||||
{
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
return ext->ink_in_time;
|
||||
#else
|
||||
(void)btn; /*Unused*/
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the wait time before the ink disappears
|
||||
* @param btn pointer to a button object
|
||||
* @return the time of the ink animation
|
||||
*/
|
||||
uint16_t lv_btn_get_ink_wait_time(const lv_obj_t * btn)
|
||||
{
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
return ext->ink_wait_time;
|
||||
#else
|
||||
(void)btn; /*Unused*/
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
/**
|
||||
* Get time of the ink out effect (animate to the releases state)
|
||||
* @param btn pointer to a button object
|
||||
* @return the time of the ink animation
|
||||
*/
|
||||
uint16_t lv_btn_get_ink_out_time(const lv_obj_t * btn)
|
||||
{
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
return ext->ink_in_time;
|
||||
#else
|
||||
(void)btn; /*Unused*/
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a button
|
||||
* @param btn pointer to a button object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_btn_get_style(const lv_obj_t * btn, lv_btn_style_t type)
|
||||
{
|
||||
lv_style_t * style = NULL;
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
|
||||
switch(type) {
|
||||
case LV_BTN_STYLE_REL:
|
||||
style = ext->styles[LV_BTN_STATE_REL];
|
||||
break;
|
||||
case LV_BTN_STYLE_PR:
|
||||
style = ext->styles[LV_BTN_STATE_PR];
|
||||
break;
|
||||
case LV_BTN_STYLE_TGL_REL:
|
||||
style = ext->styles[LV_BTN_STATE_TGL_REL];
|
||||
break;
|
||||
case LV_BTN_STYLE_TGL_PR:
|
||||
style = ext->styles[LV_BTN_STATE_TGL_PR];
|
||||
break;
|
||||
case LV_BTN_STYLE_INA:
|
||||
style = ext->styles[LV_BTN_STATE_INA];
|
||||
break;
|
||||
default:
|
||||
style = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the drop down lists
|
||||
* @param btn pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_btn_design(lv_obj_t * btn, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return false;
|
||||
} else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
if(btn != ink_obj) {
|
||||
ancestor_design(btn, mask, mode);
|
||||
} else {
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(btn);
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
|
||||
/*Draw the normal button*/
|
||||
if(ink_playback == false) {
|
||||
lv_style_t style_tmp;
|
||||
lv_style_copy(&style_tmp, ext->styles[ink_bg_state]);
|
||||
style_tmp.body.shadow.width = ext->styles[ink_top_state]->body.shadow.width;
|
||||
lv_draw_rect(&btn->coords, mask, &style_tmp, opa_scale);
|
||||
|
||||
lv_coord_t w = lv_obj_get_width(btn);
|
||||
lv_coord_t h = lv_obj_get_height(btn);
|
||||
lv_coord_t r_max = LV_MATH_MIN(w, h) / 2;
|
||||
|
||||
/*In the first part of the animation increase the size of the circle (ink effect) */
|
||||
lv_area_t cir_area;
|
||||
|
||||
lv_coord_t coord_state = ink_act_value < LV_BTN_INK_VALUE_MAX / 2 ? ink_act_value : LV_BTN_INK_VALUE_MAX / 2;
|
||||
lv_point_t p_act;
|
||||
p_act.x = ink_point.x;
|
||||
p_act.y = ink_point.y;
|
||||
lv_coord_t x_err = (btn->coords.x1 + w / 2) - p_act.x;
|
||||
lv_coord_t y_err = (btn->coords.y1 + h / 2) - p_act.y;
|
||||
|
||||
p_act.x += (x_err * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1);
|
||||
p_act.y += (y_err * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1);
|
||||
|
||||
lv_coord_t half_side = LV_MATH_MAX(w, h) / 2;
|
||||
cir_area.x1 = p_act.x - ((half_side * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
|
||||
cir_area.y1 = p_act.y - ((half_side * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
|
||||
cir_area.x2 = p_act.x + ((half_side * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
|
||||
cir_area.y2 = p_act.y + ((half_side * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
|
||||
|
||||
lv_area_intersect(&cir_area, &btn->coords, &cir_area); /*Limit the area. (It might be too big on the smaller side)*/
|
||||
|
||||
/*In the second part animate the radius. Circle -> body.radius*/
|
||||
lv_coord_t r_state = ink_act_value > LV_BTN_INK_VALUE_MAX / 2 ? ink_act_value - LV_BTN_INK_VALUE_MAX / 2 : 0;
|
||||
|
||||
lv_style_copy(&style_tmp, ext->styles[ink_top_state]);
|
||||
style_tmp.body.radius = r_max + (((ext->styles[ink_bg_state]->body.radius - r_max) * r_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
|
||||
style_tmp.body.border.width = 0;
|
||||
|
||||
/*Draw the circle*/
|
||||
lv_draw_rect(&cir_area, mask, &style_tmp, opa_scale);
|
||||
} else {
|
||||
lv_style_t res;
|
||||
lv_style_copy(&res, ext->styles[ink_bg_state]);
|
||||
lv_style_mix(ext->styles[ink_bg_state], ext->styles[ink_top_state], &res, ink_act_value);
|
||||
lv_draw_rect(&btn->coords, mask, &res, opa_scale);
|
||||
|
||||
}
|
||||
}
|
||||
#else
|
||||
ancestor_design(btn, mask, mode);
|
||||
#endif
|
||||
} else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
ancestor_design(btn, mask, mode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the button
|
||||
* @param btn pointer to a button object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(btn, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
|
||||
lv_btn_state_t state = lv_btn_get_state(btn);
|
||||
bool tgl = lv_btn_get_toggle(btn);
|
||||
|
||||
if(sign == LV_SIGNAL_PRESSED) {
|
||||
/*Refresh the state*/
|
||||
if(ext->state == LV_BTN_STATE_REL) {
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_PR);
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
ink_bg_state = LV_BTN_STATE_REL;
|
||||
ink_top_state = LV_BTN_STATE_PR;
|
||||
#endif
|
||||
} else if(ext->state == LV_BTN_STATE_TGL_REL) {
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_TGL_PR);
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
ink_bg_state = LV_BTN_STATE_TGL_REL;
|
||||
ink_top_state = LV_BTN_STATE_TGL_PR;
|
||||
#endif
|
||||
}
|
||||
|
||||
ext->long_pr_action_executed = 0;
|
||||
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
/*Forget the old inked button*/
|
||||
if(ink_obj != NULL && ink_obj != btn) {
|
||||
lv_anim_del(ink_obj, (lv_anim_fp_t)lv_btn_ink_effect_anim);
|
||||
lv_obj_invalidate(ink_obj);
|
||||
ink_obj = NULL;
|
||||
}
|
||||
/*Save the new data for inking and start it's animation if enabled*/
|
||||
if(ext->ink_in_time > 0) {
|
||||
ink_obj = btn;
|
||||
ink_playback = false;
|
||||
ink_ready = false;
|
||||
lv_indev_get_point(lv_indev_get_act(), &ink_point);
|
||||
|
||||
lv_anim_t a;
|
||||
a.var = btn;
|
||||
a.start = 0;
|
||||
a.end = LV_BTN_INK_VALUE_MAX;
|
||||
a.fp = (lv_anim_fp_t)lv_btn_ink_effect_anim;
|
||||
a.path = lv_anim_path_linear;
|
||||
a.end_cb = lv_btn_ink_effect_anim_ready;
|
||||
a.act_time = 0;
|
||||
a.time = ext->ink_in_time;
|
||||
a.playback = 0;
|
||||
a.playback_pause = 0;
|
||||
a.repeat = 0;
|
||||
a.repeat_pause = 0;
|
||||
lv_anim_create(&a);
|
||||
}
|
||||
#endif
|
||||
/*Call the press action, 'param' is the caller indev_proc*/
|
||||
if(ext->actions[LV_BTN_ACTION_PR] && state != LV_BTN_STATE_INA) {
|
||||
res = ext->actions[LV_BTN_ACTION_PR](btn);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_PRESS_LOST) {
|
||||
/*Refresh the state*/
|
||||
if(ext->state == LV_BTN_STATE_PR) lv_btn_set_state(btn, LV_BTN_STATE_REL);
|
||||
else if(ext->state == LV_BTN_STATE_TGL_PR) lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
|
||||
} else if(sign == LV_SIGNAL_PRESSING) {
|
||||
/*When the button begins to drag revert pressed states to released*/
|
||||
if(lv_indev_is_dragging(param) != false) {
|
||||
if(ext->state == LV_BTN_STATE_PR) lv_btn_set_state(btn, LV_BTN_STATE_REL);
|
||||
else if(ext->state == LV_BTN_STATE_TGL_PR) lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_RELEASED) {
|
||||
/*If not dragged and it was not long press action then
|
||||
*change state and run the action*/
|
||||
if(lv_indev_is_dragging(param) == false && ext->long_pr_action_executed == 0) {
|
||||
if(ext->state == LV_BTN_STATE_PR && tgl == false) {
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_REL);
|
||||
} else if(ext->state == LV_BTN_STATE_TGL_PR && tgl == false) {
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
|
||||
} else if(ext->state == LV_BTN_STATE_PR && tgl == true) {
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
|
||||
} else if(ext->state == LV_BTN_STATE_TGL_PR && tgl == true) {
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_REL);
|
||||
}
|
||||
|
||||
if(ext->actions[LV_BTN_ACTION_CLICK] && state != LV_BTN_STATE_INA) {
|
||||
res = ext->actions[LV_BTN_ACTION_CLICK](btn);
|
||||
}
|
||||
} else { /*If dragged change back the state*/
|
||||
if(ext->state == LV_BTN_STATE_PR) {
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_REL);
|
||||
} else if(ext->state == LV_BTN_STATE_TGL_PR) {
|
||||
lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
/*Draw the toggled state in the inking instead*/
|
||||
if(ext->toggle) {
|
||||
ink_top_state = ext->state;
|
||||
}
|
||||
/*If not a toggle button and the "IN" inking is ready then start an "OUT" inking*/
|
||||
else if(ink_ready && ext->ink_out_time > 0) {
|
||||
ink_obj = btn;
|
||||
ink_playback = true; /*It is the playback. If not set `lv_btn_ink_effect_anim_ready` will start its own playback*/
|
||||
lv_indev_get_point(lv_indev_get_act(), &ink_point);
|
||||
|
||||
lv_anim_t a;
|
||||
a.var = ink_obj;
|
||||
a.start = LV_BTN_INK_VALUE_MAX;
|
||||
a.end = 0;
|
||||
a.fp = (lv_anim_fp_t)lv_btn_ink_effect_anim;
|
||||
a.path = lv_anim_path_linear;
|
||||
a.end_cb = lv_btn_ink_effect_anim_ready;
|
||||
a.act_time = 0;
|
||||
a.time = ext->ink_out_time;
|
||||
a.playback = 0;
|
||||
a.playback_pause = 0;
|
||||
a.repeat = 0;
|
||||
a.repeat_pause = 0;
|
||||
lv_anim_create(&a);
|
||||
}
|
||||
#endif
|
||||
} else if(sign == LV_SIGNAL_LONG_PRESS) {
|
||||
if(ext->actions[LV_BTN_ACTION_LONG_PR] && state != LV_BTN_STATE_INA) {
|
||||
ext->long_pr_action_executed = 1;
|
||||
res = ext->actions[LV_BTN_ACTION_LONG_PR](btn);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_LONG_PRESS_REP) {
|
||||
if(ext->actions[LV_BTN_ACTION_LONG_PR_REPEAT] && state != LV_BTN_STATE_INA) {
|
||||
res = ext->actions[LV_BTN_ACTION_LONG_PR_REPEAT](btn);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_CONTROLL) {
|
||||
char c = *((char *)param);
|
||||
if(c == LV_GROUP_KEY_RIGHT || c == LV_GROUP_KEY_UP) {
|
||||
if(lv_btn_get_toggle(btn) != false) lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
|
||||
if(ext->actions[LV_BTN_ACTION_CLICK] && lv_btn_get_state(btn) != LV_BTN_STATE_INA) {
|
||||
res = ext->actions[LV_BTN_ACTION_CLICK](btn);
|
||||
}
|
||||
} else if(c == LV_GROUP_KEY_LEFT || c == LV_GROUP_KEY_DOWN) {
|
||||
if(lv_btn_get_toggle(btn) != false) lv_btn_set_state(btn, LV_BTN_STATE_REL);
|
||||
if(ext->actions[LV_BTN_ACTION_CLICK] && lv_btn_get_state(btn) != LV_BTN_STATE_INA) {
|
||||
res = ext->actions[LV_BTN_ACTION_CLICK](btn);
|
||||
}
|
||||
} else if(c == LV_GROUP_KEY_ENTER) {
|
||||
if(!ext->long_pr_action_executed) {
|
||||
if(lv_btn_get_toggle(btn)) {
|
||||
if(state == LV_BTN_STATE_REL || state == LV_BTN_STATE_PR) lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
|
||||
else if(state == LV_BTN_STATE_TGL_REL || state == LV_BTN_STATE_TGL_PR) lv_btn_set_state(btn, LV_BTN_STATE_REL);
|
||||
} else {
|
||||
if(state == LV_BTN_STATE_REL || state == LV_BTN_STATE_PR) lv_btn_set_state(btn, LV_BTN_STATE_REL);
|
||||
else if(state == LV_BTN_STATE_TGL_REL || state == LV_BTN_STATE_TGL_PR) lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
|
||||
}
|
||||
if(ext->actions[LV_BTN_ACTION_CLICK] && state != LV_BTN_STATE_INA) {
|
||||
res = ext->actions[LV_BTN_ACTION_CLICK](btn);
|
||||
}
|
||||
}
|
||||
if(res != LV_RES_INV) {
|
||||
ext->long_pr_action_executed = 0;
|
||||
}
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_CLEANUP) {
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
if(btn == ink_obj) {
|
||||
lv_anim_del(ink_obj, (lv_anim_fp_t)lv_btn_ink_effect_anim);
|
||||
ink_obj = NULL;
|
||||
}
|
||||
#endif
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_btn";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
|
||||
|
||||
/**
|
||||
* The animator function of inking. CAlled to increase the radius of ink
|
||||
* @param btn pointer to the animated button
|
||||
* @param val the new radius
|
||||
*/
|
||||
static void lv_btn_ink_effect_anim(lv_obj_t * btn, int32_t val)
|
||||
{
|
||||
if(btn) {
|
||||
ink_act_value = val;
|
||||
lv_obj_invalidate(btn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to clean up when the ink animation is ready
|
||||
* @param p unused
|
||||
*/
|
||||
static void lv_btn_ink_effect_anim_ready(void * p)
|
||||
{
|
||||
(void) p; /*Unused*/
|
||||
|
||||
lv_btn_ext_t * ext = lv_obj_get_ext_attr(ink_obj);
|
||||
lv_btn_state_t state = lv_btn_get_state(ink_obj);
|
||||
|
||||
lv_obj_invalidate(ink_obj);
|
||||
ink_ready = true;
|
||||
|
||||
if((state == LV_BTN_STATE_REL || state == LV_BTN_STATE_TGL_REL) && ext->toggle == 0 && ink_playback == false) {
|
||||
lv_anim_t a;
|
||||
a.var = ink_obj;
|
||||
a.start = LV_BTN_INK_VALUE_MAX;
|
||||
a.end = 0;
|
||||
a.fp = (lv_anim_fp_t)lv_btn_ink_effect_anim;
|
||||
a.path = lv_anim_path_linear;
|
||||
a.end_cb = lv_btn_ink_effect_anim_ready;
|
||||
a.act_time = -ext->ink_wait_time;
|
||||
a.time = ext->ink_out_time;
|
||||
a.playback = 0;
|
||||
a.playback_pause = 0;
|
||||
a.repeat = 0;
|
||||
a.repeat_pause = 0;
|
||||
lv_anim_create(&a);
|
||||
|
||||
ink_playback = true;
|
||||
} else {
|
||||
ink_obj = NULL;
|
||||
}
|
||||
}
|
||||
#endif /*USE_LV_ANIMATION*/
|
||||
|
||||
#endif
|
280
bdk/libs/lvgl/lv_objx/lv_btn.h
Normal file
280
bdk/libs/lvgl/lv_objx/lv_btn.h
Normal file
|
@ -0,0 +1,280 @@
|
|||
/**
|
||||
* @file lv_btn.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_BTN_H
|
||||
#define LV_BTN_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_BTN != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_CONT == 0
|
||||
#error "lv_btn: lv_cont is required. Enable it in lv_conf.h (USE_LV_CONT 1) "
|
||||
#endif
|
||||
|
||||
#include "lv_cont.h"
|
||||
#include "../lv_core/lv_indev.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/* Button states
|
||||
* It can be used not only by buttons but other button-like objects too*/
|
||||
enum
|
||||
{
|
||||
LV_BTN_STATE_REL,
|
||||
LV_BTN_STATE_PR,
|
||||
LV_BTN_STATE_TGL_REL,
|
||||
LV_BTN_STATE_TGL_PR,
|
||||
LV_BTN_STATE_INA,
|
||||
LV_BTN_STATE_NUM,
|
||||
};
|
||||
typedef uint8_t lv_btn_state_t;
|
||||
|
||||
enum
|
||||
{
|
||||
LV_BTN_ACTION_CLICK,
|
||||
LV_BTN_ACTION_PR,
|
||||
LV_BTN_ACTION_LONG_PR,
|
||||
LV_BTN_ACTION_LONG_PR_REPEAT,
|
||||
LV_BTN_ACTION_NUM,
|
||||
};
|
||||
typedef uint8_t lv_btn_action_t;
|
||||
|
||||
|
||||
/*Data of button*/
|
||||
typedef struct
|
||||
{
|
||||
lv_cont_ext_t cont; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_action_t actions[LV_BTN_ACTION_NUM];
|
||||
lv_style_t * styles[LV_BTN_STATE_NUM]; /*Styles in each state*/
|
||||
lv_btn_state_t state; /*Current state of the button from 'lv_btn_state_t' enum*/
|
||||
int idx;
|
||||
#if LV_BTN_INK_EFFECT
|
||||
uint16_t ink_in_time; /*[ms] Time of ink fill effect (0: disable ink effect)*/
|
||||
uint16_t ink_wait_time; /*[ms] Wait before the ink disappears */
|
||||
uint16_t ink_out_time; /*[ms] Time of ink disappearing*/
|
||||
#endif
|
||||
uint8_t toggle :1; /*1: Toggle enabled*/
|
||||
uint8_t long_pr_action_executed :1; /*1: Long press action executed (Handled by the library)*/
|
||||
} lv_btn_ext_t;
|
||||
|
||||
/*Styles*/
|
||||
enum {
|
||||
LV_BTN_STYLE_REL,
|
||||
LV_BTN_STYLE_PR,
|
||||
LV_BTN_STYLE_TGL_REL,
|
||||
LV_BTN_STYLE_TGL_PR,
|
||||
LV_BTN_STYLE_INA,
|
||||
};
|
||||
typedef uint8_t lv_btn_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a button objects
|
||||
* @param par pointer to an object, it will be the parent of the new button
|
||||
* @param copy pointer to a button object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created button
|
||||
*/
|
||||
lv_obj_t * lv_btn_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Enable the toggled states. On release the button will change from/to toggled state.
|
||||
* @param btn pointer to a button object
|
||||
* @param tgl true: enable toggled states, false: disable
|
||||
*/
|
||||
void lv_btn_set_toggle(lv_obj_t * btn, bool tgl);
|
||||
|
||||
/**
|
||||
* Set the state of the button
|
||||
* @param btn pointer to a button object
|
||||
* @param state the new state of the button (from lv_btn_state_t enum)
|
||||
*/
|
||||
void lv_btn_set_state(lv_obj_t * btn, lv_btn_state_t state);
|
||||
|
||||
/**
|
||||
* Toggle the state of the button (ON->OFF, OFF->ON)
|
||||
* @param btn pointer to a button object
|
||||
*/
|
||||
void lv_btn_toggle(lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Set a function to call when a button event happens
|
||||
* @param btn pointer to a button object
|
||||
* @param action type of event form 'lv_action_t' (press, release, long press, long press repeat)
|
||||
*/
|
||||
void lv_btn_set_action(lv_obj_t * btn, lv_btn_action_t type, lv_action_t action);
|
||||
|
||||
/**
|
||||
* Set the layout on a button
|
||||
* @param btn pointer to a button object
|
||||
* @param layout a layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
static inline void lv_btn_set_layout(lv_obj_t * btn, lv_layout_t layout)
|
||||
{
|
||||
lv_cont_set_layout(btn, layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the horizontal or vertical fit.
|
||||
* The button size will be set to involve the children horizontally or vertically.
|
||||
* @param btn pointer to a button object
|
||||
* @param hor_en true: enable the horizontal fit
|
||||
* @param ver_en true: enable the vertical fit
|
||||
*/
|
||||
static inline void lv_btn_set_fit(lv_obj_t * btn, bool hor_en, bool ver_en)
|
||||
{
|
||||
lv_cont_set_fit(btn, hor_en, ver_en);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set time of the ink effect (draw a circle on click to animate in the new state)
|
||||
* @param btn pointer to a button object
|
||||
* @param time the time of the ink animation
|
||||
*/
|
||||
void lv_btn_set_ink_in_time(lv_obj_t * btn, uint16_t time);
|
||||
|
||||
/**
|
||||
* Set the wait time before the ink disappears
|
||||
* @param btn pointer to a button object
|
||||
* @param time the time of the ink animation
|
||||
*/
|
||||
void lv_btn_set_ink_wait_time(lv_obj_t * btn, uint16_t time);
|
||||
|
||||
/**
|
||||
* Set time of the ink out effect (animate to the released state)
|
||||
* @param btn pointer to a button object
|
||||
* @param time the time of the ink animation
|
||||
*/
|
||||
void lv_btn_set_ink_out_time(lv_obj_t * btn, uint16_t time);
|
||||
|
||||
/**
|
||||
* Set a style of a button.
|
||||
* @param btn pointer to button object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
* */
|
||||
void lv_btn_set_style(lv_obj_t * btn, lv_btn_style_t type, lv_style_t *style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the current state of the button
|
||||
* @param btn pointer to a button object
|
||||
* @return the state of the button (from lv_btn_state_t enum)
|
||||
*/
|
||||
lv_btn_state_t lv_btn_get_state(const lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Get the toggle enable attribute of the button
|
||||
* @param btn pointer to a button object
|
||||
* @return ture: toggle enabled, false: disabled
|
||||
*/
|
||||
bool lv_btn_get_toggle(const lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Get the release action of a button
|
||||
* @param btn pointer to a button object
|
||||
* @return pointer to the release action function
|
||||
*/
|
||||
lv_action_t lv_btn_get_action(const lv_obj_t * btn, lv_btn_action_t type);
|
||||
|
||||
/**
|
||||
* Get the layout of a button
|
||||
* @param btn pointer to button object
|
||||
* @return the layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
static inline lv_layout_t lv_btn_get_layout(const lv_obj_t * btn)
|
||||
{
|
||||
return lv_cont_get_layout(btn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get horizontal fit enable attribute of a button
|
||||
* @param btn pointer to a button object
|
||||
* @return true: horizontal fit is enabled; false: disabled
|
||||
*/
|
||||
static inline bool lv_btn_get_hor_fit(const lv_obj_t * btn)
|
||||
{
|
||||
return lv_cont_get_hor_fit(btn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get vertical fit enable attribute of a container
|
||||
* @param btn pointer to a button object
|
||||
* @return true: vertical fit is enabled; false: disabled
|
||||
*/
|
||||
static inline bool lv_btn_get_ver_fit(const lv_obj_t * btn)
|
||||
{
|
||||
return lv_cont_get_ver_fit(btn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get time of the ink in effect (draw a circle on click to animate in the new state)
|
||||
* @param btn pointer to a button object
|
||||
* @return the time of the ink animation
|
||||
*/
|
||||
uint16_t lv_btn_get_ink_in_time(const lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Get the wait time before the ink disappears
|
||||
* @param btn pointer to a button object
|
||||
* @return the time of the ink animation
|
||||
*/
|
||||
uint16_t lv_btn_get_ink_wait_time(const lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Get time of the ink out effect (animate to the releases state)
|
||||
* @param btn pointer to a button object
|
||||
* @return the time of the ink animation
|
||||
*/
|
||||
uint16_t lv_btn_get_ink_out_time(const lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Get style of a button.
|
||||
* @param btn pointer to button object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
* */
|
||||
lv_style_t * lv_btn_get_style(const lv_obj_t * btn, lv_btn_style_t type);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_BUTTON*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_BTN_H*/
|
881
bdk/libs/lvgl/lv_objx/lv_btnm.c
Normal file
881
bdk/libs/lvgl/lv_objx/lv_btnm.c
Normal file
|
@ -0,0 +1,881 @@
|
|||
/**
|
||||
* @file lv_btnm.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_btnm.h"
|
||||
#if USE_LV_BTNM != 0
|
||||
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_core/lv_refr.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_txt.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_btnm_signal(lv_obj_t * btnm, lv_signal_t sign, void * param);
|
||||
static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static uint8_t get_button_width(const char * btn_str);
|
||||
static bool button_is_hidden(const char * btn_str);
|
||||
static bool button_is_repeat_disabled(const char * btn_str);
|
||||
static bool button_is_inactive(const char * btn_str);
|
||||
const char * cut_ctrl_byte(const char * btn_str);
|
||||
static uint16_t get_button_from_point(lv_obj_t * btnm, lv_point_t * p);
|
||||
static uint16_t get_button_text(lv_obj_t * btnm, uint16_t btn_id);
|
||||
static void allocate_btn_areas(lv_obj_t * btnm, const char ** map);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static const char * lv_btnm_def_map[] = {"Btn1", "Btn2", "Btn3", "\n",
|
||||
"\002Btn4", "Btn5", ""
|
||||
};
|
||||
|
||||
static lv_design_func_t ancestor_design_f;
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a button matrix objects
|
||||
* @param par pointer to an object, it will be the parent of the new button matrix
|
||||
* @param copy pointer to a button matrix object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created button matrix
|
||||
*/
|
||||
lv_obj_t * lv_btnm_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("button matrix create started");
|
||||
|
||||
/*Create the ancestor object*/
|
||||
lv_obj_t * new_btnm = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_btnm);
|
||||
if(new_btnm == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_btnm);
|
||||
|
||||
/*Allocate the object type specific extended data*/
|
||||
lv_btnm_ext_t * ext = lv_obj_allocate_ext_attr(new_btnm, sizeof(lv_btnm_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->btn_cnt = 0;
|
||||
ext->btn_id_pr = LV_BTNM_PR_NONE;
|
||||
ext->btn_id_tgl = LV_BTNM_PR_NONE;
|
||||
ext->button_areas = NULL;
|
||||
ext->action = NULL;
|
||||
ext->map_p = NULL;
|
||||
ext->toggle = 0;
|
||||
ext->recolor = 0;
|
||||
ext->styles_btn[LV_BTN_STATE_REL] = &lv_style_btn_rel;
|
||||
ext->styles_btn[LV_BTN_STATE_PR] = &lv_style_btn_pr;
|
||||
ext->styles_btn[LV_BTN_STATE_TGL_REL] = &lv_style_btn_tgl_rel;
|
||||
ext->styles_btn[LV_BTN_STATE_TGL_PR] = &lv_style_btn_tgl_pr;
|
||||
ext->styles_btn[LV_BTN_STATE_INA] = &lv_style_btn_ina;
|
||||
|
||||
if(ancestor_design_f == NULL) ancestor_design_f = lv_obj_get_design_func(new_btnm);
|
||||
|
||||
lv_obj_set_signal_func(new_btnm, lv_btnm_signal);
|
||||
lv_obj_set_design_func(new_btnm, lv_btnm_design);
|
||||
|
||||
/*Init the new button matrix object*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_size(new_btnm, LV_HOR_RES / 2, LV_VER_RES / 4);
|
||||
lv_btnm_set_map(new_btnm, lv_btnm_def_map);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_btnm_set_style(new_btnm, LV_BTNM_STYLE_BG, th->btnm.bg);
|
||||
lv_btnm_set_style(new_btnm, LV_BTNM_STYLE_BTN_REL, th->btnm.btn.rel);
|
||||
lv_btnm_set_style(new_btnm, LV_BTNM_STYLE_BTN_PR, th->btnm.btn.pr);
|
||||
lv_btnm_set_style(new_btnm, LV_BTNM_STYLE_BTN_TGL_REL, th->btnm.btn.tgl_rel);
|
||||
lv_btnm_set_style(new_btnm, LV_BTNM_STYLE_BTN_TGL_PR, th->btnm.btn.tgl_pr);
|
||||
lv_btnm_set_style(new_btnm, LV_BTNM_STYLE_BTN_INA, th->btnm.btn.ina);
|
||||
} else {
|
||||
lv_obj_set_style(new_btnm, &lv_style_pretty);
|
||||
}
|
||||
}
|
||||
/*Copy an existing object*/
|
||||
else {
|
||||
lv_btnm_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
memcpy(ext->styles_btn, copy_ext->styles_btn, sizeof(ext->styles_btn));
|
||||
ext->action = copy_ext->action;
|
||||
ext->toggle = copy_ext->toggle;
|
||||
ext->btn_id_tgl = copy_ext->btn_id_tgl;
|
||||
lv_btnm_set_map(new_btnm, lv_btnm_get_map(copy));
|
||||
}
|
||||
|
||||
LV_LOG_INFO("button matrix created");
|
||||
|
||||
return new_btnm;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new map. Buttons will be created/deleted according to the map.
|
||||
* @param btnm pointer to a button matrix object
|
||||
* @param map pointer a string array. The last string has to be: "".
|
||||
* Use "\n" to begin a new line.
|
||||
* The first byte can be a control data:
|
||||
* - bit 7: always 1
|
||||
* - bit 6: always 0
|
||||
* - bit 5: inactive (disabled) (\24x)
|
||||
* - bit 4: no repeat (on long press) (\22x)
|
||||
* - bit 3: hidden (\21x)
|
||||
* - bit 2..0: button relative width
|
||||
* Example (practically use octal numbers): "\224abc": "abc" text with 4 width and no long press
|
||||
*/
|
||||
void lv_btnm_set_map(lv_obj_t * btnm, const char ** map)
|
||||
{
|
||||
if(map == NULL) return;
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
ext->map_p = map;
|
||||
|
||||
/*Analyze the map and create the required number of buttons*/
|
||||
allocate_btn_areas(btnm, map);
|
||||
|
||||
/*Set size and positions of the buttons*/
|
||||
lv_style_t * style_bg = lv_btnm_get_style(btnm, LV_BTNM_STYLE_BG);
|
||||
lv_coord_t max_w = lv_obj_get_width(btnm) - 2 * style_bg->body.padding.hor;
|
||||
lv_coord_t max_h = lv_obj_get_height(btnm) - 2 * style_bg->body.padding.ver;
|
||||
lv_coord_t act_y = style_bg->body.padding.ver;
|
||||
|
||||
/*Count the lines to calculate button height*/
|
||||
uint8_t line_cnt = 1;
|
||||
uint8_t li;
|
||||
for(li = 0; strlen(map[li]) != 0; li++) {
|
||||
if(strcmp(map[li], "\n") == 0) line_cnt ++;
|
||||
}
|
||||
|
||||
lv_coord_t btn_h = max_h - ((line_cnt - 1) * style_bg->body.padding.inner);
|
||||
btn_h = btn_h / line_cnt;
|
||||
btn_h --; /*-1 because e.g. height = 100 means 101 pixels (0..100)*/
|
||||
|
||||
/* Count the units and the buttons in a line
|
||||
* (A button can be 1,2,3... unit wide)*/
|
||||
uint16_t unit_cnt; /*Number of units in a row*/
|
||||
uint16_t unit_act_cnt; /*Number of units currently put in a row*/
|
||||
uint16_t btn_cnt; /*Number of buttons in a row*/
|
||||
uint16_t i_tot = 0; /*Act. index in the str map*/
|
||||
uint16_t btn_i = 0; /*Act. index of button areas*/
|
||||
const char ** map_p_tmp = map;
|
||||
|
||||
/*Count the units and the buttons in a line*/
|
||||
while(1) {
|
||||
unit_cnt = 0;
|
||||
btn_cnt = 0;
|
||||
/*Count the buttons in a line*/
|
||||
while(strcmp(map_p_tmp[btn_cnt], "\n") != 0 &&
|
||||
strlen(map_p_tmp[btn_cnt]) != 0) { /*Check a line*/
|
||||
unit_cnt += get_button_width(map_p_tmp[btn_cnt]);
|
||||
btn_cnt ++;
|
||||
}
|
||||
|
||||
/*Make sure the last row is at the bottom of 'btnm'*/
|
||||
if(map_p_tmp[btn_cnt][0] == '\0') { /*Last row?*/
|
||||
btn_h = max_h - act_y + style_bg->body.padding.ver - 1;
|
||||
}
|
||||
|
||||
/*Only deal with the non empty lines*/
|
||||
if(btn_cnt != 0) {
|
||||
/*Calculate the width of all units*/
|
||||
lv_coord_t all_unit_w = max_w - ((btn_cnt - 1) * style_bg->body.padding.inner);
|
||||
|
||||
/*Set the button size and positions and set the texts*/
|
||||
uint16_t i;
|
||||
lv_coord_t act_x = style_bg->body.padding.hor;
|
||||
lv_coord_t act_unit_w;
|
||||
unit_act_cnt = 0;
|
||||
for(i = 0; i < btn_cnt; i++) {
|
||||
/* one_unit_w = all_unit_w / unit_cnt
|
||||
* act_unit_w = one_unit_w * button_width
|
||||
* do this two operations but the multiply first to divide a greater number */
|
||||
act_unit_w = (all_unit_w * get_button_width(map_p_tmp[i])) / unit_cnt;
|
||||
act_unit_w --; /*-1 because e.g. width = 100 means 101 pixels (0..100)*/
|
||||
|
||||
/*Always recalculate act_x because of rounding errors */
|
||||
act_x = (unit_act_cnt * all_unit_w) / unit_cnt + i * style_bg->body.padding.inner + style_bg->body.padding.hor;
|
||||
|
||||
/* Set the button's area.
|
||||
* If inner padding is zero then use the prev. button x2 as x1 to avoid rounding errors*/
|
||||
if(style_bg->body.padding.inner == 0 && act_x != style_bg->body.padding.hor) {
|
||||
lv_area_set(&ext->button_areas[btn_i], ext->button_areas[btn_i - 1].x2, act_y,
|
||||
act_x + act_unit_w, act_y + btn_h);
|
||||
} else {
|
||||
lv_area_set(&ext->button_areas[btn_i], act_x, act_y,
|
||||
act_x + act_unit_w, act_y + btn_h);
|
||||
}
|
||||
|
||||
unit_act_cnt += get_button_width(map_p_tmp[i]);
|
||||
|
||||
i_tot ++;
|
||||
btn_i ++;
|
||||
}
|
||||
}
|
||||
act_y += btn_h + style_bg->body.padding.inner;
|
||||
|
||||
|
||||
if(strlen(map_p_tmp[btn_cnt]) == 0) break; /*Break on end of map*/
|
||||
map_p_tmp = &map_p_tmp[btn_cnt + 1]; /*Set the map to the next line*/
|
||||
i_tot ++; /*Skip the '\n'*/
|
||||
}
|
||||
|
||||
lv_obj_invalidate(btnm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new callback function for the buttons (It will be called when a button is released)
|
||||
* @param btnm: pointer to button matrix object
|
||||
* @param cb pointer to a callback function
|
||||
*/
|
||||
void lv_btnm_set_action(lv_obj_t * btnm, lv_btnm_action_t action)
|
||||
{
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
ext->action = action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable button toggling
|
||||
* @param btnm pointer to button matrix object
|
||||
* @param en true: enable toggling; false: disable toggling
|
||||
* @param id index of the currently toggled button (ignored if 'en' == false)
|
||||
*/
|
||||
void lv_btnm_set_toggle(lv_obj_t * btnm, bool en, uint16_t id)
|
||||
{
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
ext->toggle = en == false ? 0 : 1;
|
||||
if(ext->toggle != 0) {
|
||||
if(id >= ext->btn_cnt) id = ext->btn_cnt - 1;
|
||||
ext->btn_id_tgl = id;
|
||||
} else {
|
||||
ext->btn_id_tgl = LV_BTNM_PR_NONE;
|
||||
}
|
||||
|
||||
lv_obj_invalidate(btnm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a button matrix
|
||||
* @param btnm pointer to a button matrix object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_btnm_set_style(lv_obj_t * btnm, lv_btnm_style_t type, lv_style_t * style)
|
||||
{
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
switch(type) {
|
||||
case LV_BTNM_STYLE_BG:
|
||||
lv_obj_set_style(btnm, style);
|
||||
break;
|
||||
case LV_BTNM_STYLE_BTN_REL:
|
||||
ext->styles_btn[LV_BTN_STATE_REL] = style;
|
||||
lv_obj_invalidate(btnm);
|
||||
break;
|
||||
case LV_BTNM_STYLE_BTN_PR:
|
||||
ext->styles_btn[LV_BTN_STATE_PR] = style;
|
||||
lv_obj_invalidate(btnm);
|
||||
break;
|
||||
case LV_BTNM_STYLE_BTN_TGL_REL:
|
||||
ext->styles_btn[LV_BTN_STATE_TGL_REL] = style;
|
||||
lv_obj_invalidate(btnm);
|
||||
break;
|
||||
case LV_BTNM_STYLE_BTN_TGL_PR:
|
||||
ext->styles_btn[LV_BTN_STATE_TGL_PR] = style;
|
||||
lv_obj_invalidate(btnm);
|
||||
break;
|
||||
case LV_BTNM_STYLE_BTN_INA:
|
||||
ext->styles_btn[LV_BTN_STATE_INA] = style;
|
||||
lv_obj_invalidate(btnm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_btnm_set_recolor(const lv_obj_t * btnm, bool en)
|
||||
{
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
ext->recolor = en;
|
||||
lv_obj_invalidate(btnm);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the current map of a button matrix
|
||||
* @param btnm pointer to a button matrix object
|
||||
* @return the current map
|
||||
*/
|
||||
const char ** lv_btnm_get_map(const lv_obj_t * btnm)
|
||||
{
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
return ext->map_p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a the callback function of the buttons on a button matrix
|
||||
* @param btnm: pointer to button matrix object
|
||||
* @return pointer to the callback function
|
||||
*/
|
||||
lv_btnm_action_t lv_btnm_get_action(const lv_obj_t * btnm)
|
||||
{
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
return ext->action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pressed button
|
||||
* @param btnm pointer to button matrix object
|
||||
* @return index of the currently pressed button (LV_BTNM_PR_NONE: if unset)
|
||||
*/
|
||||
uint16_t lv_btnm_get_pressed(const lv_obj_t * btnm)
|
||||
{
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
return ext->btn_id_pr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the toggled button
|
||||
* @param btnm pointer to button matrix object
|
||||
* @return index of the currently toggled button (LV_BTNM_PR_NONE: if unset)
|
||||
*/
|
||||
uint16_t lv_btnm_get_toggled(const lv_obj_t * btnm)
|
||||
{
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
if(ext->toggle == 0) return LV_BTNM_PR_NONE;
|
||||
else return ext->btn_id_tgl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a button matrix
|
||||
* @param btnm pointer to a button matrix object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_btnm_get_style(const lv_obj_t * btnm, lv_btnm_style_t type)
|
||||
{
|
||||
lv_style_t * style = NULL;
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
switch(type) {
|
||||
case LV_BTNM_STYLE_BG:
|
||||
style = lv_obj_get_style(btnm);
|
||||
break;
|
||||
case LV_BTNM_STYLE_BTN_REL:
|
||||
style = ext->styles_btn[LV_BTN_STATE_REL];
|
||||
break;
|
||||
case LV_BTNM_STYLE_BTN_PR:
|
||||
style = ext->styles_btn[LV_BTN_STATE_PR];
|
||||
break;
|
||||
case LV_BTNM_STYLE_BTN_TGL_REL:
|
||||
style = ext->styles_btn[LV_BTN_STATE_TGL_REL];
|
||||
break;
|
||||
case LV_BTNM_STYLE_BTN_TGL_PR:
|
||||
style = ext->styles_btn[LV_BTN_STATE_TGL_PR];
|
||||
break;
|
||||
case LV_BTNM_STYLE_BTN_INA:
|
||||
style = ext->styles_btn[LV_BTN_STATE_INA];
|
||||
break;
|
||||
default:
|
||||
style = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
bool lv_btnm_get_recolor(const lv_obj_t * btnm)
|
||||
{
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
return ext->recolor;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the button matrixs
|
||||
* @param btnm pointer to a button matrix object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return ancestor_design_f(btnm, mask, mode);
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
|
||||
ancestor_design_f(btnm, mask, mode);
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
lv_style_t * bg_style = lv_obj_get_style(btnm);
|
||||
lv_style_t * btn_style;
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(btnm);
|
||||
|
||||
lv_area_t area_btnm;
|
||||
lv_obj_get_coords(btnm, &area_btnm);
|
||||
|
||||
lv_area_t area_tmp;
|
||||
lv_coord_t btn_w;
|
||||
lv_coord_t btn_h;
|
||||
|
||||
uint16_t btn_i = 0;
|
||||
uint16_t txt_i = 0;
|
||||
lv_style_t style_tmp;
|
||||
lv_txt_flag_t txt_flag = LV_TXT_FLAG_NONE;
|
||||
|
||||
if(ext->recolor) txt_flag = LV_TXT_FLAG_RECOLOR;
|
||||
|
||||
for(btn_i = 0; btn_i < ext->btn_cnt; btn_i ++, txt_i ++) {
|
||||
/*Search the next valid text in the map*/
|
||||
while(strcmp(ext->map_p[txt_i], "\n") == 0) {
|
||||
txt_i ++;
|
||||
}
|
||||
|
||||
/*Skip hidden buttons*/
|
||||
if(button_is_hidden(ext->map_p[txt_i])) continue;
|
||||
|
||||
lv_area_copy(&area_tmp, &ext->button_areas[btn_i]);
|
||||
area_tmp.x1 += area_btnm.x1;
|
||||
area_tmp.y1 += area_btnm.y1;
|
||||
area_tmp.x2 += area_btnm.x1;
|
||||
area_tmp.y2 += area_btnm.y1;
|
||||
|
||||
btn_w = lv_area_get_width(&area_tmp);
|
||||
btn_h = lv_area_get_height(&area_tmp);
|
||||
|
||||
/*Load the style*/
|
||||
if(button_is_inactive(ext->map_p[txt_i])) btn_style = lv_btnm_get_style(btnm, LV_BTNM_STYLE_BTN_INA);
|
||||
else if(btn_i != ext->btn_id_pr && btn_i != ext->btn_id_tgl) btn_style = lv_btnm_get_style(btnm, LV_BTNM_STYLE_BTN_REL);
|
||||
else if(btn_i == ext->btn_id_pr && btn_i != ext->btn_id_tgl) btn_style = lv_btnm_get_style(btnm, LV_BTNM_STYLE_BTN_PR);
|
||||
else if(btn_i != ext->btn_id_pr && btn_i == ext->btn_id_tgl) btn_style = lv_btnm_get_style(btnm, LV_BTNM_STYLE_BTN_TGL_REL);
|
||||
else if(btn_i == ext->btn_id_pr && btn_i == ext->btn_id_tgl) btn_style = lv_btnm_get_style(btnm, LV_BTNM_STYLE_BTN_TGL_PR);
|
||||
else btn_style = lv_btnm_get_style(btnm, LV_BTNM_STYLE_BTN_REL); /*Not possible option, just to be sure*/
|
||||
|
||||
lv_style_copy(&style_tmp, btn_style);
|
||||
|
||||
/*Remove borders on the edges if `LV_BORDER_INTERNAL`*/
|
||||
if(style_tmp.body.border.part & LV_BORDER_INTERNAL) {
|
||||
if(area_tmp.y1 == btnm->coords.y1 + bg_style->body.padding.ver) {
|
||||
style_tmp.body.border.part &= ~LV_BORDER_TOP;
|
||||
}
|
||||
if(area_tmp.y2 == btnm->coords.y2 - bg_style->body.padding.ver) {
|
||||
style_tmp.body.border.part &= ~LV_BORDER_BOTTOM;
|
||||
}
|
||||
|
||||
if(txt_i == 0) {
|
||||
style_tmp.body.border.part &= ~LV_BORDER_LEFT;
|
||||
}
|
||||
else if(strcmp(ext->map_p[txt_i - 1],"\n") == 0) {
|
||||
style_tmp.body.border.part &= ~LV_BORDER_LEFT;
|
||||
}
|
||||
|
||||
if(ext->map_p[txt_i + 1][0] == '\0' || strcmp(ext->map_p[txt_i + 1], "\n") == 0) {
|
||||
style_tmp.body.border.part &= ~LV_BORDER_RIGHT;
|
||||
}
|
||||
}
|
||||
lv_draw_rect(&area_tmp, mask, &style_tmp, opa_scale);
|
||||
|
||||
/*Calculate the size of the text*/
|
||||
if(btn_style->glass) btn_style = bg_style;
|
||||
const lv_font_t * font = btn_style->text.font;
|
||||
lv_point_t txt_size;
|
||||
lv_txt_get_size(&txt_size, ext->map_p[txt_i], font,
|
||||
btn_style->text.letter_space, btn_style->text.line_space,
|
||||
lv_area_get_width(&area_btnm), txt_flag);
|
||||
|
||||
area_tmp.x1 += (btn_w - txt_size.x) / 2;
|
||||
area_tmp.y1 += (btn_h - txt_size.y) / 2;
|
||||
area_tmp.x2 = area_tmp.x1 + txt_size.x;
|
||||
area_tmp.y2 = area_tmp.y1 + txt_size.y;
|
||||
|
||||
lv_draw_label(&area_tmp, mask, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the button matrix
|
||||
* @param btnm pointer to a button matrix object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_btnm_signal(lv_obj_t * btnm, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(btnm, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
lv_area_t btnm_area;
|
||||
lv_area_t btn_area;
|
||||
lv_point_t p;
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
lv_mem_free(ext->button_areas);
|
||||
} else if(sign == LV_SIGNAL_STYLE_CHG || sign == LV_SIGNAL_CORD_CHG) {
|
||||
lv_btnm_set_map(btnm, ext->map_p);
|
||||
} else if(sign == LV_SIGNAL_PRESSING) {
|
||||
uint16_t btn_pr;
|
||||
/*Search the pressed area*/
|
||||
lv_indev_get_point(param, &p);
|
||||
btn_pr = get_button_from_point(btnm, &p);
|
||||
/*Invalidate to old and the new areas*/;
|
||||
lv_obj_get_coords(btnm, &btnm_area);
|
||||
if(btn_pr != ext->btn_id_pr) {
|
||||
lv_indev_reset_lpr(param);
|
||||
if(ext->btn_id_pr != LV_BTNM_PR_NONE) {
|
||||
lv_area_copy(&btn_area, &ext->button_areas[ext->btn_id_pr]);
|
||||
btn_area.x1 += btnm_area.x1;
|
||||
btn_area.y1 += btnm_area.y1;
|
||||
btn_area.x2 += btnm_area.x1;
|
||||
btn_area.y2 += btnm_area.y1;
|
||||
lv_inv_area(&btn_area);
|
||||
}
|
||||
if(btn_pr != LV_BTNM_PR_NONE) {
|
||||
lv_area_copy(&btn_area, &ext->button_areas[btn_pr]);
|
||||
btn_area.x1 += btnm_area.x1;
|
||||
btn_area.y1 += btnm_area.y1;
|
||||
btn_area.x2 += btnm_area.x1;
|
||||
btn_area.y2 += btnm_area.y1;
|
||||
lv_inv_area(&btn_area);
|
||||
}
|
||||
}
|
||||
|
||||
ext->btn_id_pr = btn_pr;
|
||||
}
|
||||
|
||||
else if(sign == LV_SIGNAL_LONG_PRESS_REP) {
|
||||
if(ext->action && ext->btn_id_pr != LV_BTNM_PR_NONE) {
|
||||
uint16_t txt_i = get_button_text(btnm, ext->btn_id_pr);
|
||||
if(txt_i != LV_BTNM_PR_NONE) {
|
||||
if(button_is_repeat_disabled(ext->map_p[txt_i]) == false &&
|
||||
button_is_inactive(ext->map_p[txt_i]) == false) {
|
||||
res = ext->action(btnm, cut_ctrl_byte(ext->map_p[txt_i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_RELEASED) {
|
||||
if(ext->btn_id_pr != LV_BTNM_PR_NONE) {
|
||||
uint16_t txt_i = get_button_text(btnm, ext->btn_id_pr);
|
||||
if(button_is_inactive(ext->map_p[txt_i]) == false && txt_i != LV_BTNM_PR_NONE) { /*Ignore the inactive buttons anf click between the buttons*/
|
||||
if(ext->action) res = ext->action(btnm, cut_ctrl_byte(ext->map_p[txt_i]));
|
||||
if(res == LV_RES_OK) {
|
||||
|
||||
/*Invalidate to old pressed area*/;
|
||||
lv_obj_get_coords(btnm, &btnm_area);
|
||||
lv_area_copy(&btn_area, &ext->button_areas[ext->btn_id_pr]);
|
||||
btn_area.x1 += btnm_area.x1;
|
||||
btn_area.y1 += btnm_area.y1;
|
||||
btn_area.x2 += btnm_area.x1;
|
||||
btn_area.y2 += btnm_area.y1;
|
||||
lv_inv_area(&btn_area);
|
||||
|
||||
if(ext->toggle != 0) {
|
||||
/*Invalidate to old toggled area*/;
|
||||
lv_area_copy(&btn_area, &ext->button_areas[ext->btn_id_tgl]);
|
||||
btn_area.x1 += btnm_area.x1;
|
||||
btn_area.y1 += btnm_area.y1;
|
||||
btn_area.x2 += btnm_area.x1;
|
||||
btn_area.y2 += btnm_area.y1;
|
||||
lv_inv_area(&btn_area);
|
||||
ext->btn_id_tgl = ext->btn_id_pr;
|
||||
|
||||
}
|
||||
|
||||
#if USE_LV_GROUP
|
||||
/*Leave the clicked button when releases if this not the focused object in a group*/
|
||||
lv_group_t * g = lv_obj_get_group(btnm);
|
||||
if(lv_group_get_focused(g) != btnm) {
|
||||
ext->btn_id_pr = LV_BTNM_PR_NONE;
|
||||
}
|
||||
#else
|
||||
ext->btn_id_pr = LV_BTNM_PR_NONE;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_DEFOCUS) {
|
||||
ext->btn_id_pr = LV_BTNM_PR_NONE;
|
||||
lv_obj_invalidate(btnm);
|
||||
} else if(sign == LV_SIGNAL_FOCUS) {
|
||||
#if USE_LV_GROUP
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
lv_hal_indev_type_t indev_type = lv_indev_get_type(indev);
|
||||
if(indev_type == LV_INDEV_TYPE_POINTER) {
|
||||
/*Select the clicked button*/
|
||||
lv_point_t p1;
|
||||
lv_indev_get_point(indev, &p1);
|
||||
uint16_t btn_i = get_button_from_point(btnm, &p1);
|
||||
ext->btn_id_pr = btn_i;
|
||||
} else if(indev_type == LV_INDEV_TYPE_ENCODER) {
|
||||
/*In navigation mode don't select any button but in edit mode select the fist*/
|
||||
if(lv_group_get_editing(lv_obj_get_group(btnm))) ext->btn_id_pr = 0;
|
||||
else ext->btn_id_pr = LV_BTNM_PR_NONE;
|
||||
} else {
|
||||
ext->btn_id_pr = 0;
|
||||
}
|
||||
#else
|
||||
ext->btn_id_pr = 0;
|
||||
#endif
|
||||
lv_obj_invalidate(btnm);
|
||||
} else if(sign == LV_SIGNAL_CONTROLL) {
|
||||
char c = *((char *)param);
|
||||
if(c == LV_GROUP_KEY_RIGHT) {
|
||||
if(ext->btn_id_pr == LV_BTNM_PR_NONE) ext->btn_id_pr = 0;
|
||||
else ext->btn_id_pr++;
|
||||
if(ext->btn_id_pr >= ext->btn_cnt - 1) ext->btn_id_pr = ext->btn_cnt - 1;
|
||||
lv_obj_invalidate(btnm);
|
||||
} else if(c == LV_GROUP_KEY_LEFT) {
|
||||
if(ext->btn_id_pr == LV_BTNM_PR_NONE) ext->btn_id_pr = 0;
|
||||
if(ext->btn_id_pr > 0) ext->btn_id_pr--;
|
||||
lv_obj_invalidate(btnm);
|
||||
} else if(c == LV_GROUP_KEY_DOWN) {
|
||||
lv_style_t * style = lv_btnm_get_style(btnm, LV_BTNM_STYLE_BG);
|
||||
/*Find the area below the the current*/
|
||||
if(ext->btn_id_pr == LV_BTNM_PR_NONE) {
|
||||
ext->btn_id_pr = 0;
|
||||
} else {
|
||||
uint16_t area_below;
|
||||
lv_coord_t pr_center = ext->button_areas[ext->btn_id_pr].x1 + (lv_area_get_width(&ext->button_areas[ext->btn_id_pr]) >> 1);
|
||||
|
||||
for(area_below = ext->btn_id_pr; area_below < ext->btn_cnt; area_below ++) {
|
||||
if(ext->button_areas[area_below].y1 > ext->button_areas[ext->btn_id_pr].y1 &&
|
||||
pr_center >= ext->button_areas[area_below].x1 &&
|
||||
pr_center <= ext->button_areas[area_below].x2 + style->body.padding.hor) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(area_below < ext->btn_cnt) ext->btn_id_pr = area_below;
|
||||
}
|
||||
lv_obj_invalidate(btnm);
|
||||
} else if(c == LV_GROUP_KEY_UP) {
|
||||
lv_style_t * style = lv_btnm_get_style(btnm, LV_BTNM_STYLE_BG);
|
||||
/*Find the area below the the current*/
|
||||
if(ext->btn_id_pr == LV_BTNM_PR_NONE) {
|
||||
ext->btn_id_pr = 0;
|
||||
} else {
|
||||
int16_t area_above;
|
||||
lv_coord_t pr_center = ext->button_areas[ext->btn_id_pr].x1 + (lv_area_get_width(&ext->button_areas[ext->btn_id_pr]) >> 1);
|
||||
|
||||
for(area_above = ext->btn_id_pr; area_above >= 0; area_above --) {
|
||||
if(ext->button_areas[area_above].y1 < ext->button_areas[ext->btn_id_pr].y1 &&
|
||||
pr_center >= ext->button_areas[area_above].x1 - style->body.padding.hor &&
|
||||
pr_center <= ext->button_areas[area_above].x2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(area_above >= 0) ext->btn_id_pr = area_above;
|
||||
|
||||
}
|
||||
lv_obj_invalidate(btnm);
|
||||
} else if(c == LV_GROUP_KEY_ENTER) {
|
||||
if(ext->action != NULL) {
|
||||
uint16_t txt_i = get_button_text(btnm, ext->btn_id_pr);
|
||||
if(txt_i != LV_BTNM_PR_NONE) {
|
||||
res = ext->action(btnm, cut_ctrl_byte(ext->map_p[txt_i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_EDITABLE) {
|
||||
bool * editable = (bool *)param;
|
||||
*editable = true;
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_btnm";
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the required number of buttons according to a map
|
||||
* @param btnm pointer to button matrix object
|
||||
* @param map_p pointer to a string array
|
||||
*/
|
||||
static void allocate_btn_areas(lv_obj_t * btnm, const char ** map)
|
||||
{
|
||||
/*Count the buttons in the map*/
|
||||
uint16_t btn_cnt = 0;
|
||||
uint16_t i = 0;
|
||||
while(strlen(map[i]) != 0) {
|
||||
if(strcmp(map[i], "\n") != 0) { /*Do not count line breaks*/
|
||||
btn_cnt ++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
|
||||
if(ext->button_areas != NULL) {
|
||||
lv_mem_free(ext->button_areas);
|
||||
ext->button_areas = NULL;
|
||||
}
|
||||
|
||||
ext->button_areas = lv_mem_alloc(sizeof(lv_area_t) * btn_cnt);
|
||||
lv_mem_assert(ext->button_areas);
|
||||
if(ext->button_areas == NULL) btn_cnt = 0;
|
||||
|
||||
ext->btn_cnt = btn_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width of a button in units. It comes from the first "letter".
|
||||
* @param btn_str The descriptor string of a button. E.g. "apple" or "\004banana"
|
||||
* @return the width of the button in units
|
||||
*/
|
||||
static uint8_t get_button_width(const char * btn_str)
|
||||
{
|
||||
if((btn_str[0] & LV_BTNM_CTRL_MASK) == LV_BTNM_CTRL_CODE) {
|
||||
return btn_str[0] & LV_BTNM_WIDTH_MASK;
|
||||
}
|
||||
|
||||
return 1; /*Default width is 1*/
|
||||
}
|
||||
|
||||
static bool button_is_hidden(const char * btn_str)
|
||||
{
|
||||
/*If control byte presents and hidden bit is '1' then the button is hidden*/
|
||||
if(((btn_str[0] & LV_BTNM_CTRL_MASK) == LV_BTNM_CTRL_CODE) &&
|
||||
(btn_str[0] & LV_BTNM_HIDE_MASK)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool button_is_repeat_disabled(const char * btn_str)
|
||||
{
|
||||
/*If control byte presents and hidden bit is '1' then the button is hidden*/
|
||||
if(((btn_str[0] & LV_BTNM_CTRL_MASK) == LV_BTNM_CTRL_CODE) &&
|
||||
(btn_str[0] & LV_BTNM_REPEAT_DISABLE_MASK)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool button_is_inactive(const char * btn_str)
|
||||
{
|
||||
/*If control byte presents and hidden bit is '1' then the button is hidden*/
|
||||
if(((btn_str[0] & LV_BTNM_CTRL_MASK) == LV_BTNM_CTRL_CODE) &&
|
||||
(btn_str[0] & LV_BTNM_INACTIVE_MASK)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const char * cut_ctrl_byte(const char * btn_str)
|
||||
{
|
||||
/*Cut the control byte if present*/
|
||||
if((btn_str[0] & LV_BTNM_CTRL_MASK) == LV_BTNM_CTRL_CODE) return &btn_str[1];
|
||||
else return btn_str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the button id of a button under a given point
|
||||
* @param btnm pointer to a button matrix object
|
||||
* @param p a point with absolute coordinates
|
||||
* @return the id of the button or LV_BTNM_PR_NONE.
|
||||
*/
|
||||
static uint16_t get_button_from_point(lv_obj_t * btnm, lv_point_t * p)
|
||||
{
|
||||
lv_area_t btnm_cords;
|
||||
lv_area_t btn_area;
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
uint16_t i;
|
||||
lv_obj_get_coords(btnm, &btnm_cords);
|
||||
|
||||
for(i = 0; i < ext->btn_cnt; i++) {
|
||||
lv_area_copy(&btn_area, &ext->button_areas[i]);
|
||||
btn_area.x1 += btnm_cords.x1;
|
||||
btn_area.y1 += btnm_cords.y1;
|
||||
btn_area.x2 += btnm_cords.x1;
|
||||
btn_area.y2 += btnm_cords.y1;
|
||||
if(lv_area_is_point_on(&btn_area, p) != false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i == ext->btn_cnt) i = LV_BTNM_PR_NONE;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text of a button
|
||||
* @param btnm pointer to a button matrix object
|
||||
* @param btn_id button id
|
||||
* @return text id in ext->map_p or LV_BTNM_PR_NONE if 'btn_id' was invalid
|
||||
*/
|
||||
static uint16_t get_button_text(lv_obj_t * btnm, uint16_t btn_id)
|
||||
{
|
||||
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
|
||||
if(btn_id > ext->btn_cnt) return LV_BTNM_PR_NONE;
|
||||
|
||||
uint16_t txt_i = 0;
|
||||
uint16_t btn_i = 0;
|
||||
|
||||
/* Search the text of ext->btn_pr the buttons text in the map
|
||||
* Skip "\n"-s*/
|
||||
while(btn_i != btn_id) {
|
||||
btn_i ++;
|
||||
txt_i ++;
|
||||
if(strcmp(ext->map_p[txt_i], "\n") == 0) txt_i ++;
|
||||
}
|
||||
|
||||
if(btn_i == ext->btn_cnt) return LV_BTNM_PR_NONE;
|
||||
|
||||
return txt_i;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
197
bdk/libs/lvgl/lv_objx/lv_btnm.h
Normal file
197
bdk/libs/lvgl/lv_objx/lv_btnm.h
Normal file
|
@ -0,0 +1,197 @@
|
|||
/**
|
||||
* @file lv_btnm.h
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_BTNM_H
|
||||
#define LV_BTNM_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_BTNM != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_label.h"
|
||||
#include "lv_btn.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/*Control byte*/
|
||||
#define LV_BTNM_CTRL_CODE 0x80 /*The control byte has to begin (if present) with 0b10xxxxxx*/
|
||||
#define LV_BTNM_CTRL_MASK 0xC0
|
||||
#define LV_BTNM_WIDTH_MASK 0x07
|
||||
#define LV_BTNM_HIDE_MASK 0x08
|
||||
#define LV_BTNM_REPEAT_DISABLE_MASK 0x10
|
||||
#define LV_BTNM_INACTIVE_MASK 0x20
|
||||
|
||||
|
||||
#define LV_BTNM_PR_NONE 0xFFFF
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/* Type of callback function which is called when a button is released or long pressed on the button matrix
|
||||
* Parameters: button matrix, text of the released button
|
||||
* return LV_ACTION_RES_INV if the button matrix is deleted else LV_ACTION_RES_OK*/
|
||||
typedef lv_res_t (*lv_btnm_action_t) (lv_obj_t *, const char *txt);
|
||||
|
||||
/*Data of button matrix*/
|
||||
typedef struct
|
||||
{
|
||||
/*No inherited ext.*/ /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
const char ** map_p; /*Pointer to the current map*/
|
||||
lv_area_t *button_areas; /*Array of areas of buttons*/
|
||||
lv_btnm_action_t action; /*A function to call when a button is releases*/
|
||||
lv_style_t *styles_btn[LV_BTN_STATE_NUM]; /*Styles of buttons in each state*/
|
||||
uint16_t btn_cnt; /*Number of button in 'map_p'(Handled by the library)*/
|
||||
uint16_t btn_id_pr; /*Index of the currently pressed button (in `button_areas`) or LV_BTNM_PR_NONE*/
|
||||
uint16_t btn_id_tgl; /*Index of the currently toggled button (in `button_areas`) or LV_BTNM_PR_NONE */
|
||||
uint8_t toggle :1; /*Enable toggling*/
|
||||
uint8_t recolor :1; /*Enable button recoloring*/
|
||||
} lv_btnm_ext_t;
|
||||
|
||||
enum {
|
||||
LV_BTNM_STYLE_BG,
|
||||
LV_BTNM_STYLE_BTN_REL,
|
||||
LV_BTNM_STYLE_BTN_PR,
|
||||
LV_BTNM_STYLE_BTN_TGL_REL,
|
||||
LV_BTNM_STYLE_BTN_TGL_PR,
|
||||
LV_BTNM_STYLE_BTN_INA,
|
||||
};
|
||||
typedef uint8_t lv_btnm_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a button matrix objects
|
||||
* @param par pointer to an object, it will be the parent of the new button matrix
|
||||
* @param copy pointer to a button matrix object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created button matrix
|
||||
*/
|
||||
lv_obj_t * lv_btnm_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new map. Buttons will be created/deleted according to the map.
|
||||
* @param btnm pointer to a button matrix object
|
||||
* @param map pointer a string array. The last string has to be: "".
|
||||
* Use "\n" to begin a new line.
|
||||
* The first byte can be a control data:
|
||||
* - bit 7: always 1
|
||||
* - bit 6: always 0
|
||||
* - bit 5: inactive (disabled)
|
||||
* - bit 4: no repeat (on long press)
|
||||
* - bit 3: hidden
|
||||
* - bit 2..0: button relative width
|
||||
* Example (practically use octal numbers): "\224abc": "abc" text with 4 width and no long press
|
||||
*/
|
||||
void lv_btnm_set_map(lv_obj_t * btnm, const char ** map);
|
||||
|
||||
/**
|
||||
* Set a new callback function for the buttons (It will be called when a button is released)
|
||||
* @param btnm: pointer to button matrix object
|
||||
* @param action pointer to a callback function
|
||||
*/
|
||||
void lv_btnm_set_action(lv_obj_t * btnm, lv_btnm_action_t action);
|
||||
|
||||
/**
|
||||
* Enable or disable button toggling
|
||||
* @param btnm pointer to button matrix object
|
||||
* @param en true: enable toggling; false: disable toggling
|
||||
* @param id index of the currently toggled button (ignored if 'en' == false)
|
||||
*/
|
||||
void lv_btnm_set_toggle(lv_obj_t * btnm, bool en, uint16_t id);
|
||||
|
||||
/**
|
||||
* Set a style of a button matrix
|
||||
* @param btnm pointer to a button matrix object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_btnm_set_style(lv_obj_t *btnm, lv_btnm_style_t type, lv_style_t *style);
|
||||
|
||||
/**
|
||||
* Set whether recoloring is enabled
|
||||
* @param btnm pointer to button matrix object
|
||||
* @param en whether recoloring is enabled
|
||||
*/
|
||||
void lv_btnm_set_recolor(const lv_obj_t * btnm, bool en);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the current map of a button matrix
|
||||
* @param btnm pointer to a button matrix object
|
||||
* @return the current map
|
||||
*/
|
||||
const char ** lv_btnm_get_map(const lv_obj_t * btnm);
|
||||
|
||||
/**
|
||||
* Get a the callback function of the buttons on a button matrix
|
||||
* @param btnm: pointer to button matrix object
|
||||
* @return pointer to the callback function
|
||||
*/
|
||||
lv_btnm_action_t lv_btnm_get_action(const lv_obj_t * btnm);
|
||||
|
||||
/**
|
||||
* Get the pressed button
|
||||
* @param btnm pointer to button matrix object
|
||||
* @return index of the currently pressed button (LV_BTNM_PR_NONE: if unset)
|
||||
*/
|
||||
uint16_t lv_btnm_get_pressed(const lv_obj_t * btnm);
|
||||
|
||||
/**
|
||||
* Get the toggled button
|
||||
* @param btnm pointer to button matrix object
|
||||
* @return index of the currently toggled button (LV_BTNM_PR_NONE: if unset)
|
||||
*/
|
||||
uint16_t lv_btnm_get_toggled(const lv_obj_t * btnm);
|
||||
|
||||
/**
|
||||
* Get a style of a button matrix
|
||||
* @param btnm pointer to a button matrix object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_btnm_get_style(const lv_obj_t *btnm, lv_btnm_style_t type);
|
||||
|
||||
/**
|
||||
* Find whether recoloring is enabled
|
||||
* @param btnm pointer to button matrix object
|
||||
* @return whether recoloring is enabled
|
||||
*/
|
||||
bool lv_btnm_get_recolor(const lv_obj_t * btnm);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_BTNM*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_BTNM_H*/
|
1038
bdk/libs/lvgl/lv_objx/lv_calendar.c
Normal file
1038
bdk/libs/lvgl/lv_objx/lv_calendar.c
Normal file
File diff suppressed because it is too large
Load diff
246
bdk/libs/lvgl/lv_objx/lv_calendar.h
Normal file
246
bdk/libs/lvgl/lv_objx/lv_calendar.h
Normal file
|
@ -0,0 +1,246 @@
|
|||
/**
|
||||
* @file lv_calendar.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_CALENDAR_H
|
||||
#define LV_CALENDAR_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_CALENDAR != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
uint16_t year;
|
||||
int8_t month;
|
||||
int8_t day;
|
||||
} lv_calendar_date_t;
|
||||
|
||||
enum
|
||||
{
|
||||
LV_CALENDAR_ACTION_CLICK,
|
||||
LV_CALENDAR_ACTION_PR,
|
||||
LV_CALENDAR_ACTION_LONG_PR,
|
||||
LV_CALENDAR_ACTION_LONG_PR_REPEAT,
|
||||
LV_CALENDAR_ACTION_NUM,
|
||||
};
|
||||
typedef uint8_t lv_calendar_action_t;
|
||||
|
||||
/*Data of calendar*/
|
||||
typedef struct {
|
||||
/*None*/ /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_calendar_date_t today; /*Date of today*/
|
||||
lv_calendar_date_t showed_date; /*Currently visible month (day is ignored)*/
|
||||
lv_calendar_date_t * highlighted_dates; /*Apply different style on these days (pointer to an array defined by the user)*/
|
||||
uint8_t highlighted_dates_num; /*Number of elements in `highlighted_days`*/
|
||||
int8_t btn_pressing; /*-1: prev month pressing, +1 next month pressing on the header*/
|
||||
lv_calendar_date_t pressed_date;
|
||||
const char ** day_names; /*Pointer to an array with the name of the days (NULL: use default names)*/
|
||||
const char ** month_names; /*Pointer to an array with the name of the month (NULL. use default names)*/
|
||||
lv_action_t actions[LV_CALENDAR_ACTION_NUM];
|
||||
|
||||
/*Styles*/
|
||||
lv_style_t * style_header;
|
||||
lv_style_t * style_header_pr;
|
||||
lv_style_t * style_day_names;
|
||||
lv_style_t * style_highlighted_days;
|
||||
lv_style_t * style_inactive_days;
|
||||
lv_style_t * style_week_box;
|
||||
lv_style_t * style_today_box;
|
||||
} lv_calendar_ext_t;
|
||||
|
||||
/*Styles*/
|
||||
enum {
|
||||
LV_CALENDAR_STYLE_BG, /*Also the style of the "normal" date numbers*/
|
||||
LV_CALENDAR_STYLE_HEADER,
|
||||
LV_CALENDAR_STYLE_HEADER_PR,
|
||||
LV_CALENDAR_STYLE_DAY_NAMES,
|
||||
LV_CALENDAR_STYLE_HIGHLIGHTED_DAYS,
|
||||
LV_CALENDAR_STYLE_INACTIVE_DAYS,
|
||||
LV_CALENDAR_STYLE_WEEK_BOX,
|
||||
LV_CALENDAR_STYLE_TODAY_BOX,
|
||||
};
|
||||
typedef uint8_t lv_calendar_style_t;
|
||||
|
||||
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a calendar objects
|
||||
* @param par pointer to an object, it will be the parent of the new calendar
|
||||
* @param copy pointer to a calendar object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created calendar
|
||||
*/
|
||||
lv_obj_t * lv_calendar_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
/**
|
||||
* Set a function to call when a calendar event happens
|
||||
* @param calendar pointer to a calendar object
|
||||
* @param action type of event form 'lv_action_t' (press, release, long press, long press repeat)
|
||||
*/
|
||||
void lv_calendar_set_action(lv_obj_t * calendar, lv_calendar_action_t type, lv_action_t action);
|
||||
|
||||
/**
|
||||
* Set the today's date
|
||||
* @param calendar pointer to a calendar object
|
||||
* @param today pointer to an `lv_calendar_date_t` variable containing the date of today. The value will be saved it can be local variable too.
|
||||
*/
|
||||
void lv_calendar_set_today_date(lv_obj_t * calendar, lv_calendar_date_t * today);
|
||||
|
||||
/**
|
||||
* Set the currently showed
|
||||
* @param calendar pointer to a calendar object
|
||||
* @param showed pointer to an `lv_calendar_date_t` variable containing the date to show. The value will be saved it can be local variable too.
|
||||
*/
|
||||
void lv_calendar_set_showed_date(lv_obj_t * calendar, lv_calendar_date_t * showed);
|
||||
|
||||
/**
|
||||
* Set the the highlighted dates
|
||||
* @param calendar pointer to a calendar object
|
||||
* @param highlighted pointer to an `lv_calendar_date_t` array containing the dates. ONLY A POINTER WILL BE SAVED! CAN'T BE LOCAL ARRAY.
|
||||
* @param date_num number of dates in the array
|
||||
*/
|
||||
void lv_calendar_set_highlighted_dates(lv_obj_t * calendar, lv_calendar_date_t * highlighted, uint16_t date_num);
|
||||
|
||||
|
||||
/**
|
||||
* Set the name of the days
|
||||
* @param calendar pointer to a calendar object
|
||||
* @param day_names pointer to an array with the names. E.g. `const char * days[7] = {"Sun", "Mon", ...}`
|
||||
* Only the pointer will be saved so this variable can't be local which will be destroyed later.
|
||||
*/
|
||||
void lv_calendar_set_day_names(lv_obj_t * calendar, const char ** day_names);
|
||||
|
||||
/**
|
||||
* Set the name of the month
|
||||
* @param calendar pointer to a calendar object
|
||||
* @param day_names pointer to an array with the names. E.g. `const char * days[12] = {"Jan", "Feb", ...}`
|
||||
* Only the pointer will be saved so this variable can't be local which will be destroyed later.
|
||||
*/
|
||||
void lv_calendar_set_month_names(lv_obj_t * calendar, const char ** day_names);
|
||||
|
||||
/**
|
||||
* Set a style of a calendar.
|
||||
* @param calendar pointer to calendar object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
* */
|
||||
void lv_calendar_set_style(lv_obj_t * calendar, lv_calendar_style_t type, lv_style_t *style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
/**
|
||||
* Get the action of a calendar
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return pointer to the action function
|
||||
*/
|
||||
lv_action_t lv_calendar_get_action(const lv_obj_t * calendar, lv_calendar_action_t type);
|
||||
|
||||
/**
|
||||
* Get the today's date
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return return pointer to an `lv_calendar_date_t` variable containing the date of today.
|
||||
*/
|
||||
lv_calendar_date_t * lv_calendar_get_today_date(const lv_obj_t * calendar);
|
||||
|
||||
/**
|
||||
* Get the currently showed
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return pointer to an `lv_calendar_date_t` variable containing the date is being shown.
|
||||
*/
|
||||
lv_calendar_date_t * lv_calendar_get_showed_date(const lv_obj_t * calendar);
|
||||
|
||||
/**
|
||||
* Get the the pressed date.
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return pointer to an `lv_calendar_date_t` variable containing the pressed date.
|
||||
*/
|
||||
lv_calendar_date_t * lv_calendar_get_pressed_date(const lv_obj_t * calendar);
|
||||
|
||||
/**
|
||||
* Get the the highlighted dates
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return pointer to an `lv_calendar_date_t` array containing the dates.
|
||||
*/
|
||||
lv_calendar_date_t * lv_calendar_get_highlighted_dates(const lv_obj_t * calendar);
|
||||
|
||||
/**
|
||||
* Get the number of the highlighted dates
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return number of highlighted days
|
||||
*/
|
||||
uint16_t lv_calendar_get_highlighted_dates_num(const lv_obj_t * calendar);
|
||||
|
||||
|
||||
/**
|
||||
* Get the name of the days
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return pointer to the array of day names
|
||||
*/
|
||||
const char ** lv_calendar_get_day_names(const lv_obj_t * calendar);
|
||||
|
||||
/**
|
||||
* Get the name of the month
|
||||
* @param calendar pointer to a calendar object
|
||||
* @return pointer to the array of month names
|
||||
*/
|
||||
const char ** lv_calendar_get_month_names(const lv_obj_t * calendar);
|
||||
|
||||
/**
|
||||
* Get style of a calendar.
|
||||
* @param calendar pointer to calendar object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
* */
|
||||
lv_style_t * lv_calendar_get_style(const lv_obj_t * calendar, lv_calendar_style_t type);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_CALENDAR*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_CALENDAR_H*/
|
593
bdk/libs/lvgl/lv_objx/lv_canvas.c
Normal file
593
bdk/libs/lvgl/lv_objx/lv_canvas.c
Normal file
|
@ -0,0 +1,593 @@
|
|||
/**
|
||||
* @file lv_canvas.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_canvas.h"
|
||||
#if USE_LV_CANVAS != 0
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_canvas_signal(lv_obj_t * canvas, lv_signal_t sign, void * param);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
static lv_design_func_t ancestor_design;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a canvas object
|
||||
* @param par pointer to an object, it will be the parent of the new canvas
|
||||
* @param copy pointer to a canvas object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created canvas
|
||||
*/
|
||||
lv_obj_t * lv_canvas_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("canvas create started");
|
||||
|
||||
/*Create the ancestor of canvas*/
|
||||
lv_obj_t * new_canvas = lv_img_create(par, copy);
|
||||
lv_mem_assert(new_canvas);
|
||||
if(new_canvas == NULL) return NULL;
|
||||
|
||||
/*Allocate the canvas type specific extended data*/
|
||||
lv_canvas_ext_t * ext = lv_obj_allocate_ext_attr(new_canvas, sizeof(lv_canvas_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_canvas);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_canvas);
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->dsc.header.always_zero = 0;
|
||||
ext->dsc.header.cf = LV_IMG_CF_TRUE_COLOR;
|
||||
ext->dsc.header.h = 0;
|
||||
ext->dsc.header.w = 0;
|
||||
ext->dsc.data_size = 0;
|
||||
ext->dsc.data = NULL;
|
||||
|
||||
lv_img_set_src(new_canvas, &ext->dsc);
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_canvas, lv_canvas_signal);
|
||||
|
||||
/*Init the new canvas canvas*/
|
||||
if(copy == NULL) {
|
||||
|
||||
}
|
||||
/*Copy an existing canvas*/
|
||||
else {
|
||||
//lv_canvas_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_canvas);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("canvas created");
|
||||
|
||||
return new_canvas;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a buffer for the canvas.
|
||||
* @param buf a buffer where the content of the canvas will be.
|
||||
* The required size is (lv_img_color_format_get_px_size(cf) * w * h) / 8)
|
||||
* It can be allocated with `lv_mem_alloc()` or
|
||||
* it can be statically allocated array (e.g. static lv_color_t buf[100*50]) or
|
||||
* it can be an address in RAM or external SRAM
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param w width of the canvas
|
||||
* @param h height of the canvas
|
||||
* @param cf color format. The following formats are supported:
|
||||
* LV_IMG_CF_TRUE_COLOR, LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED, LV_IMG_CF_INDEXES_1/2/4/8BIT
|
||||
*
|
||||
*/
|
||||
void lv_canvas_set_buffer(lv_obj_t * canvas, void * buf, lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)
|
||||
{
|
||||
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
|
||||
|
||||
ext->dsc.header.cf = cf;
|
||||
ext->dsc.header.w = w;
|
||||
ext->dsc.header.h = h;
|
||||
ext->dsc.data = buf;
|
||||
ext->dsc.data_size = (lv_img_color_format_get_px_size(cf) * w * h) / 8;
|
||||
|
||||
lv_img_set_src(canvas, &ext->dsc);
|
||||
}
|
||||
/**
|
||||
* Set the color of a pixel on the canvas
|
||||
* @param canvas
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param c color of the point
|
||||
*/
|
||||
void lv_canvas_set_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c)
|
||||
{
|
||||
|
||||
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
|
||||
if(x >= ext->dsc.header.w || y >= ext->dsc.header.h) {
|
||||
LV_LOG_WARN("lv_canvas_set_px: x or y out of the canvas");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t * buf_u8 = (uint8_t *) ext->dsc.data;
|
||||
|
||||
if(ext->dsc.header.cf == LV_IMG_CF_TRUE_COLOR ||
|
||||
ext->dsc.header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED)
|
||||
{
|
||||
uint32_t px = ext->dsc.header.w * y * sizeof(lv_color_t) + x * sizeof(lv_color_t);
|
||||
|
||||
memcpy(&buf_u8[px], &c, sizeof(lv_color_t));
|
||||
}
|
||||
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_1BIT) {
|
||||
buf_u8 += 4 * 2;
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
uint32_t px = (ext->dsc.header.w >> 3) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0x1) << (7 - bit));
|
||||
}
|
||||
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_2BIT) {
|
||||
buf_u8 += 4 * 4;
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
uint32_t px = (ext->dsc.header.w >> 2) * y + x;
|
||||
|
||||
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0x3) << (6 - bit));
|
||||
}
|
||||
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_4BIT) {
|
||||
buf_u8 += 4 * 16;
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
uint32_t px = (ext->dsc.header.w >> 1) * y + x;
|
||||
|
||||
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0xF) << (4 - bit));
|
||||
}
|
||||
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
buf_u8 += 4 * 256;
|
||||
uint32_t px = ext->dsc.header.w * y + x;
|
||||
buf_u8[px] = c.full;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a canvas.
|
||||
* @param canvas pointer to canvas object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_canvas_set_style(lv_obj_t * canvas, lv_canvas_style_t type, lv_style_t * style)
|
||||
{
|
||||
switch(type) {
|
||||
case LV_CANVAS_STYLE_MAIN:
|
||||
lv_img_set_style(canvas, style);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the color of a pixel on the canvas
|
||||
* @param canvas
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @return color of the point
|
||||
*/
|
||||
lv_color_t lv_canvas_get_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
lv_color_t p_color = LV_COLOR_BLACK;
|
||||
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
|
||||
if(x >= ext->dsc.header.w || y >= ext->dsc.header.h) {
|
||||
LV_LOG_WARN("lv_canvas_get_px: x or y out of the canvas");
|
||||
return p_color;
|
||||
}
|
||||
|
||||
uint8_t * buf_u8 = (uint8_t *) ext->dsc.data;
|
||||
|
||||
if(ext->dsc.header.cf == LV_IMG_CF_TRUE_COLOR ||
|
||||
ext->dsc.header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED)
|
||||
{
|
||||
uint32_t px = ext->dsc.header.w * y * sizeof(lv_color_t) + x * sizeof(lv_color_t);
|
||||
memcpy(&p_color, &buf_u8[px], sizeof(lv_color_t));
|
||||
}
|
||||
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_1BIT) {
|
||||
buf_u8 += 4 * 2;
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
uint32_t px = (ext->dsc.header.w >> 3) * y + x;
|
||||
p_color.full = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit);
|
||||
}
|
||||
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_2BIT) {
|
||||
buf_u8 += 4 * 4;
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
uint32_t px = (ext->dsc.header.w >> 2) * y + x;
|
||||
p_color.full = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit);
|
||||
}
|
||||
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_4BIT) {
|
||||
buf_u8 += 4 * 16;
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
uint32_t px = (ext->dsc.header.w >> 1) * y + x;
|
||||
p_color.full = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit);
|
||||
}
|
||||
else if(ext->dsc.header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
buf_u8 += 4 * 256;
|
||||
uint32_t px = ext->dsc.header.w * y + x;
|
||||
p_color.full = buf_u8[px];
|
||||
}
|
||||
return p_color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get style of a canvas.
|
||||
* @param canvas pointer to canvas object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
*/
|
||||
lv_style_t * lv_canvas_get_style(const lv_obj_t * canvas, lv_canvas_style_t type)
|
||||
{
|
||||
// lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
|
||||
lv_style_t * style = NULL;
|
||||
|
||||
switch(type) {
|
||||
case LV_CANVAS_STYLE_MAIN:
|
||||
style = lv_img_get_style(canvas);
|
||||
break;
|
||||
default:
|
||||
style = NULL;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Copy a buffer to the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param to_copy buffer to copy. The color format has to match with the canvas's buffer color format
|
||||
* @param w width of the buffer to copy
|
||||
* @param h height of the buffer to copy
|
||||
* @param x left side of the destination position
|
||||
* @param y top side of the destination position
|
||||
*/
|
||||
void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t w, lv_coord_t h, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
|
||||
if(x + w >= ext->dsc.header.w || y + h >= ext->dsc.header.h) {
|
||||
LV_LOG_WARN("lv_canvas_copy_buf: x or y out of the canvas");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t px_size = lv_img_color_format_get_px_size(ext->dsc.header.cf) >> 3;
|
||||
uint32_t px = ext->dsc.header.w * y * px_size + x * px_size;
|
||||
uint8_t * to_copy8 = (uint8_t *) to_copy;
|
||||
lv_coord_t i;
|
||||
for(i = 0; i < h; i++) {
|
||||
memcpy((void*)&ext->dsc.data[px], to_copy8, w * px_size);
|
||||
px += ext->dsc.header.w * px_size;
|
||||
to_copy8 += w * px_size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply a buffer with the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param to_copy buffer to copy (multiply). LV_IMG_CF_TRUE_COLOR_ALPHA is not supported
|
||||
* @param w width of the buffer to copy
|
||||
* @param h height of the buffer to copy
|
||||
* @param x left side of the destination position
|
||||
* @param y top side of the destination position
|
||||
*/
|
||||
void lv_canvas_mult_buf(lv_obj_t * canvas, void * to_copy, lv_coord_t w, lv_coord_t h, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas);
|
||||
if(x + w >= ext->dsc.header.w || y + h >= ext->dsc.header.h) {
|
||||
LV_LOG_WARN("lv_canvas_mult_buf: x or y out of the canvas");
|
||||
return;
|
||||
}
|
||||
|
||||
if(ext->dsc.header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
LV_LOG_WARN("lv_canvas_mult_buf: LV_IMG_CF_TRUE_COLOR_ALPHA is not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t px_size = lv_img_color_format_get_px_size(ext->dsc.header.cf) >> 3;
|
||||
uint32_t px = ext->dsc.header.w * y * px_size + x * px_size;
|
||||
lv_color_t * copy_buf_color = (lv_color_t *) to_copy;
|
||||
lv_color_t * canvas_buf_color = (lv_color_t *) &ext->dsc.data[px];
|
||||
|
||||
lv_coord_t i;
|
||||
lv_coord_t j;
|
||||
for(i = 0; i < h; i++) {
|
||||
for(j = 0; j < w; j++) {
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
canvas_buf_color[j].red = (uint16_t) ((uint16_t) canvas_buf_color[j].red * copy_buf_color[j].red) >> 8;
|
||||
canvas_buf_color[j].green = (uint16_t) ((uint16_t) canvas_buf_color[j].green * copy_buf_color[j].green) >> 8;
|
||||
canvas_buf_color[j].blue = (uint16_t) ((uint16_t) canvas_buf_color[j].blue * copy_buf_color[j].blue) >> 8;
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
|
||||
canvas_buf_color[j].red = (uint16_t) ((uint16_t) canvas_buf_color[j].red * copy_buf_color[j].red) >> 5;
|
||||
canvas_buf_color[j].blue = (uint16_t) ((uint16_t) canvas_buf_color[j].blue * copy_buf_color[j].blue) >> 5;
|
||||
# if LV_COLOR_16_SWAP == 0
|
||||
canvas_buf_color[j].green = (uint16_t) ((uint16_t) canvas_buf_color[j].green * copy_buf_color[j].green) >> 6;
|
||||
# else
|
||||
uint8_t green_canvas = (canvas_buf_color[j].green_h << 3) + (canvas_buf_color[j].green_l);
|
||||
uint8_t green_buf = (copy_buf_color[j].green_h << 3) + (copy_buf_color[j].green_l);
|
||||
uint8_t green_res = (uint16_t)((uint16_t)green_canvas * green_buf) >> 6;
|
||||
canvas_buf_color[j].green_h = (green_res >> 3) & 0x07;
|
||||
canvas_buf_color[j].green_l = green_res & 0x07;
|
||||
# endif /*LV_COLOR_16_SWAP*/
|
||||
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
canvas_buf_color[j].red = (uint16_t) ((uint16_t) canvas_buf_color[j].red * copy_buf_color[j].red) >> 3;
|
||||
canvas_buf_color[j].green = (uint16_t) ((uint16_t) canvas_buf_color[j].green * copy_buf_color[j].green) >> 3;
|
||||
canvas_buf_color[j].blue = (uint16_t) ((uint16_t) canvas_buf_color[j].blue * copy_buf_color[j].blue) >> 2;
|
||||
#endif
|
||||
}
|
||||
copy_buf_color += w;
|
||||
canvas_buf_color += ext->dsc.header.w;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw circle function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param x0 x coordinate of the circle
|
||||
* @param y0 y coordinate of the circle
|
||||
* @param radius radius of the circle
|
||||
* @param color border color of the circle
|
||||
*/
|
||||
void lv_canvas_draw_circle(lv_obj_t * canvas, lv_coord_t x0, lv_coord_t y0, lv_coord_t radius, lv_color_t color)
|
||||
{
|
||||
int x = radius;
|
||||
int y = 0;
|
||||
int err = 0;
|
||||
|
||||
while (x >= y)
|
||||
{
|
||||
lv_canvas_set_px(canvas, x0 + x, y0 + y, color);
|
||||
lv_canvas_set_px(canvas, x0 + y, y0 + x, color);
|
||||
lv_canvas_set_px(canvas, x0 - y, y0 + x, color);
|
||||
lv_canvas_set_px(canvas, x0 - x, y0 + y, color);
|
||||
lv_canvas_set_px(canvas, x0 - x, y0 - y, color);
|
||||
lv_canvas_set_px(canvas, x0 - y, y0 - x, color);
|
||||
lv_canvas_set_px(canvas, x0 + y, y0 - x, color);
|
||||
lv_canvas_set_px(canvas, x0 + x, y0 - y, color);
|
||||
|
||||
if (err <= 0)
|
||||
{
|
||||
y += 1;
|
||||
err += 2*y + 1;
|
||||
}
|
||||
|
||||
if (err > 0)
|
||||
{
|
||||
x -= 1;
|
||||
err -= 2*x + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw line function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param point1 start point of the line
|
||||
* @param point2 end point of the line
|
||||
* @param color color of the line
|
||||
*
|
||||
* NOTE: The lv_canvas_draw_line function originates from https://github.com/jb55/bresenham-line.c.
|
||||
*/
|
||||
/*
|
||||
* NOTE: The lv_canvas_draw_line function originates from https://github.com/jb55/bresenham-line.c.
|
||||
*/
|
||||
void lv_canvas_draw_line(lv_obj_t * canvas, lv_point_t point1, lv_point_t point2, lv_color_t color)
|
||||
{
|
||||
lv_coord_t x0, y0, x1, y1;
|
||||
|
||||
x0 = point1.x;
|
||||
y0 = point1.y;
|
||||
x1 = point2.x;
|
||||
y1 = point2.y;
|
||||
|
||||
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
|
||||
int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
|
||||
int err = (dx>dy ? dx : -dy)/2, e2;
|
||||
|
||||
for(;;){
|
||||
lv_canvas_set_px(canvas, x0, y0, color);
|
||||
|
||||
if (x0==x1 && y0==y1) break;
|
||||
e2 = err;
|
||||
if (e2 >-dx) { err -= dy; x0 += sx; }
|
||||
if (e2 < dy) { err += dx; y0 += sy; }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw triangle function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param points edge points of the triangle
|
||||
* @param color line color of the triangle
|
||||
*/
|
||||
void lv_canvas_draw_triangle(lv_obj_t * canvas, lv_point_t * points, lv_color_t color)
|
||||
{
|
||||
lv_canvas_draw_polygon(canvas, points, 3, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw rectangle function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param points edge points of the rectangle
|
||||
* @param color line color of the rectangle
|
||||
*/
|
||||
void lv_canvas_draw_rect(lv_obj_t * canvas, lv_point_t * points, lv_color_t color)
|
||||
{
|
||||
lv_canvas_draw_polygon(canvas, points, 4, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw polygon function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param points edge points of the polygon
|
||||
* @param size edge count of the polygon
|
||||
* @param color line color of the polygon
|
||||
*/
|
||||
void lv_canvas_draw_polygon(lv_obj_t * canvas, lv_point_t * points, size_t size, lv_color_t color)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for(i=0; i < (size - 1); i++) {
|
||||
lv_canvas_draw_line(canvas, points[i], points[i + 1], color);
|
||||
}
|
||||
|
||||
lv_canvas_draw_line(canvas, points[size - 1], points[0], color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill polygon function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param points edge points of the polygon
|
||||
* @param size edge count of the polygon
|
||||
* @param boundary_color line color of the polygon
|
||||
* @param fill_color fill color of the polygon
|
||||
*/
|
||||
void lv_canvas_fill_polygon(lv_obj_t * canvas, lv_point_t * points, size_t size, lv_color_t boundary_color, lv_color_t fill_color)
|
||||
{
|
||||
uint32_t x = 0, y = 0;
|
||||
uint8_t i;
|
||||
|
||||
for(i=0; i<size; i++) {
|
||||
x += points[i].x;
|
||||
y += points[i].y;
|
||||
}
|
||||
|
||||
x = x / size;
|
||||
y = y / size;
|
||||
|
||||
lv_canvas_boundary_fill4(canvas, (lv_coord_t) x, (lv_coord_t) y, boundary_color, fill_color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Boundary fill function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param x x coordinate of the start position (seed)
|
||||
* @param y y coordinate of the start position (seed)
|
||||
* @param boundary_color edge/boundary color of the area
|
||||
* @param fill_color fill color of the area
|
||||
*/
|
||||
void lv_canvas_boundary_fill4(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t boundary_color, lv_color_t fill_color)
|
||||
{
|
||||
lv_color_t c;
|
||||
|
||||
c = lv_canvas_get_px(canvas, x, y);
|
||||
|
||||
if(c.full != boundary_color.full &&
|
||||
c.full != fill_color.full)
|
||||
{
|
||||
lv_canvas_set_px(canvas, x, y, fill_color);
|
||||
|
||||
lv_canvas_boundary_fill4(canvas, x + 1, y, boundary_color, fill_color);
|
||||
lv_canvas_boundary_fill4(canvas, x, y + 1, boundary_color, fill_color);
|
||||
lv_canvas_boundary_fill4(canvas, x - 1, y, boundary_color, fill_color);
|
||||
lv_canvas_boundary_fill4(canvas, x, y - 1, boundary_color, fill_color);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flood fill function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param x x coordinate of the start position (seed)
|
||||
* @param y y coordinate of the start position (seed)
|
||||
* @param fill_color fill color of the area
|
||||
* @param bg_color background color of the area
|
||||
*/
|
||||
void lv_canvas_flood_fill(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t fill_color, lv_color_t bg_color)
|
||||
{
|
||||
lv_color_t c;
|
||||
|
||||
c = lv_canvas_get_px(canvas, x, y);
|
||||
|
||||
if(c.full == bg_color.full)
|
||||
{
|
||||
lv_canvas_set_px(canvas, x, y, fill_color);
|
||||
|
||||
lv_canvas_flood_fill(canvas, x+1, y, fill_color, bg_color);
|
||||
lv_canvas_flood_fill(canvas, x, y+1, fill_color, bg_color);
|
||||
lv_canvas_flood_fill(canvas, x-1, y, fill_color, bg_color);
|
||||
lv_canvas_flood_fill(canvas, x, y-1, fill_color, bg_color);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_canvas_signal(lv_obj_t * canvas, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(canvas, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_canvas";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
229
bdk/libs/lvgl/lv_objx/lv_canvas.h
Normal file
229
bdk/libs/lvgl/lv_objx/lv_canvas.h
Normal file
|
@ -0,0 +1,229 @@
|
|||
/**
|
||||
* @file lv_canvas.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_CANVAS_H
|
||||
#define LV_CANVAS_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_CANVAS != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_objx/lv_img.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Data of canvas*/
|
||||
typedef struct {
|
||||
lv_img_ext_t img; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_img_dsc_t dsc;
|
||||
} lv_canvas_ext_t;
|
||||
|
||||
|
||||
/*Styles*/
|
||||
enum {
|
||||
LV_CANVAS_STYLE_MAIN,
|
||||
};
|
||||
typedef uint8_t lv_canvas_style_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a canvas object
|
||||
* @param par pointer to an object, it will be the parent of the new canvas
|
||||
* @param copy pointer to a canvas object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created canvas
|
||||
*/
|
||||
lv_obj_t * lv_canvas_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a buffer for the canvas.
|
||||
* @param buf a buffer where the content of the canvas will be.
|
||||
* The required size is (lv_img_color_format_get_px_size(cf) * w * h) / 8)
|
||||
* It can be allocated with `lv_mem_alloc()` or
|
||||
* it can be statically allocated array (e.g. static lv_color_t buf[100*50]) or
|
||||
* it can be an address in RAM or external SRAM
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param w width of the canvas
|
||||
* @param h height of the canvas
|
||||
* @param cf color format. The following formats are supported:
|
||||
* LV_IMG_CF_TRUE_COLOR, LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED, LV_IMG_CF_INDEXES_1/2/4/8BIT
|
||||
*/
|
||||
void lv_canvas_set_buffer(lv_obj_t * canvas, void * buf, lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
|
||||
|
||||
/**
|
||||
* Set the color of a pixel on the canvas
|
||||
* @param canvas
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param c color of the point
|
||||
*/
|
||||
void lv_canvas_set_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t c);
|
||||
|
||||
/**
|
||||
* Set a style of a canvas.
|
||||
* @param canvas pointer to canvas object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_canvas_set_style(lv_obj_t * canvas, lv_canvas_style_t type, lv_style_t * style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the color of a pixel on the canvas
|
||||
* @param canvas
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @return color of the point
|
||||
*/
|
||||
lv_color_t lv_canvas_get_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
/**
|
||||
* Get style of a canvas.
|
||||
* @param canvas pointer to canvas object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
*/
|
||||
lv_style_t * lv_canvas_get_style(const lv_obj_t * canvas, lv_canvas_style_t type);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Copy a buffer to the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param to_copy buffer to copy. The color format has to match with the canvas's buffer color format
|
||||
* @param w width of the buffer to copy
|
||||
* @param h height of the buffer to copy
|
||||
* @param x left side of the destination position
|
||||
* @param y top side of the destination position
|
||||
*/
|
||||
void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t w, lv_coord_t h, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
/**
|
||||
* Multiply a buffer with the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param to_copy buffer to copy (multiply). LV_IMG_CF_TRUE_COLOR_ALPHA is not supported
|
||||
* @param w width of the buffer to copy
|
||||
* @param h height of the buffer to copy
|
||||
* @param x left side of the destination position
|
||||
* @param y top side of the destination position
|
||||
*/
|
||||
void lv_canvas_mult_buf(lv_obj_t * canvas, void * to_copy, lv_coord_t w, lv_coord_t h, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
/**
|
||||
* Draw circle function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param x0 x coordinate of the circle
|
||||
* @param y0 y coordinate of the circle
|
||||
* @param radius radius of the circle
|
||||
* @param color border color of the circle
|
||||
*/
|
||||
void lv_canvas_draw_circle(lv_obj_t * canvas, lv_coord_t x0, lv_coord_t y0, lv_coord_t radius, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Draw line function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param point1 start point of the line
|
||||
* @param point2 end point of the line
|
||||
* @param color color of the line
|
||||
*
|
||||
* NOTE: The lv_canvas_draw_line function originates from https://github.com/jb55/bresenham-line.c.
|
||||
*/
|
||||
void lv_canvas_draw_line(lv_obj_t * canvas, lv_point_t point1, lv_point_t point2, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Draw triangle function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param points edge points of the triangle
|
||||
* @param color line color of the triangle
|
||||
*/
|
||||
void lv_canvas_draw_triangle(lv_obj_t * canvas, lv_point_t * points, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Draw rectangle function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param points edge points of the rectangle
|
||||
* @param color line color of the rectangle
|
||||
*/
|
||||
void lv_canvas_draw_rect(lv_obj_t * canvas, lv_point_t * points, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Draw polygon function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param points edge points of the polygon
|
||||
* @param size edge count of the polygon
|
||||
* @param color line color of the polygon
|
||||
*/
|
||||
void lv_canvas_draw_polygon(lv_obj_t * canvas, lv_point_t * points, size_t size, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Fill polygon function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param points edge points of the polygon
|
||||
* @param size edge count of the polygon
|
||||
* @param boundary_color line color of the polygon
|
||||
* @param fill_color fill color of the polygon
|
||||
*/
|
||||
void lv_canvas_fill_polygon(lv_obj_t * canvas, lv_point_t * points, size_t size, lv_color_t boundary_color, lv_color_t fill_color);
|
||||
/**
|
||||
* Boundary fill function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param x x coordinate of the start position (seed)
|
||||
* @param y y coordinate of the start position (seed)
|
||||
* @param boundary_color edge/boundary color of the area
|
||||
* @param fill_color fill color of the area
|
||||
*/
|
||||
void lv_canvas_boundary_fill4(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t boundary_color, lv_color_t fill_color);
|
||||
|
||||
/**
|
||||
* Flood fill function of the canvas
|
||||
* @param canvas pointer to a canvas object
|
||||
* @param x x coordinate of the start position (seed)
|
||||
* @param y y coordinate of the start position (seed)
|
||||
* @param fill_color fill color of the area
|
||||
* @param bg_color background color of the area
|
||||
*/
|
||||
void lv_canvas_flood_fill(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t fill_color, lv_color_t bg_color);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_CANVAS*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_CANVAS_H*/
|
347
bdk/libs/lvgl/lv_objx/lv_cb.c
Normal file
347
bdk/libs/lvgl/lv_objx/lv_cb.c
Normal file
|
@ -0,0 +1,347 @@
|
|||
/**
|
||||
* @file lv_cb.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_cb.h"
|
||||
#if USE_LV_CB != 0
|
||||
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_cb_design(lv_obj_t * cb, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static bool lv_bullet_design(lv_obj_t * bullet, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_cb_signal(lv_obj_t * cb, lv_signal_t sign, void * param);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_design_func_t ancestor_bg_design;
|
||||
static lv_design_func_t ancestor_bullet_design;
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a check box objects
|
||||
* @param par pointer to an object, it will be the parent of the new check box
|
||||
* @param copy pointer to a check box object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created check box
|
||||
*/
|
||||
lv_obj_t * lv_cb_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
|
||||
LV_LOG_TRACE("check box create started");
|
||||
|
||||
/*Create the ancestor basic object*/
|
||||
lv_obj_t * new_cb = lv_btn_create(par, copy);
|
||||
lv_mem_assert(new_cb);
|
||||
if(new_cb == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_cb);
|
||||
if(ancestor_bg_design == NULL) ancestor_bg_design = lv_obj_get_design_func(new_cb);
|
||||
|
||||
lv_cb_ext_t * ext = lv_obj_allocate_ext_attr(new_cb, sizeof(lv_cb_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->bullet = NULL;
|
||||
ext->label = NULL;
|
||||
|
||||
lv_obj_set_signal_func(new_cb, lv_cb_signal);
|
||||
lv_obj_set_design_func(new_cb, lv_cb_design);
|
||||
|
||||
/*Init the new checkbox object*/
|
||||
if(copy == NULL) {
|
||||
ext->bullet = lv_btn_create(new_cb, NULL);
|
||||
if(ancestor_bullet_design == NULL) ancestor_bullet_design = lv_obj_get_design_func(ext->bullet);
|
||||
lv_obj_set_click(ext->bullet, false);
|
||||
|
||||
ext->label = lv_label_create(new_cb, NULL);
|
||||
|
||||
lv_cb_set_text(new_cb, "Check box");
|
||||
lv_btn_set_layout(new_cb, LV_LAYOUT_ROW_M);
|
||||
lv_btn_set_fit(new_cb, true, true);
|
||||
lv_btn_set_toggle(new_cb, true);
|
||||
lv_obj_set_protect(new_cb, LV_PROTECT_PRESS_LOST);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_cb_set_style(new_cb, LV_CB_STYLE_BG, th->cb.bg);
|
||||
lv_cb_set_style(new_cb, LV_CB_STYLE_BOX_REL, th->cb.box.rel);
|
||||
lv_cb_set_style(new_cb, LV_CB_STYLE_BOX_PR, th->cb.box.pr);
|
||||
lv_cb_set_style(new_cb, LV_CB_STYLE_BOX_TGL_REL, th->cb.box.tgl_rel);
|
||||
lv_cb_set_style(new_cb, LV_CB_STYLE_BOX_TGL_PR, th->cb.box.tgl_pr);
|
||||
lv_cb_set_style(new_cb, LV_CB_STYLE_BOX_INA, th->cb.box.ina);
|
||||
} else {
|
||||
lv_cb_set_style(new_cb, LV_CB_STYLE_BG, &lv_style_transp);
|
||||
lv_cb_set_style(new_cb, LV_CB_STYLE_BOX_REL, &lv_style_pretty);
|
||||
}
|
||||
} else {
|
||||
lv_cb_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->bullet = lv_btn_create(new_cb, copy_ext->bullet);
|
||||
ext->label = lv_label_create(new_cb, copy_ext->label);
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_cb);
|
||||
}
|
||||
|
||||
lv_obj_set_design_func(ext->bullet, lv_bullet_design);
|
||||
|
||||
|
||||
LV_LOG_INFO("check box created");
|
||||
|
||||
return new_cb;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the text of a check box
|
||||
* @param cb pointer to a check box
|
||||
* @param txt the text of the check box
|
||||
*/
|
||||
void lv_cb_set_text(lv_obj_t * cb, const char * txt)
|
||||
{
|
||||
lv_cb_ext_t * ext = lv_obj_get_ext_attr(cb);
|
||||
lv_label_set_text(ext->label, txt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a check box
|
||||
* @param cb pointer to check box object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
* */
|
||||
void lv_cb_set_style(lv_obj_t * cb, lv_cb_style_t type, lv_style_t * style)
|
||||
{
|
||||
lv_cb_ext_t * ext = lv_obj_get_ext_attr(cb);
|
||||
|
||||
switch(type) {
|
||||
case LV_CB_STYLE_BG:
|
||||
lv_btn_set_style(cb, LV_BTN_STYLE_REL, style);
|
||||
lv_btn_set_style(cb, LV_BTN_STYLE_PR, style);
|
||||
lv_btn_set_style(cb, LV_BTN_STYLE_TGL_REL, style);
|
||||
lv_btn_set_style(cb, LV_BTN_STYLE_TGL_PR, style);
|
||||
lv_btn_set_style(cb, LV_BTN_STYLE_INA, style);
|
||||
break;
|
||||
case LV_CB_STYLE_BOX_REL:
|
||||
lv_btn_set_style(ext->bullet, LV_BTN_STYLE_REL, style);
|
||||
break;
|
||||
case LV_CB_STYLE_BOX_PR:
|
||||
lv_btn_set_style(ext->bullet, LV_BTN_STYLE_PR, style);
|
||||
break;
|
||||
case LV_CB_STYLE_BOX_TGL_REL:
|
||||
lv_btn_set_style(ext->bullet, LV_BTN_STYLE_TGL_REL, style);
|
||||
break;
|
||||
case LV_CB_STYLE_BOX_TGL_PR:
|
||||
lv_btn_set_style(ext->bullet, LV_BTN_STYLE_TGL_PR, style);
|
||||
break;
|
||||
case LV_CB_STYLE_BOX_INA:
|
||||
lv_btn_set_style(ext->bullet, LV_BTN_STYLE_INA, style);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the text of a check box
|
||||
* @param cb pointer to check box object
|
||||
* @return pointer to the text of the check box
|
||||
*/
|
||||
const char * lv_cb_get_text(const lv_obj_t * cb)
|
||||
{
|
||||
lv_cb_ext_t * ext = lv_obj_get_ext_attr(cb);
|
||||
return lv_label_get_text(ext->label);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a style of a button
|
||||
* @param cb pointer to check box object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
* */
|
||||
lv_style_t * lv_cb_get_style(const lv_obj_t * cb, lv_cb_style_t type)
|
||||
{
|
||||
lv_style_t * style = NULL;
|
||||
lv_cb_ext_t * ext = lv_obj_get_ext_attr(cb);
|
||||
|
||||
switch(type) {
|
||||
case LV_CB_STYLE_BOX_REL:
|
||||
style = lv_btn_get_style(ext->bullet, LV_BTN_STYLE_REL);
|
||||
break;
|
||||
case LV_CB_STYLE_BOX_PR:
|
||||
style = lv_btn_get_style(ext->bullet, LV_BTN_STYLE_PR);
|
||||
break;
|
||||
case LV_CB_STYLE_BOX_TGL_REL:
|
||||
style = lv_btn_get_style(ext->bullet, LV_BTN_STYLE_TGL_REL);
|
||||
break;
|
||||
case LV_CB_STYLE_BOX_TGL_PR:
|
||||
style = lv_btn_get_style(ext->bullet, LV_BTN_STYLE_TGL_PR);
|
||||
break;
|
||||
case LV_CB_STYLE_BOX_INA:
|
||||
style = lv_btn_get_style(ext->bullet, LV_BTN_STYLE_INA);
|
||||
break;
|
||||
default:
|
||||
style = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the check boxes
|
||||
* @param cb pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_cb_design(lv_obj_t * cb, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
result = ancestor_bg_design(cb, mask, mode);
|
||||
} else if(mode == LV_DESIGN_DRAW_MAIN || mode == LV_DESIGN_DRAW_POST) {
|
||||
lv_cb_ext_t * cb_ext = lv_obj_get_ext_attr(cb);
|
||||
lv_btn_ext_t * bullet_ext = lv_obj_get_ext_attr(cb_ext->bullet);
|
||||
|
||||
/*Be sure the state of the bullet is the same as the parent button*/
|
||||
bullet_ext->state = cb_ext->bg_btn.state;
|
||||
|
||||
result = ancestor_bg_design(cb, mask, mode);
|
||||
|
||||
} else {
|
||||
result = ancestor_bg_design(cb, mask, mode);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the check boxes
|
||||
* @param bullet pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_bullet_design(lv_obj_t * bullet, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return ancestor_bullet_design(bullet, mask, mode);
|
||||
} else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
#if USE_LV_GROUP
|
||||
/* If the check box is the active in a group and
|
||||
* the background is not visible (transparent or empty)
|
||||
* then activate the style of the bullet*/
|
||||
lv_style_t * style_ori = lv_obj_get_style(bullet);
|
||||
lv_obj_t * bg = lv_obj_get_parent(bullet);
|
||||
lv_style_t * style_page = lv_obj_get_style(bg);
|
||||
lv_group_t * g = lv_obj_get_group(bg);
|
||||
if(style_page->body.empty != 0 || style_page->body.opa == LV_OPA_TRANSP) { /*Background is visible?*/
|
||||
if(lv_group_get_focused(g) == bg) {
|
||||
lv_style_t * style_mod;
|
||||
style_mod = lv_group_mod_style(g, style_ori);
|
||||
bullet->style_p = style_mod; /*Temporally change the style to the activated */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ancestor_bullet_design(bullet, mask, mode);
|
||||
|
||||
#if USE_LV_GROUP
|
||||
bullet->style_p = style_ori; /*Revert the style*/
|
||||
#endif
|
||||
} else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
ancestor_bullet_design(bullet, mask, mode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Signal function of the check box
|
||||
* @param cb pointer to a check box object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_cb_signal(lv_obj_t * cb, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(cb, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_cb_ext_t * ext = lv_obj_get_ext_attr(cb);
|
||||
|
||||
if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
lv_style_t * label_style = lv_label_get_style(ext->label);
|
||||
lv_obj_set_size(ext->bullet, lv_font_get_height(label_style->text.font), lv_font_get_height(label_style->text.font));
|
||||
lv_btn_set_state(ext->bullet, lv_btn_get_state(cb));
|
||||
} else if(sign == LV_SIGNAL_PRESSED ||
|
||||
sign == LV_SIGNAL_RELEASED ||
|
||||
sign == LV_SIGNAL_PRESS_LOST) {
|
||||
lv_btn_set_state(ext->bullet, lv_btn_get_state(cb));
|
||||
} else if(sign == LV_SIGNAL_CONTROLL) {
|
||||
char c = *((char *)param);
|
||||
if(c == LV_GROUP_KEY_RIGHT || c == LV_GROUP_KEY_DOWN ||
|
||||
c == LV_GROUP_KEY_LEFT || c == LV_GROUP_KEY_UP ||
|
||||
c == LV_GROUP_KEY_ENTER) {
|
||||
lv_btn_set_state(ext->bullet, lv_btn_get_state(cb));
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_cb";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
174
bdk/libs/lvgl/lv_objx/lv_cb.h
Normal file
174
bdk/libs/lvgl/lv_objx/lv_cb.h
Normal file
|
@ -0,0 +1,174 @@
|
|||
/**
|
||||
* @file lv_cb.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_CB_H
|
||||
#define LV_CB_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_CB != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_BTN == 0
|
||||
#error "lv_cb: lv_btn is required. Enable it in lv_conf.h (USE_LV_BTN 1) "
|
||||
#endif
|
||||
|
||||
#if USE_LV_LABEL == 0
|
||||
#error "lv_cb: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_btn.h"
|
||||
#include "lv_label.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Data of check box*/
|
||||
typedef struct
|
||||
{
|
||||
lv_btn_ext_t bg_btn; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_obj_t * bullet; /*Pointer to button*/
|
||||
lv_obj_t * label; /*Pointer to label*/
|
||||
} lv_cb_ext_t;
|
||||
|
||||
enum {
|
||||
LV_CB_STYLE_BG,
|
||||
LV_CB_STYLE_BOX_REL,
|
||||
LV_CB_STYLE_BOX_PR,
|
||||
LV_CB_STYLE_BOX_TGL_REL,
|
||||
LV_CB_STYLE_BOX_TGL_PR,
|
||||
LV_CB_STYLE_BOX_INA,
|
||||
};
|
||||
typedef uint8_t lv_cb_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a check box objects
|
||||
* @param par pointer to an object, it will be the parent of the new check box
|
||||
* @param copy pointer to a check box object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created check box
|
||||
*/
|
||||
lv_obj_t * lv_cb_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the text of a check box
|
||||
* @param cb pointer to a check box
|
||||
* @param txt the text of the check box
|
||||
*/
|
||||
void lv_cb_set_text(lv_obj_t * cb, const char * txt);
|
||||
|
||||
/**
|
||||
* Set the state of the check box
|
||||
* @param cb pointer to a check box object
|
||||
* @param checked true: make the check box checked; false: make it unchecked
|
||||
*/
|
||||
static inline void lv_cb_set_checked(lv_obj_t * cb, bool checked)
|
||||
{
|
||||
lv_btn_set_state(cb, checked ? LV_BTN_STATE_TGL_REL : LV_BTN_STATE_REL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the check box inactive (disabled)
|
||||
* @param cb pointer to a check box object
|
||||
*/
|
||||
static inline void lv_cb_set_inactive(lv_obj_t * cb)
|
||||
{
|
||||
lv_btn_set_state(cb, LV_BTN_STATE_INA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a function to call when the check box is clicked
|
||||
* @param cb pointer to a check box object
|
||||
*/
|
||||
static inline void lv_cb_set_action(lv_obj_t * cb, lv_action_t action)
|
||||
{
|
||||
lv_btn_set_action(cb, LV_BTN_ACTION_CLICK, action);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a style of a check box
|
||||
* @param cb pointer to check box object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
* */
|
||||
void lv_cb_set_style(lv_obj_t * cb, lv_cb_style_t type, lv_style_t *style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the text of a check box
|
||||
* @param cb pointer to check box object
|
||||
* @return pointer to the text of the check box
|
||||
*/
|
||||
const char * lv_cb_get_text(const lv_obj_t * cb);
|
||||
|
||||
/**
|
||||
* Get the current state of the check box
|
||||
* @param cb pointer to a check box object
|
||||
* @return true: checked; false: not checked
|
||||
*/
|
||||
static inline bool lv_cb_is_checked(const lv_obj_t * cb)
|
||||
{
|
||||
return lv_btn_get_state(cb) == LV_BTN_STATE_REL ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the action of a check box
|
||||
* @param cb pointer to a button object
|
||||
* @return pointer to the action function
|
||||
*/
|
||||
static inline lv_action_t lv_cb_get_action(const lv_obj_t * cb)
|
||||
{
|
||||
return lv_btn_get_action(cb, LV_BTN_ACTION_CLICK);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a style of a button
|
||||
* @param cb pointer to check box object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
* */
|
||||
lv_style_t * lv_cb_get_style(const lv_obj_t * cb, lv_cb_style_t type);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_CB*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_CB_H*/
|
824
bdk/libs/lvgl/lv_objx/lv_chart.c
Normal file
824
bdk/libs/lvgl/lv_objx/lv_chart.c
Normal file
|
@ -0,0 +1,824 @@
|
|||
/**
|
||||
* @file lv_chart.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_chart.h"
|
||||
#if USE_LV_CHART != 0
|
||||
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_CHART_YMIN_DEF 0
|
||||
#define LV_CHART_YMAX_DEF 100
|
||||
#define LV_CHART_HDIV_DEF 3
|
||||
#define LV_CHART_VDIV_DEF 5
|
||||
#define LV_CHART_PNUM_DEF 10
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_chart_design(lv_obj_t * chart, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_chart_signal(lv_obj_t * chart, lv_signal_t sign, void * param);
|
||||
static void lv_chart_draw_div(lv_obj_t * chart, const lv_area_t * mask);
|
||||
static void lv_chart_draw_lines(lv_obj_t * chart, const lv_area_t * mask);
|
||||
static void lv_chart_draw_points(lv_obj_t * chart, const lv_area_t * mask);
|
||||
static void lv_chart_draw_cols(lv_obj_t * chart, const lv_area_t * mask);
|
||||
static void lv_chart_draw_vertical_lines(lv_obj_t * chart, const lv_area_t * mask);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_design_func_t ancestor_design_f;
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a chart background objects
|
||||
* @param par pointer to an object, it will be the parent of the new chart background
|
||||
* @param copy pointer to a chart background object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created chart background
|
||||
*/
|
||||
lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("chart create started");
|
||||
|
||||
/*Create the ancestor basic object*/
|
||||
lv_obj_t * new_chart = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_chart);
|
||||
if(new_chart == NULL) return NULL;
|
||||
|
||||
/*Allocate the object type specific extended data*/
|
||||
lv_chart_ext_t * ext = lv_obj_allocate_ext_attr(new_chart, sizeof(lv_chart_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
lv_ll_init(&ext->series_ll, sizeof(lv_chart_series_t));
|
||||
ext->series.num = 0;
|
||||
ext->ymin = LV_CHART_YMIN_DEF;
|
||||
ext->ymax = LV_CHART_YMAX_DEF;
|
||||
ext->hdiv_cnt = LV_CHART_HDIV_DEF;
|
||||
ext->vdiv_cnt = LV_CHART_VDIV_DEF;
|
||||
ext->point_cnt = LV_CHART_PNUM_DEF;
|
||||
ext->type = LV_CHART_TYPE_LINE;
|
||||
ext->series.opa = LV_OPA_COVER;
|
||||
ext->series.dark = LV_OPA_50;
|
||||
ext->series.width = 2;
|
||||
|
||||
if(ancestor_design_f == NULL) ancestor_design_f = lv_obj_get_design_func(new_chart);
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_chart);
|
||||
|
||||
lv_obj_set_signal_func(new_chart, lv_chart_signal);
|
||||
lv_obj_set_design_func(new_chart, lv_chart_design);
|
||||
|
||||
/*Init the new chart background object*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_size(new_chart, LV_HOR_RES / 3, LV_VER_RES / 3);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_chart_set_style(new_chart, th->chart);
|
||||
} else {
|
||||
lv_chart_set_style(new_chart, &lv_style_pretty);
|
||||
}
|
||||
|
||||
} else {
|
||||
lv_chart_ext_t * ext_copy = lv_obj_get_ext_attr(copy);
|
||||
ext->type = ext_copy->type;
|
||||
ext->ymin = ext_copy->ymin;
|
||||
ext->ymax = ext_copy->ymax;
|
||||
ext->hdiv_cnt = ext_copy->hdiv_cnt;
|
||||
ext->vdiv_cnt = ext_copy->vdiv_cnt;
|
||||
ext->point_cnt = ext_copy->point_cnt;
|
||||
ext->series.opa = ext_copy->series.opa;
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_chart);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("chart created");
|
||||
|
||||
|
||||
return new_chart;
|
||||
}
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Allocate and add a data series to the chart
|
||||
* @param chart pointer to a chart object
|
||||
* @param color color of the data series
|
||||
* @return pointer to the allocated data series
|
||||
*/
|
||||
lv_chart_series_t * lv_chart_add_series(lv_obj_t * chart, lv_color_t color)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
lv_chart_series_t * ser = lv_ll_ins_head(&ext->series_ll);
|
||||
lv_mem_assert(ser);
|
||||
if(ser == NULL) return NULL;
|
||||
|
||||
lv_coord_t def = LV_CHART_POINT_DEF;
|
||||
|
||||
if(ser == NULL) return NULL;
|
||||
|
||||
ser->color = color;
|
||||
|
||||
ser->points = lv_mem_alloc(sizeof(lv_coord_t) * ext->point_cnt);
|
||||
lv_mem_assert(ser->points);
|
||||
if(ser->points == NULL) {
|
||||
lv_ll_rem(&ext->series_ll, ser);
|
||||
lv_mem_free(ser);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ser->start_point = 0;
|
||||
|
||||
uint16_t i;
|
||||
lv_coord_t * p_tmp = ser->points;
|
||||
for(i = 0; i < ext->point_cnt; i++) {
|
||||
*p_tmp = def;
|
||||
p_tmp++;
|
||||
}
|
||||
|
||||
ext->series.num++;
|
||||
|
||||
return ser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the point of a serie
|
||||
* @param chart pointer to a chart object
|
||||
* @param serie pointer to the chart's serie to clear
|
||||
*/
|
||||
void lv_chart_clear_serie(lv_obj_t * chart, lv_chart_series_t * serie)
|
||||
{
|
||||
if(chart == NULL || serie == NULL)
|
||||
return;
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext == NULL) return;
|
||||
|
||||
uint32_t i;
|
||||
for(i = 0; i < ext->point_cnt; i++)
|
||||
{
|
||||
serie->points[i] = LV_CHART_POINT_DEF;
|
||||
}
|
||||
|
||||
serie->start_point = 0;
|
||||
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the number of horizontal and vertical division lines
|
||||
* @param chart pointer to a graph background object
|
||||
* @param hdiv number of horizontal division lines
|
||||
* @param vdiv number of vertical division lines
|
||||
*/
|
||||
void lv_chart_set_div_line_count(lv_obj_t * chart, uint8_t hdiv, uint8_t vdiv)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->hdiv_cnt == hdiv && ext->vdiv_cnt == vdiv) return;
|
||||
|
||||
ext->hdiv_cnt = hdiv;
|
||||
ext->vdiv_cnt = vdiv;
|
||||
|
||||
lv_obj_invalidate(chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimal and maximal y values
|
||||
* @param chart pointer to a graph background object
|
||||
* @param ymin y minimum value
|
||||
* @param ymax y maximum value
|
||||
*/
|
||||
void lv_chart_set_range(lv_obj_t * chart, lv_coord_t ymin, lv_coord_t ymax)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->ymin == ymin && ext->ymax == ymax) return;
|
||||
|
||||
ext->ymin = ymin;
|
||||
ext->ymax = ymax;
|
||||
|
||||
lv_chart_refresh(chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new type for a chart
|
||||
* @param chart pointer to a chart object
|
||||
* @param type new type of the chart (from 'lv_chart_type_t' enum)
|
||||
*/
|
||||
void lv_chart_set_type(lv_obj_t * chart, lv_chart_type_t type)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->type == type) return;
|
||||
|
||||
ext->type = type;
|
||||
|
||||
lv_chart_refresh(chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of points on a data line on a chart
|
||||
* @param chart pointer r to chart object
|
||||
* @param point_cnt new number of points on the data lines
|
||||
*/
|
||||
void lv_chart_set_point_count(lv_obj_t * chart, uint16_t point_cnt)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->point_cnt == point_cnt) return;
|
||||
|
||||
lv_chart_series_t * ser;
|
||||
uint16_t point_cnt_old = ext->point_cnt;
|
||||
uint16_t i;
|
||||
lv_coord_t def = LV_CHART_POINT_DEF;
|
||||
|
||||
if(point_cnt < 1) point_cnt = 1;
|
||||
|
||||
LL_READ_BACK(ext->series_ll, ser) {
|
||||
if(ser->start_point != 0) {
|
||||
lv_coord_t * new_points = lv_mem_alloc(sizeof(lv_coord_t) * point_cnt);
|
||||
lv_mem_assert(new_points);
|
||||
if(new_points == NULL) return;
|
||||
|
||||
if(point_cnt >= point_cnt_old) {
|
||||
for(i = 0; i < point_cnt_old; i++) {
|
||||
new_points[i] = ser->points[(i + ser->start_point) % point_cnt_old]; /*Copy old contents to new array*/
|
||||
}
|
||||
for(i = point_cnt_old; i < point_cnt; i++) {
|
||||
new_points[i] = def; /*Fill up the rest with default value*/
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < point_cnt; i++) {
|
||||
new_points[i] = ser->points[(i + ser->start_point) % point_cnt_old]; /*Copy old contents to new array*/
|
||||
}
|
||||
}
|
||||
|
||||
/*Switch over pointer from old to new*/
|
||||
lv_mem_free(ser->points);
|
||||
ser->points = new_points;
|
||||
} else {
|
||||
ser->points = lv_mem_realloc(ser->points, sizeof(lv_coord_t) * point_cnt);
|
||||
lv_mem_assert(ser->points);
|
||||
if(ser->points == NULL) return;
|
||||
/*Initialize the new points*/
|
||||
if(point_cnt > point_cnt_old) {
|
||||
for(i = point_cnt_old - 1; i < point_cnt; i++) {
|
||||
ser->points[i] = def;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ser->start_point = 0;
|
||||
}
|
||||
|
||||
ext->point_cnt = point_cnt;
|
||||
|
||||
lv_chart_refresh(chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the opacity of the data series
|
||||
* @param chart pointer to a chart object
|
||||
* @param opa opacity of the data series
|
||||
*/
|
||||
void lv_chart_set_series_opa(lv_obj_t * chart, lv_opa_t opa)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->series.opa == opa) return;
|
||||
|
||||
ext->series.opa = opa;
|
||||
lv_obj_invalidate(chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the line width or point radius of the data series
|
||||
* @param chart pointer to a chart object
|
||||
* @param width the new width
|
||||
*/
|
||||
void lv_chart_set_series_width(lv_obj_t * chart, lv_coord_t width)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->series.width == width) return;
|
||||
|
||||
ext->series.width = width;
|
||||
lv_obj_invalidate(chart);
|
||||
}
|
||||
/**
|
||||
* Set the dark effect on the bottom of the points or columns
|
||||
* @param chart pointer to a chart object
|
||||
* @param dark_eff dark effect level (LV_OPA_TRANSP to turn off)
|
||||
*/
|
||||
void lv_chart_set_series_darking(lv_obj_t * chart, lv_opa_t dark_eff)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
if(ext->series.dark == dark_eff) return;
|
||||
|
||||
ext->series.dark = dark_eff;
|
||||
lv_obj_invalidate(chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all data points with a value
|
||||
* @param chart pointer to chart object
|
||||
* @param ser pointer to a data series on 'chart'
|
||||
* @param y the new value for all points
|
||||
*/
|
||||
void lv_chart_init_points(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
uint16_t i;
|
||||
for(i = 0; i < ext->point_cnt; i++) {
|
||||
ser->points[i] = y;
|
||||
}
|
||||
ser->start_point = 0;
|
||||
lv_chart_refresh(chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value s of points from an array
|
||||
* @param chart pointer to chart object
|
||||
* @param ser pointer to a data series on 'chart'
|
||||
* @param y_array array of 'lv_coord_t' points (with 'points count' elements )
|
||||
*/
|
||||
void lv_chart_set_points(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t * y_array)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
memcpy(ser->points, y_array, ext->point_cnt * (sizeof(lv_coord_t)));
|
||||
ser->start_point = 0;
|
||||
lv_chart_refresh(chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift all data left and set the rightmost data on a data line
|
||||
* @param chart pointer to chart object
|
||||
* @param ser pointer to a data series on 'chart'
|
||||
* @param y the new value of the rightmost data
|
||||
*/
|
||||
void lv_chart_set_next(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
|
||||
ser->points[ser->start_point] = y; /*This was the place of the former left most value, after shifting it is the rightmost*/
|
||||
ser->start_point = (ser->start_point + 1) % ext->point_cnt;
|
||||
|
||||
lv_chart_refresh(chart);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the type of a chart
|
||||
* @param chart pointer to chart object
|
||||
* @return type of the chart (from 'lv_chart_t' enum)
|
||||
*/
|
||||
lv_chart_type_t lv_chart_get_type(const lv_obj_t * chart)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
return ext->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data point number per data line on chart
|
||||
* @param chart pointer to chart object
|
||||
* @return point number on each data line
|
||||
*/
|
||||
uint16_t lv_chart_get_point_cnt(const lv_obj_t * chart)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
return ext->point_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the opacity of the data series
|
||||
* @param chart pointer to chart object
|
||||
* @return the opacity of the data series
|
||||
*/
|
||||
lv_opa_t lv_chart_get_series_opa(const lv_obj_t * chart)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
return ext->series.opa;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data series width
|
||||
* @param chart pointer to chart object
|
||||
* @return the width the data series (lines or points)
|
||||
*/
|
||||
lv_coord_t lv_chart_get_series_width(const lv_obj_t * chart)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
return ext->series.width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dark effect level on the bottom of the points or columns
|
||||
* @param chart pointer to chart object
|
||||
* @return dark effect level (LV_OPA_TRANSP to turn off)
|
||||
*/
|
||||
lv_opa_t lv_chart_get_series_darking(const lv_obj_t * chart)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
return ext->series.dark;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Refresh a chart if its data line has changed
|
||||
* @param chart pointer to chart object
|
||||
*/
|
||||
void lv_chart_refresh(lv_obj_t * chart)
|
||||
{
|
||||
lv_obj_invalidate(chart);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the chart backgrounds
|
||||
* @param chart pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_chart_design(lv_obj_t * chart, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
return ancestor_design_f(chart, mask, mode);
|
||||
} else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
/*Draw the background*/
|
||||
lv_draw_rect(&chart->coords, mask, lv_obj_get_style(chart), lv_obj_get_opa_scale(chart));
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
|
||||
lv_chart_draw_div(chart, mask);
|
||||
|
||||
if(ext->type & LV_CHART_TYPE_LINE) lv_chart_draw_lines(chart, mask);
|
||||
if(ext->type & LV_CHART_TYPE_COLUMN) lv_chart_draw_cols(chart, mask);
|
||||
if(ext->type & LV_CHART_TYPE_POINT) lv_chart_draw_points(chart, mask);
|
||||
if(ext->type & LV_CHART_TYPE_VERTICAL_LINE) lv_chart_draw_vertical_lines(chart, mask);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the chart background
|
||||
* @param chart pointer to a chart background object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
*/
|
||||
static lv_res_t lv_chart_signal(lv_obj_t * chart, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(chart, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
lv_coord_t ** datal;
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
LL_READ(ext->series_ll, datal) {
|
||||
lv_mem_free(*datal);
|
||||
}
|
||||
lv_ll_clear(&ext->series_ll);
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_chart";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the division lines on chart background
|
||||
* @param chart pointer to chart object
|
||||
* @param mask mask, inherited from the design function
|
||||
*/
|
||||
static void lv_chart_draw_div(lv_obj_t * chart, const lv_area_t * mask)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
lv_style_t * style = lv_obj_get_style(chart);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(chart);
|
||||
|
||||
uint8_t div_i;
|
||||
uint8_t div_i_end;
|
||||
uint8_t div_i_start;
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
lv_coord_t w = lv_obj_get_width(chart);
|
||||
lv_coord_t h = lv_obj_get_height(chart);
|
||||
lv_coord_t x_ofs = chart->coords.x1;
|
||||
lv_coord_t y_ofs = chart->coords.y1;
|
||||
|
||||
if(ext->hdiv_cnt != 0) {
|
||||
/*Draw slide lines if no border*/
|
||||
if(style->body.border.width != 0) {
|
||||
div_i_start = 1;
|
||||
div_i_end = ext->hdiv_cnt;
|
||||
} else {
|
||||
div_i_start = 0;
|
||||
div_i_end = ext->hdiv_cnt + 1;
|
||||
}
|
||||
|
||||
p1.x = 0 + x_ofs;
|
||||
p2.x = w + x_ofs;
|
||||
for(div_i = div_i_start; div_i <= div_i_end; div_i++) {
|
||||
p1.y = (int32_t)((int32_t)h * div_i) / (ext->hdiv_cnt + 1);
|
||||
p1.y += y_ofs;
|
||||
if(div_i == div_i_start) p1.y += (style->line.width >> 1) + 1; /*The first line might not be visible*/
|
||||
if(div_i == div_i_end) p1.y -= (style->line.width >> 1) + 1; /*The last line might not be visible*/
|
||||
|
||||
p2.y = p1.y;
|
||||
lv_draw_line(&p1, &p2, mask, style, opa_scale);
|
||||
}
|
||||
}
|
||||
|
||||
if(ext->vdiv_cnt != 0) {
|
||||
/*Draw slide lines if no border*/
|
||||
if(style->body.border.width != 0) {
|
||||
div_i_start = 1;
|
||||
div_i_end = ext->vdiv_cnt;
|
||||
} else {
|
||||
div_i_start = 0;
|
||||
div_i_end = ext->vdiv_cnt + 1;
|
||||
}
|
||||
|
||||
p1.y = 0 + y_ofs;
|
||||
p2.y = h + y_ofs;
|
||||
for(div_i = div_i_start; div_i <= div_i_end; div_i ++) {
|
||||
p1.x = (int32_t)((int32_t)w * div_i) / (ext->vdiv_cnt + 1);
|
||||
p1.x += x_ofs;
|
||||
if(div_i == div_i_start) p1.x += (style->line.width >> 1) + 1; /*The first line might not be visible*/
|
||||
if(div_i == div_i_end) p1.x -= (style->line.width >> 1) + 1; /*The last line might not be visible*/
|
||||
p2.x = p1.x;
|
||||
lv_draw_line(&p1, &p2, mask, style, opa_scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the data lines as lines on a chart
|
||||
* @param obj pointer to chart object
|
||||
*/
|
||||
static void lv_chart_draw_lines(lv_obj_t * chart, const lv_area_t * mask)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
|
||||
uint16_t i;
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
lv_coord_t w = lv_obj_get_width(chart);
|
||||
lv_coord_t h = lv_obj_get_height(chart);
|
||||
lv_coord_t x_ofs = chart->coords.x1;
|
||||
lv_coord_t y_ofs = chart->coords.y1;
|
||||
int32_t y_tmp;
|
||||
lv_coord_t p_prev;
|
||||
lv_coord_t p_act;
|
||||
lv_chart_series_t * ser;
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(chart);
|
||||
lv_style_t style;
|
||||
lv_style_copy(&style, &lv_style_plain);
|
||||
style.line.opa = ext->series.opa;
|
||||
style.line.width = ext->series.width;
|
||||
|
||||
/*Go through all data lines*/
|
||||
LL_READ_BACK(ext->series_ll, ser) {
|
||||
style.line.color = ser->color;
|
||||
|
||||
p1.x = 0 + x_ofs;
|
||||
p2.x = 0 + x_ofs;
|
||||
|
||||
p_prev = ser->start_point;
|
||||
y_tmp = (int32_t)((int32_t) ser->points[p_prev] - ext->ymin) * h;
|
||||
y_tmp = y_tmp / (ext->ymax - ext->ymin);
|
||||
p2.y = h - y_tmp + y_ofs;
|
||||
|
||||
for(i = 1; i < ext->point_cnt; i ++) {
|
||||
p1.x = p2.x;
|
||||
p1.y = p2.y;
|
||||
|
||||
p2.x = ((w * i) / (ext->point_cnt - 1)) + x_ofs;
|
||||
|
||||
p_act = (ser->start_point + i) % ext->point_cnt;
|
||||
|
||||
y_tmp = (int32_t)((int32_t) ser->points[p_act] - ext->ymin) * h;
|
||||
y_tmp = y_tmp / (ext->ymax - ext->ymin);
|
||||
p2.y = h - y_tmp + y_ofs;
|
||||
|
||||
if(ser->points[p_prev] != LV_CHART_POINT_DEF && ser->points[p_act] != LV_CHART_POINT_DEF)
|
||||
lv_draw_line(&p1, &p2, mask, &style, opa_scale);
|
||||
|
||||
p_prev = p_act;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the data lines as points on a chart
|
||||
* @param chart pointer to chart object
|
||||
* @param mask mask, inherited from the design function
|
||||
*/
|
||||
static void lv_chart_draw_points(lv_obj_t * chart, const lv_area_t * mask)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
|
||||
uint16_t i;
|
||||
lv_area_t cir_a;
|
||||
lv_coord_t w = lv_obj_get_width(chart);
|
||||
lv_coord_t h = lv_obj_get_height(chart);
|
||||
lv_coord_t x_ofs = chart->coords.x1;
|
||||
lv_coord_t y_ofs = chart->coords.y1;
|
||||
int32_t y_tmp;
|
||||
lv_coord_t p_act;
|
||||
lv_chart_series_t * ser;
|
||||
uint8_t series_cnt = 0;
|
||||
lv_style_t style_point;
|
||||
lv_style_copy(&style_point, &lv_style_plain);
|
||||
|
||||
style_point.body.border.width = 0;
|
||||
style_point.body.empty = 0;
|
||||
style_point.body.radius = LV_RADIUS_CIRCLE;
|
||||
style_point.body.opa = ext->series.opa;
|
||||
style_point.body.radius = ext->series.width;
|
||||
|
||||
/*Go through all data lines*/
|
||||
LL_READ_BACK(ext->series_ll, ser) {
|
||||
style_point.body.main_color = ser->color;
|
||||
style_point.body.grad_color = lv_color_mix(LV_COLOR_BLACK, ser->color, ext->series.dark);
|
||||
|
||||
for(i = 0; i < ext->point_cnt; i ++) {
|
||||
cir_a.x1 = ((w * i) / (ext->point_cnt - 1)) + x_ofs;
|
||||
cir_a.x2 = cir_a.x1 + style_point.body.radius;
|
||||
cir_a.x1 -= style_point.body.radius;
|
||||
p_act = (ser->start_point + i) % ext->point_cnt;
|
||||
y_tmp = (int32_t)((int32_t) ser->points[p_act] - ext->ymin) * h;
|
||||
y_tmp = y_tmp / (ext->ymax - ext->ymin);
|
||||
cir_a.y1 = h - y_tmp + y_ofs;
|
||||
cir_a.y2 = cir_a.y1 + style_point.body.radius;
|
||||
cir_a.y1 -= style_point.body.radius;
|
||||
|
||||
if(ser->points[p_act] != LV_CHART_POINT_DEF)
|
||||
lv_draw_rect(&cir_a, mask, &style_point, lv_obj_get_opa_scale(chart));
|
||||
}
|
||||
series_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the data lines as columns on a chart
|
||||
* @param chart pointer to chart object
|
||||
* @param mask mask, inherited from the design function
|
||||
*/
|
||||
static void lv_chart_draw_cols(lv_obj_t * chart, const lv_area_t * mask)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
|
||||
uint16_t i;
|
||||
lv_area_t col_a;
|
||||
lv_area_t col_mask;
|
||||
bool mask_ret;
|
||||
lv_coord_t w = lv_obj_get_width(chart);
|
||||
lv_coord_t h = lv_obj_get_height(chart);
|
||||
int32_t y_tmp;
|
||||
lv_chart_series_t * ser;
|
||||
lv_style_t rects;
|
||||
lv_coord_t col_w = w / ((ext->series.num + 1) * ext->point_cnt); /* Suppose + 1 series as separator*/
|
||||
lv_coord_t x_ofs = col_w / 2; /*Shift with a half col.*/
|
||||
|
||||
lv_style_copy(&rects, &lv_style_plain);
|
||||
rects.body.border.width = 0;
|
||||
rects.body.empty = 0;
|
||||
rects.body.radius = 0;
|
||||
rects.body.opa = ext->series.opa;
|
||||
|
||||
col_a.y2 = chart->coords.y2;
|
||||
|
||||
lv_coord_t x_act;
|
||||
|
||||
/*Go through all points*/
|
||||
for(i = 0; i < ext->point_cnt; i ++) {
|
||||
x_act = (int32_t)((int32_t) w * i) / ext->point_cnt;
|
||||
x_act += chart->coords.x1 + x_ofs;
|
||||
|
||||
/*Draw the current point of all data line*/
|
||||
LL_READ_BACK(ext->series_ll, ser) {
|
||||
rects.body.main_color = ser->color;
|
||||
rects.body.grad_color = lv_color_mix(LV_COLOR_BLACK, ser->color, ext->series.dark);
|
||||
col_a.x1 = x_act;
|
||||
col_a.x2 = col_a.x1 + col_w;
|
||||
x_act += col_w;
|
||||
|
||||
lv_coord_t p_act = (ser->start_point + i) % ext->point_cnt;
|
||||
y_tmp = (int32_t)((int32_t) ser->points[p_act] - ext->ymin) * h;
|
||||
y_tmp = y_tmp / (ext->ymax - ext->ymin);
|
||||
col_a.y1 = h - y_tmp + chart->coords.y1;
|
||||
|
||||
mask_ret = lv_area_intersect(&col_mask, mask, &col_a);
|
||||
if(mask_ret != false && ser->points[p_act] != LV_CHART_POINT_DEF) {
|
||||
lv_draw_rect(&chart->coords, &col_mask, &rects, lv_obj_get_opa_scale(chart));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the data lines as vertical lines on a chart if there is only 1px between point
|
||||
* @param obj pointer to chart object
|
||||
*/
|
||||
static void lv_chart_draw_vertical_lines(lv_obj_t * chart, const lv_area_t * mask)
|
||||
{
|
||||
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
lv_coord_t w = lv_obj_get_width(chart);
|
||||
/*Vertical lines works only if the width == point count. Else use the normal line type*/
|
||||
if(ext->point_cnt != w) {
|
||||
lv_chart_draw_lines(chart, mask);
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t i;
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
lv_coord_t h = lv_obj_get_height(chart);
|
||||
lv_coord_t x_ofs = chart->coords.x1;
|
||||
lv_coord_t y_ofs = chart->coords.y1;
|
||||
int32_t y_tmp;
|
||||
lv_chart_series_t * ser;
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(chart);
|
||||
lv_style_t style;
|
||||
lv_style_copy(&style, &lv_style_plain);
|
||||
style.line.opa = ext->series.opa;
|
||||
style.line.width = ext->series.width;
|
||||
|
||||
/*Go through all data lines*/
|
||||
LL_READ_BACK(ext->series_ll, ser) {
|
||||
style.line.color = ser->color;
|
||||
|
||||
p1.x = 0 + x_ofs;
|
||||
p2.x = 0 + x_ofs;
|
||||
y_tmp = (int32_t)((int32_t) ser->points[0] - ext->ymin) * h;
|
||||
y_tmp = y_tmp / (ext->ymax - ext->ymin);
|
||||
p2.y = h - y_tmp + y_ofs;
|
||||
p1.y = p2.y;
|
||||
|
||||
for(i = 0; i < ext->point_cnt; i++)
|
||||
{
|
||||
|
||||
y_tmp = (int32_t)((int32_t) ser->points[i] - ext->ymin) * h;
|
||||
y_tmp = y_tmp / (ext->ymax - ext->ymin);
|
||||
p2.y = h - y_tmp + y_ofs;
|
||||
|
||||
if(p1.y == p2.y)
|
||||
{
|
||||
p2.x++;
|
||||
}
|
||||
|
||||
if(ser->points[i] != LV_CHART_POINT_DEF) {
|
||||
lv_draw_line(&p1, &p2, mask, &style, opa_scale);
|
||||
}
|
||||
|
||||
p2.x = ((w * i) / (ext->point_cnt - 1)) + x_ofs;
|
||||
p1.x = p2.x;
|
||||
p1.y = p2.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
262
bdk/libs/lvgl/lv_objx/lv_chart.h
Normal file
262
bdk/libs/lvgl/lv_objx/lv_chart.h
Normal file
|
@ -0,0 +1,262 @@
|
|||
/**
|
||||
* @file lv_chart.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_CHART_H
|
||||
#define LV_CHART_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_CHART != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_line.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_CHART_POINT_DEF (LV_COORD_MIN)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct
|
||||
{
|
||||
lv_coord_t * points;
|
||||
lv_color_t color;
|
||||
uint16_t start_point;
|
||||
} lv_chart_series_t;
|
||||
|
||||
/*Data of chart */
|
||||
typedef struct
|
||||
{
|
||||
/*No inherited ext*/ /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_ll_t series_ll; /*Linked list for the data line pointers (stores lv_chart_dl_t)*/
|
||||
lv_coord_t ymin; /*y min value (used to scale the data)*/
|
||||
lv_coord_t ymax; /*y max value (used to scale the data)*/
|
||||
uint8_t hdiv_cnt; /*Number of horizontal division lines*/
|
||||
uint8_t vdiv_cnt; /*Number of vertical division lines*/
|
||||
uint16_t point_cnt; /*Point number in a data line*/
|
||||
uint8_t type :4; /*Line, column or point chart (from 'lv_chart_type_t')*/
|
||||
struct {
|
||||
lv_coord_t width; /*Line width or point radius*/
|
||||
uint8_t num; /*Number of data lines in dl_ll*/
|
||||
lv_opa_t opa; /*Opacity of data lines*/
|
||||
lv_opa_t dark; /*Dark level of the point/column bottoms*/
|
||||
} series;
|
||||
} lv_chart_ext_t;
|
||||
|
||||
/*Chart types*/
|
||||
enum
|
||||
{
|
||||
LV_CHART_TYPE_LINE = 0x01, /*Connect the points with lines*/
|
||||
LV_CHART_TYPE_COLUMN = 0x02, /*Draw columns*/
|
||||
LV_CHART_TYPE_POINT = 0x04, /*Draw circles on the points*/
|
||||
LV_CHART_TYPE_VERTICAL_LINE = 0x08, /*Draw vertical lines on points (useful when chart width == point count)*/
|
||||
};
|
||||
typedef uint8_t lv_chart_type_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a chart background objects
|
||||
* @param par pointer to an object, it will be the parent of the new chart background
|
||||
* @param copy pointer to a chart background object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created chart background
|
||||
*/
|
||||
lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Allocate and add a data series to the chart
|
||||
* @param chart pointer to a chart object
|
||||
* @param color color of the data series
|
||||
* @return pointer to the allocated data series
|
||||
*/
|
||||
lv_chart_series_t * lv_chart_add_series(lv_obj_t * chart, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Clear the point of a serie
|
||||
* @param chart pointer to a chart object
|
||||
* @param serie pointer to the chart's serie to clear
|
||||
*/
|
||||
void lv_chart_clear_serie(lv_obj_t * chart, lv_chart_series_t * serie);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the number of horizontal and vertical division lines
|
||||
* @param chart pointer to a graph background object
|
||||
* @param hdiv number of horizontal division lines
|
||||
* @param vdiv number of vertical division lines
|
||||
*/
|
||||
void lv_chart_set_div_line_count(lv_obj_t * chart, uint8_t hdiv, uint8_t vdiv);
|
||||
|
||||
/**
|
||||
* Set the minimal and maximal y values
|
||||
* @param chart pointer to a graph background object
|
||||
* @param ymin y minimum value
|
||||
* @param ymax y maximum value
|
||||
*/
|
||||
void lv_chart_set_range(lv_obj_t * chart, lv_coord_t ymin, lv_coord_t ymax);
|
||||
|
||||
/**
|
||||
* Set a new type for a chart
|
||||
* @param chart pointer to a chart object
|
||||
* @param type new type of the chart (from 'lv_chart_type_t' enum)
|
||||
*/
|
||||
void lv_chart_set_type(lv_obj_t * chart, lv_chart_type_t type);
|
||||
|
||||
/**
|
||||
* Set the number of points on a data line on a chart
|
||||
* @param chart pointer r to chart object
|
||||
* @param point_cnt new number of points on the data lines
|
||||
*/
|
||||
void lv_chart_set_point_count(lv_obj_t * chart, uint16_t point_cnt);
|
||||
|
||||
/**
|
||||
* Set the opacity of the data series
|
||||
* @param chart pointer to a chart object
|
||||
* @param opa opacity of the data series
|
||||
*/
|
||||
void lv_chart_set_series_opa(lv_obj_t * chart, lv_opa_t opa);
|
||||
|
||||
/**
|
||||
* Set the line width or point radius of the data series
|
||||
* @param chart pointer to a chart object
|
||||
* @param width the new width
|
||||
*/
|
||||
void lv_chart_set_series_width(lv_obj_t * chart, lv_coord_t width);
|
||||
|
||||
/**
|
||||
* Set the dark effect on the bottom of the points or columns
|
||||
* @param chart pointer to a chart object
|
||||
* @param dark_eff dark effect level (LV_OPA_TRANSP to turn off)
|
||||
*/
|
||||
void lv_chart_set_series_darking(lv_obj_t * chart, lv_opa_t dark_eff);
|
||||
|
||||
/**
|
||||
* Initialize all data points with a value
|
||||
* @param chart pointer to chart object
|
||||
* @param ser pointer to a data series on 'chart'
|
||||
* @param y the new value for all points
|
||||
*/
|
||||
void lv_chart_init_points(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y);
|
||||
|
||||
/**
|
||||
* Set the value s of points from an array
|
||||
* @param chart pointer to chart object
|
||||
* @param ser pointer to a data series on 'chart'
|
||||
* @param y_array array of 'lv_coord_t' points (with 'points count' elements )
|
||||
*/
|
||||
void lv_chart_set_points(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t * y_array);
|
||||
|
||||
/**
|
||||
* Shift all data right and set the most right data on a data line
|
||||
* @param chart pointer to chart object
|
||||
* @param ser pointer to a data series on 'chart'
|
||||
* @param y the new value of the most right data
|
||||
*/
|
||||
void lv_chart_set_next(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y);
|
||||
|
||||
/**
|
||||
* Set the style of a chart
|
||||
* @param chart pointer to a chart object
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
static inline void lv_chart_set_style(lv_obj_t *chart, lv_style_t *style)
|
||||
{
|
||||
lv_obj_set_style(chart, style);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the type of a chart
|
||||
* @param chart pointer to chart object
|
||||
* @return type of the chart (from 'lv_chart_t' enum)
|
||||
*/
|
||||
lv_chart_type_t lv_chart_get_type(const lv_obj_t * chart);
|
||||
|
||||
/**
|
||||
* Get the data point number per data line on chart
|
||||
* @param chart pointer to chart object
|
||||
* @return point number on each data line
|
||||
*/
|
||||
uint16_t lv_chart_get_point_cnt(const lv_obj_t * chart);
|
||||
|
||||
/**
|
||||
* Get the opacity of the data series
|
||||
* @param chart pointer to chart object
|
||||
* @return the opacity of the data series
|
||||
*/
|
||||
lv_opa_t lv_chart_get_series_opa(const lv_obj_t * chart);
|
||||
|
||||
/**
|
||||
* Get the data series width
|
||||
* @param chart pointer to chart object
|
||||
* @return the width the data series (lines or points)
|
||||
*/
|
||||
lv_coord_t lv_chart_get_series_width(const lv_obj_t * chart);
|
||||
|
||||
/**
|
||||
* Get the dark effect level on the bottom of the points or columns
|
||||
* @param chart pointer to chart object
|
||||
* @return dark effect level (LV_OPA_TRANSP to turn off)
|
||||
*/
|
||||
lv_opa_t lv_chart_get_series_darking(const lv_obj_t * chart);
|
||||
|
||||
/**
|
||||
* Get the style of an chart object
|
||||
* @param chart pointer to an chart object
|
||||
* @return pointer to the chart's style
|
||||
*/
|
||||
static inline lv_style_t* lv_chart_get_style(const lv_obj_t *chart)
|
||||
{
|
||||
return lv_obj_get_style(chart);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Refresh a chart if its data line has changed
|
||||
* @param chart pointer to chart object
|
||||
*/
|
||||
void lv_chart_refresh(lv_obj_t * chart);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_CHART*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_CHART_H*/
|
642
bdk/libs/lvgl/lv_objx/lv_cont.c
Normal file
642
bdk/libs/lvgl/lv_objx/lv_cont.c
Normal file
|
@ -0,0 +1,642 @@
|
|||
/**
|
||||
* @file lv_cont.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_cont.h"
|
||||
#if USE_LV_CONT != 0
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_draw/lv_draw_vbasic.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_area.h"
|
||||
#include "../lv_misc/lv_color.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_cont_signal(lv_obj_t * cont, lv_signal_t sign, void * param);
|
||||
static void lv_cont_refr_layout(lv_obj_t * cont);
|
||||
static void lv_cont_layout_col(lv_obj_t * cont);
|
||||
static void lv_cont_layout_row(lv_obj_t * cont);
|
||||
static void lv_cont_layout_center(lv_obj_t * cont);
|
||||
static void lv_cont_layout_pretty(lv_obj_t * cont);
|
||||
static void lv_cont_layout_grid(lv_obj_t * cont);
|
||||
static void lv_cont_refr_autofit(lv_obj_t * cont);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a container objects
|
||||
* @param par pointer to an object, it will be the parent of the new container
|
||||
* @param copy pointer to a container object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created container
|
||||
*/
|
||||
lv_obj_t * lv_cont_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
|
||||
|
||||
LV_LOG_TRACE("container create started");
|
||||
|
||||
/*Create a basic object*/
|
||||
lv_obj_t * new_cont = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_cont);
|
||||
if(new_cont == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_cont);
|
||||
|
||||
lv_obj_allocate_ext_attr(new_cont, sizeof(lv_cont_ext_t));
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(new_cont);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
lv_mem_assert(ext);
|
||||
ext->hor_fit = 0;
|
||||
ext->ver_fit = 0;
|
||||
ext->layout = LV_LAYOUT_OFF;
|
||||
|
||||
lv_obj_set_signal_func(new_cont, lv_cont_signal);
|
||||
|
||||
/*Init the new container*/
|
||||
if(copy == NULL) {
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_cont_set_style(new_cont, th->cont);
|
||||
} else {
|
||||
lv_cont_set_style(new_cont, &lv_style_pretty);
|
||||
}
|
||||
}
|
||||
/*Copy an existing object*/
|
||||
else {
|
||||
lv_cont_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->hor_fit = copy_ext->hor_fit;
|
||||
ext->ver_fit = copy_ext->ver_fit;
|
||||
ext->layout = copy_ext->layout;
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_cont);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("container created");
|
||||
|
||||
|
||||
return new_cont;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a layout on a container
|
||||
* @param cont pointer to a container object
|
||||
* @param layout a layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
void lv_cont_set_layout(lv_obj_t * cont, lv_layout_t layout)
|
||||
{
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
if(ext->layout == layout) return;
|
||||
|
||||
ext->layout = layout;
|
||||
|
||||
/*Send a signal to refresh the layout*/
|
||||
cont->signal_func(cont, LV_SIGNAL_CHILD_CHG, NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable the horizontal or vertical fit.
|
||||
* The container size will be set to involve the children horizontally or vertically.
|
||||
* @param cont pointer to a container object
|
||||
* @param hor_en true: enable the horizontal fit
|
||||
* @param ver_en true: enable the vertical fit
|
||||
*/
|
||||
void lv_cont_set_fit(lv_obj_t * cont, bool hor_en, bool ver_en)
|
||||
{
|
||||
lv_obj_invalidate(cont);
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
if(ext->hor_fit == hor_en && ext->ver_fit == ver_en) return;
|
||||
|
||||
ext->hor_fit = hor_en == false ? 0 : 1;
|
||||
ext->ver_fit = ver_en == false ? 0 : 1;
|
||||
|
||||
/*Send a signal to refresh the layout*/
|
||||
cont->signal_func(cont, LV_SIGNAL_CHILD_CHG, NULL);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the layout of a container
|
||||
* @param cont pointer to container object
|
||||
* @return the layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
lv_layout_t lv_cont_get_layout(const lv_obj_t * cont)
|
||||
{
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get horizontal fit enable attribute of a container
|
||||
* @param cont pointer to a container object
|
||||
* @return true: horizontal fit is enabled; false: disabled
|
||||
*/
|
||||
bool lv_cont_get_hor_fit(const lv_obj_t * cont)
|
||||
{
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->hor_fit == 0 ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get vertical fit enable attribute of a container
|
||||
* @param cont pointer to a container object
|
||||
* @return true: vertical fit is enabled; false: disabled
|
||||
*/
|
||||
bool lv_cont_get_ver_fit(const lv_obj_t * cont)
|
||||
{
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
return ext->ver_fit == 0 ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get that width reduced by the horizontal padding. Useful if a layout is used.
|
||||
* @param cont pointer to a container object
|
||||
* @return the width which still fits into the container
|
||||
*/
|
||||
lv_coord_t lv_cont_get_fit_width(lv_obj_t * cont)
|
||||
{
|
||||
lv_style_t * style = lv_cont_get_style(cont);
|
||||
|
||||
return lv_obj_get_width(cont) - 2 * style->body.padding.hor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get that height reduced by the vertical padding. Useful if a layout is used.
|
||||
* @param cont pointer to a container object
|
||||
* @return the height which still fits into the container
|
||||
*/
|
||||
lv_coord_t lv_cont_get_fit_height(lv_obj_t * cont)
|
||||
{
|
||||
lv_style_t * style = lv_cont_get_style(cont);
|
||||
|
||||
return lv_obj_get_height(cont) - 2 * style->body.padding.ver;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the container
|
||||
* @param cont pointer to a container object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_cont_signal(lv_obj_t * cont, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(cont, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
if(sign == LV_SIGNAL_STYLE_CHG) { /*Recalculate the padding if the style changed*/
|
||||
lv_cont_refr_layout(cont);
|
||||
lv_cont_refr_autofit(cont);
|
||||
} else if(sign == LV_SIGNAL_CHILD_CHG) {
|
||||
lv_cont_refr_layout(cont);
|
||||
lv_cont_refr_autofit(cont);
|
||||
} else if(sign == LV_SIGNAL_CORD_CHG) {
|
||||
if(lv_obj_get_width(cont) != lv_area_get_width(param) ||
|
||||
lv_obj_get_height(cont) != lv_area_get_height(param)) {
|
||||
lv_cont_refr_layout(cont);
|
||||
lv_cont_refr_autofit(cont);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_cont";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Refresh the layout of a container
|
||||
* @param cont pointer to an object which layout should be refreshed
|
||||
*/
|
||||
static void lv_cont_refr_layout(lv_obj_t * cont)
|
||||
{
|
||||
lv_layout_t type = lv_cont_get_layout(cont);
|
||||
|
||||
/*'cont' has to be at least 1 child*/
|
||||
if(lv_obj_get_child(cont, NULL) == NULL) return;
|
||||
|
||||
if(type == LV_LAYOUT_OFF) return;
|
||||
|
||||
if(type == LV_LAYOUT_CENTER) {
|
||||
lv_cont_layout_center(cont);
|
||||
} else if(type == LV_LAYOUT_COL_L || type == LV_LAYOUT_COL_M || type == LV_LAYOUT_COL_R) {
|
||||
lv_cont_layout_col(cont);
|
||||
} else if(type == LV_LAYOUT_ROW_T || type == LV_LAYOUT_ROW_M || type == LV_LAYOUT_ROW_B) {
|
||||
lv_cont_layout_row(cont);
|
||||
} else if(type == LV_LAYOUT_PRETTY) {
|
||||
lv_cont_layout_pretty(cont);
|
||||
} else if(type == LV_LAYOUT_GRID) {
|
||||
lv_cont_layout_grid(cont);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle column type layouts
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_col(lv_obj_t * cont)
|
||||
{
|
||||
lv_layout_t type = lv_cont_get_layout(cont);
|
||||
lv_obj_t * child;
|
||||
|
||||
/*Adjust margin and get the alignment type*/
|
||||
lv_align_t align;
|
||||
lv_style_t * style = lv_obj_get_style(cont);
|
||||
lv_coord_t hpad_corr;
|
||||
|
||||
switch(type) {
|
||||
case LV_LAYOUT_COL_L:
|
||||
hpad_corr = style->body.padding.hor;
|
||||
align = LV_ALIGN_IN_TOP_LEFT;
|
||||
break;
|
||||
case LV_LAYOUT_COL_M:
|
||||
hpad_corr = 0;
|
||||
align = LV_ALIGN_IN_TOP_MID;
|
||||
break;
|
||||
case LV_LAYOUT_COL_R:
|
||||
hpad_corr = -style->body.padding.hor;
|
||||
align = LV_ALIGN_IN_TOP_RIGHT;
|
||||
break;
|
||||
default:
|
||||
hpad_corr = 0;
|
||||
align = LV_ALIGN_IN_TOP_LEFT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
lv_obj_set_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
/* Align the children */
|
||||
lv_coord_t last_cord = style->body.padding.ver;
|
||||
LL_READ_BACK(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false ||
|
||||
lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
|
||||
lv_obj_align(child, cont, align, hpad_corr, last_cord);
|
||||
last_cord += lv_obj_get_height(child) + style->body.padding.inner;
|
||||
}
|
||||
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle row type layouts
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_row(lv_obj_t * cont)
|
||||
{
|
||||
lv_layout_t type = lv_cont_get_layout(cont);
|
||||
lv_obj_t * child;
|
||||
|
||||
/*Adjust margin and get the alignment type*/
|
||||
lv_align_t align;
|
||||
lv_style_t * style = lv_obj_get_style(cont);
|
||||
lv_coord_t vpad_corr = style->body.padding.ver;
|
||||
|
||||
switch(type) {
|
||||
case LV_LAYOUT_ROW_T:
|
||||
vpad_corr = style->body.padding.ver;
|
||||
align = LV_ALIGN_IN_TOP_LEFT;
|
||||
break;
|
||||
case LV_LAYOUT_ROW_M:
|
||||
vpad_corr = 0;
|
||||
align = LV_ALIGN_IN_LEFT_MID;
|
||||
break;
|
||||
case LV_LAYOUT_ROW_B:
|
||||
vpad_corr = -style->body.padding.ver;
|
||||
align = LV_ALIGN_IN_BOTTOM_LEFT;
|
||||
break;
|
||||
default:
|
||||
vpad_corr = 0;
|
||||
align = LV_ALIGN_IN_TOP_LEFT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
lv_obj_set_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
|
||||
/* Align the children */
|
||||
lv_coord_t last_cord = style->body.padding.hor;
|
||||
LL_READ_BACK(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false ||
|
||||
lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
|
||||
lv_obj_align(child, cont, align, last_cord, vpad_corr);
|
||||
last_cord += lv_obj_get_width(child) + style->body.padding.inner;
|
||||
}
|
||||
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the center layout
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_center(lv_obj_t * cont)
|
||||
{
|
||||
lv_obj_t * child;
|
||||
lv_style_t * style = lv_obj_get_style(cont);
|
||||
uint32_t obj_num = 0;
|
||||
lv_coord_t h_tot = 0;
|
||||
|
||||
LL_READ(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false ||
|
||||
lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
h_tot += lv_obj_get_height(child) + style->body.padding.inner;
|
||||
obj_num ++;
|
||||
}
|
||||
|
||||
if(obj_num == 0) return;
|
||||
|
||||
h_tot -= style->body.padding.inner;
|
||||
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
lv_obj_set_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
|
||||
/* Align the children */
|
||||
lv_coord_t last_cord = - (h_tot / 2);
|
||||
LL_READ_BACK(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false ||
|
||||
lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
|
||||
lv_obj_align(child, cont, LV_ALIGN_CENTER, 0, last_cord + lv_obj_get_height(child) / 2);
|
||||
last_cord += lv_obj_get_height(child) + style->body.padding.inner;
|
||||
}
|
||||
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the pretty layout. Put as many object as possible in row
|
||||
* then begin a new row
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_pretty(lv_obj_t * cont)
|
||||
{
|
||||
lv_obj_t * child_rs; /* Row starter child */
|
||||
lv_obj_t * child_rc; /* Row closer child */
|
||||
lv_obj_t * child_tmp; /* Temporary child */
|
||||
lv_style_t * style = lv_obj_get_style(cont);
|
||||
lv_coord_t w_obj = lv_obj_get_width(cont);
|
||||
lv_coord_t act_y = style->body.padding.ver;
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
|
||||
child_rs = lv_ll_get_tail(&cont->child_ll); /*Set the row starter child*/
|
||||
if(child_rs == NULL) return; /*Return if no child*/
|
||||
|
||||
lv_obj_set_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
|
||||
child_rc = child_rs; /*Initially the the row starter and closer is the same*/
|
||||
while(child_rs != NULL) {
|
||||
lv_coord_t h_row = 0;
|
||||
lv_coord_t w_row = style->body.padding.hor * 2; /*The width is at least the left+right hpad*/
|
||||
uint32_t obj_num = 0;
|
||||
|
||||
/*Find the row closer object and collect some data*/
|
||||
do {
|
||||
if(lv_obj_get_hidden(child_rc) == false &&
|
||||
lv_obj_is_protected(child_rc, LV_PROTECT_POS) == false) {
|
||||
/*If this object is already not fit then break*/
|
||||
if(w_row + lv_obj_get_width(child_rc) > w_obj) {
|
||||
/*Step back one child because the last already not fit, so the previous is the closer*/
|
||||
if(child_rc != NULL && obj_num != 0) {
|
||||
child_rc = lv_ll_get_next(&cont->child_ll, child_rc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
w_row += lv_obj_get_width(child_rc) + style->body.padding.inner; /*Add the object width + opad*/
|
||||
h_row = LV_MATH_MAX(h_row, lv_obj_get_height(child_rc)); /*Search the highest object*/
|
||||
obj_num ++;
|
||||
if(lv_obj_is_protected(child_rc, LV_PROTECT_FOLLOW)) break; /*If can not be followed by an other object then break here*/
|
||||
|
||||
}
|
||||
child_rc = lv_ll_get_prev(&cont->child_ll, child_rc); /*Load the next object*/
|
||||
if(obj_num == 0) child_rs = child_rc; /*If the first object was hidden (or too long) then set the next as first */
|
||||
} while(child_rc != NULL);
|
||||
|
||||
/*If the object is too long then align it to the middle*/
|
||||
if(obj_num == 0) {
|
||||
if(child_rc != NULL) {
|
||||
lv_obj_align(child_rc, cont, LV_ALIGN_IN_TOP_MID, 0, act_y);
|
||||
h_row = lv_obj_get_height(child_rc); /*Not set previously because of the early break*/
|
||||
}
|
||||
}
|
||||
/*If there is only one object in the row then align it to the middle*/
|
||||
else if(obj_num == 1) {
|
||||
lv_obj_align(child_rs, cont, LV_ALIGN_IN_TOP_MID, 0, act_y);
|
||||
}
|
||||
/*If there are two object in the row then align them proportionally*/
|
||||
else if(obj_num == 2) {
|
||||
lv_obj_t * obj1 = child_rs;
|
||||
lv_obj_t * obj2 = lv_ll_get_prev(&cont->child_ll, child_rs);
|
||||
w_row = lv_obj_get_width(obj1) + lv_obj_get_width(obj2);
|
||||
lv_coord_t pad = (w_obj - w_row) / 3;
|
||||
lv_obj_align(obj1, cont, LV_ALIGN_IN_TOP_LEFT, pad, act_y + (h_row - lv_obj_get_height(obj1)) / 2);
|
||||
lv_obj_align(obj2, cont, LV_ALIGN_IN_TOP_RIGHT, -pad, act_y + (h_row - lv_obj_get_height(obj2)) / 2);
|
||||
}
|
||||
/* Align the children (from child_rs to child_rc)*/
|
||||
else {
|
||||
w_row -= style->body.padding.inner * obj_num;
|
||||
lv_coord_t new_opad = (w_obj - w_row) / (obj_num - 1);
|
||||
lv_coord_t act_x = style->body.padding.hor; /*x init*/
|
||||
child_tmp = child_rs;
|
||||
while(child_tmp != NULL) {
|
||||
if(lv_obj_get_hidden(child_tmp) == false &&
|
||||
lv_obj_is_protected(child_tmp, LV_PROTECT_POS) == false) {
|
||||
lv_obj_align(child_tmp, cont, LV_ALIGN_IN_TOP_LEFT, act_x, act_y + (h_row - lv_obj_get_height(child_tmp)) / 2);
|
||||
act_x += lv_obj_get_width(child_tmp) + new_opad;
|
||||
}
|
||||
if(child_tmp == child_rc) break;
|
||||
child_tmp = lv_ll_get_prev(&cont->child_ll, child_tmp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(child_rc == NULL) break;
|
||||
act_y += style->body.padding.inner + h_row; /*y increment*/
|
||||
child_rs = lv_ll_get_prev(&cont->child_ll, child_rc); /*Go to the next object*/
|
||||
child_rc = child_rs;
|
||||
}
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the grid layout. Align same-sized objects in a grid
|
||||
* @param cont pointer to an object which layout should be handled
|
||||
*/
|
||||
static void lv_cont_layout_grid(lv_obj_t * cont)
|
||||
{
|
||||
lv_obj_t * child;
|
||||
lv_style_t * style = lv_obj_get_style(cont);
|
||||
lv_coord_t w_tot = lv_obj_get_width(cont);
|
||||
lv_coord_t w_obj = lv_obj_get_width(lv_obj_get_child(cont, NULL));
|
||||
lv_coord_t h_obj = lv_obj_get_height(lv_obj_get_child(cont, NULL));
|
||||
uint16_t obj_row = (w_tot - (2 * style->body.padding.hor)) / (w_obj + style->body.padding.inner); /*Obj. num. in a row*/
|
||||
lv_coord_t x_ofs;
|
||||
if(obj_row > 1) {
|
||||
x_ofs = w_obj + (w_tot - (2 * style->body.padding.hor) - (obj_row * w_obj)) / (obj_row - 1);
|
||||
} else {
|
||||
x_ofs = w_tot / 2 - w_obj / 2;
|
||||
}
|
||||
lv_coord_t y_ofs = h_obj + style->body.padding.inner;
|
||||
|
||||
/* Disable child change action because the children will be moved a lot
|
||||
* an unnecessary child change signals could be sent*/
|
||||
lv_obj_set_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
|
||||
/* Align the children */
|
||||
lv_coord_t act_x = style->body.padding.hor;
|
||||
lv_coord_t act_y = style->body.padding.ver;
|
||||
uint16_t obj_cnt = 0;
|
||||
LL_READ_BACK(cont->child_ll, child) {
|
||||
if(lv_obj_get_hidden(child) != false ||
|
||||
lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
|
||||
|
||||
if(obj_row > 1) {
|
||||
lv_obj_set_pos(child, act_x, act_y);
|
||||
act_x += x_ofs;
|
||||
} else {
|
||||
lv_obj_set_pos(child, x_ofs, act_y);
|
||||
}
|
||||
obj_cnt ++;
|
||||
|
||||
if(obj_cnt >= obj_row) {
|
||||
obj_cnt = 0;
|
||||
act_x = style->body.padding.hor;
|
||||
act_y += y_ofs;
|
||||
}
|
||||
}
|
||||
|
||||
lv_obj_clear_protect(cont, LV_PROTECT_CHILD_CHG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle auto fit. Set the size of the object to involve all children.
|
||||
* @param cont pointer to an object which size will be modified
|
||||
*/
|
||||
static void lv_cont_refr_autofit(lv_obj_t * cont)
|
||||
{
|
||||
lv_cont_ext_t * ext = lv_obj_get_ext_attr(cont);
|
||||
|
||||
if(ext->hor_fit == 0 &&
|
||||
ext->ver_fit == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_area_t new_cords;
|
||||
lv_area_t ori;
|
||||
lv_style_t * style = lv_obj_get_style(cont);
|
||||
lv_obj_t * i;
|
||||
lv_coord_t hpad = style->body.padding.hor;
|
||||
lv_coord_t vpad = style->body.padding.ver;
|
||||
|
||||
/*Search the side coordinates of the children*/
|
||||
lv_obj_get_coords(cont, &ori);
|
||||
lv_obj_get_coords(cont, &new_cords);
|
||||
|
||||
new_cords.x1 = LV_COORD_MAX;
|
||||
new_cords.y1 = LV_COORD_MAX;
|
||||
new_cords.x2 = LV_COORD_MIN;
|
||||
new_cords.y2 = LV_COORD_MIN;
|
||||
|
||||
LL_READ(cont->child_ll, i) {
|
||||
if(lv_obj_get_hidden(i) != false) continue;
|
||||
new_cords.x1 = LV_MATH_MIN(new_cords.x1, i->coords.x1);
|
||||
new_cords.y1 = LV_MATH_MIN(new_cords.y1, i->coords.y1);
|
||||
new_cords.x2 = LV_MATH_MAX(new_cords.x2, i->coords.x2);
|
||||
new_cords.y2 = LV_MATH_MAX(new_cords.y2, i->coords.y2);
|
||||
}
|
||||
|
||||
/*If the value is not the init value then the page has >=1 child.*/
|
||||
if(new_cords.x1 != LV_COORD_MAX) {
|
||||
if(ext->hor_fit != 0) {
|
||||
new_cords.x1 -= hpad;
|
||||
new_cords.x2 += hpad;
|
||||
} else {
|
||||
new_cords.x1 = cont->coords.x1;
|
||||
new_cords.x2 = cont->coords.x2;
|
||||
}
|
||||
if(ext->ver_fit != 0) {
|
||||
new_cords.y1 -= vpad;
|
||||
new_cords.y2 += vpad;
|
||||
} else {
|
||||
new_cords.y1 = cont->coords.y1;
|
||||
new_cords.y2 = cont->coords.y2;
|
||||
}
|
||||
|
||||
/*Do nothing if the coordinates are not changed*/
|
||||
if(cont->coords.x1 != new_cords.x1 ||
|
||||
cont->coords.y1 != new_cords.y1 ||
|
||||
cont->coords.x2 != new_cords.x2 ||
|
||||
cont->coords.y2 != new_cords.y2) {
|
||||
|
||||
lv_obj_invalidate(cont);
|
||||
lv_area_copy(&cont->coords, &new_cords);
|
||||
lv_obj_invalidate(cont);
|
||||
|
||||
/*Notify the object about its new coordinates*/
|
||||
cont->signal_func(cont, LV_SIGNAL_CORD_CHG, &ori);
|
||||
|
||||
/*Inform the parent about the new coordinates*/
|
||||
lv_obj_t * par = lv_obj_get_parent(cont);
|
||||
par->signal_func(par, LV_SIGNAL_CHILD_CHG, cont);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
163
bdk/libs/lvgl/lv_objx/lv_cont.h
Normal file
163
bdk/libs/lvgl/lv_objx/lv_cont.h
Normal file
|
@ -0,0 +1,163 @@
|
|||
/**
|
||||
* @file lv_cont.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_CONT_H
|
||||
#define LV_CONT_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_CONT != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Layout options*/
|
||||
enum
|
||||
{
|
||||
LV_LAYOUT_OFF = 0,
|
||||
LV_LAYOUT_CENTER,
|
||||
LV_LAYOUT_COL_L, /*Column left align*/
|
||||
LV_LAYOUT_COL_M, /*Column middle align*/
|
||||
LV_LAYOUT_COL_R, /*Column right align*/
|
||||
LV_LAYOUT_ROW_T, /*Row top align*/
|
||||
LV_LAYOUT_ROW_M, /*Row middle align*/
|
||||
LV_LAYOUT_ROW_B, /*Row bottom align*/
|
||||
LV_LAYOUT_PRETTY, /*Put as many object as possible in row and begin a new row*/
|
||||
LV_LAYOUT_GRID, /*Align same-sized object into a grid*/
|
||||
};
|
||||
typedef uint8_t lv_layout_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*Inherited from 'base_obj' so no inherited ext. */ /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
uint8_t layout :4; /*A layout from 'lv_cont_layout_t' enum*/
|
||||
uint8_t hor_fit :1; /*1: Enable horizontal fit to involve all children*/
|
||||
uint8_t ver_fit :1; /*1: Enable horizontal fit to involve all children*/
|
||||
} lv_cont_ext_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a container objects
|
||||
* @param par pointer to an object, it will be the parent of the new container
|
||||
* @param copy pointer to a container object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created container
|
||||
*/
|
||||
lv_obj_t * lv_cont_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a layout on a container
|
||||
* @param cont pointer to a container object
|
||||
* @param layout a layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
void lv_cont_set_layout(lv_obj_t * cont, lv_layout_t layout);
|
||||
|
||||
|
||||
/**
|
||||
* Enable the horizontal or vertical fit.
|
||||
* The container size will be set to involve the children horizontally or vertically.
|
||||
* @param cont pointer to a container object
|
||||
* @param hor_en true: enable the horizontal fit
|
||||
* @param ver_en true: enable the vertical fit
|
||||
*/
|
||||
void lv_cont_set_fit(lv_obj_t * cont, bool hor_en, bool ver_en);
|
||||
|
||||
/**
|
||||
* Set the style of a container
|
||||
* @param cont pointer to a container object
|
||||
* @param style pointer to the new style
|
||||
*/
|
||||
static inline void lv_cont_set_style(lv_obj_t *cont, lv_style_t * style)
|
||||
{
|
||||
lv_obj_set_style(cont, style);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the layout of a container
|
||||
* @param cont pointer to container object
|
||||
* @return the layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
lv_layout_t lv_cont_get_layout(const lv_obj_t * cont);
|
||||
|
||||
/**
|
||||
* Get horizontal fit enable attribute of a container
|
||||
* @param cont pointer to a container object
|
||||
* @return true: horizontal fit is enabled; false: disabled
|
||||
*/
|
||||
bool lv_cont_get_hor_fit(const lv_obj_t * cont);
|
||||
|
||||
/**
|
||||
* Get vertical fit enable attribute of a container
|
||||
* @param cont pointer to a container object
|
||||
* @return true: vertical fit is enabled; false: disabled
|
||||
*/
|
||||
bool lv_cont_get_ver_fit(const lv_obj_t * cont);
|
||||
|
||||
|
||||
/**
|
||||
* Get that width reduced by the horizontal padding. Useful if a layout is used.
|
||||
* @param cont pointer to a container object
|
||||
* @return the width which still fits into the container
|
||||
*/
|
||||
lv_coord_t lv_cont_get_fit_width(lv_obj_t * cont);
|
||||
|
||||
/**
|
||||
* Get that height reduced by the vertical padding. Useful if a layout is used.
|
||||
* @param cont pointer to a container object
|
||||
* @return the height which still fits into the container
|
||||
*/
|
||||
lv_coord_t lv_cont_get_fit_height(lv_obj_t * cont);
|
||||
|
||||
/**
|
||||
* Get the style of a container
|
||||
* @param cont pointer to a container object
|
||||
* @return pointer to the container's style
|
||||
*/
|
||||
static inline lv_style_t * lv_cont_get_style(const lv_obj_t *cont)
|
||||
{
|
||||
return lv_obj_get_style(cont);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_CONT*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_CONT_H*/
|
981
bdk/libs/lvgl/lv_objx/lv_ddlist.c
Normal file
981
bdk/libs/lvgl/lv_objx/lv_ddlist.c
Normal file
|
@ -0,0 +1,981 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file lv_ddlist.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_ddlist.h"
|
||||
#if USE_LV_DDLIST != 0
|
||||
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_core/lv_indev.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_symbol_def.h"
|
||||
#include "../lv_misc/lv_anim.h"
|
||||
//#include <strings.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#if USE_LV_ANIMATION
|
||||
# ifndef LV_DDLIST_ANIM_TIME
|
||||
# define LV_DDLIST_ANIM_TIME 200 /*ms*/
|
||||
# endif
|
||||
#else
|
||||
# undef LV_DDLIST_ANIM_TIME
|
||||
# define LV_DDLIST_ANIM_TIME 0 /*No animation*/
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_ddlist_signal(lv_obj_t * ddlist, lv_signal_t sign, void * param);
|
||||
static lv_res_t lv_ddlist_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, void * param);
|
||||
static lv_res_t lv_ddlist_release_action(lv_obj_t * ddlist);
|
||||
static lv_res_t lv_ddlist_press_action(lv_obj_t * ddlist);
|
||||
static void lv_ddlist_refr_size(lv_obj_t * ddlist, bool anim_en);
|
||||
static void lv_ddlist_pos_current_option(lv_obj_t * ddlist);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
static lv_signal_func_t ancestor_scrl_signal;
|
||||
static lv_design_func_t ancestor_design;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a drop down list objects
|
||||
* @param par pointer to an object, it will be the parent of the new drop down list
|
||||
* @param copy pointer to a drop down list object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created drop down list
|
||||
*/
|
||||
lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("drop down list create started");
|
||||
|
||||
/*Create the ancestor drop down list*/
|
||||
lv_obj_t * new_ddlist = lv_page_create(par, copy);
|
||||
lv_mem_assert(new_ddlist);
|
||||
if(new_ddlist == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_ddlist);
|
||||
if(ancestor_scrl_signal == NULL) ancestor_scrl_signal = lv_obj_get_signal_func(lv_page_get_scrl(new_ddlist));
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_ddlist);
|
||||
|
||||
/*Allocate the drop down list type specific extended data*/
|
||||
lv_ddlist_ext_t * ext = lv_obj_allocate_ext_attr(new_ddlist, sizeof(lv_ddlist_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->label = NULL;
|
||||
ext->action = NULL;
|
||||
ext->opened = 0;
|
||||
ext->fix_height = 0;
|
||||
ext->sel_opt_id = 0;
|
||||
ext->sel_opt_id_ori = 0;
|
||||
ext->option_cnt = 0;
|
||||
ext->anim_time = LV_DDLIST_ANIM_TIME;
|
||||
ext->sel_style = &lv_style_plain_color;
|
||||
ext->draw_arrow = 0; /*Do not draw arrow by default*/
|
||||
ext->direction_up = 0;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_ddlist, lv_ddlist_signal);
|
||||
lv_obj_set_signal_func(lv_page_get_scrl(new_ddlist), lv_ddlist_scrl_signal);
|
||||
lv_obj_set_design_func(new_ddlist, lv_ddlist_design);
|
||||
|
||||
/*Init the new drop down list drop down list*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_t * scrl = lv_page_get_scrl(new_ddlist);
|
||||
lv_obj_set_drag(scrl, false);
|
||||
lv_page_set_scrl_fit(new_ddlist, true, true);
|
||||
|
||||
ext->label = lv_label_create(new_ddlist, NULL);
|
||||
lv_cont_set_fit(new_ddlist, true, false);
|
||||
lv_page_set_rel_action(new_ddlist, lv_ddlist_release_action);
|
||||
lv_page_set_pr_action(new_ddlist, lv_ddlist_press_action);
|
||||
lv_page_set_sb_mode(new_ddlist, LV_SB_MODE_DRAG);
|
||||
lv_page_set_sb_mode(new_ddlist, LV_SB_MODE_HIDE);
|
||||
lv_page_set_style(new_ddlist, LV_PAGE_STYLE_SCRL, &lv_style_transp_tight);
|
||||
|
||||
lv_ddlist_set_options(new_ddlist, "Option 1\nOption 2\nOption 3");
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_BG, th->ddlist.bg);
|
||||
lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_BGO, th->ddlist.bgo);
|
||||
lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_PR, th->ddlist.pr);
|
||||
lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SEL, th->ddlist.sel);
|
||||
lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SB, th->ddlist.sb);
|
||||
} else {
|
||||
lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_BG, &lv_style_pretty);
|
||||
lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_BGO, &lv_style_pretty);
|
||||
lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_PR, &lv_style_pretty);
|
||||
lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SEL, &lv_style_plain_color);
|
||||
lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SB, &lv_style_pretty_color);
|
||||
}
|
||||
}
|
||||
/*Copy an existing drop down list*/
|
||||
else {
|
||||
lv_ddlist_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->label = lv_label_create(new_ddlist, copy_ext->label);
|
||||
lv_label_set_text(ext->label, lv_label_get_text(copy_ext->label));
|
||||
ext->sel_opt_id = copy_ext->sel_opt_id;
|
||||
ext->fix_height = copy_ext->fix_height;
|
||||
ext->action = copy_ext->action;
|
||||
ext->option_cnt = copy_ext->option_cnt;
|
||||
ext->sel_style = copy_ext->sel_style;
|
||||
ext->anim_time = copy_ext->anim_time;
|
||||
ext->draw_arrow = copy_ext->draw_arrow;
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_ddlist);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("drop down list created");
|
||||
|
||||
|
||||
return new_ddlist;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set arrow draw in a drop down list
|
||||
* @param ddlist pointer to drop down list object
|
||||
* @param en enable/disable a arrow draw. E.g. "true" for draw.
|
||||
*/
|
||||
void lv_ddlist_set_draw_arrow(lv_obj_t * ddlist, bool en)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
/*Set the flag*/
|
||||
ext->draw_arrow = en;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the options in a drop down list from a string
|
||||
* @param ddlist pointer to drop down list object
|
||||
* @param options a string with '\n' separated options. E.g. "One\nTwo\nThree"
|
||||
*/
|
||||
void lv_ddlist_set_options(lv_obj_t * ddlist, const char * options)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
/*Count the '\n'-s to determine the number of options*/
|
||||
ext->option_cnt = 0;
|
||||
uint16_t i;
|
||||
for(i = 0; options[i] != '\0'; i++) {
|
||||
if(options[i] == '\n') ext->option_cnt++;
|
||||
}
|
||||
ext->option_cnt++; /*Last option in the at row*/
|
||||
|
||||
lv_label_set_text(ext->label, options);
|
||||
lv_ddlist_refr_size(ddlist, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the selected option
|
||||
* @param ddlist pointer to drop down list object
|
||||
* @param sel_opt id of the selected option (0 ... number of option - 1);
|
||||
*/
|
||||
void lv_ddlist_set_selected(lv_obj_t * ddlist, uint16_t sel_opt)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
if(ext->sel_opt_id == sel_opt) return;
|
||||
|
||||
ext->sel_opt_id = sel_opt < ext->option_cnt ? sel_opt : ext->option_cnt - 1;
|
||||
ext->sel_opt_id_ori = ext->sel_opt_id;
|
||||
/*Move the list to show the current option*/
|
||||
if(ext->opened == 0) {
|
||||
lv_ddlist_pos_current_option(ddlist);
|
||||
} else {
|
||||
lv_obj_invalidate(ddlist);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a function to call when a new option is chosen
|
||||
* @param ddlist pointer to a drop down list
|
||||
* @param action pointer to a call back function
|
||||
*/
|
||||
void lv_ddlist_set_action(lv_obj_t * ddlist, lv_action_t action)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
ext->action = action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fix height for the drop down list
|
||||
* If 0 then the opened ddlist will be auto. sized else the set height will be applied.
|
||||
* @param ddlist pointer to a drop down list
|
||||
* @param h the height when the list is opened (0: auto size)
|
||||
*/
|
||||
void lv_ddlist_set_fix_height(lv_obj_t * ddlist, lv_coord_t h)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
if(ext->fix_height == h) return;
|
||||
|
||||
ext->fix_height = h;
|
||||
|
||||
lv_ddlist_refr_size(ddlist, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable the horizontal fit to the content
|
||||
* @param ddlist pointer to a drop down list
|
||||
* @param en true: enable auto fit; false: disable auto fit
|
||||
*/
|
||||
void lv_ddlist_set_hor_fit(lv_obj_t * ddlist, bool en)
|
||||
{
|
||||
lv_cont_set_fit(ddlist, en, lv_cont_get_ver_fit(ddlist));
|
||||
lv_page_set_scrl_fit(ddlist, en, lv_page_get_scrl_fit_ver(ddlist));
|
||||
|
||||
lv_ddlist_refr_size(ddlist, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the open/close animation time.
|
||||
* @param ddlist pointer to a drop down list
|
||||
* @param anim_time: open/close animation time [ms]
|
||||
*/
|
||||
void lv_ddlist_set_anim_time(lv_obj_t * ddlist, uint16_t anim_time)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
#if USE_LV_ANIMATION == 0
|
||||
anim_time = 0;
|
||||
#endif
|
||||
|
||||
ext->anim_time = anim_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a drop down list
|
||||
* @param ddlist pointer to a drop down list object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_ddlist_set_style(lv_obj_t * ddlist, lv_ddlist_style_t type, lv_style_t * style)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
switch(type) {
|
||||
case LV_DDLIST_STYLE_BG:
|
||||
lv_page_set_style(ddlist, LV_PAGE_STYLE_BG, style);
|
||||
break;
|
||||
case LV_DDLIST_STYLE_BGO:
|
||||
lv_page_set_style(ddlist, LV_PAGE_STYLE_BGO, style);
|
||||
break;
|
||||
case LV_DDLIST_STYLE_PR:
|
||||
lv_page_set_style(ddlist, LV_PAGE_STYLE_PR, style);
|
||||
break;
|
||||
case LV_DDLIST_STYLE_SB:
|
||||
lv_page_set_style(ddlist, LV_PAGE_STYLE_SB, style);
|
||||
break;
|
||||
case LV_DDLIST_STYLE_SEL:
|
||||
ext->sel_style = style;
|
||||
lv_obj_t * scrl = lv_page_get_scrl(ddlist);
|
||||
lv_obj_refresh_ext_size(scrl); /*Because of the wider selected rectangle*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_ddlist_set_align(lv_obj_t *ddlist, lv_label_align_t align)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
lv_label_set_align(ext->label, align);
|
||||
}
|
||||
|
||||
void lv_ddlist_set_direction_up(lv_obj_t *ddlist, bool enable)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
ext->direction_up = enable;
|
||||
}
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get arrow draw in a drop down list
|
||||
* @param ddlist pointer to drop down list object
|
||||
*/
|
||||
bool lv_ddlist_get_draw_arrow(lv_obj_t * ddlist)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
return ext->draw_arrow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the options of a drop down list
|
||||
* @param ddlist pointer to drop down list object
|
||||
* @return the options separated by '\n'-s (E.g. "Option1\nOption2\nOption3")
|
||||
*/
|
||||
const char * lv_ddlist_get_options(const lv_obj_t * ddlist)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
return lv_label_get_text(ext->label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selected option
|
||||
* @param ddlist pointer to drop down list object
|
||||
* @return id of the selected option (0 ... number of option - 1);
|
||||
*/
|
||||
uint16_t lv_ddlist_get_selected(const lv_obj_t * ddlist)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
return ext->sel_opt_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current selected option as a string
|
||||
* @param ddlist pointer to ddlist object
|
||||
* @param buf pointer to an array to store the string
|
||||
*/
|
||||
void lv_ddlist_get_selected_str(const lv_obj_t * ddlist, char * buf)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
uint16_t i;
|
||||
uint16_t line = 0;
|
||||
const char * opt_txt = lv_label_get_text(ext->label);
|
||||
uint16_t txt_len = strlen(opt_txt);
|
||||
|
||||
|
||||
for(i = 0; i < txt_len && line != ext->sel_opt_id; i++) {
|
||||
if(opt_txt[i] == '\n') line ++;
|
||||
}
|
||||
|
||||
uint16_t c;
|
||||
for(c = 0; opt_txt[i] != '\n' && i < txt_len; c++, i++) buf[c] = opt_txt[i];
|
||||
|
||||
buf[c] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "option selected" callback function
|
||||
* @param ddlist pointer to a drop down list
|
||||
* @return pointer to the call back function
|
||||
*/
|
||||
lv_action_t lv_ddlist_get_action(const lv_obj_t * ddlist)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
return ext->action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fix height value.
|
||||
* @param ddlist pointer to a drop down list object
|
||||
* @return the height if the ddlist is opened (0: auto size)
|
||||
*/
|
||||
lv_coord_t lv_ddlist_get_fix_height(const lv_obj_t * ddlist)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
return ext->fix_height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the open/close animation time.
|
||||
* @param ddlist pointer to a drop down list
|
||||
* @return open/close animation time [ms]
|
||||
*/
|
||||
uint16_t lv_ddlist_get_anim_time(const lv_obj_t * ddlist)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
return ext->anim_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a drop down list
|
||||
* @param ddlist pointer to a drop down list object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_ddlist_get_style(const lv_obj_t * ddlist, lv_ddlist_style_t type)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
switch(type) {
|
||||
case LV_DDLIST_STYLE_BG:
|
||||
return lv_page_get_style(ddlist, LV_PAGE_STYLE_BG);
|
||||
case LV_DDLIST_STYLE_BGO:
|
||||
return lv_page_get_style(ddlist, LV_PAGE_STYLE_BGO);
|
||||
case LV_DDLIST_STYLE_PR:
|
||||
return lv_page_get_style(ddlist, LV_PAGE_STYLE_PR);
|
||||
case LV_DDLIST_STYLE_SB:
|
||||
return lv_page_get_style(ddlist, LV_PAGE_STYLE_SB);
|
||||
case LV_DDLIST_STYLE_SEL:
|
||||
return ext->sel_style;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*To avoid warning*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_label_align_t lv_ddlist_get_align(const lv_obj_t *ddlist)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
return lv_label_get_align(ext->label);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Open the drop down list with or without animation
|
||||
* @param ddlist pointer to drop down list object
|
||||
* @param anim_en true: use animation; false: not use animations
|
||||
*/
|
||||
void lv_ddlist_open(lv_obj_t * ddlist, bool anim_en)
|
||||
{
|
||||
#if USE_LV_ANIMATION == 0
|
||||
anim_en = false;
|
||||
#endif
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
ext->opened = 1;
|
||||
lv_obj_set_drag(lv_page_get_scrl(ddlist), true);
|
||||
lv_ddlist_refr_size(ddlist, anim_en);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close (Collapse) the drop down list
|
||||
* @param ddlist pointer to drop down list object
|
||||
* @param anim_en true: use animation; false: not use animations
|
||||
*/
|
||||
void lv_ddlist_close(lv_obj_t * ddlist, bool anim_en)
|
||||
{
|
||||
#if USE_LV_ANIMATION == 0
|
||||
anim_en = false;
|
||||
#endif
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
ext->opened = 0;
|
||||
lv_obj_set_drag(lv_page_get_scrl(ddlist), false);
|
||||
lv_ddlist_refr_size(ddlist, anim_en);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get the text alignment flag for a drop down list.
|
||||
* @param ddlist drop down list
|
||||
* @return text alignment flag
|
||||
*/
|
||||
static lv_txt_flag_t lv_ddlist_get_txt_flag(const lv_obj_t *ddlist)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
/*The label might be already deleted so just return with some value*/
|
||||
if(!ext->label) return LV_TXT_FLAG_CENTER;
|
||||
|
||||
lv_label_align_t align = lv_label_get_align(ext->label);
|
||||
|
||||
switch(align)
|
||||
{
|
||||
default:
|
||||
case LV_LABEL_ALIGN_LEFT:
|
||||
return LV_TXT_FLAG_NONE;
|
||||
case LV_LABEL_ALIGN_CENTER:
|
||||
return LV_TXT_FLAG_CENTER;
|
||||
case LV_LABEL_ALIGN_RIGHT:
|
||||
return LV_TXT_FLAG_RIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the drop down lists
|
||||
* @param ddlist pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return ancestor_design(ddlist, mask, mode);
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
ancestor_design(ddlist, mask, mode);
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(ddlist);
|
||||
/*If the list is opened draw a rectangle under the selected item*/
|
||||
if(ext->opened != 0) {
|
||||
lv_style_t * style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_BG);
|
||||
const lv_font_t * font = style->text.font;
|
||||
lv_coord_t font_h = lv_font_get_height(font);
|
||||
|
||||
/*Draw the selected*/
|
||||
lv_area_t rect_area;
|
||||
rect_area.y1 = ext->label->coords.y1;
|
||||
rect_area.y1 += ext->sel_opt_id * (font_h + style->text.line_space);
|
||||
rect_area.y1 -= style->text.line_space / 2;
|
||||
|
||||
rect_area.y2 = rect_area.y1 + font_h + style->text.line_space - 1;
|
||||
rect_area.x1 = ddlist->coords.x1;
|
||||
rect_area.x2 = ddlist->coords.x2;
|
||||
|
||||
lv_draw_rect(&rect_area, mask, ext->sel_style, opa_scale);
|
||||
}
|
||||
}
|
||||
/*Post draw when the children are drawn*/
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
/*Redraw the text on the selected area with a different color*/
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(ddlist);
|
||||
|
||||
/*Redraw only in opened state*/
|
||||
if(ext->opened) {
|
||||
lv_style_t * style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_BG);
|
||||
const lv_font_t * font = style->text.font;
|
||||
lv_coord_t font_h = lv_font_get_height(font);
|
||||
|
||||
lv_area_t area_sel;
|
||||
area_sel.y1 = ext->label->coords.y1;
|
||||
area_sel.y1 += ext->sel_opt_id * (font_h + style->text.line_space);
|
||||
area_sel.y1 -= style->text.line_space / 2;
|
||||
|
||||
area_sel.y2 = area_sel.y1 + font_h + style->text.line_space - 1;
|
||||
area_sel.x1 = ddlist->coords.x1;
|
||||
area_sel.x2 = ddlist->coords.x2;
|
||||
lv_area_t mask_sel;
|
||||
bool area_ok;
|
||||
area_ok = lv_area_intersect(&mask_sel, mask, &area_sel);
|
||||
if(area_ok) {
|
||||
lv_style_t * sel_style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_SEL);
|
||||
lv_style_t new_style;
|
||||
lv_style_copy(&new_style, style);
|
||||
new_style.text.color = sel_style->text.color;
|
||||
new_style.text.opa = sel_style->text.opa;
|
||||
lv_txt_flag_t flag = lv_ddlist_get_txt_flag(ddlist);
|
||||
lv_draw_label(&ext->label->coords, &mask_sel, &new_style, opa_scale,
|
||||
lv_label_get_text(ext->label), flag, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*Add a down symbol in ddlist when closed*/
|
||||
else
|
||||
{
|
||||
/*Draw a arrow in ddlist if enabled*/
|
||||
if(ext->draw_arrow)
|
||||
{
|
||||
lv_style_t * style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_BG);
|
||||
const lv_font_t * font = style->text.font;
|
||||
lv_style_t * sel_style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_BG);
|
||||
lv_coord_t font_h = lv_font_get_height(font);
|
||||
lv_style_t new_style;
|
||||
lv_style_copy(&new_style, style);
|
||||
new_style.text.color = sel_style->text.color;
|
||||
new_style.text.opa = sel_style->text.opa;
|
||||
lv_area_t area_arrow;
|
||||
area_arrow.x2 = ddlist->coords.x2 - style->body.padding.hor;
|
||||
if (!ext->direction_up)
|
||||
area_arrow.x1 = area_arrow.x2 - lv_txt_get_width(SYMBOL_DOWN, strlen(SYMBOL_DOWN), sel_style->text.font, 0, 0);
|
||||
else
|
||||
area_arrow.x1 = area_arrow.x2 - lv_txt_get_width(SYMBOL_UP, strlen(SYMBOL_UP), sel_style->text.font, 0, 0);
|
||||
|
||||
area_arrow.y1 = ddlist->coords.y1 + style->text.line_space;
|
||||
area_arrow.y2 = area_arrow.y1 + font_h;
|
||||
|
||||
|
||||
lv_area_t mask_arrow;
|
||||
bool area_ok;
|
||||
area_ok = lv_area_intersect(&mask_arrow, mask, &area_arrow);
|
||||
if (area_ok)
|
||||
{
|
||||
if (!ext->direction_up)
|
||||
lv_draw_label(&area_arrow, &mask_arrow, &new_style, opa_scale,
|
||||
SYMBOL_DOWN, LV_TXT_FLAG_NONE, NULL); /*Use a down arrow in ddlist, you can replace it with your custom symbol*/
|
||||
else
|
||||
lv_draw_label(&area_arrow, &mask_arrow, &new_style, opa_scale,
|
||||
SYMBOL_UP, LV_TXT_FLAG_NONE, NULL); /*Use a down arrow in ddlist, you can replace it with your custom symbol*/
|
||||
}
|
||||
}
|
||||
}
|
||||
/*Draw the scrollbar in the ancestor page design function*/
|
||||
ancestor_design(ddlist, mask, mode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the drop down list
|
||||
* @param ddlist pointer to a drop down list object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_ddlist_signal(lv_obj_t * ddlist, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(ddlist, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
//! lv_ddlist_refr_size(ddlist, 0); // uncommented in OG
|
||||
} else if(sign == LV_SIGNAL_CLEANUP) {
|
||||
ext->label = NULL;
|
||||
} else if(sign == LV_SIGNAL_FOCUS) {
|
||||
#if USE_LV_GROUP
|
||||
lv_group_t * g = lv_obj_get_group(ddlist);
|
||||
bool editing = lv_group_get_editing(g);
|
||||
lv_hal_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act());
|
||||
|
||||
/*Encoders need special handling*/
|
||||
if(indev_type == LV_INDEV_TYPE_ENCODER) {
|
||||
/*Open the list if editing*/
|
||||
if(editing) {
|
||||
ext->opened = true;
|
||||
ext->sel_opt_id_ori = ext->sel_opt_id;
|
||||
lv_ddlist_refr_size(ddlist, true);
|
||||
}
|
||||
/*Close the lift if navigating*/
|
||||
else {
|
||||
ext->opened = false;
|
||||
ext->sel_opt_id = ext->sel_opt_id_ori;
|
||||
lv_ddlist_refr_size(ddlist, true);
|
||||
|
||||
}
|
||||
} else {
|
||||
/*Open the list if closed*/
|
||||
if(!ext->opened) {
|
||||
ext->opened = true;
|
||||
ext->sel_opt_id_ori = ext->sel_opt_id; /*Save the current value. Used to revert this state if ENER wont't be pressed*/
|
||||
lv_ddlist_refr_size(ddlist, true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if(sign == LV_SIGNAL_DEFOCUS) {
|
||||
if(ext->opened) {
|
||||
ext->opened = false;
|
||||
ext->sel_opt_id = ext->sel_opt_id_ori;
|
||||
lv_ddlist_refr_size(ddlist, true);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_CONTROLL) {
|
||||
char c = *((char *)param);
|
||||
if(c == LV_GROUP_KEY_RIGHT || c == LV_GROUP_KEY_DOWN) {
|
||||
if(!ext->opened) {
|
||||
ext->opened = 1;
|
||||
lv_ddlist_refr_size(ddlist, true);
|
||||
}
|
||||
|
||||
if(ext->sel_opt_id + 1 < ext->option_cnt) {
|
||||
ext->sel_opt_id ++;
|
||||
lv_ddlist_pos_current_option(ddlist);
|
||||
lv_obj_invalidate(ddlist);
|
||||
}
|
||||
} else if(c == LV_GROUP_KEY_LEFT || c == LV_GROUP_KEY_UP) {
|
||||
if(!ext->opened) {
|
||||
ext->opened = 1;
|
||||
lv_ddlist_refr_size(ddlist, true);
|
||||
}
|
||||
if(ext->sel_opt_id > 0) {
|
||||
ext->sel_opt_id --;
|
||||
lv_ddlist_pos_current_option(ddlist);
|
||||
lv_obj_invalidate(ddlist);
|
||||
}
|
||||
} else if(c == LV_GROUP_KEY_ENTER) {
|
||||
if(ext->opened) {
|
||||
ext->sel_opt_id_ori = ext->sel_opt_id;
|
||||
ext->opened = 0;
|
||||
if(ext->action) ext->action(ddlist);
|
||||
|
||||
#if USE_LV_GROUP
|
||||
lv_group_t * g = lv_obj_get_group(ddlist);
|
||||
bool editing = lv_group_get_editing(g);
|
||||
if(editing) lv_group_set_editing(g, false); /*In edit mode go to navigate mode if an option is selected*/
|
||||
#endif
|
||||
} else {
|
||||
ext->opened = 1;
|
||||
}
|
||||
|
||||
lv_ddlist_refr_size(ddlist, true);
|
||||
} else if(c == LV_GROUP_KEY_ESC) {
|
||||
if(ext->opened) {
|
||||
ext->opened = 0;
|
||||
ext->sel_opt_id = ext->sel_opt_id_ori;
|
||||
lv_ddlist_refr_size(ddlist, true);
|
||||
}
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_EDITABLE) {
|
||||
bool * editable = (bool *)param;
|
||||
*editable = true;
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_ddlist";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the drop down list's scrollable part
|
||||
* @param scrl pointer to a drop down list's scrollable part
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_ddlist_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_scrl_signal(scrl, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_obj_t * ddlist = lv_obj_get_parent(scrl);
|
||||
|
||||
if(sign == LV_SIGNAL_REFR_EXT_SIZE) {
|
||||
/* Because of the wider selected rectangle ext. size
|
||||
* In this way by dragging the scrollable part the wider rectangle area can be redrawn too*/
|
||||
lv_style_t * style = lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_BG);
|
||||
if(scrl->ext_size < style->body.padding.hor) scrl->ext_size = style->body.padding.hor;
|
||||
} else if(sign == LV_SIGNAL_CLEANUP) {
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
ext->label = NULL; /*The label is already deleted*/
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a drop down list is released to open it or set new option
|
||||
* @param ddlist pointer to a drop down list object
|
||||
* @return LV_ACTION_RES_INV if the ddlist it deleted in the user callback else LV_ACTION_RES_OK
|
||||
*/
|
||||
static lv_res_t lv_ddlist_release_action(lv_obj_t * ddlist)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
if (!lv_obj_get_click(ddlist)) return LV_RES_OK;
|
||||
|
||||
if(ext->opened == 0) { /*Open the list*/
|
||||
ext->opened = 1;
|
||||
lv_ddlist_set_style(ddlist, LV_DDLIST_STYLE_BG, lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_BGO));
|
||||
lv_obj_set_drag(lv_page_get_scrl(ddlist), true);
|
||||
} else {
|
||||
ext->opened = 0;
|
||||
//lv_ddlist_set_style(ddlist, LV_DDLIST_STYLE_BG, lv_ddlist_get_style(ddlist, lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_PR)));
|
||||
lv_obj_set_drag(lv_page_get_scrl(ddlist), false);
|
||||
|
||||
/*Search the clicked option*/
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
lv_point_t p;
|
||||
lv_indev_get_point(indev, &p);
|
||||
p.x -= ext->label->coords.x1;
|
||||
p.y -= ext->label->coords.y1;
|
||||
uint16_t letter_i;
|
||||
letter_i = lv_label_get_letter_on(ext->label, &p);
|
||||
|
||||
uint16_t new_opt = 0;
|
||||
const char * txt = lv_label_get_text(ext->label);
|
||||
uint32_t i = 0;
|
||||
uint32_t line_cnt = 0;
|
||||
uint32_t letter;
|
||||
for(line_cnt = 0; line_cnt < letter_i; line_cnt++) {
|
||||
letter = lv_txt_encoded_next(txt, &i);
|
||||
if(letter == '\n') new_opt ++;
|
||||
}
|
||||
|
||||
ext->sel_opt_id = new_opt;
|
||||
|
||||
if(ext->action != NULL) {
|
||||
ext->action(ddlist);
|
||||
}
|
||||
}
|
||||
lv_ddlist_refr_size(ddlist, true);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
static lv_res_t lv_ddlist_press_action(lv_obj_t * ddlist)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
|
||||
if (!lv_obj_get_click(ddlist)) return LV_RES_OK;
|
||||
|
||||
if (ext->opened == 0)
|
||||
{ /*Open the list*/
|
||||
lv_ddlist_set_style(ddlist, LV_DDLIST_STYLE_BG, lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_PR));
|
||||
}
|
||||
else
|
||||
{
|
||||
//lv_ddlist_set_style(ddlist, LV_DDLIST_STYLE_BG, lv_ddlist_get_style(ddlist, LV_DDLIST_STYLE_BGO));
|
||||
//lv_obj_set_drag(lv_page_get_scrl(ddlist), false);
|
||||
|
||||
///*Search the clicked option*/
|
||||
//lv_indev_t * indev = lv_indev_get_act();
|
||||
//lv_point_t p;
|
||||
//lv_indev_get_point(indev, &p);
|
||||
//p.x -= ext->label->coords.x1;
|
||||
//p.y -= ext->label->coords.y1;
|
||||
//uint16_t letter_i;
|
||||
//letter_i = lv_label_get_letter_on(ext->label, &p);
|
||||
|
||||
//uint16_t new_opt = 0;
|
||||
//const char * txt = lv_label_get_text(ext->label);
|
||||
//uint32_t i = 0;
|
||||
//uint32_t line_cnt = 0;
|
||||
//uint32_t letter;
|
||||
//for (line_cnt = 0; line_cnt < letter_i; line_cnt++)
|
||||
//{
|
||||
// letter = lv_txt_encoded_next(txt, &i);
|
||||
// if (letter == '\n') new_opt++;
|
||||
//}
|
||||
|
||||
//ext->sel_opt_id = new_opt;
|
||||
|
||||
//if (ext->action != NULL)
|
||||
//{
|
||||
// ext->action(ddlist);
|
||||
//}
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the size of drop down list according to its status (open or closed)
|
||||
* @param ddlist pointer to a drop down list object
|
||||
* @param anim_en Change the size (open/close) with or without animation (true/false)
|
||||
*/
|
||||
static void lv_ddlist_refr_size(lv_obj_t * ddlist, bool anim_en)
|
||||
{
|
||||
#if USE_LV_ANIMATION == 0
|
||||
anim_en = false;
|
||||
#endif
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
lv_style_t * style = lv_obj_get_style(ddlist);
|
||||
lv_coord_t new_height, full_height;
|
||||
bool current_state = 0;
|
||||
|
||||
if(ext->opened) { /*Open the list*/
|
||||
if(ext->fix_height == 0) new_height = lv_obj_get_height(lv_page_get_scrl(ddlist)) + 2 * style->body.padding.ver;
|
||||
else new_height = ext->fix_height;
|
||||
current_state = 1;
|
||||
|
||||
lv_page_set_sb_mode(ddlist, LV_SB_MODE_UNHIDE);
|
||||
} else { /*Close the list*/
|
||||
const lv_font_t * font = style->text.font;
|
||||
lv_style_t * label_style = lv_obj_get_style(ext->label);
|
||||
lv_coord_t font_h = lv_font_get_height(font);
|
||||
new_height = font_h + 2 * label_style->text.line_space;
|
||||
//full_height = lv_obj_get_height(lv_page_get_scrl(ddlist)) + 2 * style->body.padding.ver;
|
||||
current_state = 0;
|
||||
|
||||
lv_page_set_sb_mode(ddlist, LV_SB_MODE_HIDE);
|
||||
}
|
||||
|
||||
if(anim_en == 0 || ext->direction_up) {
|
||||
lv_obj_set_height(ddlist, new_height);
|
||||
if (ext->direction_up)
|
||||
{
|
||||
full_height = lv_obj_get_height(lv_page_get_scrl(ddlist)) - lv_font_get_height(style->text.font);
|
||||
if (current_state)
|
||||
lv_obj_set_y(ddlist, lv_obj_get_y(ddlist) - full_height);
|
||||
else
|
||||
lv_obj_set_y(ddlist, lv_obj_get_y(ddlist) + full_height);
|
||||
}
|
||||
|
||||
lv_ddlist_pos_current_option(ddlist);
|
||||
#if USE_LV_ANIMATION
|
||||
lv_anim_del(ddlist, (lv_anim_fp_t)lv_obj_set_height); /*If an animation is in progress then it will overwrite this changes*/
|
||||
} else {
|
||||
lv_anim_t a;
|
||||
a.var = ddlist;
|
||||
a.start = lv_obj_get_height(ddlist);
|
||||
a.end = new_height;
|
||||
a.fp = (lv_anim_fp_t)lv_obj_set_height;
|
||||
a.path = lv_anim_path_linear;
|
||||
a.end_cb = (lv_anim_cb_t)lv_ddlist_pos_current_option;
|
||||
a.act_time = 0;
|
||||
a.time = ext->anim_time;
|
||||
a.playback = 0;
|
||||
a.playback_pause = 0;
|
||||
a.repeat = 0;
|
||||
a.repeat_pause = 0;
|
||||
|
||||
lv_anim_create(&a);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the position of list when it is closed to show the selected item
|
||||
* @param ddlist pointer to a drop down list
|
||||
*/
|
||||
static void lv_ddlist_pos_current_option(lv_obj_t * ddlist)
|
||||
{
|
||||
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
|
||||
lv_style_t * style = lv_obj_get_style(ddlist);
|
||||
const lv_font_t * font = style->text.font;
|
||||
lv_coord_t font_h = lv_font_get_height(font);
|
||||
lv_style_t * label_style = lv_obj_get_style(ext->label);
|
||||
lv_obj_t * scrl = lv_page_get_scrl(ddlist);
|
||||
|
||||
lv_coord_t h = lv_obj_get_height(ddlist);
|
||||
lv_coord_t line_y1 = ext->sel_opt_id * (font_h + label_style->text.line_space) + ext->label->coords.y1 - scrl->coords.y1;
|
||||
|
||||
lv_obj_set_y(scrl, - line_y1 + (h - font_h) / 2);
|
||||
}
|
||||
|
||||
#endif
|
286
bdk/libs/lvgl/lv_objx/lv_ddlist.h
Normal file
286
bdk/libs/lvgl/lv_objx/lv_ddlist.h
Normal file
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file lv_ddlist.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_DDLIST_H
|
||||
#define LV_DDLIST_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_DDLIST != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_PAGE == 0
|
||||
#error "lv_ddlist: lv_page is required. Enable it in lv_conf.h (USE_LV_PAGE 1) "
|
||||
#endif
|
||||
|
||||
#if USE_LV_LABEL == 0
|
||||
#error "lv_ddlist: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_objx/lv_page.h"
|
||||
#include "../lv_objx/lv_label.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Data of drop down list*/
|
||||
typedef struct
|
||||
{
|
||||
lv_page_ext_t page; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_obj_t *label; /*Label for the options*/
|
||||
lv_style_t * sel_style; /*Style of the selected option*/
|
||||
lv_action_t action; /*Pointer to function to call when an option is selected*/
|
||||
uint16_t option_cnt; /*Number of options*/
|
||||
uint16_t sel_opt_id; /*Index of the current option*/
|
||||
uint16_t sel_opt_id_ori; /*Store the original index on focus*/
|
||||
uint16_t anim_time; /*Open/Close animation time [ms]*/
|
||||
uint8_t opened :1; /*1: The list is opened (handled by the library)*/
|
||||
uint8_t draw_arrow :1; /*1: Draw arrow*/
|
||||
uint8_t direction_up : 1; /*1: Open direction*/
|
||||
|
||||
lv_coord_t fix_height; /*Height of the ddlist when opened. (0: auto-size)*/
|
||||
} lv_ddlist_ext_t;
|
||||
|
||||
enum {
|
||||
LV_DDLIST_STYLE_BG,
|
||||
LV_DDLIST_STYLE_BGO,
|
||||
LV_DDLIST_STYLE_PR,
|
||||
LV_DDLIST_STYLE_SEL,
|
||||
LV_DDLIST_STYLE_SB,
|
||||
};
|
||||
typedef uint8_t lv_ddlist_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
/**
|
||||
* Create a drop down list objects
|
||||
* @param par pointer to an object, it will be the parent of the new drop down list
|
||||
* @param copy pointer to a drop down list object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created drop down list
|
||||
*/
|
||||
lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set arrow draw in a drop down list
|
||||
* @param ddlist pointer to drop down list object
|
||||
* @param en enable/disable a arrow draw. E.g. "true" for draw.
|
||||
*/
|
||||
void lv_ddlist_set_draw_arrow(lv_obj_t * ddlist, bool en);
|
||||
|
||||
/**
|
||||
* Set the options in a drop down list from a string
|
||||
* @param ddlist pointer to drop down list object
|
||||
* @param options a string with '\n' separated options. E.g. "One\nTwo\nThree"
|
||||
*/
|
||||
void lv_ddlist_set_options(lv_obj_t * ddlist, const char * options);
|
||||
|
||||
/**
|
||||
* Set the selected option
|
||||
* @param ddlist pointer to drop down list object
|
||||
* @param sel_opt id of the selected option (0 ... number of option - 1);
|
||||
*/
|
||||
void lv_ddlist_set_selected(lv_obj_t * ddlist, uint16_t sel_opt);
|
||||
|
||||
/**
|
||||
* Set a function to call when a new option is chosen
|
||||
* @param ddlist pointer to a drop down list
|
||||
* @param action pointer to a call back function
|
||||
*/
|
||||
void lv_ddlist_set_action(lv_obj_t * ddlist, lv_action_t action);
|
||||
|
||||
/**
|
||||
* Set the fix height for the drop down list
|
||||
* If 0 then the opened ddlist will be auto. sized else the set height will be applied.
|
||||
* @param ddlist pointer to a drop down list
|
||||
* @param h the height when the list is opened (0: auto size)
|
||||
*/
|
||||
void lv_ddlist_set_fix_height(lv_obj_t * ddlist, lv_coord_t h);
|
||||
|
||||
/**
|
||||
* Enable or disable the horizontal fit to the content
|
||||
* @param ddlist pointer to a drop down list
|
||||
* @param en true: enable auto fit; false: disable auto fit
|
||||
*/
|
||||
void lv_ddlist_set_hor_fit(lv_obj_t * ddlist, bool en);
|
||||
|
||||
/**
|
||||
* Set the scroll bar mode of a drop down list
|
||||
* @param ddlist pointer to a drop down list object
|
||||
* @param sb_mode the new mode from 'lv_page_sb_mode_t' enum
|
||||
*/
|
||||
static inline void lv_ddlist_set_sb_mode(lv_obj_t * ddlist, lv_sb_mode_t mode)
|
||||
{
|
||||
lv_page_set_sb_mode(ddlist, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the open/close animation time.
|
||||
* @param ddlist pointer to a drop down list
|
||||
* @param anim_time: open/close animation time [ms]
|
||||
*/
|
||||
void lv_ddlist_set_anim_time(lv_obj_t * ddlist, uint16_t anim_time);
|
||||
|
||||
|
||||
/**
|
||||
* Set a style of a drop down list
|
||||
* @param ddlist pointer to a drop down list object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
* */
|
||||
void lv_ddlist_set_style(lv_obj_t *ddlist, lv_ddlist_style_t type, lv_style_t *style);
|
||||
|
||||
/**
|
||||
* Set the alignment of the labels in a drop down list
|
||||
* @param ddlist pointer to a drop down list object
|
||||
* @param align alignment of labels
|
||||
*/
|
||||
void lv_ddlist_set_align(lv_obj_t *ddlist, lv_label_align_t align);
|
||||
|
||||
void lv_ddlist_set_direction_up(lv_obj_t *ddlist, bool enable);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get arrow draw in a drop down list
|
||||
* @param ddlist pointer to drop down list object
|
||||
*/
|
||||
bool lv_ddlist_get_draw_arrow(lv_obj_t * ddlist);
|
||||
|
||||
/**
|
||||
* Get the options of a drop down list
|
||||
* @param ddlist pointer to drop down list object
|
||||
* @return the options separated by '\n'-s (E.g. "Option1\nOption2\nOption3")
|
||||
*/
|
||||
const char * lv_ddlist_get_options(const lv_obj_t * ddlist);
|
||||
|
||||
/**
|
||||
* Get the selected option
|
||||
* @param ddlist pointer to drop down list object
|
||||
* @return id of the selected option (0 ... number of option - 1);
|
||||
*/
|
||||
uint16_t lv_ddlist_get_selected(const lv_obj_t * ddlist);
|
||||
|
||||
/**
|
||||
* Get the current selected option as a string
|
||||
* @param ddlist pointer to ddlist object
|
||||
* @param buf pointer to an array to store the string
|
||||
*/
|
||||
void lv_ddlist_get_selected_str(const lv_obj_t * ddlist, char * buf);
|
||||
|
||||
/**
|
||||
* Get the "option selected" callback function
|
||||
* @param ddlist pointer to a drop down list
|
||||
* @return pointer to the call back function
|
||||
*/
|
||||
lv_action_t lv_ddlist_get_action(const lv_obj_t * ddlist);
|
||||
|
||||
/**
|
||||
* Get the fix height value.
|
||||
* @param ddlist pointer to a drop down list object
|
||||
* @return the height if the ddlist is opened (0: auto size)
|
||||
*/
|
||||
lv_coord_t lv_ddlist_get_fix_height(const lv_obj_t * ddlist);
|
||||
|
||||
/**
|
||||
* Get the scroll bar mode of a drop down list
|
||||
* @param ddlist pointer to a drop down list object
|
||||
* @return scrollbar mode from 'lv_page_sb_mode_t' enum
|
||||
*/
|
||||
static inline lv_sb_mode_t lv_ddlist_get_sb_mode(const lv_obj_t * ddlist)
|
||||
{
|
||||
return lv_page_get_sb_mode(ddlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the open/close animation time.
|
||||
* @param ddlist pointer to a drop down list
|
||||
* @return open/close animation time [ms]
|
||||
*/
|
||||
uint16_t lv_ddlist_get_anim_time(const lv_obj_t * ddlist);
|
||||
|
||||
/**
|
||||
* Get a style of a drop down list
|
||||
* @param ddlist pointer to a drop down list object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_ddlist_get_style(const lv_obj_t *ddlist, lv_ddlist_style_t type);
|
||||
|
||||
/**
|
||||
* Get the alignment of the labels in a drop down list
|
||||
* @param ddlist pointer to a drop down list object
|
||||
* @return alignment of labels
|
||||
*/
|
||||
lv_label_align_t lv_ddlist_get_align(const lv_obj_t *ddlist);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Open the drop down list with or without animation
|
||||
* @param ddlist pointer to drop down list object
|
||||
* @param anim_en true: use animation; false: not use animations
|
||||
*/
|
||||
void lv_ddlist_open(lv_obj_t * ddlist, bool anim_en);
|
||||
|
||||
/**
|
||||
* Close (Collapse) the drop down list
|
||||
* @param ddlist pointer to drop down list object
|
||||
* @param anim_en true: use animation; false: not use animations
|
||||
*/
|
||||
void lv_ddlist_close(lv_obj_t * ddlist, bool anim_en);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_DDLIST*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_DDLIST_H*/
|
466
bdk/libs/lvgl/lv_objx/lv_gauge.c
Normal file
466
bdk/libs/lvgl/lv_objx/lv_gauge.c
Normal file
|
@ -0,0 +1,466 @@
|
|||
/**
|
||||
* @file lv_gauge.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_gauge.h"
|
||||
#if USE_LV_GAUGE != 0
|
||||
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_txt.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_GAUGE_DEF_NEEDLE_COLOR LV_COLOR_RED
|
||||
#define LV_GAUGE_DEF_LABEL_COUNT 6
|
||||
#define LV_GAUGE_DEF_LINE_COUNT 21 /*Should be: ((label_cnt - 1) * internal_lines) + 1*/
|
||||
#define LV_GAUGE_DEF_ANGLE 220
|
||||
#define LV_GAUGE_INTERPOLATE_SHIFT 5 /*Interpolate the needle drawing between to degrees*/
|
||||
#define LV_GAUGE_INTERPOLATE_MASK 0x1F
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_gauge_design(lv_obj_t * gauge, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_gauge_signal(lv_obj_t * gauge, lv_signal_t sign, void * param);
|
||||
static void lv_gauge_draw_scale(lv_obj_t * gauge, const lv_area_t * mask);
|
||||
static void lv_gauge_draw_needle(lv_obj_t * gauge, const lv_area_t * mask);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_design_func_t ancestor_design;
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a gauge objects
|
||||
* @param par pointer to an object, it will be the parent of the new gauge
|
||||
* @param copy pointer to a gauge object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created gauge
|
||||
*/
|
||||
lv_obj_t * lv_gauge_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("gauge create started");
|
||||
|
||||
/*Create the ancestor gauge*/
|
||||
lv_obj_t * new_gauge = lv_lmeter_create(par, copy);
|
||||
lv_mem_assert(new_gauge);
|
||||
if(new_gauge == NULL) return NULL;
|
||||
|
||||
/*Allocate the gauge type specific extended data*/
|
||||
lv_gauge_ext_t * ext = lv_obj_allocate_ext_attr(new_gauge, sizeof(lv_gauge_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->needle_count = 0;
|
||||
ext->values = NULL;
|
||||
ext->needle_colors = NULL;
|
||||
ext->label_count = LV_GAUGE_DEF_LABEL_COUNT;
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_gauge);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_gauge);
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_gauge, lv_gauge_signal);
|
||||
lv_obj_set_design_func(new_gauge, lv_gauge_design);
|
||||
|
||||
/*Init the new gauge gauge*/
|
||||
if(copy == NULL) {
|
||||
lv_gauge_set_scale(new_gauge, LV_GAUGE_DEF_ANGLE, LV_GAUGE_DEF_LINE_COUNT, LV_GAUGE_DEF_LABEL_COUNT);
|
||||
lv_gauge_set_needle_count(new_gauge, 1, NULL);
|
||||
lv_gauge_set_critical_value(new_gauge, 80);
|
||||
lv_obj_set_size(new_gauge, 2 * LV_DPI, 2 * LV_DPI);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_gauge_set_style(new_gauge, th->gauge);
|
||||
} else {
|
||||
lv_gauge_set_style(new_gauge, &lv_style_pretty_color);
|
||||
}
|
||||
}
|
||||
/*Copy an existing gauge*/
|
||||
else {
|
||||
lv_gauge_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
lv_gauge_set_needle_count(new_gauge, copy_ext->needle_count, copy_ext->needle_colors);
|
||||
|
||||
uint8_t i;
|
||||
for(i = 0; i < ext->needle_count; i++) {
|
||||
ext->values[i] = copy_ext->values[i];
|
||||
}
|
||||
ext->label_count = copy_ext->label_count;
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_gauge);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("gauge created");
|
||||
|
||||
return new_gauge;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the number of needles
|
||||
* @param gauge pointer to gauge object
|
||||
* @param needle_cnt new count of needles
|
||||
* @param colors an array of colors for needles (with 'num' elements)
|
||||
*/
|
||||
void lv_gauge_set_needle_count(lv_obj_t * gauge, uint8_t needle_cnt, const lv_color_t * colors)
|
||||
{
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
|
||||
if(ext->needle_count != needle_cnt) {
|
||||
if(ext->values != NULL) {
|
||||
lv_mem_free(ext->values);
|
||||
ext->values = NULL;
|
||||
}
|
||||
|
||||
ext->values = lv_mem_realloc(ext->values, needle_cnt * sizeof(int16_t));
|
||||
lv_mem_assert(ext->values);
|
||||
if(ext->values == NULL) return;
|
||||
|
||||
int16_t min = lv_gauge_get_min_value(gauge);
|
||||
uint8_t n;
|
||||
for(n = ext->needle_count; n < needle_cnt; n++) {
|
||||
ext->values[n] = min;
|
||||
}
|
||||
|
||||
ext->needle_count = needle_cnt;
|
||||
}
|
||||
|
||||
ext->needle_colors = colors;
|
||||
lv_obj_invalidate(gauge);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a needle
|
||||
* @param gauge pointer to a gauge
|
||||
* @param needle_id the id of the needle
|
||||
* @param value the new value
|
||||
*/
|
||||
void lv_gauge_set_value(lv_obj_t * gauge, uint8_t needle_id, int16_t value)
|
||||
{
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
|
||||
if(needle_id >= ext->needle_count) return;
|
||||
if(ext->values[needle_id] == value) return;
|
||||
|
||||
|
||||
int16_t min = lv_gauge_get_min_value(gauge);
|
||||
int16_t max = lv_gauge_get_max_value(gauge);
|
||||
|
||||
if(value > max) value = max;
|
||||
else if(value < min) value = min;
|
||||
|
||||
ext->values[needle_id] = value;
|
||||
|
||||
|
||||
lv_obj_invalidate(gauge);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the scale settings of a gauge
|
||||
* @param gauge pointer to a gauge object
|
||||
* @param angle angle of the scale (0..360)
|
||||
* @param line_cnt count of scale lines.
|
||||
* The get a given "subdivision" lines between label, `line_cnt` = (sub_div + 1) * (label_cnt - 1) + 1
|
||||
* @param label_cnt count of scale labels.
|
||||
*/
|
||||
void lv_gauge_set_scale(lv_obj_t * gauge, uint16_t angle, uint8_t line_cnt, uint8_t label_cnt)
|
||||
{
|
||||
/*TODO v6.0: change `line_cnt` to `subdiv_cnt`*/
|
||||
|
||||
lv_lmeter_set_scale(gauge, angle, line_cnt);
|
||||
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
ext->label_count = label_cnt;
|
||||
lv_obj_invalidate(gauge);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the value of a needle
|
||||
* @param gauge pointer to gauge object
|
||||
* @param needle the id of the needle
|
||||
* @return the value of the needle [min,max]
|
||||
*/
|
||||
int16_t lv_gauge_get_value(const lv_obj_t * gauge, uint8_t needle)
|
||||
{
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
int16_t min = lv_gauge_get_min_value(gauge);
|
||||
|
||||
if(needle >= ext->needle_count) return min;
|
||||
|
||||
return ext->values[needle];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of needles on a gauge
|
||||
* @param gauge pointer to gauge
|
||||
* @return count of needles
|
||||
*/
|
||||
uint8_t lv_gauge_get_needle_count(const lv_obj_t * gauge)
|
||||
{
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
return ext->needle_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of labels (and the thicker lines too)
|
||||
* @param gauge pointer to a gauge object
|
||||
* @return count of labels
|
||||
*/
|
||||
uint8_t lv_gauge_get_label_count(const lv_obj_t * gauge)
|
||||
{
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
return ext->label_count;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the gauges
|
||||
* @param gauge pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_gauge_design(lv_obj_t * gauge, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return false;
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
|
||||
/* Store the real pointer because of 'lv_group'
|
||||
* If the object is in focus 'lv_obj_get_style()' will give a pointer to tmp style
|
||||
* and to the real object style. It is important because of style change tricks below*/
|
||||
lv_style_t * style_ori_p = gauge->style_p;
|
||||
lv_style_t * style = lv_obj_get_style(gauge);
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
|
||||
lv_gauge_draw_scale(gauge, mask);
|
||||
|
||||
/*Draw the ancestor line meter with max value to show the rainbow like line colors*/
|
||||
uint16_t line_cnt_tmp = ext->lmeter.line_cnt;
|
||||
ancestor_design(gauge, mask, mode); /*To draw lines*/
|
||||
|
||||
/*Temporally modify the line meter to draw thicker and longer lines where labels are*/
|
||||
lv_style_t style_tmp;
|
||||
lv_style_copy(&style_tmp, style);
|
||||
ext->lmeter.line_cnt = ext->label_count; /*Only to labels*/
|
||||
style_tmp.line.width = style_tmp.line.width * 2; /*Ticker lines*/
|
||||
style_tmp.body.padding.hor = style_tmp.body.padding.hor * 2; /*Longer lines*/
|
||||
gauge->style_p = &style_tmp;
|
||||
|
||||
ancestor_design(gauge, mask, mode); /*To draw lines*/
|
||||
|
||||
ext->lmeter.line_cnt = line_cnt_tmp; /*Restore the parameters*/
|
||||
gauge->style_p = style_ori_p; /*Restore the ORIGINAL style pointer*/
|
||||
|
||||
lv_gauge_draw_needle(gauge, mask);
|
||||
|
||||
}
|
||||
/*Post draw when the children are drawn*/
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
ancestor_design(gauge, mask, mode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the gauge
|
||||
* @param gauge pointer to a gauge object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_gauge_signal(lv_obj_t * gauge, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(gauge, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
lv_mem_free(ext->values);
|
||||
ext->values = NULL;
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_gauge";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the scale on a gauge
|
||||
* @param gauge pointer to gauge object
|
||||
* @param mask mask of drawing
|
||||
*/
|
||||
static void lv_gauge_draw_scale(lv_obj_t * gauge, const lv_area_t * mask)
|
||||
{
|
||||
char scale_txt[16];
|
||||
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
lv_style_t * style = lv_obj_get_style(gauge);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(gauge);
|
||||
lv_coord_t r = lv_obj_get_width(gauge) / 2 - (3 * style->body.padding.hor) - style->body.padding.inner;
|
||||
lv_coord_t x_ofs = lv_obj_get_width(gauge) / 2 + gauge->coords.x1;
|
||||
lv_coord_t y_ofs = lv_obj_get_height(gauge) / 2 + gauge->coords.y1;
|
||||
int16_t scale_angle = lv_lmeter_get_scale_angle(gauge);
|
||||
uint16_t label_num = ext->label_count;
|
||||
int16_t angle_ofs = 90 + (360 - scale_angle) / 2;
|
||||
int16_t min = lv_gauge_get_min_value(gauge);
|
||||
int16_t max = lv_gauge_get_max_value(gauge);
|
||||
|
||||
uint8_t i;
|
||||
for(i = 0; i < label_num; i++) {
|
||||
/*Calculate the position a scale label*/
|
||||
int16_t angle = (i * scale_angle) / (label_num - 1) + angle_ofs;
|
||||
|
||||
lv_coord_t y = (int32_t)((int32_t)lv_trigo_sin(angle) * r) / LV_TRIGO_SIN_MAX;
|
||||
y += y_ofs;
|
||||
|
||||
lv_coord_t x = (int32_t)((int32_t)lv_trigo_sin(angle + 90) * r) / LV_TRIGO_SIN_MAX;
|
||||
x += x_ofs;
|
||||
|
||||
int16_t scale_act = (int32_t)((int32_t)(max - min) * i) / (label_num - 1);
|
||||
scale_act += min;
|
||||
lv_math_num_to_str(scale_act, scale_txt);
|
||||
|
||||
lv_area_t label_cord;
|
||||
lv_point_t label_size;
|
||||
lv_txt_get_size(&label_size, scale_txt, style->text.font,
|
||||
style->text.letter_space, style->text.line_space, LV_COORD_MAX, LV_TXT_FLAG_NONE);
|
||||
|
||||
/*Draw the label*/
|
||||
label_cord.x1 = x - label_size.x / 2;
|
||||
label_cord.y1 = y - label_size.y / 2;
|
||||
label_cord.x2 = label_cord.x1 + label_size.x;
|
||||
label_cord.y2 = label_cord.y1 + label_size.y;
|
||||
|
||||
lv_draw_label(&label_cord, mask, style, opa_scale, scale_txt, LV_TXT_FLAG_NONE, NULL);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Draw the needles of a gauge
|
||||
* @param gauge pointer to gauge object
|
||||
* @param mask mask of drawing
|
||||
*/
|
||||
static void lv_gauge_draw_needle(lv_obj_t * gauge, const lv_area_t * mask)
|
||||
{
|
||||
lv_style_t style_needle;
|
||||
lv_gauge_ext_t * ext = lv_obj_get_ext_attr(gauge);
|
||||
lv_style_t * style = lv_gauge_get_style(gauge);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(gauge);
|
||||
|
||||
lv_coord_t r = lv_obj_get_width(gauge) / 2 - style->body.padding.hor;
|
||||
lv_coord_t x_ofs = lv_obj_get_width(gauge) / 2 + gauge->coords.x1;
|
||||
lv_coord_t y_ofs = lv_obj_get_height(gauge) / 2 + gauge->coords.y1;
|
||||
uint16_t angle = lv_lmeter_get_scale_angle(gauge);
|
||||
int16_t angle_ofs = 90 + (360 - angle) / 2;
|
||||
int16_t min = lv_gauge_get_min_value(gauge);
|
||||
int16_t max = lv_gauge_get_max_value(gauge);
|
||||
lv_point_t p_mid;
|
||||
lv_point_t p_end;
|
||||
lv_point_t p_end_low;
|
||||
lv_point_t p_end_high;
|
||||
uint8_t i;
|
||||
|
||||
lv_style_copy(&style_needle, style);
|
||||
|
||||
p_mid.x = x_ofs;
|
||||
p_mid.y = y_ofs;
|
||||
for(i = 0; i < ext->needle_count; i++) {
|
||||
/*Calculate the end point of a needle*/
|
||||
int16_t needle_angle = (ext->values[i] - min) * angle * (1 << LV_GAUGE_INTERPOLATE_SHIFT) / (max - min); //+ angle_ofs;
|
||||
|
||||
|
||||
int16_t needle_angle_low = (needle_angle >> LV_GAUGE_INTERPOLATE_SHIFT) + angle_ofs;
|
||||
int16_t needle_angle_high = needle_angle_low + 1;
|
||||
|
||||
|
||||
p_end_low.y = (lv_trigo_sin(needle_angle_low) * r) / LV_TRIGO_SIN_MAX + y_ofs;
|
||||
p_end_low.x = (lv_trigo_sin(needle_angle_low + 90) * r) / LV_TRIGO_SIN_MAX + x_ofs;
|
||||
|
||||
p_end_high.y = (lv_trigo_sin(needle_angle_high) * r) / LV_TRIGO_SIN_MAX + y_ofs;
|
||||
p_end_high.x = (lv_trigo_sin(needle_angle_high + 90) * r) / LV_TRIGO_SIN_MAX + x_ofs;
|
||||
|
||||
uint16_t rem = needle_angle & ((1 << LV_GAUGE_INTERPOLATE_SHIFT) - 1);
|
||||
int16_t x_mod = ((LV_MATH_ABS(p_end_high.x - p_end_low.x)) * rem) >> LV_GAUGE_INTERPOLATE_SHIFT;
|
||||
int16_t y_mod = ((LV_MATH_ABS(p_end_high.y - p_end_low.y)) * rem) >> LV_GAUGE_INTERPOLATE_SHIFT;
|
||||
|
||||
if(p_end_high.x < p_end_low.x) x_mod = -x_mod;
|
||||
if(p_end_high.y < p_end_low.y) y_mod = -y_mod;
|
||||
|
||||
p_end.x = p_end_low.x + x_mod;
|
||||
p_end.y = p_end_low.y + y_mod;
|
||||
|
||||
/*Draw the needle with the corresponding color*/
|
||||
if(ext->needle_colors == NULL) style_needle.line.color = LV_GAUGE_DEF_NEEDLE_COLOR;
|
||||
else style_needle.line.color = ext->needle_colors[i];
|
||||
|
||||
lv_draw_line(&p_mid, &p_end, mask, &style_needle, opa_scale);
|
||||
}
|
||||
|
||||
/*Draw the needle middle area*/
|
||||
lv_style_t style_neddle_mid;
|
||||
lv_style_copy(&style_neddle_mid, &lv_style_plain);
|
||||
style_neddle_mid.body.main_color = style->body.border.color;
|
||||
style_neddle_mid.body.grad_color = style->body.border.color;
|
||||
style_neddle_mid.body.radius = LV_RADIUS_CIRCLE;
|
||||
|
||||
lv_area_t nm_cord;
|
||||
nm_cord.x1 = x_ofs - style->body.padding.ver;
|
||||
nm_cord.y1 = y_ofs - style->body.padding.ver;
|
||||
nm_cord.x2 = x_ofs + style->body.padding.ver;
|
||||
nm_cord.y2 = y_ofs + style->body.padding.ver;
|
||||
|
||||
lv_draw_rect(&nm_cord, mask, &style_neddle_mid, lv_obj_get_opa_scale(gauge));
|
||||
}
|
||||
|
||||
#endif
|
222
bdk/libs/lvgl/lv_objx/lv_gauge.h
Normal file
222
bdk/libs/lvgl/lv_objx/lv_gauge.h
Normal file
|
@ -0,0 +1,222 @@
|
|||
/**
|
||||
* @file lv_gauge.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_GAUGE_H
|
||||
#define LV_GAUGE_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_GAUGE != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_LMETER == 0
|
||||
#error "lv_gauge: lv_lmeter is required. Enable it in lv_conf.h (USE_LV_LMETER 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_lmeter.h"
|
||||
#include "lv_label.h"
|
||||
#include "lv_line.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Data of gauge*/
|
||||
typedef struct
|
||||
{
|
||||
lv_lmeter_ext_t lmeter; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
int16_t * values; /*Array of the set values (for needles) */
|
||||
const lv_color_t * needle_colors; /*Color of the needles (lv_color_t my_colors[needle_num])*/
|
||||
uint8_t needle_count; /*Number of needles*/
|
||||
uint8_t label_count; /*Number of labels on the scale*/
|
||||
} lv_gauge_ext_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a gauge objects
|
||||
* @param par pointer to an object, it will be the parent of the new gauge
|
||||
* @param copy pointer to a gauge object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created gauge
|
||||
*/
|
||||
lv_obj_t * lv_gauge_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the number of needles
|
||||
* @param gauge pointer to gauge object
|
||||
* @param needle_cnt new count of needles
|
||||
* @param colors an array of colors for needles (with 'num' elements)
|
||||
*/
|
||||
void lv_gauge_set_needle_count(lv_obj_t * gauge, uint8_t needle_cnt, const lv_color_t * colors);
|
||||
|
||||
/**
|
||||
* Set the value of a needle
|
||||
* @param gauge pointer to a gauge
|
||||
* @param needle_id the id of the needle
|
||||
* @param value the new value
|
||||
*/
|
||||
void lv_gauge_set_value(lv_obj_t * gauge, uint8_t needle_id, int16_t value);
|
||||
|
||||
/**
|
||||
* Set minimum and the maximum values of a gauge
|
||||
* @param gauge pointer to he gauge object
|
||||
* @param min minimum value
|
||||
* @param max maximum value
|
||||
*/
|
||||
static inline void lv_gauge_set_range(lv_obj_t *gauge, int16_t min, int16_t max)
|
||||
{
|
||||
lv_lmeter_set_range(gauge, min, max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a critical value on the scale. After this value 'line.color' scale lines will be drawn
|
||||
* @param gauge pointer to a gauge object
|
||||
* @param value the critical value
|
||||
*/
|
||||
static inline void lv_gauge_set_critical_value(lv_obj_t * gauge, int16_t value)
|
||||
{
|
||||
lv_lmeter_set_value(gauge, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scale settings of a gauge
|
||||
* @param gauge pointer to a gauge object
|
||||
* @param angle angle of the scale (0..360)
|
||||
* @param line_cnt count of scale lines.
|
||||
* The get a given "subdivision" lines between label, `line_cnt` = (sub_div + 1) * (label_cnt - 1) + 1
|
||||
* @param label_cnt count of scale labels.
|
||||
*/
|
||||
void lv_gauge_set_scale(lv_obj_t * gauge, uint16_t angle, uint8_t line_cnt, uint8_t label_cnt);
|
||||
|
||||
/**
|
||||
* Set the styles of a gauge
|
||||
* @param gauge pointer to a gauge object
|
||||
* @param bg set the style of the gauge
|
||||
* */
|
||||
static inline void lv_gauge_set_style(lv_obj_t *gauge, lv_style_t *bg)
|
||||
{
|
||||
lv_obj_set_style(gauge, bg);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the value of a needle
|
||||
* @param gauge pointer to gauge object
|
||||
* @param needle the id of the needle
|
||||
* @return the value of the needle [min,max]
|
||||
*/
|
||||
int16_t lv_gauge_get_value(const lv_obj_t * gauge, uint8_t needle);
|
||||
|
||||
/**
|
||||
* Get the count of needles on a gauge
|
||||
* @param gauge pointer to gauge
|
||||
* @return count of needles
|
||||
*/
|
||||
uint8_t lv_gauge_get_needle_count(const lv_obj_t * gauge);
|
||||
|
||||
/**
|
||||
* Get the minimum value of a gauge
|
||||
* @param gauge pointer to a gauge object
|
||||
* @return the minimum value of the gauge
|
||||
*/
|
||||
static inline int16_t lv_gauge_get_min_value(const lv_obj_t * lmeter)
|
||||
{
|
||||
return lv_lmeter_get_min_value(lmeter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum value of a gauge
|
||||
* @param gauge pointer to a gauge object
|
||||
* @return the maximum value of the gauge
|
||||
*/
|
||||
static inline int16_t lv_gauge_get_max_value(const lv_obj_t * lmeter)
|
||||
{
|
||||
return lv_lmeter_get_max_value(lmeter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a critical value on the scale.
|
||||
* @param gauge pointer to a gauge object
|
||||
* @return the critical value
|
||||
*/
|
||||
static inline int16_t lv_gauge_get_critical_value(const lv_obj_t * gauge)
|
||||
{
|
||||
return lv_lmeter_get_value(gauge);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of labels (and the thicker lines too)
|
||||
* @param gauge pointer to a gauge object
|
||||
* @return count of labels
|
||||
*/
|
||||
uint8_t lv_gauge_get_label_count(const lv_obj_t * gauge);
|
||||
|
||||
/**
|
||||
* Get the scale number of a gauge
|
||||
* @param gauge pointer to a gauge object
|
||||
* @return number of the scale units
|
||||
*/
|
||||
static inline uint8_t lv_gauge_get_line_count(const lv_obj_t * gauge)
|
||||
{
|
||||
return lv_lmeter_get_line_count(gauge);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scale angle of a gauge
|
||||
* @param gauge pointer to a gauge object
|
||||
* @return angle of the scale
|
||||
*/
|
||||
static inline uint16_t lv_gauge_get_scale_angle(const lv_obj_t * gauge)
|
||||
{
|
||||
return lv_lmeter_get_scale_angle(gauge);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the style of a gauge
|
||||
* @param gauge pointer to a gauge object
|
||||
* @return pointer to the gauge's style
|
||||
*/
|
||||
static inline lv_style_t * lv_gauge_get_style(const lv_obj_t *gauge)
|
||||
{
|
||||
return lv_obj_get_style(gauge);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_GAUGE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_GAUGE_H*/
|
408
bdk/libs/lvgl/lv_objx/lv_img.c
Normal file
408
bdk/libs/lvgl/lv_objx/lv_img.c
Normal file
|
@ -0,0 +1,408 @@
|
|||
/**
|
||||
* @file lv_img.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_img.h"
|
||||
#if USE_LV_IMG != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_LABEL == 0
|
||||
#error "lv_img: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_lang.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_fs.h"
|
||||
#include "../lv_misc/lv_ufs.h"
|
||||
#include "../lv_misc/lv_txt.h"
|
||||
#include "../lv_misc/lv_log.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_img_design(lv_obj_t * img, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_img_signal(lv_obj_t * img, lv_signal_t sign, void * param);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create an image objects
|
||||
* @param par pointer to an object, it will be the parent of the new button
|
||||
* @param copy pointer to a image object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created image
|
||||
*/
|
||||
lv_obj_t * lv_img_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("image create started");
|
||||
|
||||
lv_obj_t * new_img = NULL;
|
||||
|
||||
/*Create a basic object*/
|
||||
new_img = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_img);
|
||||
if(new_img == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_img);
|
||||
|
||||
/*Extend the basic object to image object*/
|
||||
lv_img_ext_t * ext = lv_obj_allocate_ext_attr(new_img, sizeof(lv_img_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->src = NULL;
|
||||
ext->src_type = LV_IMG_SRC_UNKNOWN;
|
||||
ext->cf = LV_IMG_CF_UNKOWN;
|
||||
ext->w = lv_obj_get_width(new_img);
|
||||
ext->h = lv_obj_get_height(new_img);
|
||||
ext->auto_size = 1;
|
||||
#if USE_LV_MULTI_LANG
|
||||
ext->lang_txt_id = LV_LANG_TXT_ID_NONE;
|
||||
#endif
|
||||
|
||||
/*Init the new object*/
|
||||
lv_obj_set_signal_func(new_img, lv_img_signal);
|
||||
lv_obj_set_design_func(new_img, lv_img_design);
|
||||
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_click(new_img, false);
|
||||
/* Enable auto size for non screens
|
||||
* because image screens are wallpapers
|
||||
* and must be screen sized*/
|
||||
if(par != NULL) {
|
||||
ext->auto_size = 1;
|
||||
lv_obj_set_style(new_img, NULL); /*Inherit the style by default*/
|
||||
} else {
|
||||
ext->auto_size = 0;
|
||||
lv_obj_set_style(new_img, &lv_style_plain); /*Set a style for screens*/
|
||||
}
|
||||
} else {
|
||||
lv_img_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->auto_size = copy_ext->auto_size;
|
||||
lv_img_set_src(new_img, copy_ext->src);
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_img);
|
||||
}
|
||||
|
||||
|
||||
LV_LOG_INFO("image created");
|
||||
|
||||
return new_img;
|
||||
}
|
||||
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
|
||||
/**
|
||||
* Set the pixel map to display by the image
|
||||
* @param img pointer to an image object
|
||||
* @param data the image data
|
||||
*/
|
||||
void lv_img_set_src(lv_obj_t * img, const void * src_img)
|
||||
{
|
||||
lv_img_src_t src_type = lv_img_src_get_type(src_img);
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
#if LV_LOG_LEVEL >= LV_LOG_LEVEL_INFO
|
||||
switch(src_type) {
|
||||
case LV_IMG_SRC_FILE:
|
||||
LV_LOG_TRACE("lv_img_set_src: `LV_IMG_SRC_FILE` type found");
|
||||
break;
|
||||
case LV_IMG_SRC_VARIABLE:
|
||||
LV_LOG_TRACE("lv_img_set_src: `LV_IMG_SRC_VARIABLE` type found");
|
||||
break;
|
||||
case LV_IMG_SRC_SYMBOL:
|
||||
LV_LOG_TRACE("lv_img_set_src: `LV_IMG_SRC_SYMBOL` type found");
|
||||
break;
|
||||
default:
|
||||
LV_LOG_WARN("lv_img_set_src: unknown type");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*If the new source type is unknown free the memories of the old source*/
|
||||
if(src_type == LV_IMG_SRC_UNKNOWN) {
|
||||
LV_LOG_WARN("lv_img_set_src: unknown image type");
|
||||
if(ext->src_type == LV_IMG_SRC_SYMBOL || ext->src_type == LV_IMG_SRC_FILE) {
|
||||
lv_mem_free(ext->src);
|
||||
}
|
||||
ext->src = NULL;
|
||||
ext->src_type = LV_IMG_SRC_UNKNOWN;
|
||||
return;
|
||||
}
|
||||
|
||||
lv_img_header_t header;
|
||||
lv_img_dsc_get_info(src_img, &header);
|
||||
|
||||
|
||||
|
||||
/*Save the source*/
|
||||
if(src_type == LV_IMG_SRC_VARIABLE) {
|
||||
LV_LOG_INFO("lv_img_set_src: `LV_IMG_SRC_VARIABLE` type found");
|
||||
|
||||
/*If memory was allocated because of the previous `src_type` then free it*/
|
||||
if(ext->src_type == LV_IMG_SRC_FILE || ext->src_type == LV_IMG_SRC_SYMBOL) {
|
||||
lv_mem_free(ext->src);
|
||||
}
|
||||
ext->src = src_img;
|
||||
} else if(src_type == LV_IMG_SRC_FILE || src_type == LV_IMG_SRC_SYMBOL) {
|
||||
/* If the new and the old src are the same then it was only a refresh.*/
|
||||
if(ext->src != src_img) {
|
||||
/*If memory was allocated because of the previous `src_type` then free it*/
|
||||
if(ext->src_type == LV_IMG_SRC_FILE || ext->src_type == LV_IMG_SRC_SYMBOL) {
|
||||
lv_mem_free(ext->src);
|
||||
}
|
||||
char * new_str = lv_mem_alloc(strlen(src_img) + 1);
|
||||
lv_mem_assert(new_str);
|
||||
if(new_str == NULL) return;
|
||||
strcpy(new_str, src_img);
|
||||
ext->src = new_str;
|
||||
}
|
||||
}
|
||||
|
||||
if(src_type == LV_IMG_SRC_SYMBOL) {
|
||||
/*`lv_img_dsc_get_info` couldn't set the with and height of a font so set it here*/
|
||||
lv_style_t * style = lv_img_get_style(img);
|
||||
lv_point_t size;
|
||||
lv_txt_get_size(&size, src_img, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, LV_TXT_FLAG_NONE);
|
||||
header.w = size.x;
|
||||
header.h = size.y;
|
||||
}
|
||||
|
||||
ext->src_type = src_type;
|
||||
ext->w = header.w;
|
||||
ext->h = header.h;
|
||||
ext->cf = header.cf;
|
||||
|
||||
if(lv_img_get_auto_size(img) != false) {
|
||||
lv_obj_set_size(img, ext->w, ext->h);
|
||||
}
|
||||
|
||||
lv_obj_invalidate(img);
|
||||
}
|
||||
|
||||
#if USE_LV_MULTI_LANG
|
||||
/**
|
||||
* Set an ID which means a the same source but in different languages
|
||||
* @param img pointer to an image object
|
||||
* @param src_id ID of the source
|
||||
*/
|
||||
void lv_img_set_src_id(lv_obj_t * img, uint32_t src_id)
|
||||
{
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
ext->lang_txt_id = src_id;
|
||||
|
||||
/*Apply the new language*/
|
||||
img->signal_func(img, LV_SIGNAL_LANG_CHG, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Enable the auto size feature.
|
||||
* If enabled the object size will be same as the picture size.
|
||||
* @param img pointer to an image
|
||||
* @param en true: auto size enable, false: auto size disable
|
||||
*/
|
||||
void lv_img_set_auto_size(lv_obj_t * img, bool en)
|
||||
{
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
ext->auto_size = (en == false ? 0 : 1);
|
||||
}
|
||||
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
|
||||
/**
|
||||
* Get the source of the image
|
||||
* @param img pointer to an image object
|
||||
* @return the image source (symbol, file name or C array)
|
||||
*/
|
||||
const void * lv_img_get_src(lv_obj_t * img)
|
||||
{
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
return ext->src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the file set for an image
|
||||
* @param img pointer to an image
|
||||
* @return file name
|
||||
*/
|
||||
const char * lv_img_get_file_name(const lv_obj_t * img)
|
||||
{
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
if(ext->src_type == LV_IMG_SRC_FILE) return ext->src;
|
||||
else return "";
|
||||
}
|
||||
|
||||
#if USE_LV_MULTI_LANG
|
||||
/**
|
||||
* Get the source ID of the image. (Used by the multi-language feature)
|
||||
* @param img pointer to an image
|
||||
* @return ID of the source
|
||||
*/
|
||||
uint16_t lv_img_get_src_id(lv_obj_t * img)
|
||||
{
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
return ext->lang_txt_id;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get the auto size enable attribute
|
||||
* @param img pointer to an image
|
||||
* @return true: auto size is enabled, false: auto size is disabled
|
||||
*/
|
||||
bool lv_img_get_auto_size(const lv_obj_t * img)
|
||||
{
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
return ext->auto_size == 0 ? false : true;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the images
|
||||
* @param img pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_img_design(lv_obj_t * img, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
lv_style_t * style = lv_obj_get_style(img);
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
bool cover = false;
|
||||
if(ext->src_type == LV_IMG_SRC_UNKNOWN || ext->src_type == LV_IMG_SRC_SYMBOL) return false;
|
||||
|
||||
if(ext->cf == LV_IMG_CF_TRUE_COLOR || ext->cf == LV_IMG_CF_RAW) cover = lv_area_is_in(mask, &img->coords);
|
||||
|
||||
return cover;
|
||||
} else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
if(ext->h == 0 || ext->w == 0) return true;
|
||||
lv_area_t coords;
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(img);
|
||||
|
||||
lv_obj_get_coords(img, &coords);
|
||||
|
||||
if(ext->src_type == LV_IMG_SRC_FILE || ext->src_type == LV_IMG_SRC_VARIABLE) {
|
||||
LV_LOG_TRACE("lv_img_design: start to draw image");
|
||||
lv_area_t cords_tmp;
|
||||
cords_tmp.y1 = coords.y1;
|
||||
cords_tmp.y2 = coords.y1 + ext->h - 1;
|
||||
|
||||
for(; cords_tmp.y1 < coords.y2; cords_tmp.y1 += ext->h, cords_tmp.y2 += ext->h) {
|
||||
cords_tmp.x1 = coords.x1;
|
||||
cords_tmp.x2 = coords.x1 + ext->w - 1;
|
||||
for(; cords_tmp.x1 < coords.x2; cords_tmp.x1 += ext->w, cords_tmp.x2 += ext->w) {
|
||||
lv_draw_img(&cords_tmp, mask, ext->src, style, opa_scale);
|
||||
}
|
||||
}
|
||||
} else if(ext->src_type == LV_IMG_SRC_SYMBOL) {
|
||||
LV_LOG_TRACE("lv_img_design: start to draw symbol");
|
||||
lv_style_t style_mod;
|
||||
lv_style_copy(&style_mod, style);
|
||||
style_mod.text.color = style->image.color;
|
||||
lv_draw_label(&coords, mask, &style_mod, opa_scale, ext->src, LV_TXT_FLAG_NONE, NULL);
|
||||
} else {
|
||||
/*Trigger the error handler of image drawer*/
|
||||
LV_LOG_WARN("lv_img_design: image source type is unknown");
|
||||
lv_draw_img(&img->coords, mask, NULL, style, opa_scale);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Signal function of the image
|
||||
* @param img pointer to an image object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_img_signal(lv_obj_t * img, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(img, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
if(ext->src_type == LV_IMG_SRC_FILE || ext->src_type == LV_IMG_SRC_SYMBOL) {
|
||||
lv_mem_free(ext->src);
|
||||
ext->src = NULL;
|
||||
ext->src_type = LV_IMG_SRC_UNKNOWN;
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
/*Refresh the file name to refresh the symbol text size*/
|
||||
if(ext->src_type == LV_IMG_SRC_SYMBOL) {
|
||||
lv_img_set_src(img, ext->src);
|
||||
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_LANG_CHG) {
|
||||
#if USE_LV_MULTI_LANG
|
||||
if(ext->lang_txt_id != LV_LANG_TXT_ID_NONE) {
|
||||
const char * lang_src = lv_lang_get_text(ext->lang_txt_id);
|
||||
if(lang_src) {
|
||||
lv_img_set_src(img, lang_src);
|
||||
} else {
|
||||
LV_LOG_WARN("lv_lang_get_text return NULL for an image's source");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_img";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
195
bdk/libs/lvgl/lv_objx/lv_img.h
Normal file
195
bdk/libs/lvgl/lv_objx/lv_img.h
Normal file
|
@ -0,0 +1,195 @@
|
|||
/**
|
||||
* @file lv_img.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_IMG_H
|
||||
#define LV_IMG_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_IMG != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_misc/lv_fs.h"
|
||||
#include "../lv_misc/lv_symbol_def.h"
|
||||
#include "lv_label.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Data of image*/
|
||||
typedef struct
|
||||
{
|
||||
/*No inherited ext. because inherited from the base object*/ /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
const void * src; /*Image source: Pointer to an array or a file or a symbol*/
|
||||
|
||||
lv_coord_t w; /*Width of the image (Handled by the library)*/
|
||||
lv_coord_t h; /*Height of the image (Handled by the library)*/
|
||||
#if USE_LV_MULTI_LANG
|
||||
uint16_t lang_txt_id; /*The ID of the image to display. */
|
||||
#endif
|
||||
uint8_t src_type :2; /*See: lv_img_src_t*/
|
||||
uint8_t auto_size :1; /*1: automatically set the object size to the image size*/
|
||||
uint8_t cf :5; /*Color format from `lv_img_color_format_t`*/
|
||||
} lv_img_ext_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create an image objects
|
||||
* @param par pointer to an object, it will be the parent of the new button
|
||||
* @param copy pointer to a image object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created image
|
||||
*/
|
||||
lv_obj_t * lv_img_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the pixel map to display by the image
|
||||
* @param img pointer to an image object
|
||||
* @param data the image data
|
||||
*/
|
||||
void lv_img_set_src(lv_obj_t * img, const void * src_img);
|
||||
|
||||
#if USE_LV_MULTI_LANG
|
||||
/**
|
||||
* Set an ID which means a the same source but on different languages
|
||||
* @param img pointer to an image object
|
||||
* @param src_id ID of the source
|
||||
*/
|
||||
void lv_img_set_src_id(lv_obj_t * img, uint32_t txt_id);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Obsolete since v5.1. Just for compatibility with v5.0. Will be removed in v6.0.
|
||||
* Use 'lv_img_set_src()' instead.
|
||||
* @param img -
|
||||
* @param fn -
|
||||
*/
|
||||
static inline void lv_img_set_file(lv_obj_t * img, const char * fn)
|
||||
{
|
||||
(void) img;
|
||||
(void) fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the auto size feature.
|
||||
* If enabled the object size will be same as the picture size.
|
||||
* @param img pointer to an image
|
||||
* @param en true: auto size enable, false: auto size disable
|
||||
*/
|
||||
void lv_img_set_auto_size(lv_obj_t * img, bool autosize_en);
|
||||
|
||||
/**
|
||||
* Set the style of an image
|
||||
* @param img pointer to an image object
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
static inline void lv_img_set_style(lv_obj_t *img, lv_style_t *style)
|
||||
{
|
||||
lv_obj_set_style(img, style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obsolete since v5.1. Just for compatibility with v5.0. Will be removed in v6.0
|
||||
* @param img -
|
||||
* @param upscale -
|
||||
*/
|
||||
static inline void lv_img_set_upscale(lv_obj_t * img, bool upcale)
|
||||
{
|
||||
(void) img;
|
||||
(void) upcale;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the source of the image
|
||||
* @param img pointer to an image object
|
||||
* @return the image source (symbol, file name or C array)
|
||||
*/
|
||||
const void * lv_img_get_src(lv_obj_t * img);
|
||||
|
||||
/**
|
||||
* Get the name of the file set for an image
|
||||
* @param img pointer to an image
|
||||
* @return file name
|
||||
*/
|
||||
const char * lv_img_get_file_name(const lv_obj_t * img);
|
||||
|
||||
#if USE_LV_MULTI_LANG
|
||||
/**
|
||||
* Get the source ID of the image. (Used by the multi-language feature)
|
||||
* @param img pointer to an image
|
||||
* @return ID of the source
|
||||
*/
|
||||
uint16_t lv_img_get_src_id(lv_obj_t * img);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get the auto size enable attribute
|
||||
* @param img pointer to an image
|
||||
* @return true: auto size is enabled, false: auto size is disabled
|
||||
*/
|
||||
bool lv_img_get_auto_size(const lv_obj_t * img);
|
||||
|
||||
/**
|
||||
* Get the style of an image object
|
||||
* @param img pointer to an image object
|
||||
* @return pointer to the image's style
|
||||
*/
|
||||
static inline lv_style_t* lv_img_get_style(const lv_obj_t *img)
|
||||
{
|
||||
return lv_obj_get_style(img);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obsolete since v5.1. Just for compatibility with v5.0. Will be removed in v6.0
|
||||
* @param img -
|
||||
* @return false
|
||||
*/
|
||||
static inline bool lv_img_get_upscale(const lv_obj_t * img)
|
||||
{
|
||||
(void)img;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/*Use this macro to declare an image in a c file*/
|
||||
#define LV_IMG_DECLARE(var_name) extern const lv_img_dsc_t var_name;
|
||||
|
||||
#endif /*USE_LV_IMG*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_IMG_H*/
|
391
bdk/libs/lvgl/lv_objx/lv_imgbtn.c
Normal file
391
bdk/libs/lvgl/lv_objx/lv_imgbtn.c
Normal file
|
@ -0,0 +1,391 @@
|
|||
/**
|
||||
* @file lv_imgbtn.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_imgbtn.h"
|
||||
#if USE_LV_IMGBTN != 0
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_imgbtn_signal(lv_obj_t * imgbtn, lv_signal_t sign, void * param);
|
||||
static void refr_img(lv_obj_t * imgbtn);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
static lv_design_func_t ancestor_design;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a image button object
|
||||
* @param par pointer to an object, it will be the parent of the new image button
|
||||
* @param copy pointer to a image button object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created image button
|
||||
*/
|
||||
lv_obj_t * lv_imgbtn_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("image button create started");
|
||||
|
||||
/*Create the ancestor of image button*/
|
||||
lv_obj_t * new_imgbtn = lv_btn_create(par, copy);
|
||||
lv_mem_assert(new_imgbtn);
|
||||
if(new_imgbtn == NULL) return NULL;
|
||||
|
||||
/*Allocate the image button type specific extended data*/
|
||||
lv_imgbtn_ext_t * ext = lv_obj_allocate_ext_attr(new_imgbtn, sizeof(lv_imgbtn_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_imgbtn);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_imgbtn);
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
#if LV_IMGBTN_TILED == 0
|
||||
memset(ext->img_src, 0, sizeof(ext->img_src));
|
||||
#else
|
||||
memset(ext->img_src_left, 0, sizeof(ext->img_src_left));
|
||||
memset(ext->img_src_mid, 0, sizeof(ext->img_src_mid));
|
||||
memset(ext->img_src_right, 0, sizeof(ext->img_src_right));
|
||||
#endif
|
||||
|
||||
ext->act_cf = LV_IMG_CF_UNKOWN;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_imgbtn, lv_imgbtn_signal);
|
||||
lv_obj_set_design_func(new_imgbtn, lv_imgbtn_design);
|
||||
|
||||
/*Init the new image button image button*/
|
||||
if(copy == NULL) {
|
||||
|
||||
}
|
||||
/*Copy an existing image button*/
|
||||
else {
|
||||
lv_imgbtn_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
#if LV_IMGBTN_TILED == 0
|
||||
memcpy(ext->img_src, copy_ext->img_src, sizeof(ext->img_src));
|
||||
#else
|
||||
memcpy(ext->img_src_left, copy_ext->img_src_left, sizeof(ext->img_src_left));
|
||||
memcpy(ext->img_src_mid, copy_ext->img_src_mid, sizeof(ext->img_src_mid));
|
||||
memcpy(ext->img_src_right, copy_ext->img_src_right, sizeof(ext->img_src_right));
|
||||
#endif
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_imgbtn);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("image button created");
|
||||
|
||||
return new_imgbtn;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
#if LV_IMGBTN_TILED == 0
|
||||
/**
|
||||
* Set images for a state of the image button
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param state for which state set the new image (from `lv_btn_state_t`) `
|
||||
* @param src pointer to an image source (a C array or path to a file)
|
||||
*/
|
||||
void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src)
|
||||
{
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
|
||||
ext->img_src[state] = src;
|
||||
|
||||
refr_img(imgbtn);
|
||||
}
|
||||
|
||||
#else
|
||||
/**
|
||||
* Set images for a state of the image button
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param state for which state set the new image (from `lv_btn_state_t`) `
|
||||
* @param src_left pointer to an image source for the left side of the button (a C array or path to a file)
|
||||
* @param src_mid pointer to an image source for the middle of the button (ideally 1px wide) (a C array or path to a file)
|
||||
* @param src_right pointer to an image source for the right side of the button (a C array or path to a file)
|
||||
*/
|
||||
void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src_left, const void * src_mid, const void * src_right)
|
||||
{
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
|
||||
ext->img_src_left[state] = src_left;
|
||||
ext->img_src_mid[state] = src_mid;
|
||||
ext->img_src_right[state] = src_right;
|
||||
|
||||
refr_img(imgbtn);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set a style of a image button.
|
||||
* @param imgbtn pointer to image button object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_imgbtn_set_style(lv_obj_t * imgbtn, lv_imgbtn_style_t type, lv_style_t * style)
|
||||
{
|
||||
lv_btn_set_style(imgbtn, type, style);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
#if LV_IMGBTN_TILED == 0
|
||||
/**
|
||||
* Get the images in a given state
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param state the state where to get the image (from `lv_btn_state_t`) `
|
||||
* @return pointer to an image source (a C array or path to a file)
|
||||
*/
|
||||
const void * lv_imgbtn_get_src(lv_obj_t * imgbtn, lv_btn_state_t state)
|
||||
{
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
|
||||
return ext->img_src[state];
|
||||
}
|
||||
#else
|
||||
|
||||
/**
|
||||
* Get the left image in a given state
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param state the state where to get the image (from `lv_btn_state_t`) `
|
||||
* @return pointer to the left image source (a C array or path to a file)
|
||||
*/
|
||||
const void * lv_imgbtn_get_src_left(lv_obj_t * imgbtn, lv_btn_state_t state)
|
||||
{
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
|
||||
return ext->img_src_left[state];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the middle image in a given state
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param state the state where to get the image (from `lv_btn_state_t`) `
|
||||
* @return pointer to the middle image source (a C array or path to a file)
|
||||
*/
|
||||
const void * lv_imgbtn_get_src_middle(lv_obj_t * imgbtn, lv_btn_state_t state)
|
||||
{
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
|
||||
return ext->img_src_mid[state];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the right image in a given state
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param state the state where to get the image (from `lv_btn_state_t`) `
|
||||
* @return pointer to the left image source (a C array or path to a file)
|
||||
*/
|
||||
const void * lv_imgbtn_get_src_right(lv_obj_t * imgbtn, lv_btn_state_t state)
|
||||
{
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
|
||||
return ext->img_src_right[state];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get style of a image button.
|
||||
* @param imgbtn pointer to image button object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
*/
|
||||
lv_style_t * lv_imgbtn_get_style(const lv_obj_t * imgbtn, lv_imgbtn_style_t type)
|
||||
{
|
||||
return lv_btn_get_style(imgbtn, type);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/*
|
||||
* New object specific "other" functions come here
|
||||
*/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the image buttons
|
||||
* @param imgbtn pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
bool cover = false;
|
||||
if(ext->act_cf == LV_IMG_CF_TRUE_COLOR || ext->act_cf == LV_IMG_CF_RAW) {
|
||||
cover = lv_area_is_in(mask, &imgbtn->coords);
|
||||
}
|
||||
|
||||
return cover;
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
/*Just draw an image*/
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
lv_btn_state_t state = lv_imgbtn_get_state(imgbtn);
|
||||
lv_style_t * style = lv_imgbtn_get_style(imgbtn, state);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(imgbtn);
|
||||
|
||||
#if LV_IMGBTN_TILED == 0
|
||||
const void * src = ext->img_src[state];
|
||||
lv_draw_img(&imgbtn->coords, mask, src, style, opa_scale);
|
||||
#else
|
||||
const void * src;
|
||||
lv_img_header_t header;
|
||||
lv_area_t coords;
|
||||
lv_coord_t left_w = 0;
|
||||
lv_coord_t right_w = 0;
|
||||
|
||||
src = ext->img_src_left[state];
|
||||
if(src) {
|
||||
lv_img_dsc_get_info(src, &header);
|
||||
left_w = header.w;
|
||||
coords.x1 = imgbtn->coords.x1;
|
||||
coords.y1 = imgbtn->coords.y1;
|
||||
coords.x2 = coords.x1 + header.w - 1;
|
||||
coords.y2 = coords.y1 + header.h - 1;
|
||||
lv_draw_img(&coords, mask, src, style, opa_scale);
|
||||
}
|
||||
|
||||
src = ext->img_src_right[state];
|
||||
if(src) {
|
||||
lv_img_dsc_get_info(src, &header);
|
||||
right_w = header.w;
|
||||
coords.x1 = imgbtn->coords.x2 - header.w + 1;
|
||||
coords.y1 = imgbtn->coords.y1;
|
||||
coords.x2 = imgbtn->coords.x2;
|
||||
coords.y2 = imgbtn->coords.y1 + header.h - 1;
|
||||
lv_draw_img(&coords, mask, src, style, opa_scale);
|
||||
}
|
||||
|
||||
src = ext->img_src_mid[state];
|
||||
if(src) {
|
||||
lv_coord_t obj_w = lv_obj_get_width(imgbtn);
|
||||
lv_coord_t i;
|
||||
lv_img_dsc_get_info(src, &header);
|
||||
|
||||
coords.x1 = imgbtn->coords.x1 + left_w ;
|
||||
coords.y1 = imgbtn->coords.y1;
|
||||
coords.x2 = coords.x1 + header.w - 1;
|
||||
coords.y2 = imgbtn->coords.y1 + header.h - 1;
|
||||
|
||||
for(i = 0; i < obj_w - right_w - left_w; i += header.w) {
|
||||
lv_draw_img(&coords, mask, src, style, opa_scale);
|
||||
coords.x1 = coords.x2 + 1;
|
||||
coords.x2 += header.w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
/*Post draw when the children are drawn*/
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the image button
|
||||
* @param imgbtn pointer to a image button object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_imgbtn_signal(lv_obj_t * imgbtn, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(imgbtn, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
/* If the style changed then the button was clicked, released etc. so probably the state was changed as well
|
||||
* Set the new image for the new state.*/
|
||||
refr_img(imgbtn);
|
||||
} else if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_imgbtn";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static void refr_img(lv_obj_t * imgbtn)
|
||||
{
|
||||
lv_imgbtn_ext_t * ext = lv_obj_get_ext_attr(imgbtn);
|
||||
lv_btn_state_t state = lv_imgbtn_get_state(imgbtn);
|
||||
lv_img_header_t header;
|
||||
|
||||
#if LV_IMGBTN_TILED == 0
|
||||
const void * src = ext->img_src[state];
|
||||
#else
|
||||
const void * src = ext->img_src_mid[state];
|
||||
#endif
|
||||
|
||||
lv_res_t info_res;
|
||||
info_res = lv_img_dsc_get_info(src, &header);
|
||||
if(info_res == LV_RES_OK) {
|
||||
ext->act_cf = header.cf;
|
||||
#if LV_IMGBTN_TILED == 0
|
||||
lv_obj_set_size(imgbtn, header.w, header.h);
|
||||
#else
|
||||
lv_obj_set_height(imgbtn, header.h);
|
||||
#endif
|
||||
} else {
|
||||
ext->act_cf = LV_IMG_CF_UNKOWN;
|
||||
}
|
||||
|
||||
lv_obj_invalidate(imgbtn);
|
||||
}
|
||||
|
||||
#endif
|
249
bdk/libs/lvgl/lv_objx/lv_imgbtn.h
Normal file
249
bdk/libs/lvgl/lv_objx/lv_imgbtn.h
Normal file
|
@ -0,0 +1,249 @@
|
|||
/**
|
||||
* @file lv_imgbtn.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_IMGBTN_H
|
||||
#define LV_IMGBTN_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_IMGBTN != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_BTN == 0
|
||||
#error "lv_imgbtn: lv_btn is required. Enable it in lv_conf.h (USE_LV_BTN 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_btn.h"
|
||||
#include "../lv_draw/lv_draw_img.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Data of image button*/
|
||||
typedef struct {
|
||||
lv_btn_ext_t btn; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
int idx;
|
||||
#if LV_IMGBTN_TILED == 0
|
||||
const void * img_src[LV_BTN_STATE_NUM]; /*Store images to each state*/
|
||||
#else
|
||||
const void * img_src_left[LV_BTN_STATE_NUM]; /*Store left side images to each state*/
|
||||
const void * img_src_mid[LV_BTN_STATE_NUM]; /*Store center images to each state*/
|
||||
const void * img_src_right[LV_BTN_STATE_NUM]; /*Store right side images to each state*/
|
||||
#endif
|
||||
lv_img_cf_t act_cf; /*Color format of the currently active image*/
|
||||
} lv_imgbtn_ext_t;
|
||||
|
||||
|
||||
/*Styles*/
|
||||
enum {
|
||||
LV_IMGBTN_STYLE_REL,
|
||||
LV_IMGBTN_STYLE_PR,
|
||||
LV_IMGBTN_STYLE_TGL_REL,
|
||||
LV_IMGBTN_STYLE_TGL_PR,
|
||||
LV_IMGBTN_STYLE_INA,
|
||||
};
|
||||
typedef uint8_t lv_imgbtn_style_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a image button objects
|
||||
* @param par pointer to an object, it will be the parent of the new image button
|
||||
* @param copy pointer to a image button object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created image button
|
||||
*/
|
||||
lv_obj_t * lv_imgbtn_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
#if LV_IMGBTN_TILED == 0
|
||||
/**
|
||||
* Set images for a state of the image button
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param state for which state set the new image (from `lv_btn_state_t`) `
|
||||
* @param src pointer to an image source (a C array or path to a file)
|
||||
*/
|
||||
void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src);
|
||||
#else
|
||||
/**
|
||||
* Set images for a state of the image button
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param state for which state set the new image (from `lv_btn_state_t`) `
|
||||
* @param src_left pointer to an image source for the left side of the button (a C array or path to a file)
|
||||
* @param src_mid pointer to an image source for the middle of the button (ideally 1px wide) (a C array or path to a file)
|
||||
* @param src_right pointer to an image source for the right side of the button (a C array or path to a file)
|
||||
*/
|
||||
void lv_imgbtn_set_src(lv_obj_t * imgbtn, lv_btn_state_t state, const void * src_left, const void * src_mid, const void * src_right);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Enable the toggled states. On release the button will change from/to toggled state.
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param tgl true: enable toggled states, false: disable
|
||||
*/
|
||||
static inline void lv_imgbtn_set_toggle(lv_obj_t * imgbtn, bool tgl)
|
||||
{
|
||||
lv_btn_set_toggle(imgbtn, tgl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state of the image button
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param state the new state of the button (from lv_btn_state_t enum)
|
||||
*/
|
||||
static inline void lv_imgbtn_set_state(lv_obj_t * imgbtn, lv_btn_state_t state)
|
||||
{
|
||||
lv_btn_set_state(imgbtn, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the state of the image button (ON->OFF, OFF->ON)
|
||||
* @param imgbtn pointer to a image button object
|
||||
*/
|
||||
static inline void lv_imgbtn_toggle(lv_obj_t * imgbtn)
|
||||
{
|
||||
lv_btn_toggle(imgbtn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a function to call when a button event happens
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param action type of event form 'lv_action_t' (press, release, long press, long press repeat)
|
||||
*/
|
||||
static inline void lv_imgbtn_set_action(lv_obj_t * imgbtn, lv_btn_action_t type, lv_action_t action)
|
||||
{
|
||||
lv_btn_set_action(imgbtn, type, action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a image button.
|
||||
* @param imgbtn pointer to image button object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_imgbtn_set_style(lv_obj_t * imgbtn, lv_imgbtn_style_t type, lv_style_t *style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
|
||||
#if LV_IMGBTN_TILED == 0
|
||||
/**
|
||||
* Get the images in a given state
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param state the state where to get the image (from `lv_btn_state_t`) `
|
||||
* @return pointer to an image source (a C array or path to a file)
|
||||
*/
|
||||
const void * lv_imgbtn_get_src(lv_obj_t * imgbtn, lv_btn_state_t state);
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* Get the left image in a given state
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param state the state where to get the image (from `lv_btn_state_t`) `
|
||||
* @return pointer to the left image source (a C array or path to a file)
|
||||
*/
|
||||
const void * lv_imgbtn_get_src_left(lv_obj_t * imgbtn, lv_btn_state_t state);
|
||||
|
||||
/**
|
||||
* Get the middle image in a given state
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param state the state where to get the image (from `lv_btn_state_t`) `
|
||||
* @return pointer to the middle image source (a C array or path to a file)
|
||||
*/
|
||||
const void * lv_imgbtn_get_src_middle(lv_obj_t * imgbtn, lv_btn_state_t state);
|
||||
|
||||
/**
|
||||
* Get the right image in a given state
|
||||
* @param imgbtn pointer to an image button object
|
||||
* @param state the state where to get the image (from `lv_btn_state_t`) `
|
||||
* @return pointer to the left image source (a C array or path to a file)
|
||||
*/
|
||||
const void * lv_imgbtn_get_src_right(lv_obj_t * imgbtn, lv_btn_state_t state);
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Get the current state of the image button
|
||||
* @param imgbtn pointer to a image button object
|
||||
* @return the state of the button (from lv_btn_state_t enum)
|
||||
*/
|
||||
static inline lv_btn_state_t lv_imgbtn_get_state(const lv_obj_t * imgbtn)
|
||||
{
|
||||
return lv_btn_get_state(imgbtn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the toggle enable attribute of the image button
|
||||
* @param imgbtn pointer to a image button object
|
||||
* @return ture: toggle enabled, false: disabled
|
||||
*/
|
||||
static inline bool lv_imgbtn_get_toggle(const lv_obj_t * imgbtn)
|
||||
{
|
||||
return lv_btn_get_toggle(imgbtn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the release action of a image button
|
||||
* @param imgbtn pointer to a image button object
|
||||
* @return pointer to the release action function
|
||||
*/
|
||||
static inline lv_action_t lv_imgbtn_get_action(const lv_obj_t * imgbtn, lv_btn_action_t type)
|
||||
{
|
||||
return lv_btn_get_action(imgbtn, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get style of a image button.
|
||||
* @param imgbtn pointer to image button object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
*/
|
||||
lv_style_t * lv_imgbtn_get_style(const lv_obj_t * imgbtn, lv_imgbtn_style_t type);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_IMGBTN*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_IMGBTN_H*/
|
488
bdk/libs/lvgl/lv_objx/lv_kb.c
Normal file
488
bdk/libs/lvgl/lv_objx/lv_kb.c
Normal file
|
@ -0,0 +1,488 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file lv_kb.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_kb.h"
|
||||
#if USE_LV_KB != 0
|
||||
|
||||
#include "lv_ta.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_kb_signal(lv_obj_t * kb, lv_signal_t sign, void * param);
|
||||
static lv_res_t lv_kb_def_action(lv_obj_t * kb, const char * txt);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
static const char * kb_map_lc[] = {
|
||||
"\2051#", "\204q", "\204w", "\204e", "\204r", "\204t", "\204y", "\204u", "\204i", "\204o", "\204p", "\207Bksp", "\n",
|
||||
"\226ABC", "\203a", "\203s", "\203d", "\203f", "\203g", "\203h", "\203j", "\203k", "\203l", "\207Enter", "\n",
|
||||
"_", "-", "z", "x", "c", "v", "b", "n", "m", ".", ",", ":", "\n",
|
||||
"\202"SYMBOL_CLOSE, "\202"SYMBOL_LEFT, "\206 ", "\202"SYMBOL_RIGHT, "\202"SYMBOL_OK, ""
|
||||
};
|
||||
|
||||
static const char * kb_map_uc[] = {
|
||||
"\2051#", "\204Q", "\204W", "\204E", "\204R", "\204T", "\204Y", "\204U", "\204I", "\204O", "\204P", "\207Bksp", "\n",
|
||||
"\226abc", "\203A", "\203S", "\203D", "\203F", "\203G", "\203H", "\203J", "\203K", "\203L", "\207Enter", "\n",
|
||||
"_", "-", "Z", "X", "C", "V", "B", "N", "M", ".", ",", ":", "\n",
|
||||
"\202"SYMBOL_CLOSE, "\202"SYMBOL_LEFT, "\206 ", "\202"SYMBOL_RIGHT, "\202"SYMBOL_OK, ""
|
||||
};
|
||||
|
||||
static const char * kb_map_spec[] = {
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "\202Bksp", "\n",
|
||||
"\222abc", "+", "-", "/", "*", "=", "%", "!", "?", "#", "<", ">", "\n",
|
||||
"\\", "@", "$", "(", ")", "{", "}", "[", "]", ";", "\"", "'", "\n",
|
||||
"\202"SYMBOL_CLOSE, "\202"SYMBOL_LEFT, "\206 ", "\202"SYMBOL_RIGHT, "\202"SYMBOL_OK, ""
|
||||
};
|
||||
|
||||
static const char * kb_map_num[] = {
|
||||
"1", "2", "3", "\202"SYMBOL_CLOSE, "\n",
|
||||
"4", "5", "6", "\202"SYMBOL_OK, "\n",
|
||||
"7", "8", "9", "\202Bksp", "\n",
|
||||
"+/-", "0", ".", SYMBOL_LEFT, SYMBOL_RIGHT, ""
|
||||
};
|
||||
|
||||
static const char * kb_map_hex[] = {
|
||||
"1", "2", "3", "A", "D", "\212", "\n",
|
||||
"4", "5", "6", "B", "E", "\202Bksp", "\n",
|
||||
"7", "8", "9", "C", "F", "\202"SYMBOL_OK, "\n",
|
||||
"\211", "0", "\213", SYMBOL_LEFT, SYMBOL_RIGHT, ""
|
||||
};
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a keyboard objects
|
||||
* @param par pointer to an object, it will be the parent of the new keyboard
|
||||
* @param copy pointer to a keyboard object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created keyboard
|
||||
*/
|
||||
lv_obj_t * lv_kb_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("keyboard create started");
|
||||
|
||||
/*Create the ancestor of keyboard*/
|
||||
lv_obj_t * new_kb = lv_btnm_create(par, copy);
|
||||
lv_mem_assert(new_kb);
|
||||
if(new_kb == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_kb);
|
||||
|
||||
/*Allocate the keyboard type specific extended data*/
|
||||
lv_kb_ext_t * ext = lv_obj_allocate_ext_attr(new_kb, sizeof(lv_kb_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
|
||||
ext->ta = NULL;
|
||||
ext->mode = LV_KB_MODE_TEXT;
|
||||
ext->cursor_mng = 0;
|
||||
ext->hide_action = NULL;
|
||||
ext->ok_action = NULL;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_kb, lv_kb_signal);
|
||||
|
||||
/*Init the new keyboard keyboard*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_size(new_kb, LV_HOR_RES, LV_VER_RES / 2);
|
||||
lv_obj_align(new_kb, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
|
||||
lv_btnm_set_action(new_kb, lv_kb_def_action);
|
||||
lv_btnm_set_map(new_kb, kb_map_lc);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_kb_set_style(new_kb, LV_KB_STYLE_BG, th->kb.bg);
|
||||
lv_kb_set_style(new_kb, LV_KB_STYLE_BTN_REL, th->kb.btn.rel);
|
||||
lv_kb_set_style(new_kb, LV_KB_STYLE_BTN_PR, th->kb.btn.pr);
|
||||
lv_kb_set_style(new_kb, LV_KB_STYLE_BTN_TGL_REL, th->kb.btn.tgl_rel);
|
||||
lv_kb_set_style(new_kb, LV_KB_STYLE_BTN_TGL_PR, th->kb.btn.tgl_pr);
|
||||
lv_kb_set_style(new_kb, LV_KB_STYLE_BTN_INA, th->kb.btn.ina);
|
||||
} else {
|
||||
/*Let the button matrix's styles*/
|
||||
}
|
||||
}
|
||||
/*Copy an existing keyboard*/
|
||||
else {
|
||||
lv_kb_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->ta = NULL;
|
||||
ext->ta = copy_ext->ta;
|
||||
ext->mode = copy_ext->mode;
|
||||
ext->cursor_mng = copy_ext->cursor_mng;
|
||||
ext->hide_action = copy_ext->hide_action;
|
||||
ext->ok_action = copy_ext->ok_action;
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_kb);
|
||||
}
|
||||
|
||||
|
||||
LV_LOG_INFO("keyboard created");
|
||||
|
||||
|
||||
return new_kb;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Assign a Text Area to the Keyboard. The pressed characters will be put there.
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param ta pointer to a Text Area object to write there
|
||||
*/
|
||||
void lv_kb_set_ta(lv_obj_t * kb, lv_obj_t * ta)
|
||||
{
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
lv_cursor_type_t cur_type;
|
||||
|
||||
/*Hide the cursor of the old Text area if cursor management is enabled*/
|
||||
if(ext->ta && ext->cursor_mng) {
|
||||
cur_type = lv_ta_get_cursor_type(ext->ta);
|
||||
lv_ta_set_cursor_type(ext->ta, cur_type | LV_CURSOR_HIDDEN);
|
||||
}
|
||||
|
||||
ext->ta = ta;
|
||||
|
||||
/*Show the cursor of the new Text area if cursor management is enabled*/
|
||||
if(ext->ta && ext->cursor_mng) {
|
||||
cur_type = lv_ta_get_cursor_type(ext->ta);
|
||||
lv_ta_set_cursor_type(ext->ta, cur_type & (~LV_CURSOR_HIDDEN));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new a mode (text or number map)
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param mode the mode from 'lv_kb_mode_t'
|
||||
*/
|
||||
void lv_kb_set_mode(lv_obj_t * kb, lv_kb_mode_t mode)
|
||||
{
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
if(ext->mode == mode) return;
|
||||
|
||||
ext->mode = mode;
|
||||
if(mode == LV_KB_MODE_TEXT) lv_btnm_set_map(kb, kb_map_lc);
|
||||
else if(mode == LV_KB_MODE_NUM) lv_btnm_set_map(kb, kb_map_num);
|
||||
else if (mode == LV_KB_MODE_HEX) lv_btnm_set_map(kb, kb_map_hex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Automatically hide or show the cursor of Text Area
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param en true: show cursor on the current text area, false: hide cursor
|
||||
*/
|
||||
void lv_kb_set_cursor_manage(lv_obj_t * kb, bool en)
|
||||
{
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
if(ext->cursor_mng == en) return;
|
||||
|
||||
ext->cursor_mng = en == false ? 0 : 1;
|
||||
|
||||
if(ext->ta) {
|
||||
lv_cursor_type_t cur_type;
|
||||
cur_type = lv_ta_get_cursor_type(ext->ta);
|
||||
|
||||
if(ext->cursor_mng) {
|
||||
lv_ta_set_cursor_type(ext->ta, cur_type & (~LV_CURSOR_HIDDEN));
|
||||
} else {
|
||||
lv_ta_set_cursor_type(ext->ta, cur_type | LV_CURSOR_HIDDEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set call back to call when the "Ok" button is pressed
|
||||
* @param kb pointer to Keyboard object
|
||||
* @param action a callback with 'lv_action_t' type
|
||||
*/
|
||||
void lv_kb_set_ok_action(lv_obj_t * kb, lv_action_t action)
|
||||
{
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
ext->ok_action = action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set call back to call when the "Hide" button is pressed
|
||||
* @param kb pointer to Keyboard object
|
||||
* @param action a callback with 'lv_action_t' type
|
||||
*/
|
||||
void lv_kb_set_hide_action(lv_obj_t * kb, lv_action_t action)
|
||||
{
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
ext->hide_action = action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a keyboard
|
||||
* @param kb pointer to a keyboard object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_kb_set_style(lv_obj_t * kb, lv_kb_style_t type, lv_style_t * style)
|
||||
{
|
||||
switch(type) {
|
||||
case LV_KB_STYLE_BG:
|
||||
lv_btnm_set_style(kb, LV_BTNM_STYLE_BG, style);
|
||||
break;
|
||||
case LV_KB_STYLE_BTN_REL:
|
||||
lv_btnm_set_style(kb, LV_BTNM_STYLE_BTN_REL, style);
|
||||
break;
|
||||
case LV_KB_STYLE_BTN_PR:
|
||||
lv_btnm_set_style(kb, LV_BTNM_STYLE_BTN_PR, style);
|
||||
break;
|
||||
case LV_KB_STYLE_BTN_TGL_REL:
|
||||
lv_btnm_set_style(kb, LV_BTNM_STYLE_BTN_TGL_REL, style);
|
||||
break;
|
||||
case LV_KB_STYLE_BTN_TGL_PR:
|
||||
lv_btnm_set_style(kb, LV_BTNM_STYLE_BTN_TGL_PR, style);
|
||||
break;
|
||||
case LV_KB_STYLE_BTN_INA:
|
||||
lv_btnm_set_style(kb, LV_BTNM_STYLE_BTN_INA, style);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Assign a Text Area to the Keyboard. The pressed characters will be put there.
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @return pointer to the assigned Text Area object
|
||||
*/
|
||||
lv_obj_t * lv_kb_get_ta(const lv_obj_t * kb)
|
||||
{
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
return ext->ta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new a mode (text or number map)
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @return the current mode from 'lv_kb_mode_t'
|
||||
*/
|
||||
lv_kb_mode_t lv_kb_get_mode(const lv_obj_t * kb)
|
||||
{
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
return ext->mode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the current cursor manage mode.
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @return true: show cursor on the current text area, false: hide cursor
|
||||
*/
|
||||
bool lv_kb_get_cursor_manage(const lv_obj_t * kb)
|
||||
{
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
return ext->cursor_mng == 0 ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the callback to call when the "Ok" button is pressed
|
||||
* @param kb pointer to Keyboard object
|
||||
* @return the ok callback
|
||||
*/
|
||||
lv_action_t lv_kb_get_ok_action(const lv_obj_t * kb)
|
||||
{
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
return ext->ok_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the callback to call when the "Hide" button is pressed
|
||||
* @param kb pointer to Keyboard object
|
||||
* @return the close callback
|
||||
*/
|
||||
lv_action_t lv_kb_get_hide_action(const lv_obj_t * kb)
|
||||
{
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
return ext->hide_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a keyboard
|
||||
* @param kb pointer to a keyboard object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_kb_get_style(const lv_obj_t * kb, lv_kb_style_t type)
|
||||
{
|
||||
lv_style_t * style = NULL;
|
||||
|
||||
switch(type) {
|
||||
case LV_KB_STYLE_BG:
|
||||
style = lv_btnm_get_style(kb, LV_BTNM_STYLE_BG);
|
||||
break;
|
||||
case LV_KB_STYLE_BTN_REL:
|
||||
style = lv_btnm_get_style(kb, LV_BTNM_STYLE_BTN_REL);
|
||||
break;
|
||||
case LV_KB_STYLE_BTN_PR:
|
||||
style = lv_btnm_get_style(kb, LV_BTNM_STYLE_BTN_PR);
|
||||
break;
|
||||
case LV_KB_STYLE_BTN_TGL_REL:
|
||||
style = lv_btnm_get_style(kb, LV_BTNM_STYLE_BTN_TGL_REL);
|
||||
break;
|
||||
case LV_KB_STYLE_BTN_TGL_PR:
|
||||
style = lv_btnm_get_style(kb, LV_BTNM_STYLE_BTN_TGL_PR);
|
||||
break;
|
||||
case LV_KB_STYLE_BTN_INA:
|
||||
style = lv_btnm_get_style(kb, LV_BTNM_STYLE_BTN_INA);
|
||||
break;
|
||||
default:
|
||||
style = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the keyboard
|
||||
* @param kb pointer to a keyboard object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_kb_signal(lv_obj_t * kb, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(kb, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_kb";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a button of 'kb_btnm' is released
|
||||
* @param btnm pointer to 'kb_btnm'
|
||||
* @param i the index of the released button from the current btnm map
|
||||
* @return LV_ACTION_RES_INV if the btnm is deleted else LV_ACTION_RES_OK
|
||||
*/
|
||||
static lv_res_t lv_kb_def_action(lv_obj_t * kb, const char * txt)
|
||||
{
|
||||
lv_kb_ext_t * ext = lv_obj_get_ext_attr(kb);
|
||||
lv_res_t res = LV_RES_OK;
|
||||
|
||||
/*Do the corresponding action according to the text of the button*/
|
||||
if(strcmp(txt, "abc") == 0) {
|
||||
lv_btnm_set_map(kb, kb_map_lc);
|
||||
return LV_RES_OK;
|
||||
} else if(strcmp(txt, "ABC") == 0) {
|
||||
lv_btnm_set_map(kb, kb_map_uc);
|
||||
return LV_RES_OK;
|
||||
} else if(strcmp(txt, "1#") == 0) {
|
||||
lv_btnm_set_map(kb, kb_map_spec);
|
||||
return LV_RES_OK;
|
||||
} else if(strcmp(txt, SYMBOL_CLOSE) == 0) {
|
||||
if(ext->hide_action) res = ext->hide_action(kb);
|
||||
else {
|
||||
lv_kb_set_ta(kb, NULL); /*De-assign the text area to hide it cursor if needed*/
|
||||
lv_obj_del(kb);
|
||||
}
|
||||
return res;
|
||||
} else if(strcmp(txt, SYMBOL_OK) == 0) {
|
||||
if(ext->ok_action) res = ext->ok_action(kb);
|
||||
else {
|
||||
lv_kb_set_ta(kb, NULL); /*De-assign the text area to hide it cursor if needed*/
|
||||
res = lv_obj_del(kb);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
if(res != LV_RES_OK) return res; /*The keyboard might be deleted in the actions*/
|
||||
|
||||
/*Add the characters to the text area if set*/
|
||||
if(ext->ta == NULL) return res;
|
||||
|
||||
if(strcmp(txt, "Enter") == 0)lv_ta_add_char(ext->ta, '\n');
|
||||
else if(strcmp(txt, SYMBOL_LEFT) == 0) lv_ta_cursor_left(ext->ta);
|
||||
else if(strcmp(txt, SYMBOL_RIGHT) == 0) lv_ta_cursor_right(ext->ta);
|
||||
else if(strcmp(txt, "Bksp") == 0) lv_ta_del_char(ext->ta);
|
||||
else if(strcmp(txt, "+/-") == 0) {
|
||||
uint16_t cur = lv_ta_get_cursor_pos(ext->ta);
|
||||
const char * ta_txt = lv_ta_get_text(ext->ta);
|
||||
if(ta_txt[0] == '-') {
|
||||
lv_ta_set_cursor_pos(ext->ta, 1);
|
||||
lv_ta_del_char(ext->ta);
|
||||
lv_ta_add_char(ext->ta, '+');
|
||||
lv_ta_set_cursor_pos(ext->ta, cur);
|
||||
} else if(ta_txt[0] == '+') {
|
||||
lv_ta_set_cursor_pos(ext->ta, 1);
|
||||
lv_ta_del_char(ext->ta);
|
||||
lv_ta_add_char(ext->ta, '-');
|
||||
lv_ta_set_cursor_pos(ext->ta, cur);
|
||||
} else {
|
||||
lv_ta_set_cursor_pos(ext->ta, 0);
|
||||
lv_ta_add_char(ext->ta, '-');
|
||||
lv_ta_set_cursor_pos(ext->ta, cur + 1);
|
||||
}
|
||||
} else {
|
||||
lv_ta_add_text(ext->ta, txt);
|
||||
}
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
#endif
|
216
bdk/libs/lvgl/lv_objx/lv_kb.h
Normal file
216
bdk/libs/lvgl/lv_objx/lv_kb.h
Normal file
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file lv_kb.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_KB_H
|
||||
#define LV_KB_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_KB != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_BTNM == 0
|
||||
#error "lv_kb: lv_btnm is required. Enable it in lv_conf.h (USE_LV_BTNM 1) "
|
||||
#endif
|
||||
|
||||
#if USE_LV_TA == 0
|
||||
#error "lv_kb: lv_ta is required. Enable it in lv_conf.h (USE_LV_TA 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_btnm.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
enum {
|
||||
LV_KB_MODE_TEXT,
|
||||
LV_KB_MODE_NUM,
|
||||
LV_KB_MODE_HEX
|
||||
};
|
||||
typedef uint8_t lv_kb_mode_t;
|
||||
|
||||
/*Data of keyboard*/
|
||||
typedef struct {
|
||||
lv_btnm_ext_t btnm; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_obj_t *ta; /*Pointer to the assigned text area*/
|
||||
lv_kb_mode_t mode; /*Key map type*/
|
||||
uint8_t cursor_mng :1; /*1: automatically show/hide cursor when a text area is assigned or left*/
|
||||
lv_action_t ok_action; /*Called when the "Ok" button is clicked*/
|
||||
lv_action_t hide_action; /*Called when the "Hide" button is clicked*/
|
||||
} lv_kb_ext_t;
|
||||
|
||||
enum {
|
||||
LV_KB_STYLE_BG,
|
||||
LV_KB_STYLE_BTN_REL,
|
||||
LV_KB_STYLE_BTN_PR,
|
||||
LV_KB_STYLE_BTN_TGL_REL,
|
||||
LV_KB_STYLE_BTN_TGL_PR,
|
||||
LV_KB_STYLE_BTN_INA,
|
||||
};
|
||||
typedef uint8_t lv_kb_style_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a keyboard objects
|
||||
* @param par pointer to an object, it will be the parent of the new keyboard
|
||||
* @param copy pointer to a keyboard object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created keyboard
|
||||
*/
|
||||
lv_obj_t * lv_kb_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Assign a Text Area to the Keyboard. The pressed characters will be put there.
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param ta pointer to a Text Area object to write there
|
||||
*/
|
||||
void lv_kb_set_ta(lv_obj_t * kb, lv_obj_t * ta);
|
||||
|
||||
/**
|
||||
* Set a new a mode (text or number map)
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param mode the mode from 'lv_kb_mode_t'
|
||||
*/
|
||||
void lv_kb_set_mode(lv_obj_t * kb, lv_kb_mode_t mode);
|
||||
|
||||
/**
|
||||
* Automatically hide or show the cursor of the current Text Area
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param en true: show cursor on the current text area, false: hide cursor
|
||||
*/
|
||||
void lv_kb_set_cursor_manage(lv_obj_t * kb, bool en);
|
||||
|
||||
/**
|
||||
* Set call back to call when the "Ok" button is pressed
|
||||
* @param kb pointer to Keyboard object
|
||||
* @param action a callback with 'lv_action_t' type
|
||||
*/
|
||||
void lv_kb_set_ok_action(lv_obj_t * kb, lv_action_t action);
|
||||
|
||||
/**
|
||||
* Set call back to call when the "Hide" button is pressed
|
||||
* @param kb pointer to Keyboard object
|
||||
* @param action a callback with 'lv_action_t' type
|
||||
*/
|
||||
void lv_kb_set_hide_action(lv_obj_t * kb, lv_action_t action);
|
||||
|
||||
/**
|
||||
* Set a new map for the keyboard
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @param map pointer to a string array to describe the map.
|
||||
* See 'lv_btnm_set_map()' for more info.
|
||||
*/
|
||||
static inline void lv_kb_set_map(lv_obj_t *kb, const char ** map)
|
||||
{
|
||||
lv_btnm_set_map(kb, map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a keyboard
|
||||
* @param kb pointer to a keyboard object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_kb_set_style(lv_obj_t *kb, lv_kb_style_t type, lv_style_t *style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Assign a Text Area to the Keyboard. The pressed characters will be put there.
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @return pointer to the assigned Text Area object
|
||||
*/
|
||||
lv_obj_t * lv_kb_get_ta(const lv_obj_t * kb);
|
||||
|
||||
/**
|
||||
* Set a new a mode (text or number map)
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @return the current mode from 'lv_kb_mode_t'
|
||||
*/
|
||||
lv_kb_mode_t lv_kb_get_mode(const lv_obj_t * kb);
|
||||
|
||||
/**
|
||||
* Get the current cursor manage mode.
|
||||
* @param kb pointer to a Keyboard object
|
||||
* @return true: show cursor on the current text area, false: hide cursor
|
||||
*/
|
||||
bool lv_kb_get_cursor_manage(const lv_obj_t * kb);
|
||||
|
||||
/**
|
||||
* Get the callback to call when the "Ok" button is pressed
|
||||
* @param kb pointer to Keyboard object
|
||||
* @return the ok callback
|
||||
*/
|
||||
lv_action_t lv_kb_get_ok_action(const lv_obj_t * kb);
|
||||
|
||||
/**
|
||||
* Get the callback to call when the "Hide" button is pressed
|
||||
* @param kb pointer to Keyboard object
|
||||
* @return the close callback
|
||||
*/
|
||||
lv_action_t lv_kb_get_hide_action(const lv_obj_t * kb);
|
||||
|
||||
/**
|
||||
* Get a style of a keyboard
|
||||
* @param kb pointer to a keyboard object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_kb_get_style(const lv_obj_t *kb, lv_kb_style_t type);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_KB*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_KB_H*/
|
987
bdk/libs/lvgl/lv_objx/lv_label.c
Normal file
987
bdk/libs/lvgl/lv_objx/lv_label.c
Normal file
|
@ -0,0 +1,987 @@
|
|||
/**
|
||||
* @file lv_rect.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_label.h"
|
||||
#if USE_LV_LABEL != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_core/lv_lang.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_misc/lv_color.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*Test configurations*/
|
||||
#ifndef LV_LABEL_SCROLL_SPEED
|
||||
#define LV_LABEL_SCROLL_SPEED (25) /*Hor, or ver. scroll speed (px/sec) in 'LV_LABEL_LONG_SCROLL/ROLL' mode*/
|
||||
#endif
|
||||
|
||||
#define ANIM_WAIT_CHAR_COUNT 3
|
||||
|
||||
#define LV_LABEL_DOT_END_INV 0xFFFF
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_label_signal(lv_obj_t * label, lv_signal_t sign, void * param);
|
||||
static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static void lv_label_refr_text(lv_obj_t * label);
|
||||
static void lv_label_revert_dots(lv_obj_t * label);
|
||||
|
||||
#if USE_LV_ANIMATION
|
||||
static void lv_label_set_offset_x(lv_obj_t * label, lv_coord_t x);
|
||||
static void lv_label_set_offset_y(lv_obj_t * label, lv_coord_t y);
|
||||
#endif
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a label objects
|
||||
* @param par pointer to an object, it will be the parent of the new label
|
||||
* @param copy pointer to a button object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created button
|
||||
*/
|
||||
lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("label create started");
|
||||
|
||||
/*Create a basic object*/
|
||||
lv_obj_t * new_label = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_label);
|
||||
if(new_label == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_label);
|
||||
|
||||
/*Extend the basic object to a label object*/
|
||||
lv_obj_allocate_ext_attr(new_label, sizeof(lv_label_ext_t));
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(new_label);
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->text = NULL;
|
||||
ext->static_txt = 0;
|
||||
ext->recolor = 0;
|
||||
ext->body_draw = 0;
|
||||
ext->align = LV_LABEL_ALIGN_LEFT;
|
||||
ext->dot_end = LV_LABEL_DOT_END_INV;
|
||||
ext->long_mode = LV_LABEL_LONG_EXPAND;
|
||||
ext->anim_speed = LV_LABEL_SCROLL_SPEED;
|
||||
ext->offset.x = 0;
|
||||
ext->offset.y = 0;
|
||||
#if USE_LV_MULTI_LANG
|
||||
ext->lang_txt_id = LV_LANG_TXT_ID_NONE;
|
||||
#endif
|
||||
lv_obj_set_design_func(new_label, lv_label_design);
|
||||
lv_obj_set_signal_func(new_label, lv_label_signal);
|
||||
|
||||
/*Init the new label*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_click(new_label, false);
|
||||
lv_label_set_long_mode(new_label, LV_LABEL_LONG_EXPAND);
|
||||
lv_label_set_text(new_label, "Text");
|
||||
lv_label_set_style(new_label, NULL); /*Inherit parent's style*/
|
||||
}
|
||||
/*Copy 'copy' if not NULL*/
|
||||
else {
|
||||
lv_label_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
lv_label_set_long_mode(new_label, lv_label_get_long_mode(copy));
|
||||
lv_label_set_recolor(new_label, lv_label_get_recolor(copy));
|
||||
lv_label_set_body_draw(new_label, lv_label_get_body_draw(copy));
|
||||
lv_label_set_align(new_label, lv_label_get_align(copy));
|
||||
if(copy_ext->static_txt == 0) lv_label_set_text(new_label, lv_label_get_text(copy));
|
||||
else lv_label_set_static_text(new_label, lv_label_get_text(copy));
|
||||
|
||||
/*In DOT mode save the text byte-to-byte because a '\0' can be in the middle*/
|
||||
if(copy_ext->long_mode == LV_LABEL_LONG_DOT) {
|
||||
ext->text = lv_mem_realloc(ext->text, lv_mem_get_size(copy_ext->text));
|
||||
lv_mem_assert(ext->text);
|
||||
if(ext->text == NULL) return NULL;
|
||||
memcpy(ext->text, copy_ext->text, lv_mem_get_size(copy_ext->text));
|
||||
}
|
||||
|
||||
memcpy(ext->dot_tmp, copy_ext->dot_tmp, sizeof(ext->dot_tmp));
|
||||
ext->dot_end = copy_ext->dot_end;
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_label);
|
||||
}
|
||||
|
||||
|
||||
LV_LOG_INFO("label created");
|
||||
|
||||
return new_label;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new text for a label. Memory will be allocated to store the text by the label.
|
||||
* @param label pointer to a label object
|
||||
* @param text '\0' terminated character string. NULL to refresh with the current text.
|
||||
*/
|
||||
void lv_label_set_text(lv_obj_t * label, const char * text)
|
||||
{
|
||||
lv_obj_invalidate(label);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
|
||||
/*If text is NULL then refresh */
|
||||
if(text == NULL) {
|
||||
lv_label_refr_text(label);
|
||||
return;
|
||||
}
|
||||
|
||||
if(ext->text == text && ext->static_txt == 0) {
|
||||
/*If set its own text then reallocate it (maybe its size changed)*/
|
||||
ext->text = lv_mem_realloc(ext->text, strlen(ext->text) + 1);
|
||||
lv_mem_assert(ext->text);
|
||||
if(ext->text == NULL) return;
|
||||
} else {
|
||||
/*Allocate space for the new text*/
|
||||
uint32_t len = strlen(text) + 1;
|
||||
if(ext->text != NULL && ext->static_txt == 0) {
|
||||
lv_mem_free(ext->text);
|
||||
ext->text = NULL;
|
||||
}
|
||||
|
||||
ext->text = lv_mem_alloc(len);
|
||||
lv_mem_assert(ext->text);
|
||||
if(ext->text == NULL) return;
|
||||
|
||||
strcpy(ext->text, text);
|
||||
ext->static_txt = 0; /*Now the text is dynamically allocated*/
|
||||
}
|
||||
|
||||
lv_label_refr_text(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new text for a label from a character array. The array don't has to be '\0' terminated.
|
||||
* Memory will be allocated to store the array by the label.
|
||||
* @param label pointer to a label object
|
||||
* @param array array of characters or NULL to refresh the label
|
||||
* @param size the size of 'array' in bytes
|
||||
*/
|
||||
void lv_label_set_array_text(lv_obj_t * label, const char * array, uint16_t size)
|
||||
{
|
||||
lv_obj_invalidate(label);
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
|
||||
/*If trying to set its own text or the array is NULL then refresh */
|
||||
if(array == ext->text || array == NULL) {
|
||||
lv_label_refr_text(label);
|
||||
return;
|
||||
}
|
||||
|
||||
/*Allocate space for the new text*/
|
||||
if(ext->text != NULL && ext->static_txt == 0) {
|
||||
lv_mem_free(ext->text);
|
||||
ext->text = NULL;
|
||||
}
|
||||
ext->text = lv_mem_alloc(size + 1);
|
||||
lv_mem_assert(ext->text);
|
||||
if(ext->text == NULL) return;
|
||||
|
||||
memcpy(ext->text, array, size);
|
||||
ext->text[size] = '\0';
|
||||
ext->static_txt = 0; /*Now the text is dynamically allocated*/
|
||||
|
||||
lv_label_refr_text(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a static text. It will not be saved by the label so the 'text' variable
|
||||
* has to be 'alive' while the label exist.
|
||||
* @param label pointer to a label object
|
||||
* @param text pointer to a text. NULL to refresh with the current text.
|
||||
*/
|
||||
void lv_label_set_static_text(lv_obj_t * label, const char * text)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
if(ext->static_txt == 0 && ext->text != NULL) {
|
||||
lv_mem_free(ext->text);
|
||||
ext->text = NULL;
|
||||
}
|
||||
|
||||
if(text != NULL) {
|
||||
ext->static_txt = 1;
|
||||
ext->text = (char *) text;
|
||||
}
|
||||
|
||||
lv_label_refr_text(label);
|
||||
}
|
||||
|
||||
#if USE_LV_MULTI_LANG
|
||||
/**
|
||||
*Set a text ID which refers a the same text but in a different languages
|
||||
* @param label pointer to a label object
|
||||
* @param txt_id ID of the text
|
||||
*/
|
||||
void lv_label_set_text_id(lv_obj_t * label, uint32_t txt_id)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
ext->lang_txt_id = txt_id;
|
||||
|
||||
/*Apply the new language*/
|
||||
label->signal_func(label, LV_SIGNAL_LANG_CHG, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set the behavior of the label with longer text then the object size
|
||||
* @param label pointer to a label object
|
||||
* @param long_mode the new mode from 'lv_label_long_mode' enum.
|
||||
* In LV_LONG_BREAK/LONG/ROLL the size of the label should be set AFTER this function
|
||||
*/
|
||||
void lv_label_set_long_mode(lv_obj_t * label, lv_label_long_mode_t long_mode)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
|
||||
#if USE_LV_ANIMATION
|
||||
/*Delete the old animation (if exists)*/
|
||||
lv_anim_del(label, (lv_anim_fp_t) lv_obj_set_x);
|
||||
lv_anim_del(label, (lv_anim_fp_t) lv_obj_set_y);
|
||||
lv_anim_del(label, (lv_anim_fp_t) lv_label_set_offset_x);
|
||||
lv_anim_del(label, (lv_anim_fp_t) lv_label_set_offset_y);
|
||||
#endif
|
||||
ext->offset.x = 0;
|
||||
ext->offset.y = 0;
|
||||
|
||||
if(long_mode == LV_LABEL_LONG_ROLL || long_mode == LV_LABEL_LONG_CROP) ext->expand = 1;
|
||||
else ext->expand = 0;
|
||||
|
||||
/*Restore the character under the dots*/
|
||||
if(ext->long_mode == LV_LABEL_LONG_DOT && ext->dot_end != LV_LABEL_DOT_END_INV) {
|
||||
lv_label_revert_dots(label);
|
||||
}
|
||||
|
||||
ext->long_mode = long_mode;
|
||||
lv_label_refr_text(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the align of the label (left or center)
|
||||
* @param label pointer to a label object
|
||||
* @param align 'LV_LABEL_ALIGN_LEFT' or 'LV_LABEL_ALIGN_LEFT'
|
||||
*/
|
||||
void lv_label_set_align(lv_obj_t * label, lv_label_align_t align)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
if(ext->align == align) return;
|
||||
|
||||
ext->align = align;
|
||||
|
||||
lv_obj_invalidate(label); /*Enough to invalidate because alignment is only drawing related (lv_refr_label_text() not required)*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the recoloring by in-line commands
|
||||
* @param label pointer to a label object
|
||||
* @param en true: enable recoloring, false: disable
|
||||
*/
|
||||
void lv_label_set_recolor(lv_obj_t * label, bool en)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
if(ext->recolor == en) return;
|
||||
|
||||
ext->recolor = en == false ? 0 : 1;
|
||||
|
||||
lv_label_refr_text(label); /*Refresh the text because the potential colo codes in text needs to be hided or revealed*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the label to draw (or not draw) background specified in its style's body
|
||||
* @param label pointer to a label object
|
||||
* @param en true: draw body; false: don't draw body
|
||||
*/
|
||||
void lv_label_set_body_draw(lv_obj_t * label, bool en)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
if(ext->body_draw == en) return;
|
||||
|
||||
ext->body_draw = en == false ? 0 : 1;
|
||||
|
||||
lv_obj_refresh_ext_size(label);
|
||||
|
||||
lv_obj_invalidate(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the label's animation speed in LV_LABEL_LONG_ROLL and SCROLL modes
|
||||
* @param label pointer to a label object
|
||||
* @param anim_speed speed of animation in px/sec unit
|
||||
*/
|
||||
void lv_label_set_anim_speed(lv_obj_t * label, uint16_t anim_speed)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
if(ext->anim_speed == anim_speed) return;
|
||||
|
||||
ext->anim_speed = anim_speed;
|
||||
|
||||
if(ext->long_mode == LV_LABEL_LONG_ROLL || ext->long_mode == LV_LABEL_LONG_SCROLL) {
|
||||
lv_label_refr_text(label);
|
||||
}
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the text of a label
|
||||
* @param label pointer to a label object
|
||||
* @return the text of the label
|
||||
*/
|
||||
char * lv_label_get_text(const lv_obj_t * label)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
|
||||
return ext->text;
|
||||
}
|
||||
|
||||
#if USE_LV_MULTI_LANG
|
||||
/**
|
||||
* Get the text ID of the label. (Used by the multi-language feature)
|
||||
* @param label pointer to a label object
|
||||
* @return ID of the text
|
||||
*/
|
||||
uint16_t lv_label_get_text_id(lv_obj_t * label)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
return ext->lang_txt_id;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get the long mode of a label
|
||||
* @param label pointer to a label object
|
||||
* @return the long mode
|
||||
*/
|
||||
lv_label_long_mode_t lv_label_get_long_mode(const lv_obj_t * label)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
return ext->long_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the align attribute
|
||||
* @param label pointer to a label object
|
||||
* @return LV_LABEL_ALIGN_LEFT or LV_LABEL_ALIGN_CENTER
|
||||
*/
|
||||
lv_label_align_t lv_label_get_align(const lv_obj_t * label)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
return ext->align;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the recoloring attribute
|
||||
* @param label pointer to a label object
|
||||
* @return true: recoloring is enabled, false: disable
|
||||
*/
|
||||
bool lv_label_get_recolor(const lv_obj_t * label)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
return ext->recolor == 0 ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the body draw attribute
|
||||
* @param label pointer to a label object
|
||||
* @return true: draw body; false: don't draw body
|
||||
*/
|
||||
bool lv_label_get_body_draw(const lv_obj_t * label)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
return ext->body_draw == 0 ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the label's animation speed in LV_LABEL_LONG_ROLL and SCROLL modes
|
||||
* @param label pointer to a label object
|
||||
* @return speed of animation in px/sec unit
|
||||
*/
|
||||
uint16_t lv_label_get_anim_speed(const lv_obj_t * label)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
return ext->anim_speed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relative x and y coordinates of a letter
|
||||
* @param label pointer to a label object
|
||||
* @param index index of the letter [0 ... text length]. Expressed in character index, not byte index (different in UTF-8)
|
||||
* @param pos store the result here (E.g. index = 0 gives 0;0 coordinates)
|
||||
*/
|
||||
void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t * pos)
|
||||
{
|
||||
const char * txt = lv_label_get_text(label);
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
uint32_t line_start = 0;
|
||||
uint32_t new_line_start = 0;
|
||||
lv_coord_t max_w = lv_obj_get_width(label);
|
||||
lv_style_t * style = lv_obj_get_style(label);
|
||||
const lv_font_t * font = style->text.font;
|
||||
uint8_t letter_height = lv_font_get_height(font);
|
||||
lv_coord_t y = 0;
|
||||
lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
|
||||
|
||||
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
|
||||
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
|
||||
if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
||||
|
||||
/*If the width will be expanded the set the max length to very big */
|
||||
if(ext->long_mode == LV_LABEL_LONG_EXPAND || ext->long_mode == LV_LABEL_LONG_SCROLL) {
|
||||
max_w = LV_COORD_MAX;
|
||||
}
|
||||
|
||||
index = lv_txt_encoded_get_byte_id(txt, index);
|
||||
|
||||
/*Search the line of the index letter */;
|
||||
while(txt[new_line_start] != '\0') {
|
||||
new_line_start += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, max_w, flag);
|
||||
if(index < new_line_start || txt[new_line_start] == '\0') break; /*The line of 'index' letter begins at 'line_start'*/
|
||||
|
||||
y += letter_height + style->text.line_space;
|
||||
line_start = new_line_start;
|
||||
}
|
||||
|
||||
/*If the last character is line break then go to the next line*/
|
||||
if(index > 0) {
|
||||
if((txt[index - 1] == '\n' || txt[index - 1] == '\r') && txt[index] == '\0') {
|
||||
y += letter_height + style->text.line_space;
|
||||
line_start = index;
|
||||
}
|
||||
}
|
||||
|
||||
/*Calculate the x coordinate*/
|
||||
lv_coord_t x = lv_txt_get_width(&txt[line_start], index - line_start,
|
||||
font, style->text.letter_space, flag);
|
||||
|
||||
if(index != line_start) x += style->text.letter_space;
|
||||
|
||||
if(ext->align == LV_LABEL_ALIGN_CENTER) {
|
||||
lv_coord_t line_w;
|
||||
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start,
|
||||
font, style->text.letter_space, flag);
|
||||
x += lv_obj_get_width(label) / 2 - line_w / 2;
|
||||
|
||||
} else if(ext->align == LV_LABEL_ALIGN_RIGHT) {
|
||||
lv_coord_t line_w;
|
||||
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start,
|
||||
font, style->text.letter_space, flag);
|
||||
|
||||
x += lv_obj_get_width(label) - line_w;
|
||||
}
|
||||
pos->x = x;
|
||||
pos->y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of letter on a relative point of a label
|
||||
* @param label pointer to label object
|
||||
* @param pos pointer to point with coordinates on a the label
|
||||
* @return the index of the letter on the 'pos_p' point (E.g. on 0;0 is the 0. letter)
|
||||
* Expressed in character index and not byte index (different in UTF-8)
|
||||
*/
|
||||
uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
|
||||
{
|
||||
const char * txt = lv_label_get_text(label);
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
uint32_t line_start = 0;
|
||||
uint32_t new_line_start = 0;
|
||||
lv_coord_t max_w = lv_obj_get_width(label);
|
||||
lv_style_t * style = lv_obj_get_style(label);
|
||||
const lv_font_t * font = style->text.font;
|
||||
uint8_t letter_height = lv_font_get_height(font);
|
||||
lv_coord_t y = 0;
|
||||
lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
|
||||
|
||||
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
|
||||
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
|
||||
if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
||||
|
||||
/*If the width will be expanded set the max length to very big */
|
||||
if(ext->long_mode == LV_LABEL_LONG_EXPAND || ext->long_mode == LV_LABEL_LONG_SCROLL) {
|
||||
max_w = LV_COORD_MAX;
|
||||
}
|
||||
|
||||
/*Search the line of the index letter */;
|
||||
while(txt[line_start] != '\0') {
|
||||
new_line_start += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, max_w, flag);
|
||||
|
||||
if(pos->y <= y + letter_height) break; /*The line is found (stored in 'line_start')*/
|
||||
y += letter_height + style->text.line_space;
|
||||
|
||||
line_start = new_line_start;
|
||||
}
|
||||
|
||||
/*Calculate the x coordinate*/
|
||||
lv_coord_t x = 0;
|
||||
if(ext->align == LV_LABEL_ALIGN_CENTER) {
|
||||
lv_coord_t line_w;
|
||||
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start,
|
||||
font, style->text.letter_space, flag);
|
||||
x += lv_obj_get_width(label) / 2 - line_w / 2;
|
||||
}
|
||||
|
||||
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
||||
uint32_t i = line_start;
|
||||
uint32_t i_current = i;
|
||||
uint32_t letter;
|
||||
while(i < new_line_start - 1) {
|
||||
letter = lv_txt_encoded_next(txt, &i); /*Be careful 'i' already points to the next character*/
|
||||
/*Handle the recolor command*/
|
||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||
if(lv_txt_is_cmd(&cmd_state, txt[i]) != false) {
|
||||
continue; /*Skip the letter is it is part of a command*/
|
||||
}
|
||||
}
|
||||
|
||||
x += lv_font_get_width(font, letter);
|
||||
if(pos->x < x) {
|
||||
i = i_current;
|
||||
break;
|
||||
}
|
||||
x += style->text.letter_space;
|
||||
i_current = i;
|
||||
}
|
||||
|
||||
return lv_encoded_get_char_id(txt, i);
|
||||
}
|
||||
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Insert a text to the label. The label text can not be static.
|
||||
* @param label pointer to a label object
|
||||
* @param pos character index to insert. Expressed in character index and not byte index (Different in UTF-8)
|
||||
* 0: before first char.
|
||||
* LV_LABEL_POS_LAST: after last char.
|
||||
* @param txt pointer to the text to insert
|
||||
*/
|
||||
void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
|
||||
/*Can not append to static text*/
|
||||
if(ext->static_txt != 0) return;
|
||||
|
||||
lv_obj_invalidate(label);
|
||||
|
||||
/*Allocate space for the new text*/
|
||||
uint32_t old_len = strlen(ext->text);
|
||||
uint32_t ins_len = strlen(txt);
|
||||
uint32_t new_len = ins_len + old_len;
|
||||
ext->text = lv_mem_realloc(ext->text, new_len + 1);
|
||||
lv_mem_assert(ext->text);
|
||||
if(ext->text == NULL) return;
|
||||
|
||||
if(pos == LV_LABEL_POS_LAST) {
|
||||
#if LV_TXT_UTF8 == 0
|
||||
pos = old_len;
|
||||
#else
|
||||
pos = lv_txt_get_encoded_length(ext->text);
|
||||
#endif
|
||||
}
|
||||
|
||||
lv_txt_ins(ext->text, pos, txt);
|
||||
|
||||
lv_label_refr_text(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete characters from a label. The label text can not be static.
|
||||
* @param label pointer to a label object
|
||||
* @param pos character index to insert. Expressed in character index and not byte index (Different in UTF-8)
|
||||
* 0: before first char.
|
||||
* @param cnt number of characters to cut
|
||||
*/
|
||||
void lv_label_cut_text(lv_obj_t * label, uint32_t pos, uint32_t cnt)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
|
||||
/*Can not append to static text*/
|
||||
if(ext->static_txt != 0) return;
|
||||
|
||||
lv_obj_invalidate(label);
|
||||
|
||||
char * label_txt = lv_label_get_text(label);
|
||||
/*Delete the characters*/
|
||||
lv_txt_cut(label_txt, pos, cnt);
|
||||
|
||||
/*Refresh the label*/
|
||||
lv_label_refr_text(label);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the labels
|
||||
* @param label pointer to a label object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
/* A label never covers an area */
|
||||
if(mode == LV_DESIGN_COVER_CHK) return false;
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
lv_area_t coords;
|
||||
lv_style_t * style = lv_obj_get_style(label);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(label);
|
||||
lv_obj_get_coords(label, &coords);
|
||||
|
||||
#if USE_LV_GROUP
|
||||
lv_group_t * g = lv_obj_get_group(label);
|
||||
if(lv_group_get_focused(g) == label) {
|
||||
lv_draw_rect(&coords, mask, style, opa_scale);
|
||||
}
|
||||
#endif
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
|
||||
if(ext->body_draw) {
|
||||
lv_area_t bg;
|
||||
lv_obj_get_coords(label, &bg);
|
||||
bg.x1 -= style->body.padding.hor;
|
||||
bg.x2 += style->body.padding.hor;
|
||||
bg.y1 -= style->body.padding.ver;
|
||||
bg.y2 += style->body.padding.ver;
|
||||
|
||||
lv_draw_rect(&bg, mask, style, lv_obj_get_opa_scale(label));
|
||||
}
|
||||
|
||||
/*TEST: draw a background for the label*/
|
||||
//lv_draw_rect(&label->coords, mask, &lv_style_plain_color, LV_OPA_COVER);
|
||||
|
||||
lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
|
||||
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
|
||||
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
|
||||
if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
|
||||
if(ext->align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT;
|
||||
|
||||
/* In ROLL mode the CENTER and RIGHT are pointless so remove them.
|
||||
* (In addition they will result mis-alignment is this case)*/
|
||||
if((ext->long_mode == LV_LABEL_LONG_ROLL) &&
|
||||
(ext->align == LV_LABEL_ALIGN_CENTER || ext->align == LV_LABEL_ALIGN_RIGHT)) {
|
||||
lv_point_t size;
|
||||
lv_txt_get_size(&size, ext->text, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, flag);
|
||||
if(size.x > lv_obj_get_width(label)) {
|
||||
flag &= ~LV_TXT_FLAG_RIGHT;
|
||||
flag &= ~LV_TXT_FLAG_CENTER;
|
||||
}
|
||||
}
|
||||
|
||||
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ext->offset);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Signal function of the label
|
||||
* @param label pointer to a label object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_label_signal(lv_obj_t * label, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(label, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
if(ext->static_txt == 0) {
|
||||
lv_mem_free(ext->text);
|
||||
ext->text = NULL;
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
/*Revert dots for proper refresh*/
|
||||
lv_label_revert_dots(label);
|
||||
|
||||
lv_label_refr_text(label);
|
||||
} else if(sign == LV_SIGNAL_CORD_CHG) {
|
||||
if(lv_area_get_width(&label->coords) != lv_area_get_width(param) ||
|
||||
lv_area_get_height(&label->coords) != lv_area_get_height(param)) {
|
||||
lv_label_revert_dots(label);
|
||||
lv_label_refr_text(label);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_REFR_EXT_SIZE) {
|
||||
if(ext->body_draw) {
|
||||
lv_style_t * style = lv_label_get_style(label);
|
||||
label->ext_size = LV_MATH_MAX(label->ext_size, style->body.padding.hor);
|
||||
label->ext_size = LV_MATH_MAX(label->ext_size, style->body.padding.ver);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_LANG_CHG) {
|
||||
#if USE_LV_MULTI_LANG
|
||||
if(ext->lang_txt_id != LV_LANG_TXT_ID_NONE) {
|
||||
const char * lang_txt = lv_lang_get_text(ext->lang_txt_id);
|
||||
if(lang_txt) {
|
||||
lv_label_set_text(label, lang_txt);
|
||||
} else {
|
||||
LV_LOG_WARN("lv_lang_get_text return NULL for a label's text");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_label";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the label with its text stored in its extended data
|
||||
* @param label pointer to a label object
|
||||
*/
|
||||
static void lv_label_refr_text(lv_obj_t * label)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
|
||||
if(ext->text == NULL) return;
|
||||
|
||||
lv_coord_t max_w = lv_obj_get_width(label);
|
||||
lv_style_t * style = lv_obj_get_style(label);
|
||||
const lv_font_t * font = style->text.font;
|
||||
|
||||
/*If the width will be expanded set the max length to very big */
|
||||
if(ext->long_mode == LV_LABEL_LONG_EXPAND ||
|
||||
ext->long_mode == LV_LABEL_LONG_SCROLL) {
|
||||
max_w = LV_COORD_MAX;
|
||||
}
|
||||
|
||||
/*Calc. the height and longest line*/
|
||||
lv_point_t size;
|
||||
lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
|
||||
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
|
||||
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
|
||||
lv_txt_get_size(&size, ext->text, font, style->text.letter_space, style->text.line_space, max_w, flag);
|
||||
|
||||
/*Set the full size in expand mode*/
|
||||
if(ext->long_mode == LV_LABEL_LONG_EXPAND || ext->long_mode == LV_LABEL_LONG_SCROLL) {
|
||||
lv_obj_set_size(label, size.x, size.y);
|
||||
|
||||
/*Start scrolling if the label is greater then its parent*/
|
||||
if(ext->long_mode == LV_LABEL_LONG_SCROLL) {
|
||||
#if USE_LV_ANIMATION
|
||||
lv_obj_t * parent = lv_obj_get_parent(label);
|
||||
|
||||
/*Delete the potential previous scroller animations*/
|
||||
lv_anim_del(label, (lv_anim_fp_t) lv_obj_set_x);
|
||||
lv_anim_del(label, (lv_anim_fp_t) lv_obj_set_y);
|
||||
|
||||
lv_anim_t anim;
|
||||
anim.var = label;
|
||||
anim.repeat = 1;
|
||||
anim.playback = 1;
|
||||
anim.start = 0;
|
||||
anim.act_time = 0;
|
||||
anim.end_cb = NULL;
|
||||
anim.path = lv_anim_path_linear;
|
||||
|
||||
anim.playback_pause = (((lv_font_get_width(style->text.font, ' ') +
|
||||
style->text.letter_space) * 1000) / ext->anim_speed) * ANIM_WAIT_CHAR_COUNT;
|
||||
anim.repeat_pause = anim.playback_pause;
|
||||
|
||||
if(lv_obj_get_width(label) > lv_obj_get_width(parent)) {
|
||||
anim.end = lv_obj_get_width(parent) - lv_obj_get_width(label);
|
||||
anim.fp = (lv_anim_fp_t) lv_obj_set_x;
|
||||
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
|
||||
lv_anim_create(&anim);
|
||||
} else if(lv_obj_get_height(label) > lv_obj_get_height(parent)) {
|
||||
anim.end = lv_obj_get_height(parent) - lv_obj_get_height(label) - lv_font_get_height(font);
|
||||
anim.fp = (lv_anim_fp_t)lv_obj_set_y;
|
||||
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
|
||||
lv_anim_create(&anim);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*In roll mode keep the size but start offset animations*/
|
||||
else if(ext->long_mode == LV_LABEL_LONG_ROLL) {
|
||||
#if USE_LV_ANIMATION
|
||||
lv_anim_t anim;
|
||||
anim.var = label;
|
||||
anim.repeat = 1;
|
||||
anim.playback = 1;
|
||||
anim.start = 0;
|
||||
anim.act_time = 0;
|
||||
anim.end_cb = NULL;
|
||||
anim.path = lv_anim_path_linear;
|
||||
anim.playback_pause = (((lv_font_get_width(style->text.font, ' ') + style->text.letter_space) * 1000) / ext->anim_speed) * ANIM_WAIT_CHAR_COUNT;
|
||||
anim.repeat_pause = anim.playback_pause;
|
||||
|
||||
bool hor_anim = false;
|
||||
if(size.x > lv_obj_get_width(label)) {
|
||||
anim.end = lv_obj_get_width(label) - size.x;
|
||||
anim.fp = (lv_anim_fp_t) lv_label_set_offset_x;
|
||||
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
|
||||
lv_anim_create(&anim);
|
||||
hor_anim = true;
|
||||
} else {
|
||||
/*Delete the offset animation if not required*/
|
||||
lv_anim_del(label, (lv_anim_fp_t) lv_label_set_offset_x);
|
||||
ext->offset.x = 0;
|
||||
}
|
||||
|
||||
if(size.y > lv_obj_get_height(label) && hor_anim == false) {
|
||||
anim.end = lv_obj_get_height(label) - size.y - (lv_font_get_height(font));
|
||||
anim.fp = (lv_anim_fp_t)lv_label_set_offset_y;
|
||||
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
|
||||
lv_anim_create(&anim);
|
||||
} else {
|
||||
/*Delete the offset animation if not required*/
|
||||
lv_anim_del(label, (lv_anim_fp_t) lv_label_set_offset_y);
|
||||
ext->offset.y = 0;
|
||||
}
|
||||
#endif
|
||||
} else if(ext->long_mode == LV_LABEL_LONG_DOT) {
|
||||
if(size.y <= lv_obj_get_height(label)) { /*No dots are required, the text is short enough*/
|
||||
ext->dot_end = LV_LABEL_DOT_END_INV;
|
||||
} else if(lv_txt_get_encoded_length(ext->text) <= LV_LABEL_DOT_NUM) { /*Don't turn to dots all the characters*/
|
||||
ext->dot_end = LV_LABEL_DOT_END_INV;
|
||||
} else {
|
||||
lv_point_t p;
|
||||
p.x = lv_obj_get_width(label) - (lv_font_get_width(style->text.font, '.') + style->text.letter_space) * LV_LABEL_DOT_NUM; /*Shrink with dots*/
|
||||
p.y = lv_obj_get_height(label);
|
||||
p.y -= p.y % (lv_font_get_height(style->text.font) + style->text.line_space); /*Round down to the last line*/
|
||||
p.y -= style->text.line_space; /*Trim the last line space*/
|
||||
uint32_t letter_id = lv_label_get_letter_on(label, &p);
|
||||
|
||||
|
||||
#if LV_TXT_UTF8 == 0
|
||||
/*Save letters under the dots and replace them with dots*/
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_LABEL_DOT_NUM; i++) {
|
||||
ext->dot_tmp[i] = ext->text[letter_id + i];
|
||||
ext->text[letter_id + i] = '.';
|
||||
}
|
||||
|
||||
ext->dot_tmp[LV_LABEL_DOT_NUM] = ext->text[letter_id + LV_LABEL_DOT_NUM];
|
||||
ext->text[letter_id + LV_LABEL_DOT_NUM] = '\0';
|
||||
|
||||
ext->dot_end = letter_id + LV_LABEL_DOT_NUM;
|
||||
#else
|
||||
/*Save letters under the dots and replace them with dots*/
|
||||
uint32_t i;
|
||||
uint32_t byte_id = lv_txt_encoded_get_byte_id(ext->text, letter_id);
|
||||
uint32_t byte_id_ori = byte_id;
|
||||
uint8_t len = 0;
|
||||
for(i = 0; i <= LV_LABEL_DOT_NUM; i++) {
|
||||
len += lv_txt_encoded_size(&ext->text[byte_id]);
|
||||
lv_txt_encoded_next(ext->text, &byte_id);
|
||||
}
|
||||
|
||||
memcpy(ext->dot_tmp, &ext->text[byte_id_ori], len);
|
||||
ext->dot_tmp[len] = '\0'; /*Close with a zero*/
|
||||
|
||||
for(i = 0; i < LV_LABEL_DOT_NUM; i++) {
|
||||
ext->text[byte_id_ori + i] = '.';
|
||||
}
|
||||
ext->text[byte_id_ori + LV_LABEL_DOT_NUM] = '\0';
|
||||
|
||||
ext->dot_end = letter_id + LV_LABEL_DOT_NUM;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
/*In break mode only the height can change*/
|
||||
else if(ext->long_mode == LV_LABEL_LONG_BREAK) {
|
||||
lv_obj_set_height(label, size.y);
|
||||
}
|
||||
/*Do not set the size in Clip mode*/
|
||||
else if(ext->long_mode == LV_LABEL_LONG_CROP) {
|
||||
/*Do nothing*/
|
||||
}
|
||||
|
||||
|
||||
lv_obj_invalidate(label);
|
||||
}
|
||||
|
||||
static void lv_label_revert_dots(lv_obj_t * label)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
if(ext->long_mode != LV_LABEL_LONG_DOT) return;
|
||||
if(ext->dot_end == LV_LABEL_DOT_END_INV) return;
|
||||
#if LV_TXT_UTF8 == 0
|
||||
uint32_t i;
|
||||
for(i = 0; i <= LV_LABEL_DOT_NUM; i++) {
|
||||
ext->text[ext->dot_end - i] = ext->dot_tmp[LV_LABEL_DOT_NUM - i];
|
||||
}
|
||||
#else
|
||||
uint32_t letter_i = ext->dot_end - LV_LABEL_DOT_NUM;
|
||||
uint32_t byte_i = lv_txt_encoded_get_byte_id(ext->text, letter_i);
|
||||
|
||||
/*Restore the characters*/
|
||||
uint8_t i = 0;
|
||||
while(ext->dot_tmp[i] != '\0') {
|
||||
ext->text[byte_i + i] = ext->dot_tmp[i];
|
||||
i++;
|
||||
}
|
||||
#endif
|
||||
|
||||
ext->dot_end = LV_LABEL_DOT_END_INV;
|
||||
}
|
||||
|
||||
#if USE_LV_ANIMATION
|
||||
static void lv_label_set_offset_x(lv_obj_t * label, lv_coord_t x)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
ext->offset.x = x;
|
||||
lv_obj_invalidate(label);
|
||||
}
|
||||
|
||||
static void lv_label_set_offset_y(lv_obj_t * label, lv_coord_t y)
|
||||
{
|
||||
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
|
||||
ext->offset.y = y;
|
||||
lv_obj_invalidate(label);
|
||||
}
|
||||
#endif
|
||||
#endif
|
295
bdk/libs/lvgl/lv_objx/lv_label.h
Normal file
295
bdk/libs/lvgl/lv_objx/lv_label.h
Normal file
|
@ -0,0 +1,295 @@
|
|||
/**
|
||||
* @file lv_rect.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_LABEL_H
|
||||
#define LV_LABEL_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_LABEL != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_misc/lv_font.h"
|
||||
#include "../lv_misc/lv_txt.h"
|
||||
#include "../lv_misc/lv_symbol_def.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_LABEL_DOT_NUM 3
|
||||
#define LV_LABEL_POS_LAST 0xFFFF
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Long mode behaviors. Used in 'lv_label_ext_t' */
|
||||
enum
|
||||
{
|
||||
LV_LABEL_LONG_EXPAND, /*Expand the object size to the text size*/
|
||||
LV_LABEL_LONG_BREAK, /*Keep the object width, break the too long lines and expand the object height*/
|
||||
LV_LABEL_LONG_SCROLL, /*Expand the object size and scroll the text on the parent (move the label object)*/
|
||||
LV_LABEL_LONG_DOT, /*Keep the size and write dots at the end if the text is too long*/
|
||||
LV_LABEL_LONG_ROLL, /*Keep the size and roll the text infinitely*/
|
||||
LV_LABEL_LONG_CROP, /*Keep the size and crop the text out of it*/
|
||||
};
|
||||
typedef uint8_t lv_label_long_mode_t;
|
||||
|
||||
/*Label align policy*/
|
||||
enum {
|
||||
LV_LABEL_ALIGN_LEFT,
|
||||
LV_LABEL_ALIGN_CENTER,
|
||||
LV_LABEL_ALIGN_RIGHT,
|
||||
};
|
||||
typedef uint8_t lv_label_align_t;
|
||||
|
||||
/*Data of label*/
|
||||
typedef struct
|
||||
{
|
||||
/*Inherited from 'base_obj' so no inherited ext.*/ /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
char * text; /*Text of the label*/
|
||||
lv_label_long_mode_t long_mode; /*Determinate what to do with the long texts*/
|
||||
#if LV_TXT_UTF8 == 0
|
||||
char dot_tmp[LV_LABEL_DOT_NUM + 1]; /*Store the character which are replaced by dots (Handled by the library)*/
|
||||
#else
|
||||
char dot_tmp[LV_LABEL_DOT_NUM * 4 + 1]; /*Store the character which are replaced by dots (Handled by the library)*/
|
||||
#endif
|
||||
|
||||
#if USE_LV_MULTI_LANG
|
||||
uint16_t lang_txt_id; /*The ID of the text to display*/
|
||||
#endif
|
||||
uint16_t dot_end; /*The text end position in dot mode (Handled by the library)*/
|
||||
uint16_t anim_speed; /*Speed of scroll and roll animation in px/sec unit*/
|
||||
lv_point_t offset; /*Text draw position offset*/
|
||||
uint8_t static_txt :1; /*Flag to indicate the text is static*/
|
||||
uint8_t align :2; /*Align type from 'lv_label_align_t'*/
|
||||
uint8_t recolor :1; /*Enable in-line letter re-coloring*/
|
||||
uint8_t expand :1; /*Ignore real width (used by the library with LV_LABEL_LONG_ROLL)*/
|
||||
uint8_t body_draw :1; /*Draw background body*/
|
||||
} lv_label_ext_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
|
||||
/**
|
||||
* Create a label objects
|
||||
* @param par pointer to an object, it will be the parent of the new label
|
||||
* @param copy pointer to a button object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created button
|
||||
*/
|
||||
lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new text for a label. Memory will be allocated to store the text by the label.
|
||||
* @param label pointer to a label object
|
||||
* @param text '\0' terminated character string. NULL to refresh with the current text.
|
||||
*/
|
||||
void lv_label_set_text(lv_obj_t * label, const char * text);
|
||||
|
||||
/**
|
||||
* Set a new text for a label from a character array. The array don't has to be '\0' terminated.
|
||||
* Memory will be allocated to store the array by the label.
|
||||
* @param label pointer to a label object
|
||||
* @param array array of characters or NULL to refresh the label
|
||||
* @param size the size of 'array' in bytes
|
||||
*/
|
||||
void lv_label_set_array_text(lv_obj_t * label, const char * array, uint16_t size);
|
||||
|
||||
/**
|
||||
* Set a static text. It will not be saved by the label so the 'text' variable
|
||||
* has to be 'alive' while the label exist.
|
||||
* @param label pointer to a label object
|
||||
* @param text pointer to a text. NULL to refresh with the current text.
|
||||
*/
|
||||
void lv_label_set_static_text(lv_obj_t * label, const char * text);
|
||||
|
||||
/**
|
||||
*Set a text ID which means a the same text but on different languages
|
||||
* @param label pointer to a label object
|
||||
* @param txt_id ID of the text
|
||||
*/
|
||||
#if USE_LV_MULTI_LANG
|
||||
void lv_label_set_text_id(lv_obj_t * label, uint32_t txt_id);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set the behavior of the label with longer text then the object size
|
||||
* @param label pointer to a label object
|
||||
* @param long_mode the new mode from 'lv_label_long_mode' enum.
|
||||
* In LV_LONG_BREAK/LONG/ROLL the size of the label should be set AFTER this function
|
||||
*/
|
||||
void lv_label_set_long_mode(lv_obj_t * label, lv_label_long_mode_t long_mode);
|
||||
|
||||
/**
|
||||
* Set the align of the label (left or center)
|
||||
* @param label pointer to a label object
|
||||
* @param align 'LV_LABEL_ALIGN_LEFT' or 'LV_LABEL_ALIGN_LEFT'
|
||||
*/
|
||||
void lv_label_set_align(lv_obj_t *label, lv_label_align_t align);
|
||||
|
||||
/**
|
||||
* Enable the recoloring by in-line commands
|
||||
* @param label pointer to a label object
|
||||
* @param en true: enable recoloring, false: disable
|
||||
*/
|
||||
void lv_label_set_recolor(lv_obj_t * label, bool en);
|
||||
|
||||
/**
|
||||
* Set the label to draw (or not draw) background specified in its style's body
|
||||
* @param label pointer to a label object
|
||||
* @param en true: draw body; false: don't draw body
|
||||
*/
|
||||
void lv_label_set_body_draw(lv_obj_t *label, bool en);
|
||||
|
||||
/**
|
||||
* Set the label's animation speed in LV_LABEL_LONG_ROLL and SCROLL modes
|
||||
* @param label pointer to a label object
|
||||
* @param anim_speed speed of animation in px/sec unit
|
||||
*/
|
||||
void lv_label_set_anim_speed(lv_obj_t *label, uint16_t anim_speed);
|
||||
|
||||
/**
|
||||
* Set the style of an label
|
||||
* @param label pointer to an label object
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
static inline void lv_label_set_style(lv_obj_t *label, lv_style_t *style)
|
||||
{
|
||||
lv_obj_set_style(label, style);
|
||||
}
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the text of a label
|
||||
* @param label pointer to a label object
|
||||
* @return the text of the label
|
||||
*/
|
||||
char * lv_label_get_text(const lv_obj_t * label);
|
||||
|
||||
#if USE_LV_MULTI_LANG
|
||||
/**
|
||||
* Get the text ID of the label. (Used by the multi-language feature)
|
||||
* @param label pointer to a label object
|
||||
* @return ID of the text
|
||||
*/
|
||||
uint16_t lv_label_get_text_id(lv_obj_t * label);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get the long mode of a label
|
||||
* @param label pointer to a label object
|
||||
* @return the long mode
|
||||
*/
|
||||
lv_label_long_mode_t lv_label_get_long_mode(const lv_obj_t * label);
|
||||
|
||||
/**
|
||||
* Get the align attribute
|
||||
* @param label pointer to a label object
|
||||
* @return LV_LABEL_ALIGN_LEFT or LV_LABEL_ALIGN_CENTER
|
||||
*/
|
||||
lv_label_align_t lv_label_get_align(const lv_obj_t * label);
|
||||
|
||||
/**
|
||||
* Get the recoloring attribute
|
||||
* @param label pointer to a label object
|
||||
* @return true: recoloring is enabled, false: disable
|
||||
*/
|
||||
bool lv_label_get_recolor(const lv_obj_t * label);
|
||||
|
||||
/**
|
||||
* Get the body draw attribute
|
||||
* @param label pointer to a label object
|
||||
* @return true: draw body; false: don't draw body
|
||||
*/
|
||||
bool lv_label_get_body_draw(const lv_obj_t *label);
|
||||
|
||||
/**
|
||||
* Get the label's animation speed in LV_LABEL_LONG_ROLL and SCROLL modes
|
||||
* @param label pointer to a label object
|
||||
* @return speed of animation in px/sec unit
|
||||
*/
|
||||
uint16_t lv_label_get_anim_speed(const lv_obj_t *label);
|
||||
|
||||
/**
|
||||
* Get the relative x and y coordinates of a letter
|
||||
* @param label pointer to a label object
|
||||
* @param index index of the letter [0 ... text length]. Expressed in character index, not byte index (different in UTF-8)
|
||||
* @param pos store the result here (E.g. index = 0 gives 0;0 coordinates)
|
||||
*/
|
||||
void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t * pos);
|
||||
|
||||
/**
|
||||
* Get the index of letter on a relative point of a label
|
||||
* @param label pointer to label object
|
||||
* @param pos pointer to point with coordinates on a the label
|
||||
* @return the index of the letter on the 'pos_p' point (E.g. on 0;0 is the 0. letter)
|
||||
* Expressed in character index and not byte index (different in UTF-8)
|
||||
*/
|
||||
uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos);
|
||||
|
||||
/**
|
||||
* Get the style of an label object
|
||||
* @param label pointer to an label object
|
||||
* @return pointer to the label's style
|
||||
*/
|
||||
static inline lv_style_t* lv_label_get_style(const lv_obj_t *label)
|
||||
{
|
||||
return lv_obj_get_style(label);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Insert a text to the label. The label text can not be static.
|
||||
* @param label pointer to a label object
|
||||
* @param pos character index to insert. Expressed in character index and not byte index (Different in UTF-8)
|
||||
* 0: before first char.
|
||||
* LV_LABEL_POS_LAST: after last char.
|
||||
* @param txt pointer to the text to insert
|
||||
*/
|
||||
void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt);
|
||||
|
||||
/**
|
||||
* Delete characters from a label. The label text can not be static.
|
||||
* @param label pointer to a label object
|
||||
* @param pos character index to insert. Expressed in character index and not byte index (Different in UTF-8)
|
||||
* 0: before first char.
|
||||
* @param cnt number of characters to cut
|
||||
*/
|
||||
void lv_label_cut_text(lv_obj_t * label, uint32_t pos, uint32_t cnt);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_LABEL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_LABEL_H*/
|
244
bdk/libs/lvgl/lv_objx/lv_led.c
Normal file
244
bdk/libs/lvgl/lv_objx/lv_led.c
Normal file
|
@ -0,0 +1,244 @@
|
|||
/**
|
||||
* @file lv_led.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_led.h"
|
||||
#if USE_LV_LED != 0
|
||||
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_LED_WIDTH_DEF (LV_DPI / 3)
|
||||
#define LV_LED_HEIGHT_DEF (LV_DPI / 3)
|
||||
#define LV_LED_BRIGHT_OFF 100
|
||||
#define LV_LED_BRIGHT_ON 255
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_led_design(lv_obj_t * led, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_led_signal(lv_obj_t * led, lv_signal_t sign, void * param);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_design_func_t ancestor_design_f;
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a led objects
|
||||
* @param par pointer to an object, it will be the parent of the new led
|
||||
* @param copy pointer to a led object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created led
|
||||
*/
|
||||
lv_obj_t * lv_led_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("led create started");
|
||||
|
||||
/*Create the ancestor basic object*/
|
||||
lv_obj_t * new_led = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_led);
|
||||
if(new_led == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_led);
|
||||
if(ancestor_design_f == NULL) ancestor_design_f = lv_obj_get_design_func(new_led);
|
||||
|
||||
/*Allocate the object type specific extended data*/
|
||||
lv_led_ext_t * ext = lv_obj_allocate_ext_attr(new_led, sizeof(lv_led_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->bright = LV_LED_BRIGHT_ON;
|
||||
|
||||
lv_obj_set_signal_func(new_led, lv_led_signal);
|
||||
lv_obj_set_design_func(new_led, lv_led_design);
|
||||
|
||||
/*Init the new led object*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_size(new_led, LV_LED_WIDTH_DEF, LV_LED_HEIGHT_DEF);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_led_set_style(new_led, th->led);
|
||||
} else {
|
||||
lv_led_set_style(new_led, &lv_style_pretty_color);
|
||||
}
|
||||
}
|
||||
/*Copy an existing object*/
|
||||
else {
|
||||
lv_led_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->bright = copy_ext->bright;
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_led);
|
||||
}
|
||||
|
||||
|
||||
LV_LOG_INFO("led created");
|
||||
|
||||
return new_led;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the brightness of a LED object
|
||||
* @param led pointer to a LED object
|
||||
* @param bright 0 (max. dark) ... 255 (max. light)
|
||||
*/
|
||||
void lv_led_set_bright(lv_obj_t * led, uint8_t bright)
|
||||
{
|
||||
/*Set the brightness*/
|
||||
lv_led_ext_t * ext = lv_obj_get_ext_attr(led);
|
||||
if(ext->bright == bright) return;
|
||||
|
||||
ext->bright = bright;
|
||||
|
||||
/*Invalidate the object there fore it will be redrawn*/
|
||||
lv_obj_invalidate(led);
|
||||
}
|
||||
|
||||
/**
|
||||
* Light on a LED
|
||||
* @param led pointer to a LED object
|
||||
*/
|
||||
void lv_led_on(lv_obj_t * led)
|
||||
{
|
||||
lv_led_set_bright(led, LV_LED_BRIGHT_ON);
|
||||
}
|
||||
|
||||
/**
|
||||
* Light off a LED
|
||||
* @param led pointer to a LED object
|
||||
*/
|
||||
void lv_led_off(lv_obj_t * led)
|
||||
{
|
||||
lv_led_set_bright(led, LV_LED_BRIGHT_OFF);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Toggle the state of a LED
|
||||
* @param led pointer to a LED object
|
||||
*/
|
||||
void lv_led_toggle(lv_obj_t * led)
|
||||
{
|
||||
uint8_t bright = lv_led_get_bright(led);
|
||||
if(bright > (LV_LED_BRIGHT_OFF + LV_LED_BRIGHT_ON) >> 1) lv_led_off(led);
|
||||
else lv_led_on(led);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the brightness of a LEd object
|
||||
* @param led pointer to LED object
|
||||
* @return bright 0 (max. dark) ... 255 (max. light)
|
||||
*/
|
||||
uint8_t lv_led_get_bright(const lv_obj_t * led)
|
||||
{
|
||||
lv_led_ext_t * ext = lv_obj_get_ext_attr(led);
|
||||
return ext->bright;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the leds
|
||||
* @param led pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_led_design(lv_obj_t * led, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
/*Return false if the object is not covers the mask area*/
|
||||
return ancestor_design_f(led, mask, mode);
|
||||
} else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
/*Make darker colors in a temporary style according to the brightness*/
|
||||
lv_led_ext_t * ext = lv_obj_get_ext_attr(led);
|
||||
lv_style_t * style = lv_obj_get_style(led);
|
||||
|
||||
/* Store the real pointer because of 'lv_group'
|
||||
* If the object is in focus 'lv_obj_get_style()' will give a pointer to tmp style
|
||||
* and to the real object style. It is important because of style change tricks below*/
|
||||
lv_style_t * style_ori_p = led->style_p;
|
||||
|
||||
/*Create a temporal style*/
|
||||
lv_style_t leds_tmp;
|
||||
memcpy(&leds_tmp, style, sizeof(leds_tmp));
|
||||
|
||||
/*Mix. the color with black proportionally with brightness*/
|
||||
leds_tmp.body.main_color = lv_color_mix(leds_tmp.body.main_color, LV_COLOR_BLACK, ext->bright);
|
||||
leds_tmp.body.grad_color = lv_color_mix(leds_tmp.body.grad_color, LV_COLOR_BLACK, ext->bright);
|
||||
leds_tmp.body.border.color = lv_color_mix(leds_tmp.body.border.color, LV_COLOR_BLACK, ext->bright);
|
||||
|
||||
/*Set the current swidth according to brightness proportionally between LV_LED_BRIGHT_OFF and LV_LED_BRIGHT_ON*/
|
||||
uint16_t bright_tmp = ext->bright;
|
||||
leds_tmp.body.shadow.width = ((bright_tmp - LV_LED_BRIGHT_OFF) * style->body.shadow.width) / (LV_LED_BRIGHT_ON - LV_LED_BRIGHT_OFF);
|
||||
|
||||
led->style_p = &leds_tmp;
|
||||
ancestor_design_f(led, mask, mode);
|
||||
led->style_p = style_ori_p; /*Restore the ORIGINAL style pointer*/
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the led
|
||||
* @param led pointer to a led object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_led_signal(lv_obj_t * led, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(led, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
|
||||
if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_led";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
116
bdk/libs/lvgl/lv_objx/lv_led.h
Normal file
116
bdk/libs/lvgl/lv_objx/lv_led.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
/**
|
||||
* @file lv_led.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_LED_H
|
||||
#define LV_LED_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_LED != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Data of led*/
|
||||
typedef struct
|
||||
{
|
||||
/*No inherited ext.*/
|
||||
/*New data for this type */
|
||||
uint8_t bright; /*Current brightness of the LED (0..255)*/
|
||||
} lv_led_ext_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a led objects
|
||||
* @param par pointer to an object, it will be the parent of the new led
|
||||
* @param copy pointer to a led object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created led
|
||||
*/
|
||||
lv_obj_t * lv_led_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/**
|
||||
* Set the brightness of a LED object
|
||||
* @param led pointer to a LED object
|
||||
* @param bright 0 (max. dark) ... 255 (max. light)
|
||||
*/
|
||||
void lv_led_set_bright(lv_obj_t * led, uint8_t bright);
|
||||
|
||||
/**
|
||||
* Light on a LED
|
||||
* @param led pointer to a LED object
|
||||
*/
|
||||
void lv_led_on(lv_obj_t * led);
|
||||
|
||||
/**
|
||||
* Light off a LED
|
||||
* @param led pointer to a LED object
|
||||
*/
|
||||
void lv_led_off(lv_obj_t * led);
|
||||
|
||||
/**
|
||||
* Toggle the state of a LED
|
||||
* @param led pointer to a LED object
|
||||
*/
|
||||
void lv_led_toggle(lv_obj_t * led);
|
||||
|
||||
/**
|
||||
* Set the style of a led
|
||||
* @param led pointer to a led object
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
static inline void lv_led_set_style(lv_obj_t *led, lv_style_t *style)
|
||||
{
|
||||
lv_obj_set_style(led, style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the brightness of a LEd object
|
||||
* @param led pointer to LED object
|
||||
* @return bright 0 (max. dark) ... 255 (max. light)
|
||||
*/
|
||||
uint8_t lv_led_get_bright(const lv_obj_t * led);
|
||||
|
||||
/**
|
||||
* Get the style of an led object
|
||||
* @param led pointer to an led object
|
||||
* @return pointer to the led's style
|
||||
*/
|
||||
static inline lv_style_t* lv_led_get_style(const lv_obj_t *led)
|
||||
{
|
||||
return lv_obj_get_style(led);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_LED*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_LED_H*/
|
301
bdk/libs/lvgl/lv_objx/lv_line.c
Normal file
301
bdk/libs/lvgl/lv_objx/lv_line.c
Normal file
|
@ -0,0 +1,301 @@
|
|||
/**
|
||||
* @file lv_line.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_line.h"
|
||||
|
||||
#if USE_LV_LINE != 0
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_line_design(lv_obj_t * line, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_line_signal(lv_obj_t * line, lv_signal_t sign, void * param);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a line objects
|
||||
* @param par pointer to an object, it will be the parent of the new line
|
||||
* @return pointer to the created line
|
||||
*/
|
||||
lv_obj_t * lv_line_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("line create started");
|
||||
|
||||
/*Create a basic object*/
|
||||
lv_obj_t * new_line = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_line);
|
||||
if(new_line == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_line);
|
||||
|
||||
/*Extend the basic object to line object*/
|
||||
lv_line_ext_t * ext = lv_obj_allocate_ext_attr(new_line, sizeof(lv_line_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->point_num = 0;
|
||||
ext->point_array = NULL;
|
||||
ext->auto_size = 1;
|
||||
ext->y_inv = 0;
|
||||
|
||||
lv_obj_set_design_func(new_line, lv_line_design);
|
||||
lv_obj_set_signal_func(new_line, lv_line_signal);
|
||||
|
||||
/*Init the new line*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_size(new_line, LV_DPI, LV_DPI); /*Auto size is enables, but set default size until no points are added*/
|
||||
lv_obj_set_style(new_line, NULL); /*Inherit parent's style*/
|
||||
lv_obj_set_click(new_line, false);
|
||||
}
|
||||
/*Copy an existing object*/
|
||||
else {
|
||||
lv_line_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
lv_line_set_auto_size(new_line, lv_line_get_auto_size(copy));
|
||||
lv_line_set_y_invert(new_line, lv_line_get_y_invert(copy));
|
||||
lv_line_set_auto_size(new_line, lv_line_get_auto_size(copy));
|
||||
lv_line_set_points(new_line, copy_ext->point_array, copy_ext->point_num);
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_line);
|
||||
}
|
||||
|
||||
|
||||
LV_LOG_INFO("line created");
|
||||
|
||||
return new_line;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set an array of points. The line object will connect these points.
|
||||
* @param line pointer to a line object
|
||||
* @param point_a an array of points. Only the address is saved,
|
||||
* so the array can NOT be a local variable which will be destroyed
|
||||
* @param point_num number of points in 'point_a'
|
||||
*/
|
||||
void lv_line_set_points(lv_obj_t * line, const lv_point_t * point_a, uint16_t point_num)
|
||||
{
|
||||
lv_line_ext_t * ext = lv_obj_get_ext_attr(line);
|
||||
ext->point_array = point_a;
|
||||
ext->point_num = point_num;
|
||||
|
||||
if(point_num > 0 && ext->auto_size != 0) {
|
||||
uint16_t i;
|
||||
lv_coord_t xmax = LV_COORD_MIN;
|
||||
lv_coord_t ymax = LV_COORD_MIN;
|
||||
for(i = 0; i < point_num; i++) {
|
||||
xmax = LV_MATH_MAX(point_a[i].x, xmax);
|
||||
ymax = LV_MATH_MAX(point_a[i].y, ymax);
|
||||
}
|
||||
|
||||
lv_style_t * style = lv_line_get_style(line);
|
||||
lv_obj_set_size(line, xmax + style->line.width, ymax + style->line.width);
|
||||
}
|
||||
|
||||
lv_obj_invalidate(line);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable (or disable) the auto-size option. The size of the object will fit to its points.
|
||||
* (set width to x max and height to y max)
|
||||
* @param line pointer to a line object
|
||||
* @param en true: auto size is enabled, false: auto size is disabled
|
||||
*/
|
||||
void lv_line_set_auto_size(lv_obj_t * line, bool en)
|
||||
{
|
||||
lv_line_ext_t * ext = lv_obj_get_ext_attr(line);
|
||||
if(ext->auto_size == en) return;
|
||||
|
||||
ext->auto_size = en == false ? 0 : 1;
|
||||
|
||||
/*Refresh the object*/
|
||||
if(en) lv_line_set_points(line, ext->point_array, ext->point_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable (or disable) the y coordinate inversion.
|
||||
* If enabled then y will be subtracted from the height of the object,
|
||||
* therefore the y=0 coordinate will be on the bottom.
|
||||
* @param line pointer to a line object
|
||||
* @param en true: enable the y inversion, false:disable the y inversion
|
||||
*/
|
||||
void lv_line_set_y_invert(lv_obj_t * line, bool en)
|
||||
{
|
||||
lv_line_ext_t * ext = lv_obj_get_ext_attr(line);
|
||||
if(ext->y_inv == en) return;
|
||||
|
||||
ext->y_inv = en == false ? 0 : 1;
|
||||
|
||||
lv_obj_invalidate(line);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the auto size attribute
|
||||
* @param line pointer to a line object
|
||||
* @return true: auto size is enabled, false: disabled
|
||||
*/
|
||||
bool lv_line_get_auto_size(const lv_obj_t * line)
|
||||
{
|
||||
lv_line_ext_t * ext = lv_obj_get_ext_attr(line);
|
||||
|
||||
return ext->auto_size == 0 ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the y inversion attribute
|
||||
* @param line pointer to a line object
|
||||
* @return true: y inversion is enabled, false: disabled
|
||||
*/
|
||||
bool lv_line_get_y_invert(const lv_obj_t * line)
|
||||
{
|
||||
lv_line_ext_t * ext = lv_obj_get_ext_attr(line);
|
||||
|
||||
return ext->y_inv == 0 ? false : true;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the lines
|
||||
* @param line pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_line_design(lv_obj_t * line, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
/*A line never covers an area*/
|
||||
if(mode == LV_DESIGN_COVER_CHK) return false;
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
lv_line_ext_t * ext = lv_obj_get_ext_attr(line);
|
||||
|
||||
if(ext->point_num == 0 || ext->point_array == NULL) return false;
|
||||
|
||||
lv_style_t * style = lv_obj_get_style(line);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(line);
|
||||
lv_area_t area;
|
||||
lv_obj_get_coords(line, &area);
|
||||
lv_coord_t x_ofs = area.x1;
|
||||
lv_coord_t y_ofs = area.y1;
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
lv_coord_t h = lv_obj_get_height(line);
|
||||
uint16_t i;
|
||||
|
||||
lv_style_t circle_style; /*If rounded...*/
|
||||
lv_style_copy(&circle_style, style);
|
||||
circle_style.body.radius = LV_RADIUS_CIRCLE;
|
||||
circle_style.body.main_color = style->line.color;
|
||||
circle_style.body.grad_color = style->line.color;
|
||||
circle_style.body.opa = style->line.opa;
|
||||
lv_area_t circle_area;
|
||||
|
||||
/*Read all points and draw the lines*/
|
||||
for(i = 0; i < ext->point_num - 1; i++) {
|
||||
|
||||
p1.x = ext->point_array[i].x + x_ofs;
|
||||
p2.x = ext->point_array[i + 1].x + x_ofs;
|
||||
|
||||
if(ext->y_inv == 0) {
|
||||
p1.y = ext->point_array[i].y + y_ofs;
|
||||
p2.y = ext->point_array[i + 1].y + y_ofs;
|
||||
} else {
|
||||
p1.y = h - ext->point_array[i].y + y_ofs;
|
||||
p2.y = h - ext->point_array[i + 1].y + y_ofs;
|
||||
}
|
||||
lv_draw_line(&p1, &p2, mask, style, opa_scale);
|
||||
|
||||
/*Draw circle on the joints if enabled*/
|
||||
if(style->line.rounded) {
|
||||
circle_area.x1 = p1.x - ((style->line.width - 1) >> 1) - ((style->line.width - 1) & 0x1);
|
||||
circle_area.y1 = p1.y - ((style->line.width - 1) >> 1) - ((style->line.width - 1) & 0x1);
|
||||
circle_area.x2 = p1.x + ((style->line.width - 1) >> 1);
|
||||
circle_area.y2 = p1.y + ((style->line.width - 1) >> 1);
|
||||
lv_draw_rect(&circle_area, mask, &circle_style, opa_scale);
|
||||
}
|
||||
}
|
||||
|
||||
/*Draw circle on the last point too if enabled*/
|
||||
if(style->line.rounded) {
|
||||
circle_area.x1 = p2.x - ((style->line.width - 1) >> 1) - ((style->line.width - 1) & 0x1);
|
||||
circle_area.y1 = p2.y - ((style->line.width - 1) >> 1) - ((style->line.width - 1) & 0x1);
|
||||
circle_area.x2 = p2.x + ((style->line.width - 1) >> 1);
|
||||
circle_area.y2 = p2.y + ((style->line.width - 1) >> 1);
|
||||
lv_draw_rect(&circle_area, mask, &circle_style, opa_scale);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the line
|
||||
* @param line pointer to a line object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_line_signal(lv_obj_t * line, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(line, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
|
||||
if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_line";
|
||||
} else if(sign == LV_SIGNAL_REFR_EXT_SIZE) {
|
||||
lv_style_t * style = lv_line_get_style(line);
|
||||
if(line->ext_size < style->line.width) line->ext_size = style->line.width;
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
158
bdk/libs/lvgl/lv_objx/lv_line.h
Normal file
158
bdk/libs/lvgl/lv_objx/lv_line.h
Normal file
|
@ -0,0 +1,158 @@
|
|||
/**
|
||||
* @file lv_line.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_LINE_H
|
||||
#define LV_LINE_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_LINE != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Data of line*/
|
||||
typedef struct
|
||||
{
|
||||
/*Inherited from 'base_obj' so no inherited ext.*/ /*Ext. of ancestor*/
|
||||
const lv_point_t * point_array; /*Pointer to an array with the points of the line*/
|
||||
uint16_t point_num; /*Number of points in 'point_array' */
|
||||
uint8_t auto_size :1; /*1: set obj. width to x max and obj. height to y max */
|
||||
uint8_t y_inv :1; /*1: y == 0 will be on the bottom*/
|
||||
} lv_line_ext_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
|
||||
/**
|
||||
* Create a line objects
|
||||
* @param par pointer to an object, it will be the parent of the new line
|
||||
* @return pointer to the created line
|
||||
*/
|
||||
lv_obj_t * lv_line_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set an array of points. The line object will connect these points.
|
||||
* @param line pointer to a line object
|
||||
* @param point_a an array of points. Only the address is saved,
|
||||
* so the array can NOT be a local variable which will be destroyed
|
||||
* @param point_num number of points in 'point_a'
|
||||
*/
|
||||
void lv_line_set_points(lv_obj_t * line, const lv_point_t * point_a, uint16_t point_num);
|
||||
|
||||
/**
|
||||
* Enable (or disable) the auto-size option. The size of the object will fit to its points.
|
||||
* (set width to x max and height to y max)
|
||||
* @param line pointer to a line object
|
||||
* @param en true: auto size is enabled, false: auto size is disabled
|
||||
*/
|
||||
void lv_line_set_auto_size(lv_obj_t * line, bool en);
|
||||
|
||||
/**
|
||||
* Enable (or disable) the y coordinate inversion.
|
||||
* If enabled then y will be subtracted from the height of the object,
|
||||
* therefore the y=0 coordinate will be on the bottom.
|
||||
* @param line pointer to a line object
|
||||
* @param en true: enable the y inversion, false:disable the y inversion
|
||||
*/
|
||||
void lv_line_set_y_invert(lv_obj_t * line, bool en);
|
||||
|
||||
#define lv_line_set_y_inv lv_line_set_y_invert /*The name was inconsistent. In v.6.0 only `lv_line_set_y_invert`will work */
|
||||
|
||||
/**
|
||||
* Set the style of a line
|
||||
* @param line pointer to a line object
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
static inline void lv_line_set_style(lv_obj_t *line, lv_style_t *style)
|
||||
{
|
||||
lv_obj_set_style(line, style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obsolete since v5.1. Just for compatibility with v5.0. Will be removed in v6.0
|
||||
* @param line -
|
||||
* @param upscale -
|
||||
*/
|
||||
static inline void lv_line_set_upscale(lv_obj_t * line, bool upcale)
|
||||
{
|
||||
(void) line;
|
||||
(void) upcale;
|
||||
}
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the auto size attribute
|
||||
* @param line pointer to a line object
|
||||
* @return true: auto size is enabled, false: disabled
|
||||
*/
|
||||
bool lv_line_get_auto_size(const lv_obj_t * line);
|
||||
|
||||
/**
|
||||
* Get the y inversion attribute
|
||||
* @param line pointer to a line object
|
||||
* @return true: y inversion is enabled, false: disabled
|
||||
*/
|
||||
bool lv_line_get_y_invert(const lv_obj_t * line);
|
||||
|
||||
/**
|
||||
* Get the style of an line object
|
||||
* @param line pointer to an line object
|
||||
* @return pointer to the line's style
|
||||
*/
|
||||
static inline lv_style_t* lv_line_get_style(const lv_obj_t *line)
|
||||
{
|
||||
return lv_obj_get_style(line);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obsolete since v5.1. Just for compatibility with v5.0. Will be removed in v6.0
|
||||
* @param line -
|
||||
* @return false
|
||||
*/
|
||||
static inline bool lv_line_get_upscale(const lv_obj_t * line)
|
||||
{
|
||||
(void) line;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_LINE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_LINE_H*/
|
1052
bdk/libs/lvgl/lv_objx/lv_list.c
Normal file
1052
bdk/libs/lvgl/lv_objx/lv_list.c
Normal file
File diff suppressed because it is too large
Load diff
336
bdk/libs/lvgl/lv_objx/lv_list.h
Normal file
336
bdk/libs/lvgl/lv_objx/lv_list.h
Normal file
|
@ -0,0 +1,336 @@
|
|||
/**
|
||||
* @file lv_list.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_LIST_H
|
||||
#define LV_LIST_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_LIST != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_PAGE == 0
|
||||
#error "lv_list: lv_page is required. Enable it in lv_conf.h (USE_LV_PAGE 1) "
|
||||
#endif
|
||||
|
||||
#if USE_LV_BTN == 0
|
||||
#error "lv_list: lv_btn is required. Enable it in lv_conf.h (USE_LV_BTN 1) "
|
||||
#endif
|
||||
|
||||
#if USE_LV_LABEL == 0
|
||||
#error "lv_list: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) "
|
||||
#endif
|
||||
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_page.h"
|
||||
#include "lv_btn.h"
|
||||
#include "lv_label.h"
|
||||
#include "lv_img.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Data of list*/
|
||||
typedef struct
|
||||
{
|
||||
lv_page_ext_t page; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
uint16_t anim_time; /*Scroll animation time*/
|
||||
lv_style_t *styles_btn[LV_BTN_STATE_NUM]; /*Styles of the list element buttons*/
|
||||
lv_style_t *style_img; /*Style of the list element images on buttons*/
|
||||
uint32_t size; /*the number of items(buttons) in the list*/
|
||||
bool single_mode; /* whether single selected mode is enabled */
|
||||
#if USE_LV_GROUP
|
||||
lv_obj_t * last_sel; /* The last selected button. It will be reverted when the list is focused again */
|
||||
lv_obj_t * selected_btn; /* The button is currently being selected*/
|
||||
#endif
|
||||
} lv_list_ext_t;
|
||||
|
||||
enum {
|
||||
LV_LIST_STYLE_BG,
|
||||
LV_LIST_STYLE_SCRL,
|
||||
LV_LIST_STYLE_SB,
|
||||
LV_LIST_STYLE_EDGE_FLASH,
|
||||
LV_LIST_STYLE_BTN_REL,
|
||||
LV_LIST_STYLE_BTN_PR,
|
||||
LV_LIST_STYLE_BTN_TGL_REL,
|
||||
LV_LIST_STYLE_BTN_TGL_PR,
|
||||
LV_LIST_STYLE_BTN_INA,
|
||||
};
|
||||
typedef uint8_t lv_list_style_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a list objects
|
||||
* @param par pointer to an object, it will be the parent of the new list
|
||||
* @param copy pointer to a list object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created list
|
||||
*/
|
||||
lv_obj_t * lv_list_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_list_clean(lv_obj_t *obj);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Add a list element to the list
|
||||
* @param list pointer to list object
|
||||
* @param img_fn file name of an image before the text (NULL if unused)
|
||||
* @param txt text of the list element (NULL if unused)
|
||||
* @param rel_action pointer to release action function (like with lv_btn)
|
||||
* @return pointer to the new list element which can be customized (a button)
|
||||
*/
|
||||
lv_obj_t * lv_list_add(lv_obj_t * list, const void * img_src, const char * txt, lv_action_t rel_action);
|
||||
|
||||
/**
|
||||
* Remove the index of the button in the list
|
||||
* @param list pointer to a list object
|
||||
* @param index pointer to a the button's index in the list, index must be 0 <= index < lv_list_ext_t.size
|
||||
* @return true: successfully deleted
|
||||
*/
|
||||
bool lv_list_remove(const lv_obj_t * list, uint32_t index);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set single button selected mode, only one button will be selected if enabled.
|
||||
* @param list pointer to the currently pressed list object
|
||||
* @param mode, enable(true)/disable(false) single selected mode.
|
||||
*/
|
||||
void lv_list_set_single_mode(lv_obj_t *list, bool mode);
|
||||
|
||||
#if USE_LV_GROUP
|
||||
|
||||
/**
|
||||
* Make a button selected. Can be used while navigating in the list with a keypad.
|
||||
* @param list pointer to a list object
|
||||
* @param btn pointer to a button to select
|
||||
*/
|
||||
void lv_list_set_btn_selected(lv_obj_t * list, lv_obj_t * btn);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set scroll animation duration on 'list_up()' 'list_down()' 'list_focus()'
|
||||
* @param list pointer to a list object
|
||||
* @param anim_time duration of animation [ms]
|
||||
*/
|
||||
void lv_list_set_anim_time(lv_obj_t *list, uint16_t anim_time);
|
||||
|
||||
/**
|
||||
* Set the scroll bar mode of a list
|
||||
* @param list pointer to a list object
|
||||
* @param sb_mode the new mode from 'lv_page_sb_mode_t' enum
|
||||
*/
|
||||
static inline void lv_list_set_sb_mode(lv_obj_t * list, lv_sb_mode_t mode)
|
||||
{
|
||||
lv_page_set_sb_mode(list, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the scroll propagation feature. If enabled then the List will move its parent if there is no more space to scroll.
|
||||
* @param list pointer to a List
|
||||
* @param en true or false to enable/disable scroll propagation
|
||||
*/
|
||||
static inline void lv_list_set_scroll_propagation(lv_obj_t * list, bool en)
|
||||
{
|
||||
lv_page_set_scroll_propagation(list, en);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the edge flash effect. (Show an arc when the an edge is reached)
|
||||
* @param list pointer to a List
|
||||
* @param en true or false to enable/disable end flash
|
||||
*/
|
||||
static inline void lv_list_set_edge_flash(lv_obj_t * list, bool en)
|
||||
{
|
||||
lv_page_set_edge_flash(list, en);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a list
|
||||
* @param list pointer to a list object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_list_set_style(lv_obj_t *list, lv_list_style_t type, lv_style_t *style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get single button selected mode.
|
||||
* @param list pointer to the currently pressed list object.
|
||||
*/
|
||||
bool lv_list_get_single_mode(lv_obj_t *list);
|
||||
|
||||
/**
|
||||
* Get the text of a list element
|
||||
* @param btn pointer to list element
|
||||
* @return pointer to the text
|
||||
*/
|
||||
const char * lv_list_get_btn_text(const lv_obj_t * btn);
|
||||
/**
|
||||
* Get the label object from a list element
|
||||
* @param btn pointer to a list element (button)
|
||||
* @return pointer to the label from the list element or NULL if not found
|
||||
*/
|
||||
lv_obj_t * lv_list_get_btn_label(const lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Get the image object from a list element
|
||||
* @param btn pointer to a list element (button)
|
||||
* @return pointer to the image from the list element or NULL if not found
|
||||
*/
|
||||
lv_obj_t * lv_list_get_btn_img(const lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Get the next button from list. (Starts from the bottom button)
|
||||
* @param list pointer to a list object
|
||||
* @param prev_btn pointer to button. Search the next after it.
|
||||
* @return pointer to the next button or NULL when no more buttons
|
||||
*/
|
||||
lv_obj_t * lv_list_get_prev_btn(const lv_obj_t * list, lv_obj_t * prev_btn);
|
||||
|
||||
/**
|
||||
* Get the previous button from list. (Starts from the top button)
|
||||
* @param list pointer to a list object
|
||||
* @param prev_btn pointer to button. Search the previous before it.
|
||||
* @return pointer to the previous button or NULL when no more buttons
|
||||
*/
|
||||
lv_obj_t * lv_list_get_next_btn(const lv_obj_t * list, lv_obj_t * prev_btn);
|
||||
|
||||
/**
|
||||
* Get the index of the button in the list
|
||||
* @param list pointer to a list object. If NULL, assumes btn is part of a list.
|
||||
* @param btn pointer to a list element (button)
|
||||
* @return the index of the button in the list, or -1 of the button not in this list
|
||||
*/
|
||||
int32_t lv_list_get_btn_index(const lv_obj_t * list, const lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Get the number of buttons in the list
|
||||
* @param list pointer to a list object
|
||||
* @return the number of buttons in the list
|
||||
*/
|
||||
uint32_t lv_list_get_size(const lv_obj_t * list);
|
||||
|
||||
#if USE_LV_GROUP
|
||||
/**
|
||||
* Get the currently selected button. Can be used while navigating in the list with a keypad.
|
||||
* @param list pointer to a list object
|
||||
* @return pointer to the selected button
|
||||
*/
|
||||
lv_obj_t * lv_list_get_btn_selected(const lv_obj_t * list);
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Get scroll animation duration
|
||||
* @param list pointer to a list object
|
||||
* @return duration of animation [ms]
|
||||
*/
|
||||
uint16_t lv_list_get_anim_time(const lv_obj_t *list);
|
||||
|
||||
|
||||
/**
|
||||
* Get the scroll bar mode of a list
|
||||
* @param list pointer to a list object
|
||||
* @return scrollbar mode from 'lv_page_sb_mode_t' enum
|
||||
*/
|
||||
static inline lv_sb_mode_t lv_list_get_sb_mode(const lv_obj_t * list)
|
||||
{
|
||||
return lv_page_get_sb_mode(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scroll propagation property
|
||||
* @param list pointer to a List
|
||||
* @return true or false
|
||||
*/
|
||||
static inline bool lv_list_get_scroll_propagation(lv_obj_t * list)
|
||||
{
|
||||
return lv_page_get_scroll_propagation(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scroll propagation property
|
||||
* @param list pointer to a List
|
||||
* @return true or false
|
||||
*/
|
||||
static inline bool lv_list_get_edge_flash(lv_obj_t * list)
|
||||
{
|
||||
return lv_page_get_edge_flash(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a list
|
||||
* @param list pointer to a list object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
* */
|
||||
lv_style_t * lv_list_get_style(const lv_obj_t *list, lv_list_style_t type);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Move the list elements up by one
|
||||
* @param list pointer a to list object
|
||||
*/
|
||||
void lv_list_up(const lv_obj_t * list);
|
||||
/**
|
||||
* Move the list elements down by one
|
||||
* @param list pointer to a list object
|
||||
*/
|
||||
void lv_list_down(const lv_obj_t * list);
|
||||
|
||||
/**
|
||||
* Focus on a list button. It ensures that the button will be visible on the list.
|
||||
* @param btn pointer to a list button to focus
|
||||
* @param anim_en true: scroll with animation, false: without animation
|
||||
*/
|
||||
void lv_list_focus(const lv_obj_t *btn, bool anim_en);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_LIST*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_LIST_H*/
|
382
bdk/libs/lvgl/lv_objx/lv_lmeter.c
Normal file
382
bdk/libs/lvgl/lv_objx/lv_lmeter.c
Normal file
|
@ -0,0 +1,382 @@
|
|||
/**
|
||||
* @file lv_lmeter.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_lmeter.h"
|
||||
#if USE_LV_LMETER != 0
|
||||
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_LMETER_LINE_UPSCALE 5 /*2^x upscale of line to make rounding*/
|
||||
#define LV_LMETER_LINE_UPSCALE_MASK ((1 << LV_LMETER_LINE_UPSCALE) - 1)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_lmeter_design(lv_obj_t * lmeter, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_lmeter_signal(lv_obj_t * lmeter, lv_signal_t sign, void * param);
|
||||
static lv_coord_t lv_lmeter_coord_round(int32_t x);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a line meter objects
|
||||
* @param par pointer to an object, it will be the parent of the new line meter
|
||||
* @param copy pointer to a line meter object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created line meter
|
||||
*/
|
||||
lv_obj_t * lv_lmeter_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("line meter create started");
|
||||
|
||||
/*Create the ancestor of line meter*/
|
||||
lv_obj_t * new_lmeter = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_lmeter);
|
||||
if(new_lmeter == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_lmeter);
|
||||
|
||||
/*Allocate the line meter type specific extended data*/
|
||||
lv_lmeter_ext_t * ext = lv_obj_allocate_ext_attr(new_lmeter, sizeof(lv_lmeter_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->min_value = 0;
|
||||
ext->max_value = 100;
|
||||
ext->cur_value = 0;
|
||||
ext->line_cnt = 21; /*Odd scale number looks better*/
|
||||
ext->scale_angle = 240; /*(scale_num - 1) * N looks better */
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_lmeter, lv_lmeter_signal);
|
||||
lv_obj_set_design_func(new_lmeter, lv_lmeter_design);
|
||||
|
||||
/*Init the new line meter line meter*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_size(new_lmeter, LV_DPI, LV_DPI);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_lmeter_set_style(new_lmeter, th->lmeter);
|
||||
} else {
|
||||
lv_lmeter_set_style(new_lmeter, &lv_style_pretty_color);
|
||||
}
|
||||
}
|
||||
/*Copy an existing line meter*/
|
||||
else {
|
||||
lv_lmeter_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->scale_angle = copy_ext->scale_angle;
|
||||
ext->line_cnt = copy_ext->line_cnt;
|
||||
ext->min_value = copy_ext->min_value;
|
||||
ext->max_value = copy_ext->max_value;
|
||||
ext->cur_value = copy_ext->cur_value;
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_lmeter);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("line meter created");
|
||||
|
||||
return new_lmeter;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new value on the line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param value new value
|
||||
*/
|
||||
void lv_lmeter_set_value(lv_obj_t * lmeter, int16_t value)
|
||||
{
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
if(ext->cur_value == value) return;
|
||||
|
||||
ext->cur_value = value > ext->max_value ? ext->max_value : value;
|
||||
ext->cur_value = ext->cur_value < ext->min_value ? ext->min_value : ext->cur_value;
|
||||
lv_obj_invalidate(lmeter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set minimum and the maximum values of a line meter
|
||||
* @param lmeter pointer to he line meter object
|
||||
* @param min minimum value
|
||||
* @param max maximum value
|
||||
*/
|
||||
void lv_lmeter_set_range(lv_obj_t * lmeter, int16_t min, int16_t max)
|
||||
{
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
if(ext->min_value == min && ext->max_value == max) return;
|
||||
|
||||
ext->max_value = max;
|
||||
ext->min_value = min;
|
||||
if(ext->cur_value > max) {
|
||||
ext->cur_value = max;
|
||||
lv_lmeter_set_value(lmeter, ext->cur_value);
|
||||
}
|
||||
if(ext->cur_value < min) {
|
||||
ext->cur_value = min;
|
||||
lv_lmeter_set_value(lmeter, ext->cur_value);
|
||||
}
|
||||
lv_obj_invalidate(lmeter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scale settings of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param angle angle of the scale (0..360)
|
||||
* @param line_cnt number of lines
|
||||
*/
|
||||
void lv_lmeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint8_t line_cnt)
|
||||
{
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
if(ext->scale_angle == angle && ext->line_cnt == line_cnt) return;
|
||||
|
||||
ext->scale_angle = angle;
|
||||
ext->line_cnt = line_cnt;
|
||||
|
||||
lv_obj_invalidate(lmeter);
|
||||
}
|
||||
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the value of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return the value of the line meter
|
||||
*/
|
||||
int16_t lv_lmeter_get_value(const lv_obj_t * lmeter)
|
||||
{
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->cur_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minimum value of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return the minimum value of the line meter
|
||||
*/
|
||||
int16_t lv_lmeter_get_min_value(const lv_obj_t * lmeter)
|
||||
{
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->min_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum value of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return the maximum value of the line meter
|
||||
*/
|
||||
int16_t lv_lmeter_get_max_value(const lv_obj_t * lmeter)
|
||||
{
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->max_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scale number of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return number of the scale units
|
||||
*/
|
||||
uint8_t lv_lmeter_get_line_count(const lv_obj_t * lmeter)
|
||||
{
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->line_cnt ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scale angle of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return angle of the scale
|
||||
*/
|
||||
uint16_t lv_lmeter_get_scale_angle(const lv_obj_t * lmeter)
|
||||
{
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
return ext->scale_angle;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the line meters
|
||||
* @param lmeter pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_lmeter_design(lv_obj_t * lmeter, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return false;
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
lv_style_t * style = lv_obj_get_style(lmeter);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(lmeter);
|
||||
lv_style_t style_tmp;
|
||||
memcpy(&style_tmp, style, sizeof(lv_style_t));
|
||||
|
||||
|
||||
#if USE_LV_GROUP
|
||||
lv_group_t * g = lv_obj_get_group(lmeter);
|
||||
if(lv_group_get_focused(g) == lmeter) {
|
||||
style_tmp.line.width += 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
lv_coord_t r_out = lv_obj_get_width(lmeter) / 2;
|
||||
lv_coord_t r_in = r_out - style->body.padding.hor;
|
||||
if(r_in < 1) r_in = 1;
|
||||
|
||||
lv_coord_t x_ofs = lv_obj_get_width(lmeter) / 2 + lmeter->coords.x1;
|
||||
lv_coord_t y_ofs = lv_obj_get_height(lmeter) / 2 + lmeter->coords.y1;
|
||||
int16_t angle_ofs = 90 + (360 - ext->scale_angle) / 2;
|
||||
int16_t level = (int32_t)((int32_t)(ext->cur_value - ext->min_value) * ext->line_cnt) / (ext->max_value - ext->min_value);
|
||||
uint8_t i;
|
||||
|
||||
style_tmp.line.color = style->body.main_color;
|
||||
|
||||
/*Calculate every coordinate in a bigger size to make rounding later*/
|
||||
r_out = r_out << LV_LMETER_LINE_UPSCALE;
|
||||
r_in = r_in << LV_LMETER_LINE_UPSCALE;
|
||||
|
||||
for(i = 0; i < ext->line_cnt; i++) {
|
||||
/*Calculate the position a scale label*/
|
||||
int16_t angle = (i * ext->scale_angle) / (ext->line_cnt - 1) + angle_ofs;
|
||||
|
||||
lv_coord_t y_out = (int32_t)((int32_t)lv_trigo_sin(angle) * r_out) >> LV_TRIGO_SHIFT;
|
||||
lv_coord_t x_out = (int32_t)((int32_t)lv_trigo_sin(angle + 90) * r_out) >> LV_TRIGO_SHIFT;
|
||||
lv_coord_t y_in = (int32_t)((int32_t)lv_trigo_sin(angle) * r_in) >> LV_TRIGO_SHIFT;
|
||||
lv_coord_t x_in = (int32_t)((int32_t)lv_trigo_sin(angle + 90) * r_in) >> LV_TRIGO_SHIFT;
|
||||
|
||||
/*Rounding*/
|
||||
x_out = lv_lmeter_coord_round(x_out);
|
||||
x_in = lv_lmeter_coord_round(x_in);
|
||||
y_out = lv_lmeter_coord_round(y_out);
|
||||
y_in = lv_lmeter_coord_round(y_in);
|
||||
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
|
||||
p2.x = x_in + x_ofs;
|
||||
p2.y = y_in + y_ofs;
|
||||
|
||||
p1.x = x_out + x_ofs;
|
||||
p1.y = y_out + y_ofs;
|
||||
|
||||
if(i >= level) style_tmp.line.color = style->line.color;
|
||||
else {
|
||||
style_tmp.line.color = lv_color_mix(style->body.grad_color, style->body.main_color, (255 * i) / ext->line_cnt);
|
||||
}
|
||||
|
||||
lv_draw_line(&p1, &p2, mask, &style_tmp, opa_scale);
|
||||
}
|
||||
|
||||
}
|
||||
/*Post draw when the children are drawn*/
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_lmeter_signal(lv_obj_t * lmeter, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(lmeter, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
} else if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
lv_obj_refresh_ext_size(lmeter);
|
||||
} else if(sign == LV_SIGNAL_REFR_EXT_SIZE) {
|
||||
lv_style_t * style = lv_lmeter_get_style(lmeter);
|
||||
lmeter->ext_size = LV_MATH_MAX(lmeter->ext_size, style->line.width);
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_lmeter";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Round a coordinate which is upscaled (>=x.5 -> x + 1; <x.5 -> x)
|
||||
* @param x a coordinate which is greater then it should be
|
||||
* @return the downscaled and rounded coordinate (+-1)
|
||||
*/
|
||||
static lv_coord_t lv_lmeter_coord_round(int32_t x)
|
||||
{
|
||||
#if LV_LMETER_LINE_UPSCALE > 0
|
||||
bool was_negative = false;
|
||||
if(x < 0) {
|
||||
was_negative = true;
|
||||
x = -x;
|
||||
}
|
||||
|
||||
x = (x >> LV_LMETER_LINE_UPSCALE) + ((x & LV_LMETER_LINE_UPSCALE_MASK) >> (LV_LMETER_LINE_UPSCALE - 1));
|
||||
|
||||
if(was_negative) x = -x;
|
||||
|
||||
return x;
|
||||
#else
|
||||
return x;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
153
bdk/libs/lvgl/lv_objx/lv_lmeter.h
Normal file
153
bdk/libs/lvgl/lv_objx/lv_lmeter.h
Normal file
|
@ -0,0 +1,153 @@
|
|||
/**
|
||||
* @file lv_lmeter.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_LMETER_H
|
||||
#define LV_LMETER_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_LMETER != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Data of line meter*/
|
||||
typedef struct
|
||||
{
|
||||
/*No inherited ext.*/ /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
uint16_t scale_angle; /*Angle of the scale in deg. (0..360)*/
|
||||
uint8_t line_cnt; /*Count of lines */
|
||||
int16_t cur_value;
|
||||
int16_t min_value;
|
||||
int16_t max_value;
|
||||
} lv_lmeter_ext_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a line meter objects
|
||||
* @param par pointer to an object, it will be the parent of the new line meter
|
||||
* @param copy pointer to a line meter object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created line meter
|
||||
*/
|
||||
lv_obj_t * lv_lmeter_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new value on the line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param value new value
|
||||
*/
|
||||
void lv_lmeter_set_value(lv_obj_t *lmeter, int16_t value);
|
||||
|
||||
/**
|
||||
* Set minimum and the maximum values of a line meter
|
||||
* @param lmeter pointer to he line meter object
|
||||
* @param min minimum value
|
||||
* @param max maximum value
|
||||
*/
|
||||
void lv_lmeter_set_range(lv_obj_t *lmeter, int16_t min, int16_t max);
|
||||
|
||||
/**
|
||||
* Set the scale settings of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param angle angle of the scale (0..360)
|
||||
* @param line_cnt number of lines
|
||||
*/
|
||||
void lv_lmeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint8_t line_cnt);
|
||||
|
||||
/**
|
||||
* Set the styles of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param bg set the style of the line meter
|
||||
*/
|
||||
static inline void lv_lmeter_set_style(lv_obj_t *lmeter, lv_style_t *bg)
|
||||
{
|
||||
lv_obj_set_style(lmeter, bg);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the value of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return the value of the line meter
|
||||
*/
|
||||
int16_t lv_lmeter_get_value(const lv_obj_t *lmeter);
|
||||
|
||||
/**
|
||||
* Get the minimum value of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return the minimum value of the line meter
|
||||
*/
|
||||
int16_t lv_lmeter_get_min_value(const lv_obj_t * lmeter);
|
||||
|
||||
/**
|
||||
* Get the maximum value of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return the maximum value of the line meter
|
||||
*/
|
||||
int16_t lv_lmeter_get_max_value(const lv_obj_t * lmeter);
|
||||
|
||||
/**
|
||||
* Get the scale number of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return number of the scale units
|
||||
*/
|
||||
uint8_t lv_lmeter_get_line_count(const lv_obj_t * lmeter);
|
||||
|
||||
/**
|
||||
* Get the scale angle of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return angle of the scale
|
||||
*/
|
||||
uint16_t lv_lmeter_get_scale_angle(const lv_obj_t * lmeter);
|
||||
|
||||
/**
|
||||
* Get the style of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @return pointer to the line meter's style
|
||||
*/
|
||||
static inline lv_style_t * lv_lmeter_get_style(const lv_obj_t * lmeter)
|
||||
{
|
||||
return lv_obj_get_style(lmeter);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_LMETER*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_LMETER_H*/
|
532
bdk/libs/lvgl/lv_objx/lv_mbox.c
Normal file
532
bdk/libs/lvgl/lv_objx/lv_mbox.c
Normal file
|
@ -0,0 +1,532 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file lv_mbox.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_mbox.h"
|
||||
#if USE_LV_MBOX != 0
|
||||
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_anim.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if USE_LV_ANIMATION
|
||||
# ifndef LV_MBOX_CLOSE_ANIM_TIME
|
||||
# define LV_MBOX_CLOSE_ANIM_TIME 200 /*List close animation time) */
|
||||
# endif
|
||||
#else
|
||||
# undef LV_MBOX_CLOSE_ANIM_TIME
|
||||
# define LV_MBOX_CLOSE_ANIM_TIME 0 /*No animations*/
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_mbox_signal(lv_obj_t * mbox, lv_signal_t sign, void * param);
|
||||
static void mbox_realign(lv_obj_t * mbox);
|
||||
static lv_res_t lv_mbox_close_action(lv_obj_t * btn, const char * txt);
|
||||
#if USE_LV_ANIMATION
|
||||
static void lv_mbox_close_end_cb(lv_obj_t * mbox);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a message box objects
|
||||
* @param par pointer to an object, it will be the parent of the new message box
|
||||
* @param copy pointer to a message box object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created message box
|
||||
*/
|
||||
lv_obj_t * lv_mbox_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("mesasge box create started");
|
||||
|
||||
/*Create the ancestor message box*/
|
||||
lv_obj_t * new_mbox = lv_cont_create(par, copy);
|
||||
lv_mem_assert(new_mbox);
|
||||
if(new_mbox == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_mbox);
|
||||
|
||||
/*Allocate the message box type specific extended data*/
|
||||
lv_mbox_ext_t * ext = lv_obj_allocate_ext_attr(new_mbox, sizeof(lv_mbox_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->text = NULL;
|
||||
ext->btnm = NULL;
|
||||
ext->anim_time = LV_MBOX_CLOSE_ANIM_TIME;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_mbox, lv_mbox_signal);
|
||||
|
||||
/*Init the new message box message box*/
|
||||
if(copy == NULL) {
|
||||
ext->text = lv_label_create(new_mbox, NULL);
|
||||
lv_label_set_align(ext->text, LV_LABEL_ALIGN_CENTER);
|
||||
lv_label_set_long_mode(ext->text, LV_LABEL_LONG_BREAK);
|
||||
lv_label_set_text(ext->text, "Message");
|
||||
|
||||
lv_cont_set_layout(new_mbox, LV_LAYOUT_COL_M);
|
||||
lv_cont_set_fit(new_mbox, false, true);
|
||||
lv_obj_set_width(new_mbox, LV_HOR_RES / 2);
|
||||
lv_obj_align(new_mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_mbox_set_style(new_mbox, LV_MBOX_STYLE_BG, th->mbox.bg);
|
||||
} else {
|
||||
lv_mbox_set_style(new_mbox, LV_MBOX_STYLE_BG, &lv_style_pretty);
|
||||
}
|
||||
|
||||
}
|
||||
/*Copy an existing message box*/
|
||||
else {
|
||||
lv_mbox_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
|
||||
ext->text = lv_label_create(new_mbox, copy_ext->text);
|
||||
|
||||
/*Copy the buttons and the label on them*/
|
||||
if(copy_ext->btnm) ext->btnm = lv_btnm_create(new_mbox, copy_ext->btnm);
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_mbox);
|
||||
}
|
||||
|
||||
|
||||
LV_LOG_INFO("mesasge box created");
|
||||
|
||||
return new_mbox;
|
||||
}
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Add button to the message box
|
||||
* @param mbox pointer to message box object
|
||||
* @param btn_map button descriptor (button matrix map).
|
||||
* E.g. a const char *txt[] = {"ok", "close", ""} (Can not be local variable)
|
||||
* @param action a function which will be called when a button is released
|
||||
*/
|
||||
void lv_mbox_add_btns(lv_obj_t * mbox, const char ** btn_map, lv_btnm_action_t action)
|
||||
{
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
/*Create a button matrix if not exists yet*/
|
||||
if(ext->btnm == NULL) {
|
||||
ext->btnm = lv_btnm_create(mbox, NULL);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_mbox_set_style(mbox, LV_MBOX_STYLE_BTN_BG, th->mbox.btn.bg);
|
||||
lv_mbox_set_style(mbox, LV_MBOX_STYLE_BTN_REL, th->mbox.btn.rel);
|
||||
lv_mbox_set_style(mbox, LV_MBOX_STYLE_BTN_PR, th->mbox.btn.pr);
|
||||
} else {
|
||||
lv_btnm_set_style(ext->btnm, LV_BTNM_STYLE_BG, &lv_style_transp_fit);
|
||||
}
|
||||
}
|
||||
|
||||
lv_btnm_set_map(ext->btnm, btn_map);
|
||||
if(action == NULL) lv_btnm_set_action(ext->btnm, lv_mbox_close_action); /*Set a default action anyway*/
|
||||
else lv_btnm_set_action(ext->btnm, action);
|
||||
|
||||
mbox_realign(mbox);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the text of the message box
|
||||
* @param mbox pointer to a message box
|
||||
* @param txt a '\0' terminated character string which will be the message box text
|
||||
*/
|
||||
void lv_mbox_set_text(lv_obj_t * mbox, const char * txt)
|
||||
{
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
lv_label_set_text(ext->text, txt);
|
||||
|
||||
mbox_realign(mbox);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stop the action to call when button is released
|
||||
* @param pointer to an 'lv_btnm_action_t' action. In the action you need to use `lv_mbox_get_from_btn()` to get the `mbox`.
|
||||
* @param pointer to an 'lv_btnm_action_t' action
|
||||
*/
|
||||
void lv_mbox_set_action(lv_obj_t * mbox, lv_btnm_action_t action)
|
||||
{
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
lv_btnm_set_action(ext->btnm, action);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set animation duration
|
||||
* @param mbox pointer to a message box object
|
||||
* @param anim_time animation length in milliseconds (0: no animation)
|
||||
*/
|
||||
void lv_mbox_set_anim_time(lv_obj_t * mbox, uint16_t anim_time)
|
||||
{
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
#if USE_LV_ANIMATION == 0
|
||||
anim_time = 0;
|
||||
#endif
|
||||
|
||||
ext->anim_time = anim_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically delete the message box after a given time
|
||||
* @param mbox pointer to a message box object
|
||||
* @param delay a time (in milliseconds) to wait before delete the message box
|
||||
*/
|
||||
void lv_mbox_start_auto_close(lv_obj_t * mbox, uint16_t delay)
|
||||
{
|
||||
#if USE_LV_ANIMATION
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
if(ext->anim_time != 0) {
|
||||
/*Add shrinking animations*/
|
||||
lv_obj_animate(mbox, LV_ANIM_GROW_H | LV_ANIM_OUT, ext->anim_time, delay, NULL);
|
||||
lv_obj_animate(mbox, LV_ANIM_GROW_V | LV_ANIM_OUT, ext->anim_time, delay, lv_mbox_close_end_cb);
|
||||
|
||||
/*Disable fit to let shrinking work*/
|
||||
lv_cont_set_fit(mbox, false, false);
|
||||
} else {
|
||||
lv_obj_animate(mbox, LV_ANIM_NONE, ext->anim_time, delay, lv_mbox_close_end_cb);
|
||||
}
|
||||
#else
|
||||
(void)delay; /*Unused*/
|
||||
lv_obj_del(mbox);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the auto. closing of message box
|
||||
* @param mbox pointer to a message box object
|
||||
*/
|
||||
void lv_mbox_stop_auto_close(lv_obj_t * mbox)
|
||||
{
|
||||
#if USE_LV_ANIMATION
|
||||
lv_anim_del(mbox, NULL);
|
||||
#else
|
||||
(void)mbox; /*Unused*/
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a message box
|
||||
* @param mbox pointer to a message box object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_mbox_set_style(lv_obj_t * mbox, lv_mbox_style_t type, lv_style_t * style)
|
||||
{
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
switch(type) {
|
||||
case LV_MBOX_STYLE_BG:
|
||||
lv_obj_set_style(mbox, style);
|
||||
break;
|
||||
case LV_MBOX_STYLE_BTN_BG:
|
||||
lv_btnm_set_style(ext->btnm, LV_BTNM_STYLE_BG, style);
|
||||
break;
|
||||
case LV_MBOX_STYLE_BTN_REL:
|
||||
lv_btnm_set_style(ext->btnm, LV_BTNM_STYLE_BTN_REL, style);
|
||||
break;
|
||||
case LV_MBOX_STYLE_BTN_PR:
|
||||
lv_btnm_set_style(ext->btnm, LV_BTNM_STYLE_BTN_PR, style);
|
||||
break;
|
||||
case LV_MBOX_STYLE_BTN_TGL_REL:
|
||||
lv_btnm_set_style(ext->btnm, LV_BTNM_STYLE_BTN_TGL_REL, style);
|
||||
break;
|
||||
case LV_MBOX_STYLE_BTN_TGL_PR:
|
||||
lv_btnm_set_style(ext->btnm, LV_BTNM_STYLE_BTN_TGL_PR, style);
|
||||
break;
|
||||
case LV_MBOX_STYLE_BTN_INA:
|
||||
lv_btnm_set_style(ext->btnm, LV_BTNM_STYLE_BTN_INA, style);
|
||||
break;
|
||||
}
|
||||
|
||||
mbox_realign(mbox);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether recoloring is enabled
|
||||
* @param btnm pointer to button matrix object
|
||||
* @param en whether recoloring is enabled
|
||||
*/
|
||||
void lv_mbox_set_recolor(lv_obj_t * mbox, bool en)
|
||||
{
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
if(ext->btnm)
|
||||
lv_btnm_set_recolor(ext->btnm, en);
|
||||
}
|
||||
|
||||
void lv_mbox_set_recolor_text(lv_obj_t * mbox, bool en)
|
||||
{
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
if (ext->text)
|
||||
lv_label_set_recolor(ext->text, en);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the text of the message box
|
||||
* @param mbox pointer to a message box object
|
||||
* @return pointer to the text of the message box
|
||||
*/
|
||||
const char * lv_mbox_get_text(const lv_obj_t * mbox)
|
||||
{
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
return lv_label_get_text(ext->text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message box object from one of its button.
|
||||
* It is useful in the button release actions where only the button is known
|
||||
* @param btn pointer to a button of a message box
|
||||
* @return pointer to the button's message box
|
||||
*/
|
||||
lv_obj_t * lv_mbox_get_from_btn(const lv_obj_t * btn)
|
||||
{
|
||||
lv_obj_t * mbox = lv_obj_get_parent(btn);
|
||||
|
||||
return mbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the animation duration (close animation time)
|
||||
* @param mbox pointer to a message box object
|
||||
* @return animation length in milliseconds (0: no animation)
|
||||
*/
|
||||
uint16_t lv_mbox_get_anim_time(const lv_obj_t * mbox)
|
||||
{
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
return ext->anim_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a message box
|
||||
* @param mbox pointer to a message box object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_mbox_get_style(const lv_obj_t * mbox, lv_mbox_style_t type)
|
||||
{
|
||||
lv_style_t * style = NULL;
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
switch(type) {
|
||||
case LV_MBOX_STYLE_BG:
|
||||
style = lv_obj_get_style(mbox);
|
||||
break;
|
||||
case LV_MBOX_STYLE_BTN_BG:
|
||||
style = lv_btnm_get_style(ext->btnm, LV_BTNM_STYLE_BG);
|
||||
break;
|
||||
case LV_MBOX_STYLE_BTN_REL:
|
||||
style = lv_btnm_get_style(ext->btnm, LV_BTNM_STYLE_BTN_REL);
|
||||
break;
|
||||
case LV_MBOX_STYLE_BTN_PR:
|
||||
style = lv_btnm_get_style(ext->btnm, LV_BTNM_STYLE_BTN_PR);
|
||||
break;
|
||||
case LV_MBOX_STYLE_BTN_TGL_REL:
|
||||
style = lv_btnm_get_style(ext->btnm, LV_BTNM_STYLE_BTN_TGL_REL);
|
||||
break;
|
||||
case LV_MBOX_STYLE_BTN_TGL_PR:
|
||||
style = lv_btnm_get_style(ext->btnm, LV_BTNM_STYLE_BTN_TGL_PR);
|
||||
break;
|
||||
case LV_MBOX_STYLE_BTN_INA:
|
||||
style = lv_btnm_get_style(ext->btnm, LV_BTNM_STYLE_BTN_INA);
|
||||
break;
|
||||
default:
|
||||
style = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether recoloring is enabled
|
||||
* @param btnm pointer to button matrix object
|
||||
* @return whether recoloring is enabled
|
||||
*/
|
||||
bool lv_mbox_get_recolor(const lv_obj_t * mbox)
|
||||
{
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
if(!ext->btnm)
|
||||
return false;
|
||||
|
||||
return lv_btnm_get_recolor(ext->btnm);
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the message box
|
||||
* @param mbox pointer to a message box object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_mbox_signal(lv_obj_t * mbox, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/*Translate LV_GROUP_KEY_UP/DOWN to LV_GROUP_KEY_LEFT/RIGHT */
|
||||
char c_trans = 0;
|
||||
if(sign == LV_SIGNAL_CONTROLL) {
|
||||
c_trans = *((char *)param);
|
||||
if(c_trans == LV_GROUP_KEY_DOWN) c_trans = LV_GROUP_KEY_LEFT;
|
||||
if(c_trans == LV_GROUP_KEY_UP) c_trans = LV_GROUP_KEY_RIGHT;
|
||||
|
||||
param = &c_trans;
|
||||
}
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(mbox, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
if(sign == LV_SIGNAL_CORD_CHG) {
|
||||
if(lv_obj_get_width(mbox) != lv_area_get_width(param)) {
|
||||
mbox_realign(mbox);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
mbox_realign(mbox);
|
||||
|
||||
} else if(sign == LV_SIGNAL_FOCUS || sign == LV_SIGNAL_DEFOCUS ||
|
||||
sign == LV_SIGNAL_CONTROLL || sign == LV_SIGNAL_GET_EDITABLE) {
|
||||
if(ext->btnm) {
|
||||
ext->btnm->signal_func(ext->btnm, sign, param);
|
||||
}
|
||||
|
||||
/* The button matrix with ENCODER input supposes it's in a group but in this case it isn't (Only the message box's container)
|
||||
* So so some actions here instead*/
|
||||
if(sign == LV_SIGNAL_FOCUS) {
|
||||
#if USE_LV_GROUP
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
lv_hal_indev_type_t indev_type = lv_indev_get_type(indev);
|
||||
if(indev_type == LV_INDEV_TYPE_ENCODER) {
|
||||
/*In navigation mode don't select any button but in edit mode select the fist*/
|
||||
lv_btnm_ext_t * btnm_ext = lv_obj_get_ext_attr(ext->btnm);
|
||||
if(lv_group_get_editing(lv_obj_get_group(mbox))) btnm_ext->btn_id_pr = 0;
|
||||
else btnm_ext->btn_id_pr = LV_BTNM_PR_NONE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_mbox";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the button holder to fit
|
||||
* @param mbox pointer to message box object
|
||||
*/
|
||||
static void mbox_realign(lv_obj_t * mbox)
|
||||
{
|
||||
lv_mbox_ext_t * ext = lv_obj_get_ext_attr(mbox);
|
||||
|
||||
lv_style_t * style = lv_mbox_get_style(mbox, LV_MBOX_STYLE_BG);
|
||||
lv_coord_t w = lv_obj_get_width(mbox) - 2 * style->body.padding.hor;
|
||||
|
||||
if(ext->text) {
|
||||
lv_obj_set_width(ext->text, w);
|
||||
}
|
||||
|
||||
if(ext->btnm) {
|
||||
lv_style_t * btn_bg_style = lv_mbox_get_style(mbox, LV_MBOX_STYLE_BTN_BG);
|
||||
lv_style_t * btn_rel_style = lv_mbox_get_style(mbox, LV_MBOX_STYLE_BTN_REL);
|
||||
lv_coord_t font_h = lv_font_get_height(btn_rel_style->text.font);
|
||||
lv_obj_set_size(ext->btnm, w, font_h + 2 * btn_rel_style->body.padding.ver + 2 * btn_bg_style->body.padding.ver);
|
||||
}
|
||||
}
|
||||
|
||||
static lv_res_t lv_mbox_close_action(lv_obj_t * btn, const char * txt)
|
||||
{
|
||||
lv_obj_t * mbox = lv_mbox_get_from_btn(btn);
|
||||
|
||||
if(txt[0] != '\0') {
|
||||
lv_mbox_start_auto_close(mbox, 0);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
#if USE_LV_ANIMATION
|
||||
static void lv_mbox_close_end_cb(lv_obj_t * mbox)
|
||||
{
|
||||
lv_obj_del(mbox);
|
||||
}
|
||||
#endif
|
||||
#endif
|
221
bdk/libs/lvgl/lv_objx/lv_mbox.h
Normal file
221
bdk/libs/lvgl/lv_objx/lv_mbox.h
Normal file
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file lv_mbox.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_MBOX_H
|
||||
#define LV_MBOX_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_MBOX != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_CONT == 0
|
||||
#error "lv_mbox: lv_cont is required. Enable it in lv_conf.h (USE_LV_CONT 1) "
|
||||
#endif
|
||||
|
||||
#if USE_LV_BTNM == 0
|
||||
#error "lv_mbox: lv_btnm is required. Enable it in lv_conf.h (USE_LV_BTNM 1) "
|
||||
#endif
|
||||
|
||||
#if USE_LV_LABEL == 0
|
||||
#error "lv_mbox: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) "
|
||||
#endif
|
||||
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_cont.h"
|
||||
#include "lv_btnm.h"
|
||||
#include "lv_label.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Data of message box*/
|
||||
typedef struct
|
||||
{
|
||||
lv_cont_ext_t bg; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_obj_t *text; /*Text of the message box*/
|
||||
lv_obj_t *btnm; /*Button matrix for the buttons*/
|
||||
uint16_t anim_time; /*Duration of close animation [ms] (0: no animation)*/
|
||||
} lv_mbox_ext_t;
|
||||
|
||||
enum {
|
||||
LV_MBOX_STYLE_BG,
|
||||
LV_MBOX_STYLE_BTN_BG,
|
||||
LV_MBOX_STYLE_BTN_REL,
|
||||
LV_MBOX_STYLE_BTN_PR,
|
||||
LV_MBOX_STYLE_BTN_TGL_REL,
|
||||
LV_MBOX_STYLE_BTN_TGL_PR,
|
||||
LV_MBOX_STYLE_BTN_INA,
|
||||
};
|
||||
typedef uint8_t lv_mbox_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a message box objects
|
||||
* @param par pointer to an object, it will be the parent of the new message box
|
||||
* @param copy pointer to a message box object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created message box
|
||||
*/
|
||||
lv_obj_t * lv_mbox_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Add button to the message box
|
||||
* @param mbox pointer to message box object
|
||||
* @param btn_map button descriptor (button matrix map).
|
||||
* E.g. a const char *txt[] = {"ok", "close", ""} (Can not be local variable)
|
||||
* @param action a function which will be called when a button is released
|
||||
*/
|
||||
void lv_mbox_add_btns(lv_obj_t * mbox, const char **btn_map, lv_btnm_action_t action);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the text of the message box
|
||||
* @param mbox pointer to a message box
|
||||
* @param txt a '\0' terminated character string which will be the message box text
|
||||
*/
|
||||
void lv_mbox_set_text(lv_obj_t * mbox, const char * txt);
|
||||
|
||||
/**
|
||||
* Stop the action to call when button is released
|
||||
* @param mbox pointer to a message box object
|
||||
* @param pointer to an 'lv_btnm_action_t' action. In the action you need to use `lv_mbox_get_from_btn()` to get the `mbox`.
|
||||
*/
|
||||
void lv_mbox_set_action(lv_obj_t * mbox, lv_btnm_action_t action);
|
||||
|
||||
/**
|
||||
* Set animation duration
|
||||
* @param mbox pointer to a message box object
|
||||
* @param anim_time animation length in milliseconds (0: no animation)
|
||||
*/
|
||||
void lv_mbox_set_anim_time(lv_obj_t * mbox, uint16_t anim_time);
|
||||
|
||||
/**
|
||||
* Automatically delete the message box after a given time
|
||||
* @param mbox pointer to a message box object
|
||||
* @param delay a time (in milliseconds) to wait before delete the message box
|
||||
*/
|
||||
void lv_mbox_start_auto_close(lv_obj_t * mbox, uint16_t delay);
|
||||
|
||||
/**
|
||||
* Stop the auto. closing of message box
|
||||
* @param mbox pointer to a message box object
|
||||
*/
|
||||
void lv_mbox_stop_auto_close(lv_obj_t * mbox);
|
||||
|
||||
/**
|
||||
* Set a style of a message box
|
||||
* @param mbox pointer to a message box object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_mbox_set_style(lv_obj_t *mbox, lv_mbox_style_t type, lv_style_t *style);
|
||||
|
||||
/**
|
||||
* Set whether recoloring is enabled. Must be called after `lv_mbox_add_btns`.
|
||||
* @param btnm pointer to button matrix object
|
||||
* @param en whether recoloring is enabled
|
||||
*/
|
||||
void lv_mbox_set_recolor(lv_obj_t * mbox, bool en);
|
||||
|
||||
void lv_mbox_set_recolor_text(lv_obj_t * mbox, bool en);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the text of the message box
|
||||
* @param mbox pointer to a message box object
|
||||
* @return pointer to the text of the message box
|
||||
*/
|
||||
const char * lv_mbox_get_text(const lv_obj_t * mbox);
|
||||
|
||||
/**
|
||||
* Get the message box object from one of its button.
|
||||
* It is useful in the button release actions where only the button is known
|
||||
* @param btn pointer to a button of a message box
|
||||
* @return pointer to the button's message box
|
||||
*/
|
||||
lv_obj_t * lv_mbox_get_from_btn(const lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Get the animation duration (close animation time)
|
||||
* @param mbox pointer to a message box object
|
||||
* @return animation length in milliseconds (0: no animation)
|
||||
*/
|
||||
uint16_t lv_mbox_get_anim_time(const lv_obj_t * mbox);
|
||||
|
||||
|
||||
/**
|
||||
* Get a style of a message box
|
||||
* @param mbox pointer to a message box object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_mbox_get_style(const lv_obj_t *mbox, lv_mbox_style_t type);
|
||||
|
||||
/**
|
||||
* Get whether recoloring is enabled
|
||||
* @param btnm pointer to button matrix object
|
||||
* @return whether recoloring is enabled
|
||||
*/
|
||||
bool lv_mbox_get_recolor(const lv_obj_t * mbox);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
|
||||
#endif /*USE_LV_MBOX*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_MBOX_H*/
|
36
bdk/libs/lvgl/lv_objx/lv_objx.mk
Normal file
36
bdk/libs/lvgl/lv_objx/lv_objx.mk
Normal file
|
@ -0,0 +1,36 @@
|
|||
CSRCS += lv_arc.c
|
||||
CSRCS += lv_bar.c
|
||||
CSRCS += lv_cb.c
|
||||
CSRCS += lv_ddlist.c
|
||||
CSRCS += lv_kb.c
|
||||
CSRCS += lv_line.c
|
||||
CSRCS += lv_mbox.c
|
||||
CSRCS += lv_preload.c
|
||||
CSRCS += lv_roller.c
|
||||
CSRCS += lv_table.c
|
||||
CSRCS += lv_tabview.c
|
||||
CSRCS += lv_tileview.c
|
||||
CSRCS += lv_btn.c
|
||||
CSRCS += lv_calendar.c
|
||||
CSRCS += lv_chart.c
|
||||
CSRCS += lv_canvas.c
|
||||
CSRCS += lv_gauge.c
|
||||
CSRCS += lv_label.c
|
||||
CSRCS += lv_list.c
|
||||
CSRCS += lv_slider.c
|
||||
CSRCS += lv_ta.c
|
||||
CSRCS += lv_spinbox.c
|
||||
CSRCS += lv_btnm.c
|
||||
CSRCS += lv_cont.c
|
||||
CSRCS += lv_img.c
|
||||
CSRCS += lv_imgbtn.c
|
||||
CSRCS += lv_led.c
|
||||
CSRCS += lv_lmeter.c
|
||||
CSRCS += lv_page.c
|
||||
CSRCS += lv_sw.c
|
||||
CSRCS += lv_win.c
|
||||
|
||||
DEPPATH += --dep-path $(LVGL_DIR)/lvgl/lv_objx
|
||||
VPATH += :$(LVGL_DIR)/lvgl/lv_objx
|
||||
|
||||
CFLAGS += "-I$(LVGL_DIR)/lvgl/lv_objx"
|
231
bdk/libs/lvgl/lv_objx/lv_objx_templ.c
Normal file
231
bdk/libs/lvgl/lv_objx/lv_objx_templ.c
Normal file
|
@ -0,0 +1,231 @@
|
|||
/**
|
||||
* @file lv_templ.c
|
||||
*
|
||||
*/
|
||||
|
||||
/* TODO Remove these instructions
|
||||
* Search an replace: template -> object normal name with lower case (e.g. button, label etc.)
|
||||
* templ -> object short name with lower case(e.g. btn, label etc)
|
||||
* TEMPL -> object short name with upper case (e.g. BTN, LABEL etc.)
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
//#include "lv_templ.h" /*TODO uncomment this*/
|
||||
#if USE_LV_TEMPL != 0
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_templ_design(lv_obj_t * templ, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_templ_signal(lv_obj_t * templ, lv_signal_t sign, void * param);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
static lv_design_func_t ancestor_design;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a template object
|
||||
* @param par pointer to an object, it will be the parent of the new template
|
||||
* @param copy pointer to a template object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created template
|
||||
*/
|
||||
lv_obj_t * lv_templ_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("template create started");
|
||||
|
||||
/*Create the ancestor of template*/
|
||||
/*TODO modify it to the ancestor create function */
|
||||
lv_obj_t * new_templ = lv_ANCESTOR_create(par, copy);
|
||||
lv_mem_assert(new_templ);
|
||||
if(new_templ == NULL) return NULL;
|
||||
|
||||
/*Allocate the template type specific extended data*/
|
||||
lv_templ_ext_t * ext = lv_obj_allocate_ext_attr(new_templ, sizeof(lv_templ_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_templ);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_templ);
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->xyz = 0;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_templ, lv_templ_signal);
|
||||
lv_obj_set_design_func(new_templ, lv_templ_design);
|
||||
|
||||
/*Init the new template template*/
|
||||
if(copy == NULL) {
|
||||
|
||||
}
|
||||
/*Copy an existing template*/
|
||||
else {
|
||||
lv_templ_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_templ);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("template created");
|
||||
|
||||
return new_templ;
|
||||
}
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/*
|
||||
* New object specific "add" or "remove" functions come here
|
||||
*/
|
||||
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/*
|
||||
* New object specific "set" functions come here
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Set a style of a template.
|
||||
* @param templ pointer to template object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_templ_set_style(lv_obj_t * templ, lv_templ_style_t type, lv_style_t * style)
|
||||
{
|
||||
lv_templ_ext_t * ext = lv_obj_get_ext_attr(templ);
|
||||
|
||||
switch(type) {
|
||||
case LV_TEMPL_STYLE_X:
|
||||
break;
|
||||
case LV_TEMPL_STYLE_Y:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/*
|
||||
* New object specific "get" functions come here
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get style of a template.
|
||||
* @param templ pointer to template object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
*/
|
||||
lv_style_t * lv_templ_get_style(const lv_obj_t * templ, lv_templ_style_t type)
|
||||
{
|
||||
lv_templ_ext_t * ext = lv_obj_get_ext_attr(templ);
|
||||
lv_style_t * style = NULL;
|
||||
|
||||
switch(type) {
|
||||
case LV_TEMPL_STYLE_X:
|
||||
style = NULL; /*Replace NULL with a pointer to the style*/
|
||||
case LV_TEMPL_STYLE_Y:
|
||||
style = NULL; /*Replace NULL with a pointer to the style*/
|
||||
default:
|
||||
style = NULL;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/*
|
||||
* New object specific "other" functions come here
|
||||
*/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the templates
|
||||
* @param templ pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_templ_design(lv_obj_t * templ, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return false;
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
|
||||
}
|
||||
/*Post draw when the children are drawn*/
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the template
|
||||
* @param templ pointer to a template object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_templ_signal(lv_obj_t * templ, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(templ, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_templ";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
111
bdk/libs/lvgl/lv_objx/lv_objx_templ.h
Normal file
111
bdk/libs/lvgl/lv_objx/lv_objx_templ.h
Normal file
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* @file lv_templ.h
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* TODO Remove these instructions
|
||||
* Search an replace: template -> object normal name with lower case (e.g. button, label etc.)
|
||||
* templ -> object short name with lower case(e.g. btn, label etc)
|
||||
* TEMPL -> object short name with upper case (e.g. BTN, LABEL etc.)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TEMPL_H
|
||||
#define LV_TEMPL_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_TEMPL != 0
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Data of template*/
|
||||
typedef struct {
|
||||
lv_ANCESTOR_ext_t ANCESTOR; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
} lv_templ_ext_t;
|
||||
|
||||
|
||||
/*Styles*/
|
||||
enum {
|
||||
LV_TEMPL_STYLE_X,
|
||||
LV_TEMPL_STYLE_Y,
|
||||
};
|
||||
typedef uint8_t lv_templ_style_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a template objects
|
||||
* @param par pointer to an object, it will be the parent of the new template
|
||||
* @param copy pointer to a template object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created template
|
||||
*/
|
||||
lv_obj_t * lv_templ_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a style of a template.
|
||||
* @param templ pointer to template object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_templ_set_style(lv_obj_t * templ, lv_templ_style_t type, lv_style_t *style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get style of a template.
|
||||
* @param templ pointer to template object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
*/
|
||||
lv_style_t * lv_templ_get_style(const lv_obj_t * templ, lv_templ_style_t type);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_TEMPL*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_TEMPL_H*/
|
1205
bdk/libs/lvgl/lv_objx/lv_page.c
Normal file
1205
bdk/libs/lvgl/lv_objx/lv_page.c
Normal file
File diff suppressed because it is too large
Load diff
402
bdk/libs/lvgl/lv_objx/lv_page.h
Normal file
402
bdk/libs/lvgl/lv_objx/lv_page.h
Normal file
|
@ -0,0 +1,402 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file lv_page.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_PAGE_H
|
||||
#define LV_PAGE_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_PAGE != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_CONT == 0
|
||||
#error "lv_page: lv_cont is required. Enable it in lv_conf.h (USE_LV_CONT 1) "
|
||||
#endif
|
||||
|
||||
#include "lv_cont.h"
|
||||
#include "../lv_core/lv_indev.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Scrollbar modes: shows when should the scrollbars be visible*/
|
||||
enum
|
||||
{
|
||||
LV_SB_MODE_OFF = 0x0, /*Never show scrollbars*/
|
||||
LV_SB_MODE_ON = 0x1, /*Always show scrollbars*/
|
||||
LV_SB_MODE_DRAG = 0x2, /*Show scrollbars when page is being dragged*/
|
||||
LV_SB_MODE_AUTO = 0x3, /*Show scrollbars when the scrollable container is large enough to be scrolled*/
|
||||
LV_SB_MODE_HIDE = 0x4, /*Hide the scroll bar temporally*/
|
||||
LV_SB_MODE_UNHIDE = 0x5, /*Unhide the previously hidden scrollbar. Recover it's type too*/
|
||||
};
|
||||
typedef uint8_t lv_sb_mode_t;
|
||||
|
||||
/*Data of page*/
|
||||
typedef struct
|
||||
{
|
||||
lv_cont_ext_t bg; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_obj_t * scrl; /*The scrollable object on the background*/
|
||||
lv_style_t *bgo; /*The scrollable object on the background*/
|
||||
lv_style_t *pr; /*The scrollable object on the background*/
|
||||
lv_action_t rel_action; /*Function to call when the page is released*/
|
||||
lv_action_t pr_action; /*Function to call when the page is pressed*/
|
||||
struct {
|
||||
lv_style_t *style; /*Style of scrollbars*/
|
||||
lv_area_t hor_area; /*Horizontal scrollbar area relative to the page. (Handled by the library) */
|
||||
lv_area_t ver_area; /*Vertical scrollbar area relative to the page (Handled by the library)*/
|
||||
uint8_t hor_draw :1; /*1: horizontal scrollbar is visible now (Handled by the library)*/
|
||||
uint8_t ver_draw :1; /*1: vertical scrollbar is visible now (Handled by the library)*/
|
||||
lv_sb_mode_t mode:3; /*Scrollbar visibility from 'lv_page_sb_mode_t'*/
|
||||
} sb;
|
||||
struct {
|
||||
uint16_t state; /*Store the current size of the edge flash effect*/
|
||||
lv_style_t *style; /*Style of edge flash effect (usually homogeneous circle)*/
|
||||
uint8_t enabled :1; /*1: Show a flash animation on the edge*/
|
||||
uint8_t top_ip :1; /*Used internally to show that top most position is reached (flash is In Progress)*/
|
||||
uint8_t bottom_ip :1; /*Used internally to show that bottom most position is reached (flash is In Progress)*/
|
||||
uint8_t right_ip :1; /*Used internally to show that right most position is reached (flash is In Progress)*/
|
||||
uint8_t left_ip :1; /*Used internally to show that left most position is reached (flash is In Progress)*/
|
||||
}edge_flash;
|
||||
|
||||
uint8_t arrow_scroll :1; /*1: Enable scrolling with LV_GROUP_KEY_LEFT/RIGHT/UP/DOWN*/
|
||||
uint8_t scroll_prop :1; /*1: Propagate the scrolling the the parent if the edge is reached*/
|
||||
uint8_t scroll_prop_ip :1; /*1: Scroll propagation is in progress (used by the library)*/
|
||||
} lv_page_ext_t;
|
||||
|
||||
enum {
|
||||
LV_PAGE_STYLE_BG,
|
||||
LV_PAGE_STYLE_BGO,
|
||||
LV_PAGE_STYLE_PR,
|
||||
LV_PAGE_STYLE_SCRL,
|
||||
LV_PAGE_STYLE_SB,
|
||||
LV_PAGE_STYLE_EDGE_FLASH,
|
||||
};
|
||||
typedef uint8_t lv_page_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a page objects
|
||||
* @param par pointer to an object, it will be the parent of the new page
|
||||
* @param copy pointer to a page object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created page
|
||||
*/
|
||||
lv_obj_t * lv_page_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_page_clean(lv_obj_t *obj);
|
||||
|
||||
/**
|
||||
* Get the press action of the page
|
||||
* @param page pointer to a page object
|
||||
* @return a function to call when the page is pressed
|
||||
*/
|
||||
lv_action_t lv_page_get_pr_action(lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Get the release action of the page
|
||||
* @param page pointer to a page object
|
||||
* @return a function to call when the page is released
|
||||
*/
|
||||
lv_action_t lv_page_get_rel_action(lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Get the scrollable object of a page
|
||||
* @param page pointer to a page object
|
||||
* @return pointer to a container which is the scrollable part of the page
|
||||
*/
|
||||
lv_obj_t * lv_page_get_scrl(const lv_obj_t * page);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a release action for the page
|
||||
* @param page pointer to a page object
|
||||
* @param rel_action a function to call when the page is released
|
||||
*/
|
||||
void lv_page_set_rel_action(lv_obj_t * page, lv_action_t rel_action);
|
||||
|
||||
/**
|
||||
* Set a press action for the page
|
||||
* @param page pointer to a page object
|
||||
* @param pr_action a function to call when the page is pressed
|
||||
*/
|
||||
void lv_page_set_pr_action(lv_obj_t * page, lv_action_t pr_action);
|
||||
|
||||
/**
|
||||
* Set the scroll bar mode on a page
|
||||
* @param page pointer to a page object
|
||||
* @param sb_mode the new mode from 'lv_page_sb.mode_t' enum
|
||||
*/
|
||||
void lv_page_set_sb_mode(lv_obj_t * page, lv_sb_mode_t sb_mode);
|
||||
|
||||
/**
|
||||
* Enable/Disable scrolling with arrows if the page is in group (arrows: LV_GROUP_KEY_LEFT/RIGHT/UP/DOWN)
|
||||
* @param page pointer to a page object
|
||||
* @param en true: enable scrolling with arrows
|
||||
*/
|
||||
void lv_page_set_arrow_scroll(lv_obj_t * page, bool en);
|
||||
|
||||
/**
|
||||
* Enable the scroll propagation feature. If enabled then the page will move its parent if there is no more space to scroll.
|
||||
* @param page pointer to a Page
|
||||
* @param en true or false to enable/disable scroll propagation
|
||||
*/
|
||||
void lv_page_set_scroll_propagation(lv_obj_t * page, bool en);
|
||||
|
||||
/**
|
||||
* Enable the edge flash effect. (Show an arc when the an edge is reached)
|
||||
* @param page pointer to a Page
|
||||
* @param en true or false to enable/disable end flash
|
||||
*/
|
||||
void lv_page_set_edge_flash(lv_obj_t * page, bool en);
|
||||
|
||||
/**
|
||||
* Set the fit attribute of the scrollable part of a page.
|
||||
* It means it can set its size automatically to involve all children.
|
||||
* (Can be set separately horizontally and vertically)
|
||||
* @param page pointer to a page object
|
||||
* @param hor_en true: enable horizontal fit
|
||||
* @param ver_en true: enable vertical fit
|
||||
*/
|
||||
static inline void lv_page_set_scrl_fit(lv_obj_t *page, bool hor_en, bool ver_en)
|
||||
{
|
||||
lv_cont_set_fit(lv_page_get_scrl(page), hor_en, ver_en);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set width of the scrollable part of a page
|
||||
* @param page pointer to a page object
|
||||
* @param w the new width of the scrollable (it ha no effect is horizontal fit is enabled)
|
||||
*/
|
||||
static inline void lv_page_set_scrl_width(lv_obj_t *page, lv_coord_t w)
|
||||
{
|
||||
lv_obj_set_width(lv_page_get_scrl(page), w);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set height of the scrollable part of a page
|
||||
* @param page pointer to a page object
|
||||
* @param h the new height of the scrollable (it ha no effect is vertical fit is enabled)
|
||||
*/
|
||||
static inline void lv_page_set_scrl_height(lv_obj_t *page, lv_coord_t h)
|
||||
{
|
||||
lv_obj_set_height(lv_page_get_scrl(page), h);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the layout of the scrollable part of the page
|
||||
* @param page pointer to a page object
|
||||
* @param layout a layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
static inline void lv_page_set_scrl_layout(lv_obj_t * page, lv_layout_t layout)
|
||||
{
|
||||
lv_cont_set_layout(lv_page_get_scrl(page), layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a page
|
||||
* @param page pointer to a page object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_page_set_style(lv_obj_t *page, lv_page_style_t type, lv_style_t *style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the scroll bar mode on a page
|
||||
* @param page pointer to a page object
|
||||
* @return the mode from 'lv_page_sb.mode_t' enum
|
||||
*/
|
||||
lv_sb_mode_t lv_page_get_sb_mode(const lv_obj_t * page);
|
||||
|
||||
|
||||
/**
|
||||
* Get the the scrolling with arrows (LV_GROUP_KEY_LEFT/RIGHT/UP/DOWN) is enabled or not
|
||||
* @param page pointer to a page object
|
||||
* @return true: scrolling with arrows is enabled
|
||||
*/
|
||||
bool lv_page_get_arrow_scroll(const lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Get the scroll propagation property
|
||||
* @param page pointer to a Page
|
||||
* @return true or false
|
||||
*/
|
||||
bool lv_page_get_scroll_propagation(lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Get the edge flash effect property.
|
||||
* @param page pointer to a Page
|
||||
* return true or false
|
||||
*/
|
||||
bool lv_page_get_edge_flash(lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Get that width which can be set to the children to still not cause overflow (show scrollbars)
|
||||
* @param page pointer to a page object
|
||||
* @return the width which still fits into the page
|
||||
*/
|
||||
lv_coord_t lv_page_get_fit_width(lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Get that height which can be set to the children to still not cause overflow (show scrollbars)
|
||||
* @param page pointer to a page object
|
||||
* @return the height which still fits into the page
|
||||
*/
|
||||
lv_coord_t lv_page_get_fit_height(lv_obj_t * page);
|
||||
|
||||
/**
|
||||
* Get width of the scrollable part of a page
|
||||
* @param page pointer to a page object
|
||||
* @return the width of the scrollable
|
||||
*/
|
||||
static inline lv_coord_t lv_page_get_scrl_width(const lv_obj_t *page)
|
||||
{
|
||||
return lv_obj_get_width(lv_page_get_scrl(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get height of the scrollable part of a page
|
||||
* @param page pointer to a page object
|
||||
* @return the height of the scrollable
|
||||
*/
|
||||
static inline lv_coord_t lv_page_get_scrl_height(const lv_obj_t *page)
|
||||
{
|
||||
return lv_obj_get_height(lv_page_get_scrl(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the layout of the scrollable part of a page
|
||||
* @param page pointer to page object
|
||||
* @return the layout from 'lv_cont_layout_t'
|
||||
*/
|
||||
static inline lv_layout_t lv_page_get_scrl_layout(const lv_obj_t * page)
|
||||
{
|
||||
return lv_cont_get_layout(lv_page_get_scrl(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get horizontal fit attribute of the scrollable part of a page
|
||||
* @param page pointer to a page object
|
||||
* @return true: horizontal fit is enabled; false: disabled
|
||||
*/
|
||||
static inline bool lv_page_get_scrl_hor_fit(const lv_obj_t * page)
|
||||
{
|
||||
return lv_cont_get_hor_fit(lv_page_get_scrl(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get vertical fit attribute of the scrollable part of a page
|
||||
* @param page pointer to a page object
|
||||
* @return true: vertical fit is enabled; false: disabled
|
||||
*/
|
||||
static inline bool lv_page_get_scrl_fit_ver(const lv_obj_t * page)
|
||||
{
|
||||
return lv_cont_get_ver_fit(lv_page_get_scrl(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a page
|
||||
* @param page pointer to page object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_page_get_style(const lv_obj_t *page, lv_page_style_t type);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Glue the object to the page. After it the page can be moved (dragged) with this object too.
|
||||
* @param obj pointer to an object on a page
|
||||
* @param glue true: enable glue, false: disable glue
|
||||
*/
|
||||
void lv_page_glue_obj(lv_obj_t * obj, bool glue);
|
||||
|
||||
/**
|
||||
* Focus on an object. It ensures that the object will be visible on the page.
|
||||
* @param page pointer to a page object
|
||||
* @param obj pointer to an object to focus (must be on the page)
|
||||
* @param anim_time scroll animation time in milliseconds (0: no animation)
|
||||
*/
|
||||
void lv_page_focus(lv_obj_t * page, const lv_obj_t * obj, uint16_t anim_time);
|
||||
|
||||
/**
|
||||
* Scroll the page horizontally
|
||||
* @param page pointer to a page object
|
||||
* @param dist the distance to scroll (< 0: scroll left; > 0 scroll right)
|
||||
*/
|
||||
void lv_page_scroll_hor(lv_obj_t * page, lv_coord_t dist);
|
||||
|
||||
/**
|
||||
* Scroll the page vertically
|
||||
* @param page pointer to a page object
|
||||
* @param dist the distance to scroll (< 0: scroll down; > 0 scroll up)
|
||||
*/
|
||||
void lv_page_scroll_ver(lv_obj_t * page, lv_coord_t dist);
|
||||
|
||||
/**
|
||||
* Not intended to use directly by the user but by other object types internally.
|
||||
* Start an edge flash animation. Exactly one `ext->edge_flash.xxx_ip` should be set
|
||||
* @param page
|
||||
*/
|
||||
void lv_page_start_edge_flash(lv_obj_t * page);
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_PAGE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_PAGE_H*/
|
411
bdk/libs/lvgl/lv_objx/lv_preload.c
Normal file
411
bdk/libs/lvgl/lv_objx/lv_preload.c
Normal file
|
@ -0,0 +1,411 @@
|
|||
/**
|
||||
* @file lv_preload.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_preload.h"
|
||||
#if USE_LV_PRELOAD != 0
|
||||
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_draw/lv_draw_rect.h"
|
||||
#include "../lv_draw/lv_draw_arc.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#ifndef LV_PRELOAD_DEF_ARC_LENGTH
|
||||
# define LV_PRELOAD_DEF_ARC_LENGTH 60 /*[deg]*/
|
||||
#endif
|
||||
|
||||
#ifndef LV_PRELOAD_DEF_SPIN_TIME
|
||||
# define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/
|
||||
#endif
|
||||
|
||||
#ifndef LV_PRELOAD_DEF_ANIM
|
||||
# define LV_PRELOAD_DEF_ANIM LV_PRELOAD_TYPE_SPINNING_ARC /*animation type*/
|
||||
#endif
|
||||
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_preload_design(lv_obj_t * preload, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_preload_signal(lv_obj_t * preload, lv_signal_t sign, void * param);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
static lv_design_func_t ancestor_design;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a pre loader object
|
||||
* @param par pointer to an object, it will be the parent of the new pre loader
|
||||
* @param copy pointer to a pre loader object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created pre loader
|
||||
*/
|
||||
lv_obj_t * lv_preload_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("preload create started");
|
||||
|
||||
/*Create the ancestor of pre loader*/
|
||||
lv_obj_t * new_preload = lv_arc_create(par, copy);
|
||||
lv_mem_assert(new_preload);
|
||||
if(new_preload == NULL) return NULL;
|
||||
|
||||
/*Allocate the pre loader type specific extended data*/
|
||||
lv_preload_ext_t * ext = lv_obj_allocate_ext_attr(new_preload, sizeof(lv_preload_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_preload);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_preload);
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->arc_length = LV_PRELOAD_DEF_ARC_LENGTH;
|
||||
ext->anim_type = LV_PRELOAD_DEF_ANIM;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_preload, lv_preload_signal);
|
||||
lv_obj_set_design_func(new_preload, lv_preload_design);
|
||||
|
||||
|
||||
/*Init the new pre loader pre loader*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_size(new_preload, LV_DPI / 2, LV_DPI / 2);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_preload_set_style(new_preload, LV_PRELOAD_STYLE_MAIN, th->preload);
|
||||
} else {
|
||||
lv_obj_set_style(new_preload, &lv_style_pretty_color);
|
||||
}
|
||||
|
||||
ext->time = LV_PRELOAD_DEF_SPIN_TIME;
|
||||
|
||||
}
|
||||
/*Copy an existing pre loader*/
|
||||
else {
|
||||
lv_preload_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->arc_length = copy_ext->arc_length;
|
||||
ext->time = copy_ext->time;
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_preload);
|
||||
}
|
||||
|
||||
lv_preload_set_animation_type(new_preload, ext->anim_type);
|
||||
|
||||
|
||||
LV_LOG_INFO("preload created");
|
||||
|
||||
return new_preload;
|
||||
}
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Set the length of the spinning arc in degrees
|
||||
* @param preload pointer to a preload object
|
||||
* @param deg length of the arc
|
||||
*/
|
||||
void lv_preload_set_arc_length(lv_obj_t * preload, uint16_t deg)
|
||||
{
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
|
||||
ext->arc_length = deg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the spin time of the arc
|
||||
* @param preload pointer to a preload object
|
||||
* @param time time of one round in milliseconds
|
||||
*/
|
||||
void lv_preload_set_spin_time(lv_obj_t * preload, uint16_t time)
|
||||
{
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
|
||||
ext->time = time;
|
||||
lv_preload_set_animation_type(preload, ext->anim_type);
|
||||
}
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a style of a pre loader.
|
||||
* @param preload pointer to pre loader object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
* */
|
||||
void lv_preload_set_style(lv_obj_t * preload, lv_preload_style_t type, lv_style_t * style)
|
||||
{
|
||||
switch(type) {
|
||||
case LV_PRELOAD_STYLE_MAIN:
|
||||
lv_arc_set_style(preload, LV_ARC_STYLE_MAIN, style);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the animation type of a preloadeer.
|
||||
* @param preload pointer to pre loader object
|
||||
* @param type animation type of the preload
|
||||
* */
|
||||
void lv_preload_set_animation_type(lv_obj_t * preload, lv_preloader_type_t type)
|
||||
{
|
||||
#if USE_LV_ANIMATION
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
|
||||
/*delete previous animation*/
|
||||
//lv_anim_del(preload, NULL);
|
||||
switch(type)
|
||||
{
|
||||
case LV_PRELOAD_TYPE_FILLSPIN_ARC:
|
||||
{
|
||||
ext->anim_type = LV_PRELOAD_TYPE_FILLSPIN_ARC;
|
||||
lv_anim_t a;
|
||||
a.var = preload;
|
||||
a.start = 0;
|
||||
a.end = 360;
|
||||
a.fp = (lv_anim_fp_t)lv_preload_spinner_animation;
|
||||
a.path = lv_anim_path_ease_in_out;
|
||||
a.end_cb = NULL;
|
||||
a.act_time = 0;
|
||||
a.time = ext->time;
|
||||
a.playback = 0;
|
||||
a.playback_pause = 0;
|
||||
a.repeat = 1;
|
||||
a.repeat_pause = 0;
|
||||
lv_anim_create(&a);
|
||||
|
||||
lv_anim_t b;
|
||||
b.var = preload;
|
||||
b.start = ext->arc_length;
|
||||
b.end = 360 - ext->arc_length;
|
||||
b.fp = (lv_anim_fp_t)lv_preload_set_arc_length;
|
||||
b.path = lv_anim_path_ease_in_out;
|
||||
b.end_cb = NULL;
|
||||
b.act_time = 0;
|
||||
b.time = ext->time;
|
||||
b.playback = 1;
|
||||
b.playback_pause = 0;
|
||||
b.repeat = 1;
|
||||
b.repeat_pause = 0;
|
||||
lv_anim_create(&b);
|
||||
break;
|
||||
}
|
||||
case LV_PRELOAD_TYPE_SPINNING_ARC:
|
||||
default:
|
||||
{
|
||||
ext->anim_type = LV_PRELOAD_TYPE_SPINNING_ARC;
|
||||
lv_anim_t a;
|
||||
a.var = preload;
|
||||
a.start = 0;
|
||||
a.end = 360;
|
||||
a.fp = (lv_anim_fp_t)lv_preload_spinner_animation;
|
||||
a.path = lv_anim_path_ease_in_out;
|
||||
a.end_cb = NULL;
|
||||
a.act_time = 0;
|
||||
a.time = ext->time;
|
||||
a.playback = 0;
|
||||
a.playback_pause = 0;
|
||||
a.repeat = 1;
|
||||
a.repeat_pause = 0;
|
||||
lv_anim_create(&a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //USE_LV_ANIMATION
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the arc length [degree] of the a pre loader
|
||||
* @param preload pointer to a pre loader object
|
||||
*/
|
||||
uint16_t lv_preload_get_arc_length(const lv_obj_t * preload)
|
||||
{
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
return ext->arc_length;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the spin time of the arc
|
||||
* @param preload pointer to a pre loader object [milliseconds]
|
||||
*/
|
||||
uint16_t lv_preload_get_spin_time(const lv_obj_t * preload)
|
||||
{
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
return ext->time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get style of a pre loader.
|
||||
* @param preload pointer to pre loader object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
* */
|
||||
lv_style_t * lv_preload_get_style(const lv_obj_t * preload, lv_preload_style_t type)
|
||||
{
|
||||
lv_style_t * style = NULL;
|
||||
|
||||
switch(type) {
|
||||
case LV_PRELOAD_STYLE_MAIN:
|
||||
style = lv_arc_get_style(preload, LV_ARC_STYLE_MAIN);
|
||||
break;
|
||||
default:
|
||||
style = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the animation type of a preloadeer.
|
||||
* @param preload pointer to pre loader object
|
||||
* @return animation type
|
||||
* */
|
||||
lv_preloader_type_t lv_preload_get_animation_type(lv_obj_t * preload)
|
||||
{
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
return ext->anim_type;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Automatically in an animation to rotate the arc of spinner.
|
||||
* @param ptr pointer to preloader
|
||||
* @param val the current desired value [0..360]
|
||||
*/
|
||||
void lv_preload_spinner_animation(void * ptr, int32_t val)
|
||||
{
|
||||
lv_obj_t * preload = ptr;
|
||||
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
|
||||
int16_t angle_start = val - ext->arc_length / 2 + 180;
|
||||
int16_t angle_end = angle_start + ext->arc_length;
|
||||
|
||||
angle_start = angle_start % 360;
|
||||
angle_end = angle_end % 360;
|
||||
|
||||
lv_arc_set_angles(preload, angle_start, angle_end);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the pre loaders
|
||||
* @param preload pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_preload_design(lv_obj_t * preload, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return false;
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
|
||||
/*Draw a circle as background*/
|
||||
lv_style_t * style = lv_arc_get_style(preload, LV_ARC_STYLE_MAIN);
|
||||
if(style->body.border.width > 0) {
|
||||
lv_coord_t r = (LV_MATH_MIN(lv_obj_get_width(preload), lv_obj_get_height(preload))) / 2;
|
||||
r -= LV_MATH_MIN(style->body.padding.hor, style->body.padding.ver);
|
||||
|
||||
lv_coord_t x = preload->coords.x1 + lv_obj_get_width(preload) / 2;
|
||||
lv_coord_t y = preload->coords.y1 + lv_obj_get_height(preload) / 2;
|
||||
|
||||
lv_style_t bg_style;
|
||||
lv_style_copy(&bg_style, &lv_style_plain);
|
||||
bg_style.body.empty = 1;
|
||||
bg_style.body.radius = LV_RADIUS_CIRCLE;
|
||||
bg_style.body.border.color = style->body.border.color;
|
||||
bg_style.body.border.width = style->body.border.width;
|
||||
|
||||
lv_area_t bg_area;
|
||||
bg_area.x1 = x - r;
|
||||
bg_area.y1 = y - r;
|
||||
bg_area.x2 = x + r;
|
||||
bg_area.y2 = y + r;
|
||||
|
||||
lv_draw_rect(&bg_area, mask, &bg_style, lv_obj_get_opa_scale(preload));
|
||||
}
|
||||
/*Draw the arc above the background circle */
|
||||
ancestor_design(preload, mask, mode);
|
||||
}
|
||||
/*Post draw when the children are drawn*/
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the pre loader
|
||||
* @param preload pointer to a pre loader object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_preload_signal(lv_obj_t * preload, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(preload, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_preload";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
168
bdk/libs/lvgl/lv_objx/lv_preload.h
Normal file
168
bdk/libs/lvgl/lv_objx/lv_preload.h
Normal file
|
@ -0,0 +1,168 @@
|
|||
/**
|
||||
* @file lv_preload.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_PRELOAD_H
|
||||
#define LV_PRELOAD_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_PRELOAD != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_ARC == 0
|
||||
#error "lv_preload: lv_arc is required. Enable it in lv_conf.h (USE_LV_ARC 1) "
|
||||
#endif
|
||||
|
||||
#if USE_LV_ANIMATION == 0
|
||||
#error "lv_preload: animations are required. Enable it in lv_conf.h (USE_LV_ANIMATION 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_arc.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
enum {
|
||||
LV_PRELOAD_TYPE_SPINNING_ARC,
|
||||
LV_PRELOAD_TYPE_FILLSPIN_ARC,
|
||||
};
|
||||
typedef uint8_t lv_preloader_type_t;
|
||||
|
||||
/*Data of pre loader*/
|
||||
typedef struct {
|
||||
lv_arc_ext_t arc; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
uint16_t arc_length; /*Length of the spinning indicator in degree*/
|
||||
uint16_t time; /*Time of one round*/
|
||||
lv_preloader_type_t anim_type; /*Type of the arc animation*/
|
||||
} lv_preload_ext_t;
|
||||
|
||||
|
||||
/*Styles*/
|
||||
enum {
|
||||
LV_PRELOAD_STYLE_MAIN,
|
||||
};
|
||||
typedef uint8_t lv_preload_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a pre loader objects
|
||||
* @param par pointer to an object, it will be the parent of the new pre loader
|
||||
* @param copy pointer to a pre loader object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created pre loader
|
||||
*/
|
||||
lv_obj_t * lv_preload_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Set the length of the spinning arc in degrees
|
||||
* @param preload pointer to a preload object
|
||||
* @param deg length of the arc
|
||||
*/
|
||||
void lv_preload_set_arc_length(lv_obj_t * preload, uint16_t deg);
|
||||
|
||||
/**
|
||||
* Set the spin time of the arc
|
||||
* @param preload pointer to a preload object
|
||||
* @param time time of one round in milliseconds
|
||||
*/
|
||||
void lv_preload_set_spin_time(lv_obj_t * preload, uint16_t time);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a style of a pre loader.
|
||||
* @param preload pointer to pre loader object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
* */
|
||||
void lv_preload_set_style(lv_obj_t * preload, lv_preload_style_t type, lv_style_t *style);
|
||||
|
||||
/**
|
||||
* Set the animation type of a preloadeer.
|
||||
* @param preload pointer to pre loader object
|
||||
* @param type animation type of the preload
|
||||
* */
|
||||
void lv_preload_set_animation_type(lv_obj_t * preload, lv_preloader_type_t type);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the arc length [degree] of the a pre loader
|
||||
* @param preload pointer to a pre loader object
|
||||
*/
|
||||
uint16_t lv_preload_get_arc_length(const lv_obj_t * preload);
|
||||
|
||||
/**
|
||||
* Get the spin time of the arc
|
||||
* @param preload pointer to a pre loader object [milliseconds]
|
||||
*/
|
||||
uint16_t lv_preload_get_spin_time(const lv_obj_t * preload);
|
||||
|
||||
/**
|
||||
* Get style of a pre loader.
|
||||
* @param preload pointer to pre loader object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
* */
|
||||
lv_style_t * lv_preload_get_style(const lv_obj_t * preload, lv_preload_style_t type);
|
||||
|
||||
/**
|
||||
* Get the animation type of a preloadeer.
|
||||
* @param preload pointer to pre loader object
|
||||
* @return animation type
|
||||
* */
|
||||
lv_preloader_type_t lv_preload_get_animation_type(lv_obj_t * preload);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get style of a pre loader.
|
||||
* @param preload pointer to pre loader object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
* */
|
||||
void lv_preload_spinner_animation(void * ptr, int32_t val);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_PRELOAD*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_PRELOAD_H*/
|
582
bdk/libs/lvgl/lv_objx/lv_roller.c
Normal file
582
bdk/libs/lvgl/lv_objx/lv_roller.c
Normal file
|
@ -0,0 +1,582 @@
|
|||
/**
|
||||
* @file lv_roller.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_roller.h"
|
||||
#if USE_LV_ROLLER != 0
|
||||
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#if USE_LV_ANIMATION
|
||||
# ifndef LV_ROLLER_ANIM_TIME
|
||||
# define LV_ROLLER_ANIM_TIME 200 /*ms*/
|
||||
# endif
|
||||
#else
|
||||
# undef LV_ROLLER_ANIM_TIME
|
||||
# define LV_ROLLER_ANIM_TIME 0 /*No animation*/
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_roller_design(lv_obj_t * roller, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_roller_scrl_signal(lv_obj_t * roller_scrl, lv_signal_t sign, void * param);
|
||||
static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * param);
|
||||
static void refr_position(lv_obj_t * roller, bool anim_en);
|
||||
static void draw_bg(lv_obj_t * roller, const lv_area_t * mask);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
static lv_signal_func_t ancestor_scrl_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a roller object
|
||||
* @param par pointer to an object, it will be the parent of the new roller
|
||||
* @param copy pointer to a roller object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created roller
|
||||
*/
|
||||
lv_obj_t * lv_roller_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("roller create started");
|
||||
|
||||
/*Create the ancestor of roller*/
|
||||
lv_obj_t * new_roller = lv_ddlist_create(par, copy);
|
||||
lv_mem_assert(new_roller);
|
||||
if(new_roller == NULL) return NULL;
|
||||
|
||||
if(ancestor_scrl_signal == NULL) ancestor_scrl_signal = lv_obj_get_signal_func(lv_page_get_scrl(new_roller));
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_roller);
|
||||
|
||||
/*Allocate the roller type specific extended data*/
|
||||
lv_roller_ext_t * ext = lv_obj_allocate_ext_attr(new_roller, sizeof(lv_roller_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
ext->ddlist.draw_arrow = 0; /*Do not draw arrow by default*/
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_roller, lv_roller_signal);
|
||||
lv_obj_set_design_func(new_roller, lv_roller_design);
|
||||
|
||||
/*Init the new roller roller*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_t * scrl = lv_page_get_scrl(new_roller);
|
||||
lv_obj_set_drag(scrl, true); /*In ddlist is might be disabled*/
|
||||
lv_page_set_rel_action(new_roller, NULL); /*Roller don't uses it (like ddlist)*/
|
||||
lv_page_set_scrl_fit(new_roller, true, false); /*Height is specified directly*/
|
||||
lv_ddlist_open(new_roller, false);
|
||||
lv_ddlist_set_anim_time(new_roller, LV_ROLLER_ANIM_TIME);
|
||||
lv_roller_set_visible_row_count(new_roller, 3);
|
||||
lv_label_set_align(ext->ddlist.label, LV_LABEL_ALIGN_CENTER);
|
||||
|
||||
lv_obj_set_signal_func(scrl, lv_roller_scrl_signal);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_roller_set_style(new_roller, LV_ROLLER_STYLE_BG, th->roller.bg);
|
||||
lv_roller_set_style(new_roller, LV_ROLLER_STYLE_SEL, th->roller.sel);
|
||||
} else {
|
||||
/*Let the ddlist's style*/
|
||||
lv_obj_refresh_style(new_roller); /*To set scrollable size automatically*/
|
||||
}
|
||||
}
|
||||
/*Copy an existing roller*/
|
||||
else {
|
||||
lv_obj_t * scrl = lv_page_get_scrl(new_roller);
|
||||
lv_ddlist_open(new_roller, false);
|
||||
lv_obj_set_signal_func(scrl, lv_roller_scrl_signal);
|
||||
|
||||
lv_obj_refresh_style(new_roller); /*Refresh the style with new signal function*/
|
||||
}
|
||||
|
||||
|
||||
LV_LOG_INFO("roller created");
|
||||
|
||||
|
||||
return new_roller;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the align of the roller's options (left or center)
|
||||
* @param roller - pointer to a roller object
|
||||
* @param align - one of lv_label_align_t values (left, right, center)
|
||||
*/
|
||||
void lv_roller_set_align(lv_obj_t * roller, lv_label_align_t align)
|
||||
{
|
||||
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
|
||||
lv_mem_assert(ext);
|
||||
if(ext->ddlist.label == NULL) return; /*Probably the roller is being deleted if the label is NULL.*/
|
||||
lv_label_set_align(ext->ddlist.label, align);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the selected option
|
||||
* @param roller pointer to a roller object
|
||||
* @param sel_opt id of the selected option (0 ... number of option - 1);
|
||||
* @param anim_en true: set with animation; false set immediately
|
||||
*/
|
||||
void lv_roller_set_selected(lv_obj_t * roller, uint16_t sel_opt, bool anim_en)
|
||||
{
|
||||
#if USE_LV_ANIMATION == 0
|
||||
anim_en = false;
|
||||
#endif
|
||||
|
||||
if(lv_roller_get_selected(roller) == sel_opt) return;
|
||||
|
||||
lv_ddlist_set_selected(roller, sel_opt);
|
||||
refr_position(roller, anim_en);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the height to show the given number of rows (options)
|
||||
* @param roller pointer to a roller object
|
||||
* @param row_cnt number of desired visible rows
|
||||
*/
|
||||
void lv_roller_set_visible_row_count(lv_obj_t * roller, uint8_t row_cnt)
|
||||
{
|
||||
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
|
||||
lv_style_t * style_label = lv_obj_get_style(ext->ddlist.label);
|
||||
uint8_t n_line_space = (row_cnt > 1) ? row_cnt - 1 : 1;
|
||||
lv_ddlist_set_fix_height(roller, lv_font_get_height(style_label->text.font) * row_cnt + style_label->text.line_space * n_line_space);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a roller
|
||||
* @param roller pointer to a roller object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_roller_set_style(lv_obj_t * roller, lv_roller_style_t type, lv_style_t * style)
|
||||
{
|
||||
switch(type) {
|
||||
case LV_ROLLER_STYLE_BG:
|
||||
lv_obj_set_style(roller, style);
|
||||
break;
|
||||
case LV_ROLLER_STYLE_SEL:
|
||||
lv_ddlist_set_style(roller, LV_DDLIST_STYLE_SEL, style);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the align attribute. Default alignment after _create is LV_LABEL_ALIGN_CENTER
|
||||
* @param roller pointer to a roller object
|
||||
* @return LV_LABEL_ALIGN_LEFT, LV_LABEL_ALIGN_RIGHT or LV_LABEL_ALIGN_CENTER
|
||||
*/
|
||||
lv_label_align_t lv_roller_get_align(const lv_obj_t * roller)
|
||||
{
|
||||
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
|
||||
lv_mem_assert(ext);
|
||||
lv_mem_assert(ext->ddlist.label);
|
||||
return lv_label_get_align(ext->ddlist.label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the auto width set attribute
|
||||
* @param roller pointer to a roller object
|
||||
* @return true: auto size enabled; false: manual width settings enabled
|
||||
*/
|
||||
bool lv_roller_get_hor_fit(const lv_obj_t * roller)
|
||||
{
|
||||
return lv_page_get_scrl_hor_fit(roller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a roller
|
||||
* @param roller pointer to a roller object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
* */
|
||||
lv_style_t * lv_roller_get_style(const lv_obj_t * roller, lv_roller_style_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case LV_ROLLER_STYLE_BG:
|
||||
return lv_obj_get_style(roller);
|
||||
case LV_ROLLER_STYLE_SEL:
|
||||
return lv_ddlist_get_style(roller, LV_DDLIST_STYLE_SEL);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*To avoid warning*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the rollers
|
||||
* @param roller pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_roller_design(lv_obj_t * roller, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return false;
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
draw_bg(roller, mask);
|
||||
|
||||
lv_style_t * style = lv_roller_get_style(roller, LV_ROLLER_STYLE_BG);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(roller);
|
||||
const lv_font_t * font = style->text.font;
|
||||
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
|
||||
lv_coord_t font_h = lv_font_get_height(font);
|
||||
lv_area_t rect_area;
|
||||
rect_area.y1 = roller->coords.y1 + lv_obj_get_height(roller) / 2 - font_h / 2 - style->text.line_space / 2;
|
||||
if((font_h & 0x1) && (style->text.line_space & 0x1)) rect_area.y1 --; /*Compensate the two rounding error*/
|
||||
rect_area.y2 = rect_area.y1 + font_h + style->text.line_space - 1;
|
||||
rect_area.x1 = roller->coords.x1;
|
||||
rect_area.x2 = roller->coords.x2;
|
||||
|
||||
lv_draw_rect(&rect_area, mask, ext->ddlist.sel_style, opa_scale);
|
||||
}
|
||||
/*Post draw when the children are drawn*/
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
lv_style_t * style = lv_roller_get_style(roller, LV_ROLLER_STYLE_BG);
|
||||
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
|
||||
const lv_font_t * font = style->text.font;
|
||||
lv_coord_t font_h = lv_font_get_height(font);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(roller);
|
||||
|
||||
/*Redraw the text on the selected area with a different color*/
|
||||
lv_area_t rect_area;
|
||||
rect_area.y1 = roller->coords.y1 + lv_obj_get_height(roller) / 2 - font_h / 2 - style->text.line_space / 2;
|
||||
if((font_h & 0x1) && (style->text.line_space & 0x1)) rect_area.y1 --; /*Compensate the two rounding error*/
|
||||
rect_area.y2 = rect_area.y1 + font_h + style->text.line_space - 1;
|
||||
rect_area.x1 = roller->coords.x1;
|
||||
rect_area.x2 = roller->coords.x2;
|
||||
lv_area_t mask_sel;
|
||||
bool area_ok;
|
||||
area_ok = lv_area_intersect(&mask_sel, mask, &rect_area);
|
||||
if(area_ok) {
|
||||
lv_style_t * sel_style = lv_roller_get_style(roller, LV_ROLLER_STYLE_SEL);
|
||||
lv_style_t new_style;
|
||||
lv_txt_flag_t txt_align = LV_TXT_FLAG_NONE;
|
||||
|
||||
{
|
||||
lv_label_align_t label_align = lv_label_get_align(ext->ddlist.label);
|
||||
|
||||
if(LV_LABEL_ALIGN_CENTER == label_align) {
|
||||
txt_align |= LV_TXT_FLAG_CENTER;
|
||||
} else if(LV_LABEL_ALIGN_RIGHT == label_align) {
|
||||
txt_align |= LV_TXT_FLAG_RIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
lv_style_copy(&new_style, style);
|
||||
new_style.text.color = sel_style->text.color;
|
||||
new_style.text.opa = sel_style->text.opa;
|
||||
lv_draw_label(&ext->ddlist.label->coords, &mask_sel, &new_style, opa_scale,
|
||||
lv_label_get_text(ext->ddlist.label), txt_align, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the roller
|
||||
* @param roller pointer to a roller object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_roller_signal(lv_obj_t * roller, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res = LV_RES_OK;
|
||||
|
||||
/*Don't let the drop down list to handle the control signals. It works differently*/
|
||||
if(sign != LV_SIGNAL_CONTROLL && sign != LV_SIGNAL_FOCUS && sign != LV_SIGNAL_DEFOCUS) {
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(roller, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
|
||||
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
|
||||
lv_align_t obj_align = LV_ALIGN_IN_LEFT_MID;
|
||||
if(ext->ddlist.label) {
|
||||
lv_label_align_t label_align = lv_label_get_align(ext->ddlist.label);
|
||||
if(LV_LABEL_ALIGN_CENTER == label_align) obj_align = LV_ALIGN_CENTER;
|
||||
else if(LV_LABEL_ALIGN_RIGHT == label_align) obj_align = LV_ALIGN_IN_RIGHT_MID;
|
||||
}
|
||||
|
||||
if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
lv_obj_set_height(lv_page_get_scrl(roller),
|
||||
lv_obj_get_height(ext->ddlist.label) + lv_obj_get_height(roller));
|
||||
lv_obj_align(ext->ddlist.label, NULL, obj_align, 0, 0);
|
||||
lv_ddlist_set_selected(roller, ext->ddlist.sel_opt_id);
|
||||
refr_position(roller, false);
|
||||
} else if(sign == LV_SIGNAL_CORD_CHG) {
|
||||
|
||||
if(lv_obj_get_width(roller) != lv_area_get_width(param) ||
|
||||
lv_obj_get_height(roller) != lv_area_get_height(param)) {
|
||||
|
||||
lv_ddlist_set_fix_height(roller, lv_obj_get_height(roller));
|
||||
lv_obj_set_height(lv_page_get_scrl(roller),
|
||||
lv_obj_get_height(ext->ddlist.label) + lv_obj_get_height(roller));
|
||||
|
||||
lv_obj_align(ext->ddlist.label, NULL, obj_align, 0, 0);
|
||||
lv_ddlist_set_selected(roller, ext->ddlist.sel_opt_id);
|
||||
refr_position(roller, false);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_FOCUS) {
|
||||
#if USE_LV_GROUP
|
||||
lv_group_t * g = lv_obj_get_group(roller);
|
||||
bool editing = lv_group_get_editing(g);
|
||||
lv_hal_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act());
|
||||
|
||||
/*Encoders need special handling*/
|
||||
if(indev_type == LV_INDEV_TYPE_ENCODER) {
|
||||
/*In navigate mode revert the original value*/
|
||||
if(!editing) {
|
||||
if(ext->ddlist.sel_opt_id != ext->ddlist.sel_opt_id_ori) {
|
||||
ext->ddlist.sel_opt_id = ext->ddlist.sel_opt_id_ori;
|
||||
refr_position(roller, true);
|
||||
}
|
||||
}
|
||||
/*Save the current state when entered to edit mode*/
|
||||
else {
|
||||
ext->ddlist.sel_opt_id_ori = ext->ddlist.sel_opt_id;
|
||||
}
|
||||
} else {
|
||||
ext->ddlist.sel_opt_id_ori = ext->ddlist.sel_opt_id; /*Save the current value. Used to revert this state if ENER wont't be pressed*/
|
||||
|
||||
}
|
||||
#endif
|
||||
} else if(sign == LV_SIGNAL_DEFOCUS) {
|
||||
#if USE_LV_GROUP
|
||||
/*Revert the original state*/
|
||||
if(ext->ddlist.sel_opt_id != ext->ddlist.sel_opt_id_ori) {
|
||||
ext->ddlist.sel_opt_id = ext->ddlist.sel_opt_id_ori;
|
||||
refr_position(roller, true);
|
||||
}
|
||||
#endif
|
||||
} else if(sign == LV_SIGNAL_CONTROLL) {
|
||||
char c = *((char *)param);
|
||||
if(c == LV_GROUP_KEY_RIGHT || c == LV_GROUP_KEY_DOWN) {
|
||||
if(ext->ddlist.sel_opt_id + 1 < ext->ddlist.option_cnt) {
|
||||
lv_roller_set_selected(roller, ext->ddlist.sel_opt_id + 1, true);
|
||||
}
|
||||
} else if(c == LV_GROUP_KEY_LEFT || c == LV_GROUP_KEY_UP) {
|
||||
if(ext->ddlist.sel_opt_id > 0) {
|
||||
lv_roller_set_selected(roller, ext->ddlist.sel_opt_id - 1, true);
|
||||
}
|
||||
} else if(c == LV_GROUP_KEY_ENTER) {
|
||||
ext->ddlist.sel_opt_id_ori = ext->ddlist.sel_opt_id; /*Set the entered value as default*/
|
||||
if(ext->ddlist.action) ext->ddlist.action(roller);
|
||||
|
||||
#if USE_LV_GROUP
|
||||
lv_group_t * g = lv_obj_get_group(roller);
|
||||
bool editing = lv_group_get_editing(g);
|
||||
if(editing) lv_group_set_editing(g, false); /*In edit mode go to navigate mode if an option is selected*/
|
||||
#endif
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_roller";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the scrollable part of the roller.
|
||||
* @param roller_scrl ointer to the scrollable part of roller (page)
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_roller_scrl_signal(lv_obj_t * roller_scrl, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_scrl_signal(roller_scrl, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
int32_t id = -1;
|
||||
lv_obj_t * roller = lv_obj_get_parent(roller_scrl);
|
||||
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
|
||||
|
||||
if(ext->ddlist.label == NULL) return LV_RES_INV; /*On delete the ddlist signal deletes the label so nothing left to do here*/
|
||||
|
||||
lv_style_t * style_label = lv_obj_get_style(ext->ddlist.label);
|
||||
const lv_font_t * font = style_label->text.font;
|
||||
lv_coord_t font_h = lv_font_get_height(font);
|
||||
|
||||
if(sign == LV_SIGNAL_DRAG_END) {
|
||||
/*If dragged then align the list to there be an element in the middle*/
|
||||
lv_coord_t label_y1 = ext->ddlist.label->coords.y1 - roller->coords.y1;
|
||||
lv_coord_t label_unit = font_h + style_label->text.line_space;
|
||||
lv_coord_t mid = (roller->coords.y2 - roller->coords.y1) / 2;
|
||||
id = (mid - label_y1 + style_label->text.line_space / 2) / label_unit;
|
||||
if(id < 0) id = 0;
|
||||
if(id >= ext->ddlist.option_cnt) id = ext->ddlist.option_cnt - 1;
|
||||
ext->ddlist.sel_opt_id = id;
|
||||
if(ext->ddlist.action) ext->ddlist.action(roller);
|
||||
} else if(sign == LV_SIGNAL_RELEASED) {
|
||||
/*If picked an option by clicking then set it*/
|
||||
if(!lv_indev_is_dragging(indev)) {
|
||||
lv_point_t p;
|
||||
lv_indev_get_point(indev, &p);
|
||||
p.y = p.y - ext->ddlist.label->coords.y1;
|
||||
id = p.y / (font_h + style_label->text.line_space);
|
||||
if(id < 0) id = 0;
|
||||
if(id >= ext->ddlist.option_cnt) id = ext->ddlist.option_cnt - 1;
|
||||
ext->ddlist.sel_opt_id = id;
|
||||
if(ext->ddlist.action) ext->ddlist.action(roller);
|
||||
}
|
||||
}
|
||||
|
||||
/*Position the scrollable according to the new selected option*/
|
||||
if(id != -1) {
|
||||
refr_position(roller, true);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a rectangle which has gradient on its top and bottom
|
||||
* @param roller pointer to a roller object
|
||||
* @param mask pointer to the current mask (from the design function)
|
||||
*/
|
||||
static void draw_bg(lv_obj_t * roller, const lv_area_t * mask)
|
||||
{
|
||||
lv_style_t * style = lv_roller_get_style(roller, LV_ROLLER_STYLE_BG);
|
||||
lv_area_t half_mask;
|
||||
lv_area_t half_roller;
|
||||
lv_coord_t h = lv_obj_get_height(roller);
|
||||
bool union_ok;
|
||||
lv_area_copy(&half_roller, &roller->coords);
|
||||
|
||||
half_roller.x1 -= roller->ext_size; /*Add ext size too (e.g. because of shadow draw) */
|
||||
half_roller.x2 += roller->ext_size;
|
||||
half_roller.y1 -= roller->ext_size;
|
||||
half_roller.y2 = roller->coords.y1 + h / 2;
|
||||
|
||||
union_ok = lv_area_intersect(&half_mask, &half_roller, mask);
|
||||
|
||||
half_roller.x1 += roller->ext_size; /*Revert ext. size adding*/
|
||||
half_roller.x2 -= roller->ext_size;
|
||||
half_roller.y1 += roller->ext_size;
|
||||
half_roller.y2 += style->body.radius;
|
||||
|
||||
if(union_ok) {
|
||||
lv_draw_rect(&half_roller, &half_mask, style, lv_obj_get_opa_scale(roller));
|
||||
}
|
||||
|
||||
half_roller.x1 -= roller->ext_size; /*Add ext size too (e.g. because of shadow draw) */
|
||||
half_roller.x2 += roller->ext_size;
|
||||
half_roller.y2 = roller->coords.y2 + roller->ext_size;
|
||||
half_roller.y1 = roller->coords.y1 + h / 2;
|
||||
if((h & 0x1) == 0) half_roller.y1++; /*With even height the pixels in the middle would be drawn twice*/
|
||||
|
||||
union_ok = lv_area_intersect(&half_mask, &half_roller, mask);
|
||||
|
||||
half_roller.x1 += roller->ext_size; /*Revert ext. size adding*/
|
||||
half_roller.x2 -= roller->ext_size;
|
||||
half_roller.y2 -= roller->ext_size;
|
||||
half_roller.y1 -= style->body.radius;
|
||||
|
||||
if(union_ok) {
|
||||
lv_color_t main_tmp = style->body.main_color;
|
||||
lv_color_t grad_tmp = style->body.grad_color;
|
||||
|
||||
style->body.main_color = grad_tmp;
|
||||
style->body.grad_color = main_tmp;
|
||||
lv_draw_rect(&half_roller, &half_mask, style, lv_obj_get_opa_scale(roller));
|
||||
style->body.main_color = main_tmp;
|
||||
style->body.grad_color = grad_tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the position of the roller. It uses the id stored in: ext->ddlist.selected_option_id
|
||||
* @param roller pointer to a roller object
|
||||
* @param anim_en true: refresh with animation; false: without animation
|
||||
*/
|
||||
static void refr_position(lv_obj_t * roller, bool anim_en)
|
||||
{
|
||||
#if USE_LV_ANIMATION == 0
|
||||
anim_en = false;
|
||||
#endif
|
||||
lv_obj_t * roller_scrl = lv_page_get_scrl(roller);
|
||||
lv_roller_ext_t * ext = lv_obj_get_ext_attr(roller);
|
||||
lv_style_t * style_label = lv_obj_get_style(ext->ddlist.label);
|
||||
const lv_font_t * font = style_label->text.font;
|
||||
lv_coord_t font_h = lv_font_get_height(font);
|
||||
lv_coord_t h = lv_obj_get_height(roller);
|
||||
int32_t id = ext->ddlist.sel_opt_id;
|
||||
lv_coord_t line_y1 = id * (font_h + style_label->text.line_space) + ext->ddlist.label->coords.y1 - roller_scrl->coords.y1;
|
||||
lv_coord_t new_y = - line_y1 + (h - font_h) / 2;
|
||||
|
||||
if(ext->ddlist.anim_time == 0 || anim_en == false) {
|
||||
lv_obj_set_y(roller_scrl, new_y);
|
||||
} else {
|
||||
#if USE_LV_ANIMATION
|
||||
lv_anim_t a;
|
||||
a.var = roller_scrl;
|
||||
a.start = lv_obj_get_y(roller_scrl);
|
||||
a.end = new_y;
|
||||
a.fp = (lv_anim_fp_t)lv_obj_set_y;
|
||||
a.path = lv_anim_path_linear;
|
||||
a.end_cb = NULL;
|
||||
a.act_time = 0;
|
||||
a.time = ext->ddlist.anim_time;
|
||||
a.playback = 0;
|
||||
a.playback_pause = 0;
|
||||
a.repeat = 0;
|
||||
a.repeat_pause = 0;
|
||||
lv_anim_create(&a);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
224
bdk/libs/lvgl/lv_objx/lv_roller.h
Normal file
224
bdk/libs/lvgl/lv_objx/lv_roller.h
Normal file
|
@ -0,0 +1,224 @@
|
|||
/**
|
||||
* @file lv_roller.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_ROLLER_H
|
||||
#define LV_ROLLER_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_ROLLER != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_DDLIST == 0
|
||||
#error "lv_roller: lv_ddlist is required. Enable it in lv_conf.h (USE_LV_DDLIST 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_ddlist.h"
|
||||
#include "lv_label.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Data of roller*/
|
||||
typedef struct {
|
||||
lv_ddlist_ext_t ddlist; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
} lv_roller_ext_t;
|
||||
|
||||
enum {
|
||||
LV_ROLLER_STYLE_BG,
|
||||
LV_ROLLER_STYLE_SEL,
|
||||
};
|
||||
typedef uint8_t lv_roller_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a roller object
|
||||
* @param par pointer to an object, it will be the parent of the new roller
|
||||
* @param copy pointer to a roller object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created roller
|
||||
*/
|
||||
lv_obj_t * lv_roller_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the align of the roller's options (left, right or center[default])
|
||||
* @param roller - pointer to a roller object
|
||||
* @param align - one of lv_label_align_t values (left, right, center)
|
||||
*/
|
||||
void lv_roller_set_align(lv_obj_t * roller, lv_label_align_t align);
|
||||
|
||||
/**
|
||||
* Set the options on a roller
|
||||
* @param roller pointer to roller object
|
||||
* @param options a string with '\n' separated options. E.g. "One\nTwo\nThree"
|
||||
*/
|
||||
static inline void lv_roller_set_options(lv_obj_t * roller, const char * options)
|
||||
{
|
||||
lv_ddlist_set_options(roller, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the selected option
|
||||
* @param roller pointer to a roller object
|
||||
* @param sel_opt id of the selected option (0 ... number of option - 1);
|
||||
* @param anim_en true: set with animation; false set immediately
|
||||
*/
|
||||
void lv_roller_set_selected(lv_obj_t *roller, uint16_t sel_opt, bool anim_en);
|
||||
|
||||
/**
|
||||
* Set a function to call when a new option is chosen
|
||||
* @param roller pointer to a roller
|
||||
* @param action pointer to a callback function
|
||||
*/
|
||||
static inline void lv_roller_set_action(lv_obj_t * roller, lv_action_t action)
|
||||
{
|
||||
lv_ddlist_set_action(roller, action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the height to show the given number of rows (options)
|
||||
* @param roller pointer to a roller object
|
||||
* @param row_cnt number of desired visible rows
|
||||
*/
|
||||
void lv_roller_set_visible_row_count(lv_obj_t *roller, uint8_t row_cnt);
|
||||
|
||||
/**
|
||||
* Enable or disable the horizontal fit to the content
|
||||
* @param roller pointer to a roller
|
||||
* @param en true: enable auto fit; false: disable auto fit
|
||||
*/
|
||||
static inline void lv_roller_set_hor_fit(lv_obj_t * roller, bool en)
|
||||
{
|
||||
lv_ddlist_set_hor_fit(roller, en);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the open/close animation time.
|
||||
* @param roller pointer to a roller object
|
||||
* @param anim_time: open/close animation time [ms]
|
||||
*/
|
||||
static inline void lv_roller_set_anim_time(lv_obj_t *roller, uint16_t anim_time)
|
||||
{
|
||||
lv_ddlist_set_anim_time(roller, anim_time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a roller
|
||||
* @param roller pointer to a roller object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_roller_set_style(lv_obj_t *roller, lv_roller_style_t type, lv_style_t *style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the align attribute. Default alignment after _create is LV_LABEL_ALIGN_CENTER
|
||||
* @param roller pointer to a roller object
|
||||
* @return LV_LABEL_ALIGN_LEFT, LV_LABEL_ALIGN_RIGHT or LV_LABEL_ALIGN_CENTER
|
||||
*/
|
||||
lv_label_align_t lv_roller_get_align(const lv_obj_t * roller);
|
||||
|
||||
/**
|
||||
* Get the options of a roller
|
||||
* @param roller pointer to roller object
|
||||
* @return the options separated by '\n'-s (E.g. "Option1\nOption2\nOption3")
|
||||
*/
|
||||
static inline const char * lv_roller_get_options(const lv_obj_t *roller)
|
||||
{
|
||||
return lv_ddlist_get_options(roller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id of the selected option
|
||||
* @param roller pointer to a roller object
|
||||
* @return id of the selected option (0 ... number of option - 1);
|
||||
*/
|
||||
static inline uint16_t lv_roller_get_selected(const lv_obj_t *roller)
|
||||
{
|
||||
return lv_ddlist_get_selected(roller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current selected option as a string
|
||||
* @param roller pointer to roller object
|
||||
* @param buf pointer to an array to store the string
|
||||
*/
|
||||
static inline void lv_roller_get_selected_str(const lv_obj_t * roller, char * buf)
|
||||
{
|
||||
lv_ddlist_get_selected_str(roller, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "option selected" callback function
|
||||
* @param roller pointer to a roller
|
||||
* @return pointer to the call back function
|
||||
*/
|
||||
static inline lv_action_t lv_roller_get_action(const lv_obj_t * roller)
|
||||
{
|
||||
return lv_ddlist_get_action(roller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the open/close animation time.
|
||||
* @param roller pointer to a roller
|
||||
* @return open/close animation time [ms]
|
||||
*/
|
||||
static inline uint16_t lv_roller_get_anim_time(const lv_obj_t * roller)
|
||||
{
|
||||
return lv_ddlist_get_anim_time(roller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the auto width set attribute
|
||||
* @param roller pointer to a roller object
|
||||
* @return true: auto size enabled; false: manual width settings enabled
|
||||
*/
|
||||
bool lv_roller_get_hor_fit(const lv_obj_t *roller);
|
||||
|
||||
/**
|
||||
* Get a style of a roller
|
||||
* @param roller pointer to a roller object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
* */
|
||||
lv_style_t * lv_roller_get_style(const lv_obj_t *roller, lv_roller_style_t type);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_ROLLER*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_ROLLER_H*/
|
520
bdk/libs/lvgl/lv_objx/lv_slider.c
Normal file
520
bdk/libs/lvgl/lv_objx/lv_slider.c
Normal file
|
@ -0,0 +1,520 @@
|
|||
|
||||
/**
|
||||
* @file lv_slider.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_slider.h"
|
||||
#if USE_LV_SLIDER != 0
|
||||
|
||||
#include "../lv_core/lv_group.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_SLIDER_SIZE_MIN 4 /*hor. pad and ver. pad cannot make the bar or indicator smaller then this [px]*/
|
||||
#define LV_SLIDER_NOT_PRESSED INT16_MIN
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_slider_design(lv_obj_t * slider, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * param);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_design_func_t ancestor_design_f;
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a slider objects
|
||||
* @param par pointer to an object, it will be the parent of the new slider
|
||||
* @param copy pointer to a slider object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created slider
|
||||
*/
|
||||
lv_obj_t * lv_slider_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("slider create started");
|
||||
|
||||
/*Create the ancestor slider*/
|
||||
lv_obj_t * new_slider = lv_bar_create(par, copy);
|
||||
lv_mem_assert(new_slider);
|
||||
if(new_slider == NULL) return NULL;
|
||||
|
||||
if(ancestor_design_f == NULL) ancestor_design_f = lv_obj_get_design_func(new_slider);
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_slider);
|
||||
|
||||
/*Allocate the slider type specific extended data*/
|
||||
lv_slider_ext_t * ext = lv_obj_allocate_ext_attr(new_slider, sizeof(lv_slider_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->action = NULL;
|
||||
ext->drag_value = LV_SLIDER_NOT_PRESSED;
|
||||
ext->style_knob = &lv_style_pretty;
|
||||
ext->knob_in = 0;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_slider, lv_slider_signal);
|
||||
lv_obj_set_design_func(new_slider, lv_slider_design);
|
||||
|
||||
/*Init the new slider slider*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_click(new_slider, true);
|
||||
lv_obj_set_protect(new_slider, LV_PROTECT_PRESS_LOST);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_slider_set_style(new_slider, LV_SLIDER_STYLE_BG, th->slider.bg);
|
||||
lv_slider_set_style(new_slider, LV_SLIDER_STYLE_INDIC, th->slider.indic);
|
||||
lv_slider_set_style(new_slider, LV_SLIDER_STYLE_KNOB, th->slider.knob);
|
||||
} else {
|
||||
lv_slider_set_style(new_slider, LV_SLIDER_STYLE_KNOB, ext->style_knob);
|
||||
}
|
||||
}
|
||||
/*Copy an existing slider*/
|
||||
else {
|
||||
lv_slider_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->style_knob = copy_ext->style_knob;
|
||||
ext->action = copy_ext->action;
|
||||
ext->knob_in = copy_ext->knob_in;
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_slider);
|
||||
}
|
||||
|
||||
|
||||
LV_LOG_INFO("slider created");
|
||||
|
||||
|
||||
return new_slider;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a function which will be called when a new value is set on the slider
|
||||
* @param slider pointer to slider object
|
||||
* @param action a callback function
|
||||
*/
|
||||
void lv_slider_set_action(lv_obj_t * slider, lv_action_t action)
|
||||
{
|
||||
lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider);
|
||||
ext->action = action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'knob in' attribute of a slider
|
||||
* @param slider pointer to slider object
|
||||
* @param in true: the knob is drawn always in the slider;
|
||||
* false: the knob can be out on the edges
|
||||
*/
|
||||
void lv_slider_set_knob_in(lv_obj_t * slider, bool in)
|
||||
{
|
||||
lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider);
|
||||
if(ext->knob_in == in) return;
|
||||
|
||||
ext->knob_in = in == false ? 0 : 1;
|
||||
lv_obj_invalidate(slider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a slider
|
||||
* @param slider pointer to a slider object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_slider_set_style(lv_obj_t * slider, lv_slider_style_t type, lv_style_t * style)
|
||||
{
|
||||
lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider);
|
||||
|
||||
switch(type) {
|
||||
case LV_SLIDER_STYLE_BG:
|
||||
lv_bar_set_style(slider, LV_BAR_STYLE_BG, style);
|
||||
break;
|
||||
case LV_SLIDER_STYLE_INDIC:
|
||||
lv_bar_set_style(slider, LV_BAR_STYLE_INDIC, style);
|
||||
break;
|
||||
case LV_SLIDER_STYLE_KNOB:
|
||||
ext->style_knob = style;
|
||||
lv_obj_refresh_ext_size(slider);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the value of a slider
|
||||
* @param slider pointer to a slider object
|
||||
* @return the value of the slider
|
||||
*/
|
||||
int16_t lv_slider_get_value(const lv_obj_t * slider)
|
||||
{
|
||||
lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider);
|
||||
|
||||
if(ext->drag_value != LV_SLIDER_NOT_PRESSED) return ext->drag_value;
|
||||
else return lv_bar_get_value(slider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the slider action function
|
||||
* @param slider pointer to slider object
|
||||
* @return the callback function
|
||||
*/
|
||||
lv_action_t lv_slider_get_action(const lv_obj_t * slider)
|
||||
{
|
||||
lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider);
|
||||
return ext->action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give the slider is being dragged or not
|
||||
* @param slider pointer to a slider object
|
||||
* @return true: drag in progress false: not dragged
|
||||
*/
|
||||
bool lv_slider_is_dragged(const lv_obj_t * slider)
|
||||
{
|
||||
lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider);
|
||||
return ext->drag_value == LV_SLIDER_NOT_PRESSED ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the 'knob in' attribute of a slider
|
||||
* @param slider pointer to slider object
|
||||
* @return true: the knob is drawn always in the slider;
|
||||
* false: the knob can be out on the edges
|
||||
*/
|
||||
bool lv_slider_get_knob_in(const lv_obj_t * slider)
|
||||
{
|
||||
lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider);
|
||||
return ext->knob_in == 0 ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a slider
|
||||
* @param slider pointer to a slider object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_slider_get_style(const lv_obj_t * slider, lv_slider_style_t type)
|
||||
{
|
||||
lv_style_t * style = NULL;
|
||||
lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider);
|
||||
|
||||
switch(type) {
|
||||
case LV_SLIDER_STYLE_BG:
|
||||
style = lv_bar_get_style(slider, LV_BAR_STYLE_BG);
|
||||
break;
|
||||
case LV_SLIDER_STYLE_INDIC:
|
||||
style = lv_bar_get_style(slider, LV_BAR_STYLE_INDIC);
|
||||
break;
|
||||
case LV_SLIDER_STYLE_KNOB:
|
||||
style = ext->style_knob;
|
||||
break;
|
||||
default:
|
||||
style = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the sliders
|
||||
* @param slider pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_slider_design(lv_obj_t * slider, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return false;
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider);
|
||||
|
||||
lv_style_t * style_bg = lv_slider_get_style(slider, LV_SLIDER_STYLE_BG);
|
||||
lv_style_t * style_knob = lv_slider_get_style(slider, LV_SLIDER_STYLE_KNOB);
|
||||
lv_style_t * style_indic = lv_slider_get_style(slider, LV_SLIDER_STYLE_INDIC);
|
||||
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(slider);
|
||||
|
||||
lv_coord_t slider_w = lv_area_get_width(&slider->coords);
|
||||
lv_coord_t slider_h = lv_area_get_height(&slider->coords);
|
||||
|
||||
/*Draw the bar*/
|
||||
lv_area_t area_bg;
|
||||
lv_area_copy(&area_bg, &slider->coords);
|
||||
|
||||
/*Be sure at least LV_SLIDER_SIZE_MIN size will remain*/
|
||||
lv_coord_t pad_ver_bg = style_bg->body.padding.ver;
|
||||
lv_coord_t pad_hor_bg = style_bg->body.padding.hor;
|
||||
if(pad_ver_bg * 2 + LV_SLIDER_SIZE_MIN > lv_area_get_height(&area_bg)) {
|
||||
pad_ver_bg = (lv_area_get_height(&area_bg) - LV_SLIDER_SIZE_MIN) >> 1;
|
||||
}
|
||||
if(pad_hor_bg * 2 + LV_SLIDER_SIZE_MIN > lv_area_get_width(&area_bg)) {
|
||||
pad_hor_bg = (lv_area_get_width(&area_bg) - LV_SLIDER_SIZE_MIN) >> 1;
|
||||
}
|
||||
|
||||
if(ext->knob_in) { /*Enable extra size if the knob is inside */
|
||||
area_bg.x1 += pad_hor_bg;
|
||||
area_bg.x2 -= pad_hor_bg;
|
||||
area_bg.y1 += pad_hor_bg;
|
||||
area_bg.y2 -= pad_hor_bg;
|
||||
} else { /*Let space only in the perpendicular directions*/
|
||||
area_bg.x1 += slider_w < slider_h ? pad_hor_bg : 0; /*Pad only for vertical slider*/
|
||||
area_bg.x2 -= slider_w < slider_h ? pad_hor_bg : 0; /*Pad only for vertical slider*/
|
||||
area_bg.y1 += slider_w > slider_h ? pad_ver_bg : 0; /*Pad only for horizontal slider*/
|
||||
area_bg.y2 -= slider_w > slider_h ? pad_ver_bg : 0; /*Pad only for horizontal slider*/
|
||||
}
|
||||
|
||||
|
||||
#if USE_LV_GROUP == 0
|
||||
lv_draw_rect(&area_bg, mask, style_bg, lv_obj_get_opa_scale(slider));
|
||||
#else
|
||||
/* Draw the borders later if the bar is focused.
|
||||
* At value = 100% the indicator can cover to whole background and the focused style won't be visible*/
|
||||
if(lv_obj_is_focused(slider)) {
|
||||
lv_style_t style_tmp;
|
||||
lv_style_copy(&style_tmp, style_bg);
|
||||
style_tmp.body.border.width = 0;
|
||||
lv_draw_rect(&area_bg, mask, &style_tmp, opa_scale);
|
||||
} else {
|
||||
lv_draw_rect(&area_bg, mask, style_bg, opa_scale);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*Draw the indicator*/
|
||||
lv_area_t area_indic;
|
||||
lv_area_copy(&area_indic, &area_bg);
|
||||
|
||||
/*Be sure at least ver pad/hor pad width indicator will remain*/
|
||||
lv_coord_t pad_ver_indic = style_indic->body.padding.ver;
|
||||
lv_coord_t pad_hor_indic = style_indic->body.padding.hor;
|
||||
if(pad_ver_indic * 2 + LV_SLIDER_SIZE_MIN > lv_area_get_height(&area_bg)) {
|
||||
pad_ver_indic = (lv_area_get_height(&area_bg) - LV_SLIDER_SIZE_MIN) >> 1;
|
||||
}
|
||||
if(pad_hor_indic * 2 + LV_SLIDER_SIZE_MIN > lv_area_get_width(&area_bg)) {
|
||||
pad_hor_indic = (lv_area_get_width(&area_bg) - LV_SLIDER_SIZE_MIN) >> 1;
|
||||
}
|
||||
|
||||
area_indic.x1 += pad_hor_indic;
|
||||
area_indic.x2 -= pad_hor_indic;
|
||||
area_indic.y1 += pad_ver_indic;
|
||||
area_indic.y2 -= pad_ver_indic;
|
||||
|
||||
|
||||
lv_coord_t cur_value = lv_slider_get_value(slider);
|
||||
lv_coord_t min_value = lv_slider_get_min_value(slider);
|
||||
lv_coord_t max_value = lv_slider_get_max_value(slider);
|
||||
|
||||
/*If dragged draw to the drag position*/
|
||||
if(ext->drag_value != LV_SLIDER_NOT_PRESSED) cur_value = ext->drag_value;
|
||||
|
||||
if(slider_w >= slider_h) {
|
||||
area_indic.x2 = (int32_t)((int32_t)(lv_area_get_width(&area_indic)) * (cur_value - min_value)) / (max_value - min_value);
|
||||
area_indic.x2 = area_indic.x1 + area_indic.x2 - 1;
|
||||
|
||||
} else {
|
||||
area_indic.y1 = (int32_t)((int32_t)(lv_area_get_height(&area_indic)) * (cur_value - min_value)) / (max_value - min_value);
|
||||
area_indic.y1 = area_indic.y2 - area_indic.y1 + 1;
|
||||
}
|
||||
|
||||
if(cur_value != min_value) lv_draw_rect(&area_indic, mask, style_indic, opa_scale);
|
||||
|
||||
/*Before the knob add the border if required*/
|
||||
#if USE_LV_GROUP
|
||||
/* Draw the borders later if the bar is focused.
|
||||
* At value = 100% the indicator can cover to whole background and the focused style won't be visible*/
|
||||
if(lv_obj_is_focused(slider)) {
|
||||
lv_style_t style_tmp;
|
||||
lv_style_copy(&style_tmp, style_bg);
|
||||
style_tmp.body.empty = 1;
|
||||
style_tmp.body.shadow.width = 0;
|
||||
lv_draw_rect(&area_bg, mask, &style_tmp, opa_scale);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*Draw the knob*/
|
||||
lv_area_t knob_area;
|
||||
lv_area_copy(&knob_area, &slider->coords);
|
||||
|
||||
if(slider_w >= slider_h) {
|
||||
if(ext->knob_in == 0) {
|
||||
knob_area.x1 = area_indic.x2 - slider_h / 2;
|
||||
knob_area.x2 = knob_area.x1 + slider_h - 1;
|
||||
} else {
|
||||
knob_area.x1 = (int32_t)((int32_t)(slider_w - slider_h - 1) * (cur_value - min_value)) / (max_value - min_value);
|
||||
knob_area.x1 += slider->coords.x1;
|
||||
knob_area.x2 = knob_area.x1 + slider_h - 1;
|
||||
}
|
||||
|
||||
knob_area.y1 = slider->coords.y1;
|
||||
knob_area.y2 = slider->coords.y2;
|
||||
} else {
|
||||
if(ext->knob_in == 0) {
|
||||
knob_area.y1 = area_indic.y1 - slider_w / 2;
|
||||
knob_area.y2 = knob_area.y1 + slider_w - 1;
|
||||
} else {
|
||||
knob_area.y2 = (int32_t)((int32_t)(slider_h - slider_w - 1) * (cur_value - min_value)) / (max_value - min_value);
|
||||
knob_area.y2 = slider->coords.y2 - knob_area.y2;
|
||||
knob_area.y1 = knob_area.y2 - slider_w - 1;
|
||||
}
|
||||
knob_area.x1 = slider->coords.x1;
|
||||
knob_area.x2 = slider->coords.x2;
|
||||
|
||||
}
|
||||
lv_draw_rect(&knob_area, mask, style_knob, opa_scale);
|
||||
}
|
||||
/*Post draw when the children are drawn*/
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the slider
|
||||
* @param slider pointer to a slider object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(slider, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider);
|
||||
lv_point_t p;
|
||||
lv_coord_t w = lv_obj_get_width(slider);
|
||||
lv_coord_t h = lv_obj_get_height(slider);
|
||||
|
||||
if(sign == LV_SIGNAL_PRESSED) {
|
||||
ext->drag_value = lv_slider_get_value(slider);
|
||||
} else if(sign == LV_SIGNAL_PRESSING) {
|
||||
lv_indev_get_point(param, &p);
|
||||
int16_t tmp = 0;
|
||||
if(w > h) {
|
||||
lv_coord_t knob_w = h;
|
||||
p.x -= slider->coords.x1 + h / 2; /*Modify the point to shift with half knob (important on the start and end)*/
|
||||
tmp = (int32_t)((int32_t) p.x * (ext->bar.max_value - ext->bar.min_value + 1)) / (w - knob_w);
|
||||
tmp += ext->bar.min_value;
|
||||
} else {
|
||||
lv_coord_t knob_h = w;
|
||||
p.y -= slider->coords.y1 + w / 2; /*Modify the point to shift with half knob (important on the start and end)*/
|
||||
tmp = (int32_t)((int32_t) p.y * (ext->bar.max_value - ext->bar.min_value + 1)) / (h - knob_h);
|
||||
tmp = ext->bar.max_value - tmp; /*Invert the value: smaller value means higher y*/
|
||||
}
|
||||
|
||||
if(tmp < ext->bar.min_value) tmp = ext->bar.min_value;
|
||||
else if(tmp > ext->bar.max_value) tmp = ext->bar.max_value;
|
||||
|
||||
if(tmp != ext->drag_value) {
|
||||
ext->drag_value = tmp;
|
||||
lv_obj_invalidate(slider);
|
||||
if(ext->action != NULL) res = ext->action(slider);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) {
|
||||
lv_slider_set_value(slider, ext->drag_value);
|
||||
ext->drag_value = LV_SLIDER_NOT_PRESSED;
|
||||
if(ext->action != NULL) res = ext->action(slider);
|
||||
} else if(sign == LV_SIGNAL_CORD_CHG) {
|
||||
/* The knob size depends on slider size.
|
||||
* During the drawing method the ext. size is used by the knob so refresh the ext. size.*/
|
||||
if(lv_obj_get_width(slider) != lv_area_get_width(param) ||
|
||||
lv_obj_get_height(slider) != lv_area_get_height(param)) {
|
||||
slider->signal_func(slider, LV_SIGNAL_REFR_EXT_SIZE, NULL);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_REFR_EXT_SIZE) {
|
||||
lv_style_t * style = lv_slider_get_style(slider, LV_SLIDER_STYLE_BG);
|
||||
lv_style_t * knob_style = lv_slider_get_style(slider, LV_SLIDER_STYLE_KNOB);
|
||||
lv_coord_t shadow_w = knob_style->body.shadow.width;
|
||||
if(ext->knob_in == 0) {
|
||||
/* The smaller size is the knob diameter*/
|
||||
lv_coord_t x = LV_MATH_MIN(w / 2 + 1 + shadow_w, h / 2 + 1 + shadow_w);
|
||||
if(slider->ext_size < x) slider->ext_size = x;
|
||||
} else {
|
||||
lv_coord_t pad = LV_MATH_MIN(style->body.padding.hor, style->body.padding.ver);
|
||||
if(pad < 0) pad = -pad;
|
||||
if(slider->ext_size < pad) slider->ext_size = pad;
|
||||
|
||||
if(slider->ext_size < shadow_w) slider->ext_size = shadow_w;
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_CONTROLL) {
|
||||
char c = *((char *)param);
|
||||
|
||||
ext->drag_value = LV_SLIDER_NOT_PRESSED;
|
||||
|
||||
#if USE_LV_GROUP
|
||||
lv_group_t * g = lv_obj_get_group(slider);
|
||||
bool editing = lv_group_get_editing(g);
|
||||
lv_hal_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act());
|
||||
/*Encoders need special handling*/
|
||||
if(indev_type == LV_INDEV_TYPE_ENCODER && c == LV_GROUP_KEY_ENTER) {
|
||||
if(editing) lv_group_set_editing(g, false);
|
||||
}
|
||||
#endif
|
||||
if(c == LV_GROUP_KEY_RIGHT || c == LV_GROUP_KEY_UP) {
|
||||
lv_slider_set_value(slider, lv_slider_get_value(slider) + 1);
|
||||
if(ext->action != NULL) res = ext->action(slider);
|
||||
} else if(c == LV_GROUP_KEY_LEFT || c == LV_GROUP_KEY_DOWN) {
|
||||
lv_slider_set_value(slider, lv_slider_get_value(slider) - 1);
|
||||
if(ext->action != NULL) res = ext->action(slider);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_EDITABLE) {
|
||||
bool * editable = (bool *)param;
|
||||
*editable = true;
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_slider";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
202
bdk/libs/lvgl/lv_objx/lv_slider.h
Normal file
202
bdk/libs/lvgl/lv_objx/lv_slider.h
Normal file
|
@ -0,0 +1,202 @@
|
|||
/**
|
||||
* @file lv_slider.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SLIDER_H
|
||||
#define LV_SLIDER_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_SLIDER != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_BAR == 0
|
||||
#error "lv_slider: lv_bar is required. Enable it in lv_conf.h (USE_LV_BAR 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_bar.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Data of slider*/
|
||||
typedef struct
|
||||
{
|
||||
lv_bar_ext_t bar; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_action_t action; /*Function to call when a new value is set*/
|
||||
lv_style_t *style_knob; /*Style of the knob*/
|
||||
int16_t drag_value; /*Store a temporal value during press until release (Handled by the library)*/
|
||||
uint8_t knob_in :1; /*1: Draw the knob inside the bar*/
|
||||
} lv_slider_ext_t;
|
||||
|
||||
/*Built-in styles of slider*/
|
||||
enum
|
||||
{
|
||||
LV_SLIDER_STYLE_BG,
|
||||
LV_SLIDER_STYLE_INDIC,
|
||||
LV_SLIDER_STYLE_KNOB,
|
||||
};
|
||||
typedef uint8_t lv_slider_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a slider objects
|
||||
* @param par pointer to an object, it will be the parent of the new slider
|
||||
* @param copy pointer to a slider object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created slider
|
||||
*/
|
||||
lv_obj_t * lv_slider_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new value on the slider
|
||||
* @param slider pointer to a slider object
|
||||
* @param value new value
|
||||
*/
|
||||
static inline void lv_slider_set_value(lv_obj_t * slider, int16_t value)
|
||||
{
|
||||
lv_bar_set_value(slider, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new value with animation on a slider
|
||||
* @param slider pointer to a slider object
|
||||
* @param value new value
|
||||
* @param anim_time animation time in milliseconds
|
||||
*/
|
||||
static inline void lv_slider_set_value_anim(lv_obj_t * slider, int16_t value, uint16_t anim_time)
|
||||
{
|
||||
lv_bar_set_value_anim(slider, value, anim_time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set minimum and the maximum values of a bar
|
||||
* @param slider pointer to the slider object
|
||||
* @param min minimum value
|
||||
* @param max maximum value
|
||||
*/
|
||||
static inline void lv_slider_set_range(lv_obj_t *slider, int16_t min, int16_t max)
|
||||
{
|
||||
lv_bar_set_range(slider, min, max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a function which will be called when a new value is set on the slider
|
||||
* @param slider pointer to slider object
|
||||
* @param action a callback function
|
||||
*/
|
||||
void lv_slider_set_action(lv_obj_t * slider, lv_action_t action);
|
||||
|
||||
/**
|
||||
* Set the 'knob in' attribute of a slider
|
||||
* @param slider pointer to slider object
|
||||
* @param in true: the knob is drawn always in the slider;
|
||||
* false: the knob can be out on the edges
|
||||
*/
|
||||
void lv_slider_set_knob_in(lv_obj_t * slider, bool in);
|
||||
|
||||
/**
|
||||
* Set a style of a slider
|
||||
* @param slider pointer to a slider object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_slider_set_style(lv_obj_t *slider, lv_slider_style_t type, lv_style_t *style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the value of a slider
|
||||
* @param slider pointer to a slider object
|
||||
* @return the value of the slider
|
||||
*/
|
||||
int16_t lv_slider_get_value(const lv_obj_t * slider);
|
||||
|
||||
/**
|
||||
* Get the minimum value of a slider
|
||||
* @param slider pointer to a slider object
|
||||
* @return the minimum value of the slider
|
||||
*/
|
||||
static inline int16_t lv_slider_get_min_value(const lv_obj_t * slider)
|
||||
{
|
||||
return lv_bar_get_min_value(slider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum value of a slider
|
||||
* @param slider pointer to a slider object
|
||||
* @return the maximum value of the slider
|
||||
*/
|
||||
static inline int16_t lv_slider_get_max_value(const lv_obj_t * slider)
|
||||
{
|
||||
return lv_bar_get_max_value(slider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the slider action function
|
||||
* @param slider pointer to slider object
|
||||
* @return the callback function
|
||||
*/
|
||||
lv_action_t lv_slider_get_action(const lv_obj_t * slider);
|
||||
|
||||
/**
|
||||
* Give the slider is being dragged or not
|
||||
* @param slider pointer to a slider object
|
||||
* @return true: drag in progress false: not dragged
|
||||
*/
|
||||
bool lv_slider_is_dragged(const lv_obj_t * slider);
|
||||
|
||||
/**
|
||||
* Get the 'knob in' attribute of a slider
|
||||
* @param slider pointer to slider object
|
||||
* @return true: the knob is drawn always in the slider;
|
||||
* false: the knob can be out on the edges
|
||||
*/
|
||||
bool lv_slider_get_knob_in(const lv_obj_t * slider);
|
||||
|
||||
|
||||
/**
|
||||
* Get a style of a slider
|
||||
* @param slider pointer to a slider object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_slider_get_style(const lv_obj_t *slider, lv_slider_style_t type);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_SLIDER*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_SLIDER_H*/
|
471
bdk/libs/lvgl/lv_objx/lv_spinbox.c
Normal file
471
bdk/libs/lvgl/lv_objx/lv_spinbox.c
Normal file
|
@ -0,0 +1,471 @@
|
|||
/**
|
||||
* @file lv_spinbox.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_spinbox.h"
|
||||
|
||||
#if USE_LV_SPINBOX != 0
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_spinbox_signal(lv_obj_t * spinbox, lv_signal_t sign, void * param);
|
||||
static void lv_spinbox_updatevalue(lv_obj_t * spinbox);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
static lv_design_func_t ancestor_design;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a spinbox object
|
||||
* @param par pointer to an object, it will be the parent of the new spinbox
|
||||
* @param copy pointer to a spinbox object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created spinbox
|
||||
*/
|
||||
lv_obj_t * lv_spinbox_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("spinbox create started");
|
||||
|
||||
/*Create the ancestor of spinbox*/
|
||||
lv_obj_t * new_spinbox = lv_ta_create(par, copy);
|
||||
lv_mem_assert(new_spinbox);
|
||||
if(new_spinbox == NULL) return NULL;
|
||||
|
||||
/*Allocate the spinbox type specific extended data*/
|
||||
lv_spinbox_ext_t * ext = lv_obj_allocate_ext_attr(new_spinbox, sizeof(lv_spinbox_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_spinbox);
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_spinbox);
|
||||
|
||||
/*Initialize the allocated 'ext'*/
|
||||
ext->ta.one_line = 1;
|
||||
ext->ta.pwd_mode = 0;
|
||||
ext->ta.accapted_chars = "1234567890+-. ";
|
||||
|
||||
ext->value = 0;
|
||||
ext->dec_point_pos = 0;
|
||||
ext->digit_count = 5;
|
||||
ext->digit_padding_left = 0;
|
||||
ext->step = 1;
|
||||
ext->range_max = 99999;
|
||||
ext->range_min = -99999;
|
||||
ext->value_changed_cb = NULL;
|
||||
|
||||
lv_ta_set_cursor_type(new_spinbox, LV_CURSOR_BLOCK | LV_CURSOR_HIDDEN); /*hidden by default*/
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_spinbox, lv_spinbox_signal);
|
||||
lv_obj_set_design_func(new_spinbox, ancestor_design); /*Leave the Text area's design function*/
|
||||
|
||||
/*Init the new spinbox spinbox*/
|
||||
if(copy == NULL) {
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_spinbox_set_style(new_spinbox, LV_SPINBOX_STYLE_BG, th->spinbox.bg);
|
||||
lv_spinbox_set_style(new_spinbox, LV_SPINBOX_STYLE_CURSOR, th->spinbox.cursor);
|
||||
lv_spinbox_set_style(new_spinbox, LV_SPINBOX_STYLE_SB, th->spinbox.sb);
|
||||
}
|
||||
}
|
||||
/*Copy an existing spinbox*/
|
||||
else {
|
||||
lv_spinbox_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
|
||||
lv_spinbox_set_value(new_spinbox, copy_ext->value);
|
||||
lv_spinbox_set_digit_format(new_spinbox, copy_ext->digit_count, copy_ext->dec_point_pos);
|
||||
lv_spinbox_set_range(new_spinbox, copy_ext->range_min, copy_ext->range_max);
|
||||
lv_spinbox_set_step(new_spinbox, copy_ext->step);
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_spinbox);
|
||||
}
|
||||
|
||||
lv_spinbox_updatevalue(new_spinbox);
|
||||
|
||||
LV_LOG_INFO("spinbox created");
|
||||
|
||||
return new_spinbox;
|
||||
}
|
||||
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set spinbox value
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param i value to be set
|
||||
*/
|
||||
void lv_spinbox_set_value(lv_obj_t * spinbox, int32_t i)
|
||||
{
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
if(ext == NULL)
|
||||
return;
|
||||
|
||||
if(i > ext->range_max)
|
||||
i = ext->range_max;
|
||||
if(i < ext->range_min)
|
||||
i = ext->range_min;
|
||||
|
||||
ext->value = i;
|
||||
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set spinbox digit format (digit count and decimal format)
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param digit_count number of digit excluding the decimal separator and the sign
|
||||
* @param separator_position number of digit before the decimal point. If 0, decimal point is not shown
|
||||
*/
|
||||
void lv_spinbox_set_digit_format(lv_obj_t * spinbox, uint8_t digit_count, uint8_t separator_position)
|
||||
{
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
if(ext == NULL)
|
||||
return;
|
||||
|
||||
if(digit_count > LV_SPINBOX_MAX_DIGIT_COUNT)
|
||||
digit_count = LV_SPINBOX_MAX_DIGIT_COUNT;
|
||||
|
||||
if(separator_position > LV_SPINBOX_MAX_DIGIT_COUNT)
|
||||
separator_position = LV_SPINBOX_MAX_DIGIT_COUNT;
|
||||
|
||||
ext->digit_count = digit_count;
|
||||
ext->dec_point_pos = separator_position;
|
||||
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set spinbox step
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param step steps on increment/decrement
|
||||
*/
|
||||
void lv_spinbox_set_step(lv_obj_t * spinbox, uint32_t step)
|
||||
{
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
if(ext == NULL) return;
|
||||
|
||||
ext->step = step;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set spinbox value range
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param range_min maximum value, inclusive
|
||||
* @param range_max minimum value, inclusive
|
||||
*/
|
||||
void lv_spinbox_set_range(lv_obj_t * spinbox, int32_t range_min, int32_t range_max)
|
||||
{
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
if(ext == NULL) return;
|
||||
|
||||
ext->range_max = range_max;
|
||||
ext->range_min = range_min;
|
||||
|
||||
if(ext->value > ext->range_max) {
|
||||
ext->value = ext->range_max;
|
||||
lv_obj_invalidate(spinbox);
|
||||
}
|
||||
if(ext->value < ext->range_min) {
|
||||
ext->value = ext->range_min;
|
||||
lv_obj_invalidate(spinbox);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set spinbox callback on calue change
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param cb Callback function called on value change event
|
||||
*/
|
||||
void lv_spinbox_set_value_changed_cb(lv_obj_t * spinbox, lv_spinbox_value_changed_cb_t cb)
|
||||
{
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
ext->value_changed_cb = cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set spinbox left padding in digits count (added between sign and first digit)
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param cb Callback function called on value change event
|
||||
*/
|
||||
void lv_spinbox_set_padding_left(lv_obj_t * spinbox, uint8_t padding)
|
||||
{
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
ext->digit_padding_left = padding;
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the spinbox numeral value (user has to convert to float according to its digit format)
|
||||
* @param spinbox pointer to spinbox
|
||||
* @return value integer value of the spinbox
|
||||
*/
|
||||
int32_t lv_spinbox_get_value(lv_obj_t * spinbox)
|
||||
{
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
|
||||
return ext->value;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Select next lower digit for edition by dividing the step by 10
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_step_next(lv_obj_t * spinbox)
|
||||
{
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
|
||||
int32_t new_step = ext->step / 10;
|
||||
if((new_step) > 0) ext->step = new_step;
|
||||
else ext->step = 1;
|
||||
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select next higher digit for edition by multiplying the step by 10
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_step_previous(lv_obj_t * spinbox)
|
||||
{
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
int32_t step_limit;
|
||||
step_limit = LV_MATH_MAX(ext->range_max, (ext->range_min < 0 ? (-ext->range_min) : ext->range_min));
|
||||
int32_t new_step = ext->step * 10;
|
||||
if(new_step <= step_limit) ext->step = new_step;
|
||||
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment spinbox value by one step
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_increment(lv_obj_t * spinbox)
|
||||
{
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
|
||||
if(ext->value + ext->step <= ext->range_max) {
|
||||
/*Special mode when zero crossing*/
|
||||
if((ext->value + ext->step) > 0 && ext->value < 0) ext->value = -ext->value;
|
||||
ext->value += ext->step;
|
||||
|
||||
} else {
|
||||
ext->value = ext->range_max;
|
||||
}
|
||||
|
||||
if(ext->value_changed_cb != NULL) ext->value_changed_cb(spinbox, ext->value);
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement spinbox value by one step
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_decrement(lv_obj_t * spinbox)
|
||||
{
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
|
||||
if(ext->value - ext->step >= ext->range_min) {
|
||||
/*Special mode when zero crossing*/
|
||||
if((ext->value - ext->step) < 0 && ext->value > 0) ext->value = -ext->value;
|
||||
ext->value -= ext->step;
|
||||
} else {
|
||||
ext->value = ext->range_min;
|
||||
}
|
||||
|
||||
if(ext->value_changed_cb != NULL) ext->value_changed_cb(spinbox, ext->value);
|
||||
lv_spinbox_updatevalue(spinbox);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the spinbox
|
||||
* @param spinbox pointer to a spinbox object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_spinbox_signal(lv_obj_t * spinbox, lv_signal_t sign, void * param)
|
||||
{
|
||||
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
|
||||
lv_res_t res = LV_RES_OK;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
if(sign != LV_SIGNAL_CONTROLL)
|
||||
{
|
||||
res = ancestor_signal(spinbox, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE)
|
||||
{
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++)
|
||||
{ /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_spinbox";
|
||||
}
|
||||
else if(sign == LV_SIGNAL_CONTROLL) {
|
||||
lv_hal_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act());
|
||||
|
||||
uint32_t c = *((uint32_t *)param); /*uint32_t because can be UTF-8*/
|
||||
if(c == LV_GROUP_KEY_RIGHT) {
|
||||
if(indev_type == LV_INDEV_TYPE_ENCODER) lv_spinbox_increment(spinbox);
|
||||
else lv_spinbox_step_next(spinbox);
|
||||
}
|
||||
else if(c == LV_GROUP_KEY_LEFT) {
|
||||
if(indev_type == LV_INDEV_TYPE_ENCODER) lv_spinbox_decrement(spinbox);
|
||||
else lv_spinbox_step_previous(spinbox);
|
||||
}
|
||||
else if(c == LV_GROUP_KEY_UP) {
|
||||
lv_spinbox_increment(spinbox);
|
||||
}
|
||||
else if(c == LV_GROUP_KEY_DOWN) {
|
||||
lv_spinbox_decrement(spinbox);
|
||||
}
|
||||
else if(c == LV_GROUP_KEY_ENTER) {
|
||||
|
||||
if(ext->step > 1) {
|
||||
lv_spinbox_step_next(spinbox);
|
||||
} else {
|
||||
/*Restart from the MSB*/
|
||||
ext->step = 1;
|
||||
uint32_t i;
|
||||
for(i = 0; i < ext->digit_count; i++) {
|
||||
int32_t new_step = ext->step * 10;
|
||||
if(new_step >= ext->range_max) break;
|
||||
ext->step = new_step;
|
||||
}
|
||||
lv_spinbox_step_previous(spinbox);
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_ta_add_char(spinbox, c);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void lv_spinbox_updatevalue(lv_obj_t * spinbox)
|
||||
{
|
||||
lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);
|
||||
|
||||
char buf[LV_SPINBOX_MAX_DIGIT_COUNT + 8];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
char * buf_p = buf;
|
||||
|
||||
/*Add the sign*/
|
||||
(*buf_p) = ext->value >= 0 ? '+' : '-';
|
||||
buf_p++;
|
||||
|
||||
int i;
|
||||
/*padding left*/
|
||||
for(i = 0; i < ext->digit_padding_left; i++) {
|
||||
(*buf_p) = ' ';
|
||||
buf_p++;
|
||||
}
|
||||
|
||||
char digits[64];
|
||||
/*Convert the numbers to string (the sign is already handled so always covert positive number)*/
|
||||
lv_math_num_to_str(ext->value < 0 ? -ext->value : ext->value, digits);
|
||||
|
||||
/*Add leading zeros*/
|
||||
int lz_cnt = ext->digit_count - (int)strlen(digits);
|
||||
if(lz_cnt > 0) {
|
||||
for(i = strlen(digits); i >= 0; i--) {
|
||||
digits[i + lz_cnt] = digits[i];
|
||||
}
|
||||
for(i = 0; i < lz_cnt; i++) {
|
||||
digits[i] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
int32_t intDigits;
|
||||
intDigits = (ext->dec_point_pos == 0) ? ext->digit_count : ext->dec_point_pos;
|
||||
|
||||
/*Add the decimal part*/
|
||||
for(i = 0; i < intDigits && digits[i] != '\0'; i++) {
|
||||
(*buf_p) = digits[i];
|
||||
buf_p++;
|
||||
}
|
||||
|
||||
if(ext->dec_point_pos != 0) {
|
||||
/*Insert the decimal point*/
|
||||
(*buf_p) = '.';
|
||||
buf_p++;
|
||||
|
||||
for(/*Leave i*/ ;i < ext->digit_count && digits[i] != '\0'; i++) {
|
||||
(*buf_p) = digits[i];
|
||||
buf_p++;
|
||||
}
|
||||
}
|
||||
|
||||
/*Refresh the text*/
|
||||
lv_ta_set_text(spinbox, (char*)buf);
|
||||
|
||||
|
||||
/*Set the cursor position*/
|
||||
int32_t step = ext->step;
|
||||
uint8_t cur_pos = ext->digit_count;
|
||||
while(step >= 10)
|
||||
{
|
||||
step /= 10;
|
||||
cur_pos--;
|
||||
}
|
||||
|
||||
if(cur_pos > intDigits ) cur_pos ++; /*Skip teh decimal point*/
|
||||
|
||||
cur_pos += ext->digit_padding_left;
|
||||
|
||||
lv_ta_set_cursor_pos(spinbox, cur_pos);
|
||||
}
|
||||
|
||||
#endif
|
201
bdk/libs/lvgl/lv_objx/lv_spinbox.h
Normal file
201
bdk/libs/lvgl/lv_objx/lv_spinbox.h
Normal file
|
@ -0,0 +1,201 @@
|
|||
/**
|
||||
* @file lv_spinbox.h
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_SPINBOX_H
|
||||
#define LV_SPINBOX_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_SPINBOX != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_TA == 0
|
||||
#error "lv_spinbox: lv_ta is required. Enable it in lv_conf.h (USE_LV_TA 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_objx/lv_ta.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_SPINBOX_MAX_DIGIT_COUNT 16
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*callback on value change*/
|
||||
typedef void (*lv_spinbox_value_changed_cb_t)(lv_obj_t * spinbox, int32_t new_value);
|
||||
|
||||
/*Data of spinbox*/
|
||||
typedef struct {
|
||||
lv_ta_ext_t ta; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
int32_t value;
|
||||
int32_t range_max;
|
||||
int32_t range_min;
|
||||
int32_t step;
|
||||
uint16_t digit_count:4;
|
||||
uint16_t dec_point_pos:4; /*if 0, there is no separator and the number is an integer*/
|
||||
uint16_t digit_padding_left:4;
|
||||
lv_spinbox_value_changed_cb_t value_changed_cb;
|
||||
} lv_spinbox_ext_t;
|
||||
|
||||
|
||||
/*Styles*/
|
||||
enum {
|
||||
LV_SPINBOX_STYLE_BG,
|
||||
LV_SPINBOX_STYLE_SB,
|
||||
LV_SPINBOX_STYLE_CURSOR,
|
||||
};
|
||||
typedef uint8_t lv_spinbox_style_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a spinbox objects
|
||||
* @param par pointer to an object, it will be the parent of the new spinbox
|
||||
* @param copy pointer to a spinbox object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created spinbox
|
||||
*/
|
||||
lv_obj_t * lv_spinbox_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a style of a spinbox.
|
||||
* @param templ pointer to template object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
static inline void lv_spinbox_set_style(lv_obj_t * spinbox, lv_spinbox_style_t type, lv_style_t *style)
|
||||
{
|
||||
lv_ta_set_style(spinbox, type, style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set spinbox value
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param i value to be set
|
||||
*/
|
||||
void lv_spinbox_set_value(lv_obj_t * spinbox, int32_t i);
|
||||
|
||||
/**
|
||||
* Set spinbox digit format (digit count and decimal format)
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param digit_count number of digit excluding the decimal separator and the sign
|
||||
* @param separator_position number of digit before the decimal point. If 0, decimal point is not shown
|
||||
*/
|
||||
void lv_spinbox_set_digit_format(lv_obj_t * spinbox, uint8_t digit_count, uint8_t separator_position);
|
||||
|
||||
/**
|
||||
* Set spinbox step
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param step steps on increment/decrement
|
||||
*/
|
||||
void lv_spinbox_set_step(lv_obj_t * spinbox, uint32_t step);
|
||||
|
||||
/**
|
||||
* Set spinbox value range
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param range_min maximum value, inclusive
|
||||
* @param range_max minimum value, inclusive
|
||||
*/
|
||||
void lv_spinbox_set_range(lv_obj_t * spinbox, int32_t range_min, int32_t range_max);
|
||||
|
||||
/**
|
||||
* Set spinbox callback on calue change
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param cb Callback function called on value change event
|
||||
*/
|
||||
void lv_spinbox_set_value_changed_cb(lv_obj_t * spinbox, lv_spinbox_value_changed_cb_t cb);
|
||||
|
||||
/**
|
||||
* Set spinbox left padding in digits count (added between sign and first digit)
|
||||
* @param spinbox pointer to spinbox
|
||||
* @param cb Callback function called on value change event
|
||||
*/
|
||||
void lv_spinbox_set_padding_left(lv_obj_t * spinbox, uint8_t padding);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get style of a spinbox.
|
||||
* @param templ pointer to template object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
*/
|
||||
static inline lv_style_t * lv_spinbox_get_style(lv_obj_t * spinbox, lv_spinbox_style_t type)
|
||||
{
|
||||
return lv_ta_get_style(spinbox, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the spinbox numeral value (user has to convert to float according to its digit format)
|
||||
* @param spinbox pointer to spinbox
|
||||
* @return value integer value of the spinbox
|
||||
*/
|
||||
int32_t lv_spinbox_get_value(lv_obj_t * spinbox);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Select next lower digit for edition by dividing the step by 10
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_step_next(lv_obj_t * spinbox);
|
||||
|
||||
/**
|
||||
* Select next higher digit for edition by multiplying the step by 10
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_step_previous(lv_obj_t * spinbox);
|
||||
|
||||
/**
|
||||
* Increment spinbox value by one step
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_increment(lv_obj_t * spinbox);
|
||||
|
||||
/**
|
||||
* Decrement spinbox value by one step
|
||||
* @param spinbox pointer to spinbox
|
||||
*/
|
||||
void lv_spinbox_decrement(lv_obj_t * spinbox);
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_SPINBOX*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_SPINBOX_H*/
|
445
bdk/libs/lvgl/lv_objx/lv_sw.c
Normal file
445
bdk/libs/lvgl/lv_objx/lv_sw.c
Normal file
|
@ -0,0 +1,445 @@
|
|||
/**
|
||||
* @file lv_sw.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_sw.h"
|
||||
|
||||
#if USE_LV_SW != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_SLIDER == 0
|
||||
#error "lv_sw: lv_slider is required. Enable it in lv_conf.h (USE_LV_SLIDER 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param);
|
||||
static void lv_sw_anim_to_value(lv_obj_t * sw, int16_t value);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a switch objects
|
||||
* @param par pointer to an object, it will be the parent of the new switch
|
||||
* @param copy pointer to a switch object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created switch
|
||||
*/
|
||||
lv_obj_t * lv_sw_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("switch create started");
|
||||
|
||||
/*Create the ancestor of switch*/
|
||||
lv_obj_t * new_sw = lv_slider_create(par, copy);
|
||||
lv_mem_assert(new_sw);
|
||||
if(new_sw == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_sw);
|
||||
|
||||
/*Allocate the switch type specific extended data*/
|
||||
lv_sw_ext_t * ext = lv_obj_allocate_ext_attr(new_sw, sizeof(lv_sw_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->changed = 0;
|
||||
#if USE_LV_ANIMATION
|
||||
ext->anim_time = 0;
|
||||
#endif
|
||||
ext->style_knob_off = ext->slider.style_knob;
|
||||
ext->style_knob_on = ext->slider.style_knob;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_sw, lv_sw_signal);
|
||||
|
||||
/*Init the new switch switch*/
|
||||
if(copy == NULL) {
|
||||
lv_slider_set_range(new_sw, 0, 1);
|
||||
lv_obj_set_size(new_sw, 2 * LV_DPI / 3, LV_DPI / 3);
|
||||
lv_slider_set_knob_in(new_sw, true);
|
||||
lv_slider_set_range(new_sw, 0, LV_SWITCH_SLIDER_ANIM_MAX);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_sw_set_style(new_sw, LV_SW_STYLE_BG, th->sw.bg);
|
||||
lv_sw_set_style(new_sw, LV_SW_STYLE_INDIC, th->sw.indic);
|
||||
lv_sw_set_style(new_sw, LV_SW_STYLE_KNOB_OFF, th->sw.knob_off);
|
||||
lv_sw_set_style(new_sw, LV_SW_STYLE_KNOB_ON, th->sw.knob_on);
|
||||
} else {
|
||||
/*Let the slider' style*/
|
||||
}
|
||||
|
||||
}
|
||||
/*Copy an existing switch*/
|
||||
else {
|
||||
lv_sw_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->style_knob_off = copy_ext->style_knob_off;
|
||||
ext->style_knob_on = copy_ext->style_knob_on;
|
||||
#if USE_LV_ANIMATION
|
||||
ext->anim_time = copy_ext->anim_time;
|
||||
#endif
|
||||
|
||||
if(lv_sw_get_state(new_sw)) lv_slider_set_style(new_sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_on);
|
||||
else lv_slider_set_style(new_sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off);
|
||||
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_sw);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("switch created");
|
||||
|
||||
return new_sw;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Turn ON the switch
|
||||
* @param sw pointer to a switch object
|
||||
*/
|
||||
void lv_sw_on(lv_obj_t * sw)
|
||||
{
|
||||
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
|
||||
lv_slider_set_value(sw, LV_SWITCH_SLIDER_ANIM_MAX);
|
||||
|
||||
lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_on);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn OFF the switch
|
||||
* @param sw pointer to a switch object
|
||||
*/
|
||||
void lv_sw_off(lv_obj_t * sw)
|
||||
{
|
||||
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
|
||||
lv_slider_set_value(sw, 0);
|
||||
|
||||
lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the position of the switch
|
||||
* @param sw pointer to a switch object
|
||||
* @return resulting state of the switch.
|
||||
*/
|
||||
bool lv_sw_toggle(lv_obj_t *sw) {
|
||||
bool state = lv_sw_get_state(sw);
|
||||
if(state) {
|
||||
lv_sw_off(sw);
|
||||
}
|
||||
else {
|
||||
lv_sw_on(sw);
|
||||
}
|
||||
return !state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn ON the switch with an animation
|
||||
* @param sw pointer to a switch object
|
||||
*/
|
||||
void lv_sw_on_anim(lv_obj_t * sw)
|
||||
{
|
||||
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
|
||||
if(lv_sw_get_anim_time(sw) > 0)lv_sw_anim_to_value(sw, LV_SWITCH_SLIDER_ANIM_MAX);
|
||||
else lv_slider_set_value(sw, LV_SWITCH_SLIDER_ANIM_MAX);
|
||||
|
||||
lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_on);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn OFF the switch with an animation
|
||||
* @param sw pointer to a switch object
|
||||
*/
|
||||
void lv_sw_off_anim(lv_obj_t * sw)
|
||||
{
|
||||
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
|
||||
if(lv_sw_get_anim_time(sw) > 0) lv_sw_anim_to_value(sw, 0);
|
||||
else lv_slider_set_value(sw, 0);
|
||||
|
||||
lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the position of the switch with an animation
|
||||
* @param sw pointer to a switch object
|
||||
* @return resulting state of the switch.
|
||||
*/
|
||||
bool lv_sw_toggle_anim(lv_obj_t *sw) {
|
||||
bool state = lv_sw_get_state(sw);
|
||||
if(state) {
|
||||
lv_sw_off_anim(sw);
|
||||
}
|
||||
else {
|
||||
lv_sw_on_anim(sw);
|
||||
}
|
||||
return !state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a switch
|
||||
* @param sw pointer to a switch object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_sw_set_style(lv_obj_t * sw, lv_sw_style_t type, lv_style_t * style)
|
||||
{
|
||||
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
|
||||
|
||||
switch(type) {
|
||||
case LV_SLIDER_STYLE_BG:
|
||||
lv_slider_set_style(sw, LV_SLIDER_STYLE_BG, style);
|
||||
break;
|
||||
case LV_SLIDER_STYLE_INDIC:
|
||||
lv_bar_set_style(sw, LV_SLIDER_STYLE_INDIC, style);
|
||||
break;
|
||||
case LV_SW_STYLE_KNOB_OFF:
|
||||
ext->style_knob_off = style;
|
||||
if(lv_sw_get_state(sw) == 0) lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, style);
|
||||
break;
|
||||
case LV_SW_STYLE_KNOB_ON:
|
||||
ext->style_knob_on = style;
|
||||
if(lv_sw_get_state(sw) != 0) lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, style);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_sw_set_anim_time(lv_obj_t *sw, uint16_t anim_time)
|
||||
{
|
||||
#if USE_LV_ANIMATION
|
||||
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
|
||||
ext->anim_time = anim_time;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get a style of a switch
|
||||
* @param sw pointer to a switch object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_sw_get_style(const lv_obj_t * sw, lv_sw_style_t type)
|
||||
{
|
||||
lv_style_t * style = NULL;
|
||||
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
|
||||
|
||||
switch(type) {
|
||||
case LV_SW_STYLE_BG:
|
||||
style = lv_slider_get_style(sw, LV_SLIDER_STYLE_BG);
|
||||
break;
|
||||
case LV_SW_STYLE_INDIC:
|
||||
style = lv_slider_get_style(sw, LV_SLIDER_STYLE_INDIC);
|
||||
break;
|
||||
case LV_SW_STYLE_KNOB_OFF:
|
||||
style = ext->style_knob_off;
|
||||
break;
|
||||
case LV_SW_STYLE_KNOB_ON:
|
||||
style = ext->style_knob_on;
|
||||
break;
|
||||
default:
|
||||
style = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
uint16_t lv_sw_get_anim_time(const lv_obj_t *sw)
|
||||
{
|
||||
|
||||
#if USE_LV_ANIMATION
|
||||
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
|
||||
return ext->anim_time;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the switch
|
||||
* @param sw pointer to a switch object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
|
||||
|
||||
/*Save the current (old) value before slider signal modifies it*/
|
||||
int16_t old_val;
|
||||
|
||||
if(sign == LV_SIGNAL_PRESSING) old_val = ext->slider.drag_value;
|
||||
else old_val = lv_slider_get_value(sw);
|
||||
|
||||
/*Do not let the slider to call the callback. The Switch will do it if required*/
|
||||
lv_action_t slider_action = ext->slider.action;
|
||||
ext->slider.action = NULL;
|
||||
|
||||
lv_res_t res;
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(sw, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
}
|
||||
else if(sign == LV_SIGNAL_PRESSED) {
|
||||
|
||||
/*Save the x coordinate of the pressed point to see if the switch was slid*/
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
if(indev) {
|
||||
lv_point_t p;
|
||||
lv_indev_get_point(indev, &p);
|
||||
ext->start_x = p.x;
|
||||
}
|
||||
ext->slided = 0;
|
||||
ext->changed = 0;
|
||||
}
|
||||
else if(sign == LV_SIGNAL_PRESSING) {
|
||||
/*See if the switch was slid*/
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
if(indev) {
|
||||
lv_point_t p = {0,0};
|
||||
lv_indev_get_point(indev, &p);
|
||||
if(LV_MATH_ABS(p.x - ext->start_x) > LV_INDEV_DRAG_LIMIT) ext->slided = 1;
|
||||
}
|
||||
|
||||
/*If didn't slide then revert the min/max value. So click without slide won't move the switch as a slider*/
|
||||
if(ext->slided == 0) {
|
||||
if(lv_sw_get_state(sw)) ext->slider.drag_value = LV_SWITCH_SLIDER_ANIM_MAX;
|
||||
else ext->slider.drag_value = 0;
|
||||
}
|
||||
|
||||
/*If explicitly changed (by slide) don't need to be toggled on release*/
|
||||
int16_t threshold = LV_SWITCH_SLIDER_ANIM_MAX / 2;
|
||||
if((old_val < threshold && ext->slider.drag_value > threshold) ||
|
||||
(old_val > threshold && ext->slider.drag_value < threshold))
|
||||
{
|
||||
ext->changed = 1;
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_PRESS_LOST) {
|
||||
if(lv_sw_get_state(sw)) {
|
||||
lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_on);
|
||||
#if USE_LV_ANIMATION
|
||||
lv_sw_anim_to_value(sw, LV_SWITCH_SLIDER_ANIM_MAX);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off);
|
||||
#if USE_LV_ANIMATION
|
||||
lv_sw_anim_to_value(sw, 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_RELEASED) {
|
||||
/*If not dragged then toggle the switch*/
|
||||
if(ext->changed == 0) {
|
||||
if(lv_sw_get_state(sw)) lv_sw_off_anim(sw);
|
||||
else lv_sw_on_anim(sw);
|
||||
|
||||
if(slider_action != NULL) res = slider_action(sw);
|
||||
}
|
||||
/*If the switch was dragged then calculate the new state based on the current position*/
|
||||
else {
|
||||
int16_t v = lv_slider_get_value(sw);
|
||||
if(v > LV_SWITCH_SLIDER_ANIM_MAX / 2) lv_sw_on_anim(sw);
|
||||
else lv_sw_off_anim(sw);
|
||||
|
||||
if(slider_action != NULL) res = slider_action(sw);
|
||||
}
|
||||
|
||||
} else if(sign == LV_SIGNAL_CONTROLL) {
|
||||
|
||||
char c = *((char *)param);
|
||||
if(c == LV_GROUP_KEY_ENTER) {
|
||||
if(old_val) lv_sw_off_anim(sw);
|
||||
else lv_sw_on_anim(sw);
|
||||
|
||||
if(slider_action) res = slider_action(sw);
|
||||
} else if(c == LV_GROUP_KEY_UP || c == LV_GROUP_KEY_RIGHT) {
|
||||
lv_sw_on_anim(sw);
|
||||
if(slider_action) res = slider_action(sw);
|
||||
} else if(c == LV_GROUP_KEY_DOWN || c == LV_GROUP_KEY_LEFT) {
|
||||
lv_sw_off_anim(sw);
|
||||
if(slider_action) res = slider_action(sw);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_EDITABLE) {
|
||||
bool * editable = (bool *)param;
|
||||
*editable = false; /*The ancestor slider is editable the switch is not*/
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_sw";
|
||||
}
|
||||
|
||||
/*Restore the callback*/
|
||||
if(res == LV_RES_OK) ext->slider.action = slider_action;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void lv_sw_anim_to_value(lv_obj_t * sw, int16_t value)
|
||||
{
|
||||
#if USE_LV_ANIMATION
|
||||
lv_anim_t a;
|
||||
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
|
||||
a.var = sw;
|
||||
a.start = ext->slider.bar.cur_value;
|
||||
a.end = value;
|
||||
a.fp = (lv_anim_fp_t)lv_slider_set_value;
|
||||
a.path = lv_anim_path_linear;
|
||||
a.end_cb = NULL;
|
||||
a.act_time = 0;
|
||||
a.time = lv_sw_get_anim_time(sw);
|
||||
a.playback = 0;
|
||||
a.playback_pause = 0;
|
||||
a.repeat = 0;
|
||||
a.repeat_pause = 0;
|
||||
lv_anim_create(&a);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
194
bdk/libs/lvgl/lv_objx/lv_sw.h
Normal file
194
bdk/libs/lvgl/lv_objx/lv_sw.h
Normal file
|
@ -0,0 +1,194 @@
|
|||
/**
|
||||
* @file lv_sw.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SW_H
|
||||
#define LV_SW_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_SW != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_SLIDER == 0
|
||||
#error "lv_sw: lv_slider is required. Enable it in lv_conf.h (USE_LV_SLIDER 1)"
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_slider.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_SWITCH_SLIDER_ANIM_MAX 1000
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/*Data of switch*/
|
||||
typedef struct
|
||||
{
|
||||
lv_slider_ext_t slider; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_style_t *style_knob_off; /*Style of the knob when the switch is OFF*/
|
||||
lv_style_t *style_knob_on; /*Style of the knob when the switch is ON (NULL to use the same as OFF)*/
|
||||
lv_coord_t start_x;
|
||||
uint8_t changed :1; /*Indicates the switch state explicitly changed by drag*/
|
||||
uint8_t slided :1;
|
||||
#if USE_LV_ANIMATION
|
||||
uint16_t anim_time; /*switch animation time */
|
||||
#endif
|
||||
} lv_sw_ext_t;
|
||||
|
||||
enum {
|
||||
LV_SW_STYLE_BG,
|
||||
LV_SW_STYLE_INDIC,
|
||||
LV_SW_STYLE_KNOB_OFF,
|
||||
LV_SW_STYLE_KNOB_ON,
|
||||
};
|
||||
typedef uint8_t lv_sw_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a switch objects
|
||||
* @param par pointer to an object, it will be the parent of the new switch
|
||||
* @param copy pointer to a switch object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created switch
|
||||
*/
|
||||
lv_obj_t * lv_sw_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Turn ON the switch
|
||||
* @param sw pointer to a switch object
|
||||
*/
|
||||
void lv_sw_on(lv_obj_t *sw);
|
||||
|
||||
/**
|
||||
* Turn OFF the switch
|
||||
* @param sw pointer to a switch object
|
||||
*/
|
||||
void lv_sw_off(lv_obj_t *sw);
|
||||
|
||||
/**
|
||||
* Toggle the position of the switch
|
||||
* @param sw pointer to a switch object
|
||||
* @return resulting state of the switch.
|
||||
*/
|
||||
bool lv_sw_toggle(lv_obj_t *sw);
|
||||
|
||||
/**
|
||||
* Turn ON the switch with an animation
|
||||
* @param sw pointer to a switch object
|
||||
*/
|
||||
void lv_sw_on_anim(lv_obj_t * sw);
|
||||
|
||||
/**
|
||||
* Turn OFF the switch with an animation
|
||||
* @param sw pointer to a switch object
|
||||
*/
|
||||
void lv_sw_off_anim(lv_obj_t * sw);
|
||||
|
||||
/**
|
||||
* Toggle the position of the switch with an animation
|
||||
* @param sw pointer to a switch object
|
||||
* @return resulting state of the switch.
|
||||
*/
|
||||
bool lv_sw_toggle_anim(lv_obj_t *sw);
|
||||
|
||||
/**
|
||||
* Set a function which will be called when the switch is toggled by the user
|
||||
* @param sw pointer to switch object
|
||||
* @param action a callback function
|
||||
*/
|
||||
static inline void lv_sw_set_action(lv_obj_t * sw, lv_action_t action)
|
||||
{
|
||||
lv_slider_set_action(sw, action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a switch
|
||||
* @param sw pointer to a switch object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_sw_set_style(lv_obj_t *sw, lv_sw_style_t type, lv_style_t *style);
|
||||
|
||||
#if USE_LV_ANIMATION
|
||||
/**
|
||||
* Set the animation time of the switch
|
||||
* @param sw pointer to a switch object
|
||||
* @param anim_time animation time
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
void lv_sw_set_anim_time(lv_obj_t *sw, uint16_t anim_time);
|
||||
#endif
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the state of a switch
|
||||
* @param sw pointer to a switch object
|
||||
* @return false: OFF; true: ON
|
||||
*/
|
||||
static inline bool lv_sw_get_state(const lv_obj_t *sw)
|
||||
{
|
||||
return lv_bar_get_value(sw) < LV_SWITCH_SLIDER_ANIM_MAX / 2 ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the switch action function
|
||||
* @param slider pointer to a switch object
|
||||
* @return the callback function
|
||||
*/
|
||||
static inline lv_action_t lv_sw_get_action(const lv_obj_t * slider)
|
||||
{
|
||||
return lv_slider_get_action(slider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a switch
|
||||
* @param sw pointer to a switch object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_sw_get_style(const lv_obj_t *sw, lv_sw_style_t type);
|
||||
|
||||
/**
|
||||
* Get the animation time of the switch
|
||||
* @param sw pointer to a switch object
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
uint16_t lv_sw_get_anim_time(const lv_obj_t *sw);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_SW*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_SW_H*/
|
1365
bdk/libs/lvgl/lv_objx/lv_ta.c
Normal file
1365
bdk/libs/lvgl/lv_objx/lv_ta.c
Normal file
File diff suppressed because it is too large
Load diff
390
bdk/libs/lvgl/lv_objx/lv_ta.h
Normal file
390
bdk/libs/lvgl/lv_objx/lv_ta.h
Normal file
|
@ -0,0 +1,390 @@
|
|||
/**
|
||||
* @file lv_ta.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TA_H
|
||||
#define LV_TA_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_TA != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_PAGE == 0
|
||||
#error "lv_ta: lv_page is required. Enable it in lv_conf.h (USE_LV_PAGE 1) "
|
||||
#endif
|
||||
|
||||
#if USE_LV_LABEL == 0
|
||||
#error "lv_ta: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_page.h"
|
||||
#include "lv_label.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_TA_CURSOR_LAST (0x7FFF) /*Put the cursor after the last character*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
enum {
|
||||
LV_CURSOR_NONE,
|
||||
LV_CURSOR_LINE,
|
||||
LV_CURSOR_BLOCK,
|
||||
LV_CURSOR_OUTLINE,
|
||||
LV_CURSOR_UNDERLINE,
|
||||
LV_CURSOR_HIDDEN = 0x08, /*Or it to any value to hide the cursor temporally*/
|
||||
};
|
||||
typedef uint8_t lv_cursor_type_t;
|
||||
|
||||
/*Data of text area*/
|
||||
typedef struct
|
||||
{
|
||||
lv_page_ext_t page; /*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_obj_t * label; /*Label of the text area*/
|
||||
char * pwd_tmp; /*Used to store the original text in password mode*/
|
||||
const char * accapted_chars;/*Only these characters will be accepted. NULL: accept all*/
|
||||
uint16_t max_length; /*The max. number of characters. 0: no limit*/
|
||||
uint8_t pwd_mode :1; /*Replace characters with '*' */
|
||||
uint8_t one_line :1; /*One line mode (ignore line breaks)*/
|
||||
struct {
|
||||
lv_style_t *style; /*Style of the cursor (NULL to use label's style)*/
|
||||
lv_coord_t valid_x; /*Used when stepping up/down in text area when stepping to a shorter line. (Handled by the library)*/
|
||||
uint16_t pos; /*The current cursor position (0: before 1. letter; 1: before 2. letter etc.)*/
|
||||
lv_area_t area; /*Cursor area relative to the Text Area*/
|
||||
uint16_t txt_byte_pos; /*Byte index of the letter after (on) the cursor*/
|
||||
lv_cursor_type_t type:4; /*Shape of the cursor*/
|
||||
uint8_t state :1; /*Indicates that the cursor is visible now or not (Handled by the library)*/
|
||||
} cursor;
|
||||
} lv_ta_ext_t;
|
||||
|
||||
enum {
|
||||
LV_TA_STYLE_BG,
|
||||
LV_TA_STYLE_SB,
|
||||
LV_TA_STYLE_EDGE_FLASH,
|
||||
LV_TA_STYLE_CURSOR,
|
||||
};
|
||||
typedef uint8_t lv_ta_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
|
||||
/**
|
||||
* Create a text area objects
|
||||
* @param par pointer to an object, it will be the parent of the new text area
|
||||
* @param copy pointer to a text area object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created text area
|
||||
*/
|
||||
lv_obj_t * lv_ta_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Insert a character to the current cursor position.
|
||||
* To add a wide char, e.g. 'Á' use `lv_txt_encoded_conv_wc('Á')`
|
||||
* @param ta pointer to a text area object
|
||||
* @param c a character (e.g. 'a')
|
||||
*/
|
||||
void lv_ta_add_char(lv_obj_t * ta, uint32_t c);
|
||||
|
||||
/**
|
||||
* Insert a text to the current cursor position
|
||||
* @param ta pointer to a text area object
|
||||
* @param txt a '\0' terminated string to insert
|
||||
*/
|
||||
void lv_ta_add_text(lv_obj_t * ta, const char * txt);
|
||||
|
||||
/**
|
||||
* Delete a the left character from the current cursor position
|
||||
* @param ta pointer to a text area object
|
||||
*/
|
||||
void lv_ta_del_char(lv_obj_t * ta);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the text of a text area
|
||||
* @param ta pointer to a text area
|
||||
* @param txt pointer to the text
|
||||
*/
|
||||
void lv_ta_set_text(lv_obj_t * ta, const char * txt);
|
||||
|
||||
/**
|
||||
* Set the cursor position
|
||||
* @param obj pointer to a text area object
|
||||
* @param pos the new cursor position in character index
|
||||
* < 0 : index from the end of the text
|
||||
* LV_TA_CURSOR_LAST: go after the last character
|
||||
*/
|
||||
void lv_ta_set_cursor_pos(lv_obj_t * ta, int16_t pos);
|
||||
|
||||
/**
|
||||
* Set the cursor type.
|
||||
* @param ta pointer to a text area object
|
||||
* @param cur_type: element of 'lv_cursor_type_t'
|
||||
*/
|
||||
void lv_ta_set_cursor_type(lv_obj_t * ta, lv_cursor_type_t cur_type);
|
||||
|
||||
/**
|
||||
* Enable/Disable password mode
|
||||
* @param ta pointer to a text area object
|
||||
* @param en true: enable, false: disable
|
||||
*/
|
||||
void lv_ta_set_pwd_mode(lv_obj_t * ta, bool en);
|
||||
|
||||
/**
|
||||
* Configure the text area to one line or back to normal
|
||||
* @param ta pointer to a Text area object
|
||||
* @param en true: one line, false: normal
|
||||
*/
|
||||
void lv_ta_set_one_line(lv_obj_t * ta, bool en);
|
||||
|
||||
/**
|
||||
* Set the alignment of the text area.
|
||||
* In one line mode the text can be scrolled only with `LV_LABEL_ALIGN_LEFT`.
|
||||
* This function should be called if the size of text area changes.
|
||||
* @param ta pointer to a text are object
|
||||
* @param align the desired alignment from `lv_label_align_t`. (LV_LABEL_ALIGN_LEFT/CENTER/RIGHT)
|
||||
*/
|
||||
void lv_ta_set_text_align(lv_obj_t * ta, lv_label_align_t align);
|
||||
|
||||
/**
|
||||
* Set a list of characters. Only these characters will be accepted by the text area
|
||||
* @param ta pointer to Text Area
|
||||
* @param list list of characters. Only the pointer is saved. E.g. "+-.,0123456789"
|
||||
*/
|
||||
void lv_ta_set_accepted_chars(lv_obj_t * ta, const char * list);
|
||||
|
||||
/**
|
||||
* Set max length of a Text Area.
|
||||
* @param ta pointer to Text Area
|
||||
* @param num the maximal number of characters can be added (`lv_ta_set_text` ignores it)
|
||||
*/
|
||||
void lv_ta_set_max_length(lv_obj_t * ta, uint16_t num);
|
||||
|
||||
/**
|
||||
* Set an action to call when the Text area is clicked
|
||||
* @param ta pointer to a Text area
|
||||
* @param action a function pointer
|
||||
*/
|
||||
static inline void lv_ta_set_action(lv_obj_t * ta, lv_action_t action)
|
||||
{
|
||||
lv_page_set_rel_action(ta, action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scroll bar mode of a text area
|
||||
* @param ta pointer to a text area object
|
||||
* @param sb_mode the new mode from 'lv_page_sb_mode_t' enum
|
||||
*/
|
||||
static inline void lv_ta_set_sb_mode(lv_obj_t * ta, lv_sb_mode_t mode)
|
||||
{
|
||||
lv_page_set_sb_mode(ta, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the scroll propagation feature. If enabled then the Text area will move its parent if there is no more space to scroll.
|
||||
* @param ta pointer to a Text area
|
||||
* @param en true or false to enable/disable scroll propagation
|
||||
*/
|
||||
static inline void lv_ta_set_scroll_propagation(lv_obj_t * ta, bool en)
|
||||
{
|
||||
lv_page_set_scroll_propagation(ta, en);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the edge flash effect. (Show an arc when the an edge is reached)
|
||||
* @param page pointer to a Text Area
|
||||
* @param en true or false to enable/disable end flash
|
||||
*/
|
||||
static inline void lv_ta_set_edge_flash(lv_obj_t * ta, bool en)
|
||||
{
|
||||
lv_page_set_edge_flash(ta, en);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a text area
|
||||
* @param ta pointer to a text area object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_ta_set_style(lv_obj_t *ta, lv_ta_style_t type, lv_style_t *style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the text of a text area. In password mode it gives the real text (not '*'s).
|
||||
* @param ta pointer to a text area object
|
||||
* @return pointer to the text
|
||||
*/
|
||||
const char * lv_ta_get_text(const lv_obj_t * ta);
|
||||
|
||||
/**
|
||||
* Get the label of a text area
|
||||
* @param ta pointer to a text area object
|
||||
* @return pointer to the label object
|
||||
*/
|
||||
lv_obj_t * lv_ta_get_label(const lv_obj_t * ta);
|
||||
|
||||
/**
|
||||
* Get the current cursor position in character index
|
||||
* @param ta pointer to a text area object
|
||||
* @return the cursor position
|
||||
*/
|
||||
uint16_t lv_ta_get_cursor_pos(const lv_obj_t * ta);
|
||||
|
||||
/**
|
||||
* Get the current cursor visibility.
|
||||
* @param ta pointer to a text area object
|
||||
* @return true: the cursor is drawn, false: the cursor is hidden
|
||||
*/
|
||||
//bool lv_ta_get_cursor_show(const lv_obj_t * ta);
|
||||
|
||||
/**
|
||||
* Get the current cursor type.
|
||||
* @param ta pointer to a text area object
|
||||
* @return element of 'lv_cursor_type_t'
|
||||
*/
|
||||
lv_cursor_type_t lv_ta_get_cursor_type(const lv_obj_t * ta);
|
||||
|
||||
/**
|
||||
* Get the password mode attribute
|
||||
* @param ta pointer to a text area object
|
||||
* @return true: password mode is enabled, false: disabled
|
||||
*/
|
||||
bool lv_ta_get_pwd_mode(const lv_obj_t * ta);
|
||||
|
||||
/**
|
||||
* Get the one line configuration attribute
|
||||
* @param ta pointer to a text area object
|
||||
* @return true: one line configuration is enabled, false: disabled
|
||||
*/
|
||||
bool lv_ta_get_one_line(const lv_obj_t * ta);
|
||||
|
||||
/**
|
||||
* Get a list of accepted characters.
|
||||
* @param ta pointer to Text Area
|
||||
* @return list of accented characters.
|
||||
*/
|
||||
const char * lv_ta_get_accepted_chars(lv_obj_t * ta);
|
||||
|
||||
/**
|
||||
* Set max length of a Text Area.
|
||||
* @param ta pointer to Text Area
|
||||
* @return the maximal number of characters to be add
|
||||
*/
|
||||
uint16_t lv_ta_get_max_length(lv_obj_t * ta);
|
||||
|
||||
/**
|
||||
* Set an action to call when the Text area is clicked
|
||||
* @param ta pointer to a Text area
|
||||
* @param action a function pointer
|
||||
*/
|
||||
static inline lv_action_t lv_ta_get_action(lv_obj_t * ta)
|
||||
{
|
||||
return lv_page_get_rel_action(ta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scroll bar mode of a text area
|
||||
* @param ta pointer to a text area object
|
||||
* @return scrollbar mode from 'lv_page_sb_mode_t' enum
|
||||
*/
|
||||
static inline lv_sb_mode_t lv_ta_get_sb_mode(const lv_obj_t * ta)
|
||||
{
|
||||
return lv_page_get_sb_mode(ta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scroll propagation property
|
||||
* @param ta pointer to a Text area
|
||||
* @return true or false
|
||||
*/
|
||||
static inline bool lv_ta_get_scroll_propagation(lv_obj_t * ta)
|
||||
{
|
||||
return lv_page_get_scroll_propagation(ta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scroll propagation property
|
||||
* @param ta pointer to a Text area
|
||||
* @return true or false
|
||||
*/
|
||||
static inline bool lv_ta_get_edge_flash(lv_obj_t * ta)
|
||||
{
|
||||
return lv_page_get_edge_flash(ta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a text area
|
||||
* @param ta pointer to a text area object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_ta_get_style(const lv_obj_t *ta, lv_ta_style_t type);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Move the cursor one character right
|
||||
* @param ta pointer to a text area object
|
||||
*/
|
||||
void lv_ta_cursor_right(lv_obj_t * ta);
|
||||
|
||||
/**
|
||||
* Move the cursor one character left
|
||||
* @param ta pointer to a text area object
|
||||
*/
|
||||
void lv_ta_cursor_left(lv_obj_t * ta);
|
||||
|
||||
/**
|
||||
* Move the cursor one line down
|
||||
* @param ta pointer to a text area object
|
||||
*/
|
||||
void lv_ta_cursor_down(lv_obj_t * ta);
|
||||
|
||||
/**
|
||||
* Move the cursor one line up
|
||||
* @param ta pointer to a text area object
|
||||
*/
|
||||
void lv_ta_cursor_up(lv_obj_t * ta);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_TA_H*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_TA_H*/
|
855
bdk/libs/lvgl/lv_objx/lv_table.c
Normal file
855
bdk/libs/lvgl/lv_objx/lv_table.c
Normal file
|
@ -0,0 +1,855 @@
|
|||
/**
|
||||
* @file lv_table.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_table.h"
|
||||
#if USE_LV_TABLE != 0
|
||||
|
||||
#include "../lv_misc/lv_txt.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_draw/lv_draw_label.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool lv_table_design(lv_obj_t * table, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_table_signal(lv_obj_t * table, lv_signal_t sign, void * param);
|
||||
static lv_coord_t get_row_height(lv_obj_t * table, uint16_t row_id);
|
||||
static void refr_size(lv_obj_t * table);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
static lv_design_func_t ancestor_scrl_design;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a table object
|
||||
* @param par pointer to an object, it will be the parent of the new table
|
||||
* @param copy pointer to a table object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created table
|
||||
*/
|
||||
lv_obj_t * lv_table_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("table create started");
|
||||
|
||||
/*Create the ancestor of table*/
|
||||
lv_obj_t * new_table = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_table);
|
||||
if(new_table == NULL) return NULL;
|
||||
|
||||
/*Allocate the table type specific extended data*/
|
||||
lv_table_ext_t * ext = lv_obj_allocate_ext_attr(new_table, sizeof(lv_table_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_table);
|
||||
if(ancestor_scrl_design == NULL) ancestor_scrl_design = lv_obj_get_design_func(new_table);
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->cell_data = NULL;
|
||||
ext->cell_style[0] = &lv_style_plain;
|
||||
ext->cell_style[1] = &lv_style_plain;
|
||||
ext->cell_style[2] = &lv_style_plain;
|
||||
ext->cell_style[3] = &lv_style_plain;
|
||||
ext->col_cnt = 0;
|
||||
ext->row_cnt = 0;
|
||||
|
||||
uint16_t i;
|
||||
for(i = 0; i < LV_TABLE_COL_MAX; i++) {
|
||||
ext->col_w[i] = LV_DPI;
|
||||
}
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_table, lv_table_signal);
|
||||
lv_obj_set_design_func(new_table, lv_table_design);
|
||||
|
||||
/*Init the new table table*/
|
||||
if(copy == NULL) {
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_table_set_style(new_table, LV_TABLE_STYLE_BG, th->table.bg);
|
||||
lv_table_set_style(new_table, LV_TABLE_STYLE_CELL1, th->table.cell);
|
||||
lv_table_set_style(new_table, LV_TABLE_STYLE_CELL2, th->table.cell);
|
||||
lv_table_set_style(new_table, LV_TABLE_STYLE_CELL3, th->table.cell);
|
||||
lv_table_set_style(new_table, LV_TABLE_STYLE_CELL4, th->table.cell);
|
||||
} else {
|
||||
lv_table_set_style(new_table, LV_TABLE_STYLE_BG, &lv_style_plain_color);
|
||||
}
|
||||
}
|
||||
/*Copy an existing table*/
|
||||
else {
|
||||
lv_table_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->cell_style[0] = copy_ext->cell_style[0];
|
||||
ext->cell_style[1] = copy_ext->cell_style[1];
|
||||
ext->cell_style[2] = copy_ext->cell_style[2];
|
||||
ext->cell_style[3] = copy_ext->cell_style[3];
|
||||
ext->col_cnt = copy_ext->col_cnt;
|
||||
ext->row_cnt = copy_ext->row_cnt;
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_table);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("table created");
|
||||
|
||||
return new_table;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the value of a cell.
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @param txt text to display in the cell. It will be copied and saved so this variable is not required after this function call.
|
||||
*/
|
||||
void lv_table_set_cell_value(lv_obj_t * table, uint16_t row, uint16_t col, const char * txt)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
if(row >= ext->row_cnt || col >= ext->col_cnt) {
|
||||
LV_LOG_WARN("lv_table_set_cell_value: invalid row or column");
|
||||
return;
|
||||
}
|
||||
uint32_t cell = row * ext->col_cnt + col;
|
||||
lv_table_cell_format_t format;
|
||||
|
||||
/*Save the format byte*/
|
||||
if(ext->cell_data[cell]) {
|
||||
format.format_byte = ext->cell_data[cell][0];
|
||||
}
|
||||
/*Initialize the format byte*/
|
||||
else {
|
||||
format.align = LV_LABEL_ALIGN_LEFT;
|
||||
format.right_merge = 0;
|
||||
format.type = 0;
|
||||
format.crop = 0;
|
||||
}
|
||||
|
||||
|
||||
ext->cell_data[cell] = lv_mem_realloc(ext->cell_data[cell], strlen(txt) + 2); /*+1: trailing '\0; +1: format byte*/
|
||||
strcpy(ext->cell_data[cell] + 1, txt); /*Leave the format byte*/
|
||||
ext->cell_data[cell][0] = format.format_byte;
|
||||
refr_size(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of rows
|
||||
* @param table table pointer to a Table object
|
||||
* @param row_cnt number of rows
|
||||
*/
|
||||
void lv_table_set_row_cnt(lv_obj_t * table, uint16_t row_cnt)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
uint16_t old_row_cnt = ext->row_cnt;
|
||||
ext->row_cnt = row_cnt;
|
||||
|
||||
if(ext->row_cnt > 0 && ext->col_cnt > 0) {
|
||||
ext->cell_data = lv_mem_realloc(ext->cell_data, ext->row_cnt * ext->col_cnt * sizeof(char*));
|
||||
|
||||
/*Initilize the new fields*/
|
||||
if(old_row_cnt < row_cnt) {
|
||||
uint16_t old_cell_cnt = old_row_cnt * ext->col_cnt;
|
||||
uint32_t new_cell_cnt = ext->col_cnt * ext->row_cnt;
|
||||
memset(&ext->cell_data[old_cell_cnt], 0, (new_cell_cnt - old_cell_cnt) * sizeof(ext->cell_data[0]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_mem_free(ext->cell_data);
|
||||
ext->cell_data = NULL;
|
||||
}
|
||||
|
||||
refr_size(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of columns
|
||||
* @param table table pointer to a Table object
|
||||
* @param col_cnt number of columns. Must be < LV_TABLE_COL_MAX
|
||||
*/
|
||||
void lv_table_set_col_cnt(lv_obj_t * table, uint16_t col_cnt)
|
||||
{
|
||||
|
||||
if(col_cnt >= LV_TABLE_COL_MAX) {
|
||||
LV_LOG_WARN("lv_table_set_col_cnt: too many columns. Must be < LV_TABLE_COL_MAX.");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
uint16_t old_col_cnt = ext->col_cnt;
|
||||
ext->col_cnt = col_cnt;
|
||||
|
||||
if(ext->row_cnt > 0 && ext->col_cnt > 0) {
|
||||
ext->cell_data = lv_mem_realloc(ext->cell_data, ext->row_cnt * ext->col_cnt * sizeof(char*));
|
||||
/*Initilize the new fields*/
|
||||
if(old_col_cnt < col_cnt) {
|
||||
uint16_t old_cell_cnt = old_col_cnt * ext->row_cnt;
|
||||
uint32_t new_cell_cnt = ext->col_cnt * ext->row_cnt;
|
||||
memset(&ext->cell_data[old_cell_cnt], 0, (new_cell_cnt - old_cell_cnt) * sizeof(ext->cell_data[0]));
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
lv_mem_free(ext->cell_data);
|
||||
ext->cell_data = NULL;
|
||||
}
|
||||
refr_size(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width of a column
|
||||
* @param table table pointer to a Table object
|
||||
* @param col_id id of the column [0 .. LV_TABLE_COL_MAX -1]
|
||||
* @param w width of the column
|
||||
*/
|
||||
void lv_table_set_col_width(lv_obj_t * table, uint16_t col_id, lv_coord_t w)
|
||||
{
|
||||
if(col_id >= LV_TABLE_COL_MAX) {
|
||||
LV_LOG_WARN("lv_table_set_col_width: too big 'col_id'. Must be < LV_TABLE_COL_MAX.");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
ext->col_w[col_id] = w;
|
||||
refr_size(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text align in a cell
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @param align LV_LABEL_ALIGN_LEFT or LV_LABEL_ALIGN_CENTER or LV_LABEL_ALIGN_RIGHT
|
||||
*/
|
||||
void lv_table_set_cell_align(lv_obj_t * table, uint16_t row, uint16_t col, lv_label_align_t align)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
if(row >= ext->row_cnt || col >= ext->col_cnt) {
|
||||
LV_LOG_WARN("lv_table_set_cell_align: invalid row or column");
|
||||
return;
|
||||
}
|
||||
uint32_t cell = row * ext->col_cnt + col;
|
||||
|
||||
if(ext->cell_data[cell] == NULL) {
|
||||
ext->cell_data[cell] = lv_mem_alloc(2); /*+1: trailing '\0; +1: format byte*/
|
||||
ext->cell_data[cell][0] = 0;
|
||||
ext->cell_data[cell][1] = '\0';
|
||||
}
|
||||
|
||||
lv_table_cell_format_t format;
|
||||
format.format_byte = ext->cell_data[cell][0];
|
||||
format.align = align;
|
||||
ext->cell_data[cell][0] = format.format_byte;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of a cell.
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @param type 1,2,3 or 4. The cell style will be chosen accordingly.
|
||||
*/
|
||||
void lv_table_set_cell_type(lv_obj_t * table, uint16_t row, uint16_t col, uint8_t type)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
if(row >= ext->row_cnt || col >= ext->col_cnt) {
|
||||
LV_LOG_WARN("lv_table_set_cell_type: invalid row or column");
|
||||
return;
|
||||
}
|
||||
uint32_t cell = row * ext->col_cnt + col;
|
||||
|
||||
if(ext->cell_data[cell] == NULL) {
|
||||
ext->cell_data[cell] = lv_mem_alloc(2); /*+1: trailing '\0; +1: format byte*/
|
||||
ext->cell_data[cell][0] = 0;
|
||||
ext->cell_data[cell][1] = '\0';
|
||||
}
|
||||
|
||||
if(type > 0) type--; /*User gives 1,2,3,4 but easier to handle 0, 1, 2, 3*/
|
||||
if(type >= LV_TABLE_CELL_STYLE_CNT) type = LV_TABLE_CELL_STYLE_CNT - 1;
|
||||
|
||||
lv_table_cell_format_t format;
|
||||
format.format_byte = ext->cell_data[cell][0];
|
||||
format.type = type;
|
||||
ext->cell_data[cell][0] = format.format_byte;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cell crop. (Don't adjust the height of the cell according to its content)
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @param crop true: crop the cell content; false: set the cell height to the content.
|
||||
*/
|
||||
void lv_table_set_cell_crop(lv_obj_t * table, uint16_t row, uint16_t col, bool crop)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
if(row >= ext->row_cnt || col >= ext->col_cnt) {
|
||||
LV_LOG_WARN("lv_table_set_cell_crop: invalid row or column");
|
||||
return;
|
||||
}
|
||||
uint32_t cell = row * ext->col_cnt + col;
|
||||
|
||||
if(ext->cell_data[cell] == NULL) {
|
||||
ext->cell_data[cell] = lv_mem_alloc(2); /*+1: trailing '\0; +1: format byte*/
|
||||
ext->cell_data[cell][0] = 0;
|
||||
ext->cell_data[cell][1] = '\0';
|
||||
}
|
||||
|
||||
lv_table_cell_format_t format;
|
||||
format.format_byte = ext->cell_data[cell][0];
|
||||
format.crop = crop;
|
||||
ext->cell_data[cell][0] = format.format_byte;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Merge a cell with the right neighbor. The value of the cell to the right won't be displayed.
|
||||
* @param table table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @param en true: merge right; false: don't merge right
|
||||
*/
|
||||
void lv_table_set_cell_merge_right(lv_obj_t * table, uint16_t row, uint16_t col, bool en)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
if(row >= ext->row_cnt || col >= ext->col_cnt) {
|
||||
LV_LOG_WARN("lv_table_set_cell_merge_right: invalid row or column");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t cell = row * ext->col_cnt + col;
|
||||
|
||||
if(ext->cell_data[cell] == NULL) {
|
||||
ext->cell_data[cell] = lv_mem_alloc(2); /*+1: trailing '\0; +1: format byte*/
|
||||
ext->cell_data[cell][0] = 0;
|
||||
ext->cell_data[cell][1] = '\0';
|
||||
}
|
||||
|
||||
lv_table_cell_format_t format;
|
||||
format.format_byte = ext->cell_data[cell][0];
|
||||
format.right_merge = en ? 1 : 0;
|
||||
ext->cell_data[cell][0] = format.format_byte;
|
||||
refr_size(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a table.
|
||||
* @param table pointer to table object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_table_set_style(lv_obj_t * table, lv_table_style_t type, lv_style_t * style)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
|
||||
switch(type) {
|
||||
case LV_TABLE_STYLE_BG:
|
||||
lv_obj_set_style(table, style);
|
||||
refr_size(table);
|
||||
break;
|
||||
case LV_TABLE_STYLE_CELL1:
|
||||
ext->cell_style[0] = style;
|
||||
refr_size(table);
|
||||
break;
|
||||
case LV_TABLE_STYLE_CELL2:
|
||||
ext->cell_style[1] = style;
|
||||
refr_size(table);
|
||||
break;
|
||||
case LV_TABLE_STYLE_CELL3:
|
||||
ext->cell_style[2] = style;
|
||||
refr_size(table);
|
||||
break;
|
||||
case LV_TABLE_STYLE_CELL4:
|
||||
ext->cell_style[3] = style;
|
||||
refr_size(table);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the value of a cell.
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @return text in the cell
|
||||
*/
|
||||
const char * lv_table_get_cell_value(lv_obj_t * table, uint16_t row, uint16_t col)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
if(row >= ext->row_cnt || col >= ext->col_cnt) {
|
||||
LV_LOG_WARN("lv_table_set_cell_value: invalid row or column");
|
||||
return "";
|
||||
}
|
||||
uint32_t cell = row * ext->col_cnt + col;
|
||||
|
||||
if(ext->cell_data[cell] == NULL) return "";
|
||||
|
||||
return &ext->cell_data[cell][1]; /*Skip the format byte*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of rows.
|
||||
* @param table table pointer to a Table object
|
||||
* @return number of rows.
|
||||
*/
|
||||
uint16_t lv_table_get_row_cnt(lv_obj_t * table)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
return ext->row_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of columns.
|
||||
* @param table table pointer to a Table object
|
||||
* @return number of columns.
|
||||
*/
|
||||
uint16_t lv_table_get_col_cnt(lv_obj_t * table)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
return ext->col_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width of a column
|
||||
* @param table table pointer to a Table object
|
||||
* @param col_id id of the column [0 .. LV_TABLE_COL_MAX -1]
|
||||
* @return width of the column
|
||||
*/
|
||||
lv_coord_t lv_table_get_col_width(lv_obj_t * table, uint16_t col_id)
|
||||
{
|
||||
if(col_id >= LV_TABLE_COL_MAX) {
|
||||
LV_LOG_WARN("lv_table_set_col_width: too big 'col_id'. Must be < LV_TABLE_COL_MAX.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
return ext->col_w[col_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text align of a cell
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @return LV_LABEL_ALIGN_LEFT (default in case of error) or LV_LABEL_ALIGN_CENTER or LV_LABEL_ALIGN_RIGHT
|
||||
*/
|
||||
lv_label_align_t lv_table_get_cell_align(lv_obj_t * table, uint16_t row, uint16_t col)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
if(row >= ext->row_cnt || col >= ext->col_cnt) {
|
||||
LV_LOG_WARN("lv_table_set_cell_align: invalid row or column");
|
||||
return LV_LABEL_ALIGN_LEFT; /*Just return with something*/
|
||||
}
|
||||
uint32_t cell = row * ext->col_cnt + col;
|
||||
|
||||
if(ext->cell_data[cell] == NULL) return LV_LABEL_ALIGN_LEFT; /*Just return with something*/
|
||||
else {
|
||||
lv_table_cell_format_t format;
|
||||
format.format_byte = ext->cell_data[cell][0];
|
||||
return format.align;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of a cell
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @return 1,2,3 or 4
|
||||
*/
|
||||
lv_label_align_t lv_table_get_cell_type(lv_obj_t * table, uint16_t row, uint16_t col)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
if(row >= ext->row_cnt || col >= ext->col_cnt) {
|
||||
LV_LOG_WARN("lv_table_get_cell_type: invalid row or column");
|
||||
return 1; /*Just return with something*/
|
||||
}
|
||||
uint32_t cell = row * ext->col_cnt + col;
|
||||
|
||||
if(ext->cell_data[cell] == NULL) return 1; /*Just return with something*/
|
||||
else {
|
||||
lv_table_cell_format_t format;
|
||||
format.format_byte = ext->cell_data[cell][0];
|
||||
return format.type + 1; /*0,1,2,3 is stored but user sees 1,2,3,4*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the crop property of a cell
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @return true: text crop enabled; false: disabled
|
||||
*/
|
||||
lv_label_align_t lv_table_get_cell_crop(lv_obj_t * table, uint16_t row, uint16_t col)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
if(row >= ext->row_cnt || col >= ext->col_cnt) {
|
||||
LV_LOG_WARN("lv_table_get_cell_crop: invalid row or column");
|
||||
return false; /*Just return with something*/
|
||||
}
|
||||
uint32_t cell = row * ext->col_cnt + col;
|
||||
|
||||
if(ext->cell_data[cell] == NULL) return false; /*Just return with something*/
|
||||
else {
|
||||
lv_table_cell_format_t format;
|
||||
format.format_byte = ext->cell_data[cell][0];
|
||||
return format.crop;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cell merge attribute.
|
||||
* @param table table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @return true: merge right; false: don't merge right
|
||||
*/
|
||||
bool lv_table_get_cell_merge_right(lv_obj_t * table, uint16_t row, uint16_t col)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
if(row >= ext->row_cnt || col >= ext->col_cnt) {
|
||||
LV_LOG_WARN("lv_table_get_cell_merge_right: invalid row or column");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t cell = row * ext->col_cnt + col;
|
||||
|
||||
if(ext->cell_data[cell] == NULL) return false;
|
||||
else {
|
||||
lv_table_cell_format_t format;
|
||||
format.format_byte = ext->cell_data[cell][0];
|
||||
return format.right_merge ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get style of a table.
|
||||
* @param table pointer to table object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
*/
|
||||
lv_style_t * lv_table_get_style(const lv_obj_t * table, lv_table_style_t type)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
lv_style_t * style = NULL;
|
||||
|
||||
switch(type) {
|
||||
case LV_TABLE_STYLE_BG:
|
||||
style = lv_obj_get_style(table);
|
||||
break;
|
||||
case LV_TABLE_STYLE_CELL1:
|
||||
style = ext->cell_style[0];
|
||||
break;
|
||||
case LV_TABLE_STYLE_CELL2:
|
||||
style = ext->cell_style[1];
|
||||
break;
|
||||
case LV_TABLE_STYLE_CELL3:
|
||||
style = ext->cell_style[2];
|
||||
break;
|
||||
case LV_TABLE_STYLE_CELL4:
|
||||
style = ext->cell_style[3];
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Handle the drawing related tasks of the tables
|
||||
* @param table pointer to an object
|
||||
* @param mask the object will be drawn only in this area
|
||||
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
|
||||
* (return 'true' if yes)
|
||||
* LV_DESIGN_DRAW: draw the object (always return 'true')
|
||||
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
|
||||
* @param return true/false, depends on 'mode'
|
||||
*/
|
||||
static bool lv_table_design(lv_obj_t * table, const lv_area_t * mask, lv_design_mode_t mode)
|
||||
{
|
||||
/*Return false if the object is not covers the mask_p area*/
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
return false;
|
||||
}
|
||||
/*Draw the object*/
|
||||
else if(mode == LV_DESIGN_DRAW_MAIN) {
|
||||
ancestor_scrl_design(table, mask, mode);
|
||||
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
lv_style_t * bg_style = lv_obj_get_style(table);
|
||||
lv_style_t * cell_style;
|
||||
lv_coord_t h_row;
|
||||
lv_point_t txt_size;
|
||||
lv_area_t cell_area;
|
||||
lv_area_t txt_area;
|
||||
lv_txt_flag_t txt_flags;
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(table);
|
||||
|
||||
uint16_t col;
|
||||
uint16_t row;
|
||||
uint16_t cell = 0;
|
||||
|
||||
cell_area.y2 = table->coords.y1 + bg_style->body.padding.ver;
|
||||
for(row = 0; row < ext->row_cnt; row++) {
|
||||
h_row = get_row_height(table, row);
|
||||
|
||||
cell_area.y1 = cell_area.y2;
|
||||
cell_area.y2 = cell_area.y1 + h_row;
|
||||
|
||||
cell_area.x2 = table->coords.x1 + bg_style->body.padding.hor;
|
||||
|
||||
for(col = 0; col < ext->col_cnt; col++) {
|
||||
|
||||
lv_table_cell_format_t format;
|
||||
if(ext->cell_data[cell]) {
|
||||
format.format_byte = ext->cell_data[cell][0];
|
||||
} else {
|
||||
format.right_merge = 0;
|
||||
format.align = LV_LABEL_ALIGN_LEFT;
|
||||
format.type = 0;
|
||||
format.crop = 1;
|
||||
}
|
||||
|
||||
cell_style = ext->cell_style[format.type];
|
||||
cell_area.x1 = cell_area.x2;
|
||||
cell_area.x2 = cell_area.x1 + ext->col_w[col];
|
||||
|
||||
uint16_t col_merge = 0;
|
||||
for(col_merge = 0; col_merge + col < ext->col_cnt - 1; col_merge ++) {
|
||||
|
||||
if(ext->cell_data[cell + col_merge] != NULL) {
|
||||
format.format_byte = ext->cell_data[cell + col_merge][0];
|
||||
if(format.right_merge) cell_area.x2 += ext->col_w[col + col_merge + 1];
|
||||
else break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lv_draw_rect(&cell_area, mask, cell_style, opa_scale);
|
||||
|
||||
if(ext->cell_data[cell]) {
|
||||
txt_area.x1 = cell_area.x1 + cell_style->body.padding.hor;
|
||||
txt_area.x2 = cell_area.x2 - cell_style->body.padding.hor;
|
||||
txt_area.y1 = cell_area.y1 + cell_style->body.padding.ver;
|
||||
txt_area.y2 = cell_area.y2 - cell_style->body.padding.ver;
|
||||
/*Align the content to the middle if not cropped*/
|
||||
if(format.crop == 0) {
|
||||
txt_flags = LV_TXT_FLAG_NONE;
|
||||
} else {
|
||||
txt_flags = LV_TXT_FLAG_EXPAND;
|
||||
}
|
||||
|
||||
lv_txt_get_size(&txt_size, ext->cell_data[cell] + 1, cell_style->text.font,
|
||||
cell_style->text.letter_space, cell_style->text.line_space, lv_area_get_width(&txt_area), txt_flags);
|
||||
|
||||
/*Align the content to the middle if not cropped*/
|
||||
if(format.crop == 0) {
|
||||
txt_area.y1 = cell_area.y1 + h_row / 2 - txt_size.y / 2;
|
||||
txt_area.y2 = cell_area.y1 + h_row / 2 + txt_size.y / 2;
|
||||
}
|
||||
|
||||
switch(format.align) {
|
||||
default:
|
||||
case LV_LABEL_ALIGN_LEFT:
|
||||
txt_flags |= LV_TXT_FLAG_NONE;
|
||||
break;
|
||||
case LV_LABEL_ALIGN_RIGHT:
|
||||
txt_flags |= LV_TXT_FLAG_RIGHT;
|
||||
break;
|
||||
case LV_LABEL_ALIGN_CENTER:
|
||||
txt_flags |= LV_TXT_FLAG_CENTER;
|
||||
break;
|
||||
}
|
||||
|
||||
lv_area_t label_mask;
|
||||
bool label_mask_ok;
|
||||
label_mask_ok = lv_area_intersect(&label_mask, mask, &cell_area);
|
||||
if(label_mask_ok) {
|
||||
lv_draw_label(&txt_area, &label_mask, cell_style, opa_scale, ext->cell_data[cell] + 1, txt_flags, NULL);
|
||||
}
|
||||
/*Draw lines after '\n's*/
|
||||
lv_point_t p1;
|
||||
lv_point_t p2;
|
||||
p1.x = cell_area.x1;
|
||||
p2.x = cell_area.x2;
|
||||
uint16_t i;
|
||||
for(i = 1; ext->cell_data[cell][i] != '\0'; i++) {
|
||||
if(ext->cell_data[cell][i] == '\n') {
|
||||
ext->cell_data[cell][i] = '\0';
|
||||
lv_txt_get_size(&txt_size, ext->cell_data[cell] + 1, cell_style->text.font,
|
||||
cell_style->text.letter_space, cell_style->text.line_space, lv_area_get_width(&txt_area), txt_flags);
|
||||
|
||||
p1.y = txt_area.y1 + txt_size.y + cell_style->text.line_space / 2;
|
||||
p2.y = txt_area.y1 + txt_size.y + cell_style->text.line_space / 2;
|
||||
lv_draw_line(&p1, &p2, mask, cell_style, opa_scale);
|
||||
|
||||
ext->cell_data[cell][i] = '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cell += col_merge + 1;
|
||||
col += col_merge;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*Post draw when the children are drawn*/
|
||||
else if(mode == LV_DESIGN_DRAW_POST) {
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the table
|
||||
* @param table pointer to a table object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_table_signal(lv_obj_t * table, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(table, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Free the cell texts*/
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
uint16_t cell;
|
||||
for(cell = 0; cell < ext->col_cnt * ext->row_cnt; cell++) {
|
||||
if(ext->cell_data[cell]) {
|
||||
lv_mem_free(ext->cell_data[cell]);
|
||||
ext->cell_data[cell] = NULL;
|
||||
}
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_table";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void refr_size(lv_obj_t * table)
|
||||
{
|
||||
lv_coord_t h = 0;
|
||||
lv_coord_t w = 0;
|
||||
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
|
||||
uint16_t i;
|
||||
for(i= 0; i < ext->col_cnt; i++) {
|
||||
w += ext->col_w[i];
|
||||
}
|
||||
for(i= 0; i < ext->row_cnt; i++) {
|
||||
h += get_row_height(table, i);
|
||||
}
|
||||
|
||||
lv_style_t * bg_style = lv_obj_get_style(table);
|
||||
|
||||
w += bg_style->body.padding.hor * 2;
|
||||
h += bg_style->body.padding.ver * 2;
|
||||
|
||||
lv_obj_set_size(table, w + 1, h + 1);
|
||||
lv_obj_invalidate(table);
|
||||
}
|
||||
|
||||
static lv_coord_t get_row_height(lv_obj_t * table, uint16_t row_id)
|
||||
{
|
||||
lv_table_ext_t * ext = lv_obj_get_ext_attr(table);
|
||||
lv_point_t txt_size;
|
||||
lv_coord_t txt_w;
|
||||
lv_style_t * cell_style;
|
||||
|
||||
uint16_t row_start = row_id * ext->col_cnt;
|
||||
uint16_t cell;
|
||||
uint16_t col;
|
||||
lv_coord_t h_max = lv_font_get_height(ext->cell_style[0]->text.font) + 2 * ext->cell_style[0]->body.padding.ver;
|
||||
|
||||
for(cell = row_start, col = 0; cell < row_start + ext->col_cnt; cell++, col ++) {
|
||||
if(ext->cell_data[cell] != NULL) {
|
||||
|
||||
txt_w = ext->col_w[col];
|
||||
uint16_t col_merge = 0;
|
||||
for(col_merge = 0; col_merge + col < ext->col_cnt - 1; col_merge ++) {
|
||||
|
||||
if(ext->cell_data[cell + col_merge] != NULL) {
|
||||
lv_table_cell_format_t format;
|
||||
format.format_byte = ext->cell_data[cell + col_merge][0];
|
||||
if(format.right_merge) txt_w += ext->col_w[col + col_merge + 1];
|
||||
else break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lv_table_cell_format_t format;
|
||||
format.format_byte = ext->cell_data[cell][0];
|
||||
cell_style = ext->cell_style[format.type];
|
||||
|
||||
/*With text crop assume 1 line*/
|
||||
if(format.crop) {
|
||||
h_max = LV_MATH_MAX(lv_font_get_height(cell_style->text.font) + 2 * cell_style->body.padding.ver, h_max);
|
||||
}
|
||||
/*Without text crop calculate the height of the text in the cell*/
|
||||
else {
|
||||
txt_w -= 2 * cell_style->body.padding.hor;
|
||||
|
||||
lv_txt_get_size(&txt_size, ext->cell_data[cell] + 1, cell_style->text.font,
|
||||
cell_style->text.letter_space, cell_style->text.line_space, txt_w, LV_TXT_FLAG_NONE);
|
||||
|
||||
h_max = LV_MATH_MAX(txt_size.y + 2 * cell_style->body.padding.ver, h_max);
|
||||
cell += col_merge;
|
||||
col += col_merge;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return h_max;
|
||||
}
|
||||
|
||||
#endif
|
261
bdk/libs/lvgl/lv_objx/lv_table.h
Normal file
261
bdk/libs/lvgl/lv_objx/lv_table.h
Normal file
|
@ -0,0 +1,261 @@
|
|||
/**
|
||||
* @file lv_table.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TABLE_H
|
||||
#define LV_TABLE_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_TABLE != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_LABEL == 0
|
||||
#error "lv_table: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_label.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#ifndef LV_TABLE_COL_MAX
|
||||
#define LV_TABLE_COL_MAX 12
|
||||
#endif
|
||||
|
||||
#define LV_TABLE_CELL_STYLE_CNT 4
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t align:2;
|
||||
uint8_t right_merge:1;
|
||||
uint8_t type:2;
|
||||
uint8_t crop:1;
|
||||
};
|
||||
uint8_t format_byte;
|
||||
}lv_table_cell_format_t;
|
||||
|
||||
/*Data of table*/
|
||||
typedef struct {
|
||||
/*New data for this type */
|
||||
uint16_t col_cnt;
|
||||
uint16_t row_cnt;
|
||||
char ** cell_data;
|
||||
lv_style_t * cell_style[LV_TABLE_CELL_STYLE_CNT];
|
||||
lv_coord_t col_w[LV_TABLE_COL_MAX];
|
||||
} lv_table_ext_t;
|
||||
|
||||
|
||||
/*Styles*/
|
||||
enum {
|
||||
LV_TABLE_STYLE_BG,
|
||||
LV_TABLE_STYLE_CELL1,
|
||||
LV_TABLE_STYLE_CELL2,
|
||||
LV_TABLE_STYLE_CELL3,
|
||||
LV_TABLE_STYLE_CELL4,
|
||||
};
|
||||
typedef uint8_t lv_table_style_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a table object
|
||||
* @param par pointer to an object, it will be the parent of the new table
|
||||
* @param copy pointer to a table object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created table
|
||||
*/
|
||||
lv_obj_t * lv_table_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the value of a cell.
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @param txt text to display in the cell. It will be copied and saved so this variable is not required after this function call.
|
||||
*/
|
||||
void lv_table_set_cell_value(lv_obj_t * table, uint16_t row, uint16_t col, const char * txt);
|
||||
|
||||
/**
|
||||
* Set the number of rows
|
||||
* @param table table pointer to a Table object
|
||||
* @param row_cnt number of rows
|
||||
*/
|
||||
void lv_table_set_row_cnt(lv_obj_t * table, uint16_t row_cnt);
|
||||
|
||||
/**
|
||||
* Set the number of columns
|
||||
* @param table table pointer to a Table object
|
||||
* @param col_cnt number of columns. Must be < LV_TABLE_COL_MAX
|
||||
*/
|
||||
void lv_table_set_col_cnt(lv_obj_t * table, uint16_t col_cnt);
|
||||
|
||||
/**
|
||||
* Set the width of a column
|
||||
* @param table table pointer to a Table object
|
||||
* @param col_id id of the column [0 .. LV_TABLE_COL_MAX -1]
|
||||
* @param w width of the column
|
||||
*/
|
||||
void lv_table_set_col_width(lv_obj_t * table, uint16_t col_id, lv_coord_t w);
|
||||
|
||||
/**
|
||||
* Set the text align in a cell
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @param align LV_LABEL_ALIGN_LEFT or LV_LABEL_ALIGN_CENTER or LV_LABEL_ALIGN_RIGHT
|
||||
*/
|
||||
void lv_table_set_cell_align(lv_obj_t * table, uint16_t row, uint16_t col, lv_label_align_t align);
|
||||
|
||||
/**
|
||||
* Set the type of a cell.
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @param type 1,2,3 or 4. The cell style will be chosen accordingly.
|
||||
*/
|
||||
void lv_table_set_cell_type(lv_obj_t * table, uint16_t row, uint16_t col, uint8_t type);
|
||||
|
||||
/**
|
||||
* Set the cell crop. (Don't adjust the height of the cell according to its content)
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @param crop true: crop the cell content; false: set the cell height to the content.
|
||||
*/
|
||||
void lv_table_set_cell_crop(lv_obj_t * table, uint16_t row, uint16_t col, bool crop);
|
||||
|
||||
/**
|
||||
* Merge a cell with the right neighbor. The value of the cell to the right won't be displayed.
|
||||
* @param table table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @param en true: merge right; false: don't merge right
|
||||
*/
|
||||
void lv_table_set_cell_merge_right(lv_obj_t * table, uint16_t row, uint16_t col, bool en);
|
||||
|
||||
/**
|
||||
* Set a style of a table.
|
||||
* @param table pointer to table object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_table_set_style(lv_obj_t * table, lv_table_style_t type, lv_style_t * style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the value of a cell.
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @return text in the cell
|
||||
*/
|
||||
const char * lv_table_get_cell_value(lv_obj_t * table, uint16_t row, uint16_t col);
|
||||
|
||||
/**
|
||||
* Get the number of rows.
|
||||
* @param table table pointer to a Table object
|
||||
* @return number of rows.
|
||||
*/
|
||||
uint16_t lv_table_get_row_cnt(lv_obj_t * table);
|
||||
|
||||
/**
|
||||
* Get the number of columns.
|
||||
* @param table table pointer to a Table object
|
||||
* @return number of columns.
|
||||
*/
|
||||
uint16_t lv_table_get_col_cnt(lv_obj_t * table);
|
||||
|
||||
/**
|
||||
* Get the width of a column
|
||||
* @param table table pointer to a Table object
|
||||
* @param col_id id of the column [0 .. LV_TABLE_COL_MAX -1]
|
||||
* @return width of the column
|
||||
*/
|
||||
lv_coord_t lv_table_get_col_width(lv_obj_t * table, uint16_t col_id);
|
||||
|
||||
/**
|
||||
* Get the text align of a cell
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @return LV_LABEL_ALIGN_LEFT (default in case of error) or LV_LABEL_ALIGN_CENTER or LV_LABEL_ALIGN_RIGHT
|
||||
*/
|
||||
lv_label_align_t lv_table_get_cell_align(lv_obj_t * table, uint16_t row, uint16_t col);
|
||||
|
||||
/**
|
||||
* Get the type of a cell
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @return 1,2,3 or 4
|
||||
*/
|
||||
lv_label_align_t lv_table_get_cell_type(lv_obj_t * table, uint16_t row, uint16_t col);
|
||||
|
||||
|
||||
/**
|
||||
* Get the crop property of a cell
|
||||
* @param table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @return true: text crop enabled; false: disabled
|
||||
*/
|
||||
lv_label_align_t lv_table_get_cell_crop(lv_obj_t * table, uint16_t row, uint16_t col);
|
||||
|
||||
/**
|
||||
* Get the cell merge attribute.
|
||||
* @param table table pointer to a Table object
|
||||
* @param row id of the row [0 .. row_cnt -1]
|
||||
* @param col id of the column [0 .. col_cnt -1]
|
||||
* @return true: merge right; false: don't merge right
|
||||
*/
|
||||
bool lv_table_get_cell_merge_right(lv_obj_t * table, uint16_t row, uint16_t col);
|
||||
|
||||
/**
|
||||
* Get style of a table.
|
||||
* @param table pointer to table object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
*/
|
||||
lv_style_t * lv_table_get_style(const lv_obj_t * table, lv_table_style_t type);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_TABLE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_TABLE_H*/
|
909
bdk/libs/lvgl/lv_objx/lv_tabview.c
Normal file
909
bdk/libs/lvgl/lv_objx/lv_tabview.c
Normal file
|
@ -0,0 +1,909 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file lv_tab.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_tabview.h"
|
||||
#if USE_LV_TABVIEW != 0
|
||||
|
||||
#include "lv_btnm.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_anim.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#if USE_LV_ANIMATION
|
||||
# ifndef LV_TABVIEW_ANIM_TIME
|
||||
# define LV_TABVIEW_ANIM_TIME 300 /*Animation time of focusing to the a list element [ms] (0: no animation) */
|
||||
# endif
|
||||
#else
|
||||
# undef LV_TABVIEW_ANIM_TIME
|
||||
# define LV_TABVIEW_ANIM_TIME 0 /*No animations*/
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_tabview_signal(lv_obj_t * tabview, lv_signal_t sign, void * param);
|
||||
static lv_res_t tabpage_signal(lv_obj_t * tab_page, lv_signal_t sign, void * param);
|
||||
static lv_res_t tabpage_scrl_signal(lv_obj_t * tab_scrl, lv_signal_t sign, void * param);
|
||||
|
||||
static void tabpage_pressed_handler(lv_obj_t * tabview, lv_obj_t * tabpage);
|
||||
static void tabpage_pressing_handler(lv_obj_t * tabview, lv_obj_t * tabpage);
|
||||
static void tabpage_press_lost_handler(lv_obj_t * tabview, lv_obj_t * tabpage);
|
||||
static lv_res_t tab_btnm_action(lv_obj_t * tab_btnm, const char * tab_name);
|
||||
static void tabview_realign(lv_obj_t * tabview);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
static lv_signal_func_t page_signal;
|
||||
static lv_signal_func_t page_scrl_signal;
|
||||
static const char * tab_def[] = {""};
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a Tab view object
|
||||
* @param par pointer to an object, it will be the parent of the new tab
|
||||
* @param copy pointer to a tab object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created tab
|
||||
*/
|
||||
lv_obj_t * lv_tabview_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("tab view create started");
|
||||
|
||||
/*Create the ancestor of tab*/
|
||||
lv_obj_t * new_tabview = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_tabview);
|
||||
if(new_tabview == NULL) return NULL;
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_tabview);
|
||||
|
||||
/*Allocate the tab type specific extended data*/
|
||||
lv_tabview_ext_t * ext = lv_obj_allocate_ext_attr(new_tabview, sizeof(lv_tabview_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->drag_hor = 0;
|
||||
ext->draging = 0;
|
||||
ext->slide_enable = 1;
|
||||
ext->tab_cur = 0;
|
||||
ext->point_last.x = 0;
|
||||
ext->point_last.y = 0;
|
||||
ext->content = NULL;
|
||||
ext->indic = NULL;
|
||||
ext->btns = NULL;
|
||||
ext->tab_load_action = NULL;
|
||||
ext->btns_pos = LV_TABVIEW_BTNS_POS_TOP;
|
||||
ext->anim_time = LV_TABVIEW_ANIM_TIME;
|
||||
ext->btns_hide = 0;
|
||||
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_tabview, lv_tabview_signal);
|
||||
|
||||
/*Init the new tab tab*/
|
||||
if(copy == NULL) {
|
||||
ext->tab_name_ptr = lv_mem_alloc(sizeof(char *));
|
||||
lv_mem_assert(ext->tab_name_ptr);
|
||||
if(ext->tab_name_ptr == NULL) return NULL;
|
||||
ext->tab_name_ptr[0] = "";
|
||||
ext->tab_cnt = 0;
|
||||
|
||||
lv_obj_set_size(new_tabview, LV_HOR_RES, LV_VER_RES);
|
||||
|
||||
ext->btns = lv_btnm_create(new_tabview, NULL);
|
||||
lv_obj_set_height(ext->btns, 3 * LV_DPI / 4);
|
||||
lv_btnm_set_map(ext->btns, tab_def);
|
||||
lv_btnm_set_action(ext->btns, tab_btnm_action);
|
||||
lv_btnm_set_toggle(ext->btns, true, 0);
|
||||
|
||||
ext->indic = lv_obj_create(ext->btns, NULL);
|
||||
lv_obj_set_width(ext->indic, LV_DPI);
|
||||
lv_obj_align(ext->indic, ext->btns, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
|
||||
lv_obj_set_click(ext->indic, false);
|
||||
|
||||
ext->content = lv_cont_create(new_tabview, NULL);
|
||||
lv_cont_set_fit(ext->content, true, false);
|
||||
lv_cont_set_layout(ext->content, LV_LAYOUT_ROW_T);
|
||||
lv_cont_set_style(ext->content, &lv_style_transp_tight);
|
||||
lv_obj_set_height(ext->content, LV_VER_RES - lv_obj_get_height(ext->btns));
|
||||
lv_obj_align(ext->content, ext->btns, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BG, th->tabview.bg);
|
||||
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_INDIC, th->tabview.indic);
|
||||
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BTN_BG, th->tabview.btn.bg);
|
||||
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BTN_REL, th->tabview.btn.rel);
|
||||
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BTN_PR, th->tabview.btn.pr);
|
||||
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BTN_TGL_REL, th->tabview.btn.tgl_rel);
|
||||
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BTN_TGL_PR, th->tabview.btn.tgl_pr);
|
||||
} else {
|
||||
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BG, &lv_style_plain);
|
||||
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BTN_BG, &lv_style_transp);
|
||||
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_INDIC, &lv_style_plain_color);
|
||||
}
|
||||
}
|
||||
/*Copy an existing tab view*/
|
||||
else {
|
||||
lv_tabview_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->point_last.x = 0;
|
||||
ext->point_last.y = 0;
|
||||
ext->btns = lv_btnm_create(new_tabview, copy_ext->btns);
|
||||
ext->indic = lv_obj_create(ext->btns, copy_ext->indic);
|
||||
ext->content = lv_cont_create(new_tabview, copy_ext->content);
|
||||
ext->anim_time = copy_ext->anim_time;
|
||||
ext->tab_load_action = copy_ext->tab_load_action;
|
||||
|
||||
ext->tab_name_ptr = lv_mem_alloc(sizeof(char *));
|
||||
lv_mem_assert(ext->tab_name_ptr);
|
||||
if(ext->tab_name_ptr == NULL) return NULL;
|
||||
ext->tab_name_ptr[0] = "";
|
||||
lv_btnm_set_map(ext->btns, ext->tab_name_ptr);
|
||||
|
||||
uint16_t i;
|
||||
lv_obj_t * new_tab;
|
||||
lv_obj_t * copy_tab;
|
||||
for(i = 0; i < copy_ext->tab_cnt; i++) {
|
||||
new_tab = lv_tabview_add_tab(new_tabview, copy_ext->tab_name_ptr[i]);
|
||||
copy_tab = lv_tabview_get_tab(copy, i);
|
||||
lv_page_set_style(new_tab, LV_PAGE_STYLE_BG, lv_page_get_style(copy_tab, LV_PAGE_STYLE_BG));
|
||||
lv_page_set_style(new_tab, LV_PAGE_STYLE_SCRL, lv_page_get_style(copy_tab, LV_PAGE_STYLE_SCRL));
|
||||
lv_page_set_style(new_tab, LV_PAGE_STYLE_SB, lv_page_get_style(copy_tab, LV_PAGE_STYLE_SB));
|
||||
}
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_tabview);
|
||||
}
|
||||
|
||||
|
||||
LV_LOG_INFO("tab view created");
|
||||
|
||||
return new_tabview;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_tabview_clean(lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_t * scrl = lv_page_get_scrl(obj);
|
||||
lv_obj_clean(scrl);
|
||||
}
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Add a new tab with the given name
|
||||
* @param tabview pointer to Tab view object where to ass the new tab
|
||||
* @param name the text on the tab button
|
||||
* @return pointer to the created page object (lv_page). You can create your content here
|
||||
*/
|
||||
lv_obj_t * lv_tabview_add_tab(lv_obj_t * tabview, const char * name)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
|
||||
/*Create the container page*/
|
||||
lv_obj_t * h = lv_page_create(ext->content, NULL);
|
||||
lv_obj_set_size(h, lv_obj_get_width(tabview), lv_obj_get_height(ext->content));
|
||||
lv_page_set_sb_mode(h, LV_SB_MODE_OFF); // Important!
|
||||
lv_page_set_style(h, LV_PAGE_STYLE_BG, &lv_style_transp);
|
||||
lv_page_set_style(h, LV_PAGE_STYLE_SCRL, &lv_style_transp);
|
||||
|
||||
if(page_signal == NULL) page_signal = lv_obj_get_signal_func(h);
|
||||
if(page_scrl_signal == NULL) page_scrl_signal = lv_obj_get_signal_func(lv_page_get_scrl(h));
|
||||
lv_obj_set_signal_func(h, tabpage_signal);
|
||||
lv_obj_set_signal_func(lv_page_get_scrl(h), tabpage_scrl_signal);
|
||||
|
||||
/*Extend the button matrix map with the new name*/
|
||||
char * name_dm;
|
||||
if((name[0] & LV_BTNM_CTRL_MASK) == LV_BTNM_CTRL_CODE) { /*If control byte presented let is*/
|
||||
name_dm = lv_mem_alloc(strlen(name) + 1); /*+1 for the the closing '\0' */
|
||||
lv_mem_assert(name_dm);
|
||||
if(name_dm == NULL) return NULL;
|
||||
strcpy(name_dm, name);
|
||||
} else { /*Set a no long press control byte is not presented*/
|
||||
name_dm = lv_mem_alloc(strlen(name) + 2); /*+1 for the the closing '\0' and +1 for the control byte */
|
||||
lv_mem_assert(name_dm);
|
||||
if(name_dm == NULL) return NULL;
|
||||
name_dm[0] = '\221';
|
||||
strcpy(&name_dm[1], name);
|
||||
}
|
||||
|
||||
ext->tab_cnt++;
|
||||
ext->tab_name_ptr = lv_mem_realloc(ext->tab_name_ptr, sizeof(char *) * (ext->tab_cnt + 1));
|
||||
lv_mem_assert(ext->tab_name_ptr);
|
||||
if(ext->tab_name_ptr == NULL) return NULL;
|
||||
|
||||
ext->tab_name_ptr[ext->tab_cnt - 1] = name_dm;
|
||||
ext->tab_name_ptr[ext->tab_cnt] = "";
|
||||
|
||||
lv_btnm_set_map(ext->btns, ext->tab_name_ptr);
|
||||
|
||||
/*Modify the indicator size*/
|
||||
lv_style_t * style_tabs = lv_obj_get_style(ext->btns);
|
||||
lv_coord_t indic_width = (lv_obj_get_width(tabview) - style_tabs->body.padding.inner * (ext->tab_cnt - 1) - 2 * style_tabs->body.padding.hor) / ext->tab_cnt;
|
||||
lv_obj_set_width(ext->indic, indic_width);
|
||||
lv_obj_set_x(ext->indic, indic_width * ext->tab_cur + style_tabs->body.padding.inner * ext->tab_cur + style_tabs->body.padding.hor);
|
||||
|
||||
/*Set the first btn as active*/
|
||||
if(ext->tab_cnt == 1) {
|
||||
ext->tab_cur = 0;
|
||||
lv_tabview_set_tab_act(tabview, 0, false);
|
||||
tabview_realign(tabview); /*To set the proper btns height*/
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new tab
|
||||
* @param tabview pointer to Tab view object
|
||||
* @param id index of a tab to load
|
||||
* @param anim_en true: set with sliding animation; false: set immediately
|
||||
*/
|
||||
void lv_tabview_set_tab_act(lv_obj_t * tabview, uint16_t id, bool anim_en)
|
||||
{
|
||||
#if USE_LV_ANIMATION == 0
|
||||
anim_en = false;
|
||||
#endif
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
|
||||
lv_style_t * style = lv_obj_get_style(ext->content);
|
||||
|
||||
lv_res_t res = LV_RES_OK;
|
||||
if(id >= ext->tab_cnt) id = ext->tab_cnt - 1;
|
||||
if(ext->tab_load_action && id != ext->tab_cur) res = ext->tab_load_action(tabview, id);
|
||||
if(res != LV_RES_OK) return; /*Prevent the tab loading*/
|
||||
|
||||
ext->tab_cur = id;
|
||||
|
||||
lv_coord_t cont_x = -(lv_obj_get_width(tabview) * id + style->body.padding.inner * id + style->body.padding.hor);
|
||||
if(ext->anim_time == 0 || anim_en == false) {
|
||||
lv_obj_set_x(ext->content, cont_x);
|
||||
} else {
|
||||
#if USE_LV_ANIMATION
|
||||
lv_anim_t a;
|
||||
a.var = ext->content;
|
||||
a.start = lv_obj_get_x(ext->content);
|
||||
a.end = cont_x;
|
||||
a.fp = (lv_anim_fp_t)lv_obj_set_x;
|
||||
a.path = lv_anim_path_linear;
|
||||
a.end_cb = NULL;
|
||||
a.act_time = 0;
|
||||
a.time = ext->anim_time;
|
||||
a.playback = 0;
|
||||
a.playback_pause = 0;
|
||||
a.repeat = 0;
|
||||
a.repeat_pause = 0;
|
||||
lv_anim_create(&a);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*Move the indicator*/
|
||||
lv_coord_t indic_width = lv_obj_get_width(ext->indic);
|
||||
lv_style_t * tabs_style = lv_obj_get_style(ext->btns);
|
||||
lv_coord_t indic_x = indic_width * id + tabs_style->body.padding.inner * id + tabs_style->body.padding.hor;
|
||||
|
||||
if(ext->anim_time == 0 || anim_en == false) {
|
||||
lv_obj_set_x(ext->indic, indic_x);
|
||||
} else {
|
||||
#if USE_LV_ANIMATION
|
||||
lv_anim_t a;
|
||||
a.var = ext->indic;
|
||||
a.start = lv_obj_get_x(ext->indic);
|
||||
a.end = indic_x;
|
||||
a.fp = (lv_anim_fp_t)lv_obj_set_x;
|
||||
a.path = lv_anim_path_linear;
|
||||
a.end_cb = NULL;
|
||||
a.act_time = 0;
|
||||
a.time = ext->anim_time;
|
||||
a.playback = 0;
|
||||
a.playback_pause = 0;
|
||||
a.repeat = 0;
|
||||
a.repeat_pause = 0;
|
||||
lv_anim_create(&a);
|
||||
#endif
|
||||
}
|
||||
|
||||
lv_btnm_set_toggle(ext->btns, true, ext->tab_cur);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an action to call when a tab is loaded (Good to create content only if required)
|
||||
* lv_tabview_get_act() still gives the current (old) tab (to remove content from here)
|
||||
* @param tabview pointer to a tabview object
|
||||
* @param action pointer to a function to call when a btn is loaded
|
||||
*/
|
||||
void lv_tabview_set_tab_load_action(lv_obj_t * tabview, lv_tabview_action_t action)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
ext->tab_load_action = action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable horizontal sliding with touch pad
|
||||
* @param tabview pointer to Tab view object
|
||||
* @param en true: enable sliding; false: disable sliding
|
||||
*/
|
||||
void lv_tabview_set_sliding(lv_obj_t * tabview, bool en)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
ext->slide_enable = en == false ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the animation time of tab view when a new tab is loaded
|
||||
* @param tabview pointer to Tab view object
|
||||
* @param anim_time_ms time of animation in milliseconds
|
||||
*/
|
||||
void lv_tabview_set_anim_time(lv_obj_t * tabview, uint16_t anim_time)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
#if USE_LV_ANIMATION == 0
|
||||
anim_time = 0;
|
||||
#endif
|
||||
ext->anim_time = anim_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the style of a tab view
|
||||
* @param tabview pointer to a tan view object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to the new style
|
||||
*/
|
||||
void lv_tabview_set_style(lv_obj_t * tabview, lv_tabview_style_t type, lv_style_t * style)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
|
||||
switch(type) {
|
||||
case LV_TABVIEW_STYLE_BG:
|
||||
lv_obj_set_style(tabview, style);
|
||||
break;
|
||||
case LV_TABVIEW_STYLE_BTN_BG:
|
||||
lv_btnm_set_style(ext->btns, LV_BTNM_STYLE_BG, style);
|
||||
tabview_realign(tabview);
|
||||
break;
|
||||
case LV_TABVIEW_STYLE_BTN_REL:
|
||||
lv_btnm_set_style(ext->btns, LV_BTNM_STYLE_BTN_REL, style);
|
||||
tabview_realign(tabview);
|
||||
break;
|
||||
case LV_TABVIEW_STYLE_BTN_PR:
|
||||
lv_btnm_set_style(ext->btns, LV_BTNM_STYLE_BTN_PR, style);
|
||||
break;
|
||||
case LV_TABVIEW_STYLE_BTN_TGL_REL:
|
||||
lv_btnm_set_style(ext->btns, LV_BTNM_STYLE_BTN_TGL_REL, style);
|
||||
break;
|
||||
case LV_TABVIEW_STYLE_BTN_TGL_PR:
|
||||
lv_btnm_set_style(ext->btns, LV_BTNM_STYLE_BTN_TGL_PR, style);
|
||||
break;
|
||||
case LV_TABVIEW_STYLE_INDIC:
|
||||
lv_obj_set_style(ext->indic, style);
|
||||
lv_obj_set_height(ext->indic, style->body.padding.inner);
|
||||
tabview_realign(tabview);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the position of tab select buttons
|
||||
* @param tabview pointer to a tan view object
|
||||
* @param btns_pos which button position
|
||||
*/
|
||||
void lv_tabview_set_btns_pos(lv_obj_t * tabview, lv_tabview_btns_pos_t btns_pos)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
|
||||
ext->btns_pos = btns_pos;
|
||||
tabview_realign(tabview);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether tab buttons are hidden
|
||||
* @param tabview pointer to a tab view object
|
||||
* @param en whether tab buttons are hidden
|
||||
*/
|
||||
void lv_tabview_set_btns_hidden(lv_obj_t *tabview, bool en)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
|
||||
ext->btns_hide = en;
|
||||
tabview_realign(tabview);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the index of the currently active tab
|
||||
* @param tabview pointer to Tab view object
|
||||
* @return the active btn index
|
||||
*/
|
||||
uint16_t lv_tabview_get_tab_act(const lv_obj_t * tabview)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
return ext->tab_cur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of tabs
|
||||
* @param tabview pointer to Tab view object
|
||||
* @return btn count
|
||||
*/
|
||||
uint16_t lv_tabview_get_tab_count(const lv_obj_t * tabview)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
return ext->tab_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the page (content area) of a tab
|
||||
* @param tabview pointer to Tab view object
|
||||
* @param id index of the btn (>= 0)
|
||||
* @return pointer to page (lv_page) object
|
||||
*/
|
||||
lv_obj_t * lv_tabview_get_tab(const lv_obj_t * tabview, uint16_t id)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
uint16_t i = 0;
|
||||
lv_obj_t * page = lv_obj_get_child_back(ext->content, NULL);
|
||||
|
||||
while(page != NULL && i != id) {
|
||||
i++;
|
||||
page = lv_obj_get_child_back(ext->content, page);
|
||||
}
|
||||
|
||||
if(i == id) return page;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tab load action
|
||||
* @param tabview pointer to a tabview object
|
||||
* @param return the current btn load action
|
||||
*/
|
||||
lv_tabview_action_t lv_tabview_get_tab_load_action(const lv_obj_t * tabview)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
return ext->tab_load_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get horizontal sliding is enabled or not
|
||||
* @param tabview pointer to Tab view object
|
||||
* @return true: enable sliding; false: disable sliding
|
||||
*/
|
||||
bool lv_tabview_get_sliding(const lv_obj_t * tabview)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
return ext->slide_enable ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the animation time of tab view when a new tab is loaded
|
||||
* @param tabview pointer to Tab view object
|
||||
* @return time of animation in milliseconds
|
||||
*/
|
||||
uint16_t lv_tabview_get_anim_time(const lv_obj_t * tabview)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
return ext->anim_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a tab view
|
||||
* @param tabview pointer to a ab view object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_tabview_get_style(const lv_obj_t * tabview, lv_tabview_style_t type)
|
||||
{
|
||||
lv_style_t * style = NULL;
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
|
||||
switch(type) {
|
||||
case LV_TABVIEW_STYLE_BG:
|
||||
style = lv_obj_get_style(tabview);
|
||||
break;
|
||||
case LV_TABVIEW_STYLE_BTN_BG:
|
||||
style = lv_btnm_get_style(ext->btns, LV_BTNM_STYLE_BG);
|
||||
break;
|
||||
case LV_TABVIEW_STYLE_BTN_REL:
|
||||
style = lv_btnm_get_style(ext->btns, LV_BTNM_STYLE_BTN_REL);
|
||||
break;
|
||||
case LV_TABVIEW_STYLE_BTN_PR:
|
||||
style = lv_btnm_get_style(ext->btns, LV_BTNM_STYLE_BTN_PR);
|
||||
break;
|
||||
case LV_TABVIEW_STYLE_BTN_TGL_REL:
|
||||
style = lv_btnm_get_style(ext->btns, LV_BTNM_STYLE_BTN_TGL_REL);
|
||||
break;
|
||||
case LV_TABVIEW_STYLE_BTN_TGL_PR:
|
||||
style = lv_btnm_get_style(ext->btns, LV_BTNM_STYLE_BTN_TGL_PR);
|
||||
break;
|
||||
default:
|
||||
style = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get position of tab select buttons
|
||||
* @param tabview pointer to a ab view object
|
||||
*/
|
||||
lv_tabview_btns_pos_t lv_tabview_get_btns_pos(const lv_obj_t * tabview)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
return ext->btns_pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether tab buttons are hidden
|
||||
* @param tabview pointer to a tab view object
|
||||
* @return whether tab buttons are hidden
|
||||
*/
|
||||
bool lv_tabview_get_btns_hidden(const lv_obj_t *tabview)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
|
||||
return ext->btns_hide;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the Tab view
|
||||
* @param tabview pointer to a Tab view object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_tabview_signal(lv_obj_t * tabview, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(tabview, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
uint8_t i;
|
||||
for(i = 0; ext->tab_name_ptr[i][0] != '\0'; i++) lv_mem_free(ext->tab_name_ptr[i]);
|
||||
|
||||
lv_mem_free(ext->tab_name_ptr);
|
||||
ext->tab_name_ptr = NULL;
|
||||
ext->btns = NULL; /*These objects were children so they are already invalid*/
|
||||
ext->content = NULL;
|
||||
} else if(sign == LV_SIGNAL_CORD_CHG) {
|
||||
if(ext->content != NULL &&
|
||||
(lv_obj_get_width(tabview) != lv_area_get_width(param) ||
|
||||
lv_obj_get_height(tabview) != lv_area_get_height(param))) {
|
||||
tabview_realign(tabview);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_FOCUS || sign == LV_SIGNAL_DEFOCUS || sign == LV_SIGNAL_CONTROLL) {
|
||||
/* The button matrix is not in a group (the tab view is in it) but it should handle the group signals.
|
||||
* So propagate the related signals to the button matrix manually*/
|
||||
if(ext->btns) {
|
||||
ext->btns->signal_func(ext->btns, sign, param);
|
||||
}
|
||||
if(sign == LV_SIGNAL_FOCUS) {
|
||||
lv_hal_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act());
|
||||
/*With ENCODER select the first button only in edit mode*/
|
||||
if(indev_type == LV_INDEV_TYPE_ENCODER) {
|
||||
#if USE_LV_GROUP
|
||||
lv_group_t * g = lv_obj_get_group(tabview);
|
||||
if(lv_group_get_editing(g)) {
|
||||
lv_btnm_ext_t * btnm_ext = lv_obj_get_ext_attr(ext->btns);
|
||||
btnm_ext->btn_id_pr = 0;
|
||||
lv_obj_invalidate(ext->btns);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
lv_btnm_ext_t * btnm_ext = lv_obj_get_ext_attr(ext->btns);
|
||||
btnm_ext->btn_id_pr = 0;
|
||||
lv_obj_invalidate(ext->btns);
|
||||
}
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_EDITABLE) {
|
||||
bool * editable = (bool *)param;
|
||||
*editable = true;
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_tabview";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Signal function of a tab's page
|
||||
* @param tab pointer to a tab page object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t tabpage_signal(lv_obj_t * tab_page, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = page_signal(tab_page, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_obj_t * cont = lv_obj_get_parent(tab_page);
|
||||
lv_obj_t * tabview = lv_obj_get_parent(cont);
|
||||
|
||||
if(lv_tabview_get_sliding(tabview) == false) return res;
|
||||
|
||||
if(sign == LV_SIGNAL_PRESSED) {
|
||||
tabpage_pressed_handler(tabview, tab_page);
|
||||
} else if(sign == LV_SIGNAL_PRESSING) {
|
||||
tabpage_pressing_handler(tabview, tab_page);
|
||||
} else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) {
|
||||
tabpage_press_lost_handler(tabview, tab_page);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
* Signal function of the tab page's scrollable object
|
||||
* @param tab_scrl pointer to a tab page's scrollable object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t tabpage_scrl_signal(lv_obj_t * tab_scrl, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = page_scrl_signal(tab_scrl, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_obj_t * tab_page = lv_obj_get_parent(tab_scrl);
|
||||
lv_obj_t * cont = lv_obj_get_parent(tab_page);
|
||||
lv_obj_t * tabview = lv_obj_get_parent(cont);
|
||||
|
||||
if(lv_tabview_get_sliding(tabview) == false) return res;
|
||||
|
||||
if(sign == LV_SIGNAL_PRESSED) {
|
||||
tabpage_pressed_handler(tabview, tab_page);
|
||||
} else if(sign == LV_SIGNAL_PRESSING) {
|
||||
tabpage_pressing_handler(tabview, tab_page);
|
||||
} else if(sign == LV_SIGNAL_RELEASED || sign == LV_SIGNAL_PRESS_LOST) {
|
||||
tabpage_press_lost_handler(tabview, tab_page);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a tab's page or scrollable object is pressed
|
||||
* @param tabview pointer to the btn view object
|
||||
* @param tabpage pointer to the page of a btn
|
||||
*/
|
||||
static void tabpage_pressed_handler(lv_obj_t * tabview, lv_obj_t * tabpage)
|
||||
{
|
||||
(void)tabpage;
|
||||
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
lv_indev_get_point(indev, &ext->point_last);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a tab's page or scrollable object is being pressed
|
||||
* @param tabview pointer to the btn view object
|
||||
* @param tabpage pointer to the page of a btn
|
||||
*/
|
||||
static void tabpage_pressing_handler(lv_obj_t * tabview, lv_obj_t * tabpage)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
lv_point_t point_act;
|
||||
lv_indev_get_point(indev, &point_act);
|
||||
lv_coord_t x_diff = point_act.x - ext->point_last.x;
|
||||
lv_coord_t y_diff = point_act.y - ext->point_last.y;
|
||||
|
||||
if(ext->draging == 0) {
|
||||
if(x_diff >= LV_INDEV_DRAG_LIMIT || x_diff <= -LV_INDEV_DRAG_LIMIT) {
|
||||
ext->drag_hor = 1;
|
||||
ext->draging = 1;
|
||||
lv_obj_set_drag(lv_page_get_scrl(tabpage), false);
|
||||
} else if(y_diff >= LV_INDEV_DRAG_LIMIT || y_diff <= -LV_INDEV_DRAG_LIMIT) {
|
||||
ext->drag_hor = 0;
|
||||
ext->draging = 1;
|
||||
}
|
||||
}
|
||||
if(ext->drag_hor) {
|
||||
lv_obj_set_x(ext->content, lv_obj_get_x(ext->content) + point_act.x - ext->point_last.x);
|
||||
ext->point_last.x = point_act.x;
|
||||
ext->point_last.y = point_act.y;
|
||||
|
||||
/*Move the indicator*/
|
||||
lv_coord_t indic_width = lv_obj_get_width(ext->indic);
|
||||
lv_style_t * tabs_style = lv_obj_get_style(ext->btns);
|
||||
lv_style_t * indic_style = lv_obj_get_style(ext->indic);
|
||||
lv_coord_t p = ((tabpage->coords.x1 - tabview->coords.x1) * (indic_width + tabs_style->body.padding.inner)) / lv_obj_get_width(tabview);
|
||||
|
||||
lv_obj_set_x(ext->indic, indic_width * ext->tab_cur + tabs_style->body.padding.inner * ext->tab_cur + indic_style->body.padding.hor - p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a tab's page or scrollable object is released or the press id lost
|
||||
* @param tabview pointer to the btn view object
|
||||
* @param tabpage pointer to the page of a btn
|
||||
*/
|
||||
static void tabpage_press_lost_handler(lv_obj_t * tabview, lv_obj_t * tabpage)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
ext->drag_hor = 0;
|
||||
ext->draging = 0;
|
||||
|
||||
lv_obj_set_drag(lv_page_get_scrl(tabpage), true);
|
||||
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
lv_point_t point_act;
|
||||
lv_indev_get_point(indev, &point_act);
|
||||
lv_point_t vect;
|
||||
lv_indev_get_vect(indev, &vect);
|
||||
lv_coord_t x_predict = 0;
|
||||
|
||||
while(vect.x != 0) {
|
||||
x_predict += vect.x;
|
||||
vect.x = vect.x * (100 - LV_INDEV_DRAG_THROW) / 100;
|
||||
}
|
||||
|
||||
lv_coord_t page_x1 = tabpage->coords.x1 - tabview->coords.x1 + x_predict;
|
||||
lv_coord_t page_x2 = page_x1 + lv_obj_get_width(tabpage);
|
||||
lv_coord_t treshold = lv_obj_get_width(tabview) / 2;
|
||||
|
||||
uint16_t tab_cur = ext->tab_cur;
|
||||
if(page_x1 > treshold) {
|
||||
if(tab_cur != 0) tab_cur--;
|
||||
} else if(page_x2 < treshold) {
|
||||
if(tab_cur < ext->tab_cnt - 1) tab_cur++;
|
||||
}
|
||||
|
||||
lv_tabview_set_tab_act(tabview, tab_cur, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a tab button is released
|
||||
* @param tab_btnm pointer to the tab's button matrix object
|
||||
* @param id the id of the tab (>= 0)
|
||||
* @return LV_ACTION_RES_OK because the button matrix in not deleted in the function
|
||||
*/
|
||||
static lv_res_t tab_btnm_action(lv_obj_t * tab_btnm, const char * tab_name)
|
||||
{
|
||||
lv_obj_t * tab = lv_obj_get_parent(tab_btnm);
|
||||
const char ** tabs_map = lv_btnm_get_map(tab_btnm);
|
||||
|
||||
uint8_t i = 0;
|
||||
|
||||
while(tabs_map[i][0] != '\0') {
|
||||
if(strcmp(&tabs_map[i][1], tab_name) == 0) break; /*[1] to skip the control byte*/
|
||||
i++;
|
||||
}
|
||||
|
||||
lv_tabview_set_tab_act(tab, i, true);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Realign and resize the elements of Tab view
|
||||
* @param tabview pointer to a Tab view object
|
||||
*/
|
||||
static void tabview_realign(lv_obj_t * tabview)
|
||||
{
|
||||
lv_tabview_ext_t * ext = lv_obj_get_ext_attr(tabview);
|
||||
|
||||
lv_obj_set_width(ext->btns, lv_obj_get_width(tabview));
|
||||
|
||||
if(ext->btns_hide) {
|
||||
lv_obj_set_hidden(ext->btns, true);
|
||||
lv_obj_set_hidden(ext->indic, true);
|
||||
lv_obj_set_height(ext->content, lv_obj_get_height(tabview));
|
||||
lv_obj_align(ext->content, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);
|
||||
}
|
||||
else if(ext->tab_cnt != 0) {
|
||||
lv_obj_set_hidden(ext->btns, false);
|
||||
lv_obj_set_hidden(ext->indic, false);
|
||||
|
||||
lv_style_t * style_btn_bg = lv_tabview_get_style(tabview, LV_TABVIEW_STYLE_BTN_BG);
|
||||
lv_style_t * style_btn_rel = lv_tabview_get_style(tabview, LV_TABVIEW_STYLE_BTN_REL);
|
||||
|
||||
/*Set the indicator widths*/
|
||||
lv_coord_t indic_width = (lv_obj_get_width(tabview) - style_btn_bg->body.padding.inner * (ext->tab_cnt - 1) -
|
||||
2 * style_btn_bg->body.padding.hor) / ext->tab_cnt;
|
||||
lv_obj_set_width(ext->indic, indic_width);
|
||||
|
||||
/*Set the tabs height*/
|
||||
lv_coord_t btns_height = lv_font_get_height(style_btn_rel->text.font) +
|
||||
2 * style_btn_rel->body.padding.ver +
|
||||
2 * style_btn_bg->body.padding.ver;
|
||||
lv_obj_set_height(ext->btns, btns_height);
|
||||
|
||||
lv_obj_set_height(ext->content, lv_obj_get_height(tabview) - lv_obj_get_height(ext->btns));
|
||||
|
||||
switch(ext->btns_pos) {
|
||||
case LV_TABVIEW_BTNS_POS_TOP:
|
||||
lv_obj_align(ext->btns, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);
|
||||
lv_obj_align(ext->content, ext->btns, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
||||
break;
|
||||
case LV_TABVIEW_BTNS_POS_BOTTOM:
|
||||
lv_obj_align(ext->content, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);
|
||||
lv_obj_align(ext->btns, ext->content, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lv_obj_t * pages = lv_obj_get_child(ext->content, NULL);
|
||||
while(pages != NULL) {
|
||||
if(lv_obj_get_signal_func(pages) == tabpage_signal) { /*Be sure adjust only the pages (user can other things)*/
|
||||
lv_obj_set_size(pages, lv_obj_get_width(tabview), lv_obj_get_height(ext->content));
|
||||
}
|
||||
pages = lv_obj_get_child(ext->content, pages);
|
||||
}
|
||||
|
||||
if(!ext->btns_hide) {
|
||||
lv_obj_align(ext->indic, ext->btns, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
|
||||
}
|
||||
|
||||
lv_tabview_set_tab_act(tabview, ext->tab_cur, false);
|
||||
}
|
||||
#endif
|
252
bdk/libs/lvgl/lv_objx/lv_tabview.h
Normal file
252
bdk/libs/lvgl/lv_objx/lv_tabview.h
Normal file
|
@ -0,0 +1,252 @@
|
|||
/**
|
||||
* @file lv_tabview.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TABVIEW_H
|
||||
#define LV_TABVIEW_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_TABVIEW != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_BTNM == 0
|
||||
#error "lv_tabview: lv_btnm is required. Enable it in lv_conf.h (USE_LV_BTNM 1) "
|
||||
#endif
|
||||
|
||||
#if USE_LV_PAGE == 0
|
||||
#error "lv_tabview: lv_page is required. Enable it in lv_conf.h (USE_LV_PAGE 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "../lv_objx/lv_win.h"
|
||||
#include "../lv_objx/lv_page.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/* parametes: pointer to a tabview object, tab_id
|
||||
* return: LV_RES_INV: to prevent the loading of the tab; LV_RES_OK: if everything is fine*/
|
||||
typedef lv_res_t (*lv_tabview_action_t)(lv_obj_t *, uint16_t);
|
||||
|
||||
|
||||
enum {
|
||||
LV_TABVIEW_BTNS_POS_TOP,
|
||||
LV_TABVIEW_BTNS_POS_BOTTOM,
|
||||
};
|
||||
typedef uint8_t lv_tabview_btns_pos_t;
|
||||
|
||||
/*Data of tab*/
|
||||
typedef struct
|
||||
{
|
||||
/*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_obj_t * btns;
|
||||
lv_obj_t * indic;
|
||||
lv_obj_t * content; /*A rectangle to show the current tab*/
|
||||
const char ** tab_name_ptr;
|
||||
lv_point_t point_last;
|
||||
uint16_t tab_cur;
|
||||
uint16_t tab_cnt;
|
||||
uint16_t anim_time;
|
||||
uint8_t slide_enable :1; /*1: enable horizontal sliding by touch pad*/
|
||||
uint8_t draging :1;
|
||||
uint8_t drag_hor :1;
|
||||
uint8_t btns_hide :1;
|
||||
lv_tabview_btns_pos_t btns_pos :1;
|
||||
lv_tabview_action_t tab_load_action;
|
||||
} lv_tabview_ext_t;
|
||||
|
||||
enum {
|
||||
LV_TABVIEW_STYLE_BG,
|
||||
LV_TABVIEW_STYLE_INDIC,
|
||||
LV_TABVIEW_STYLE_BTN_BG,
|
||||
LV_TABVIEW_STYLE_BTN_REL,
|
||||
LV_TABVIEW_STYLE_BTN_PR,
|
||||
LV_TABVIEW_STYLE_BTN_TGL_REL,
|
||||
LV_TABVIEW_STYLE_BTN_TGL_PR,
|
||||
};
|
||||
typedef uint8_t lv_tabview_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
|
||||
/**
|
||||
* Create a Tab view object
|
||||
* @param par pointer to an object, it will be the parent of the new tab
|
||||
* @param copy pointer to a tab object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created tab
|
||||
*/
|
||||
lv_obj_t * lv_tabview_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_tabview_clean(lv_obj_t *obj);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Add a new tab with the given name
|
||||
* @param tabview pointer to Tab view object where to ass the new tab
|
||||
* @param name the text on the tab button
|
||||
* @return pointer to the created page object (lv_page). You can create your content here
|
||||
*/
|
||||
lv_obj_t * lv_tabview_add_tab(lv_obj_t * tabview, const char * name);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set a new tab
|
||||
* @param tabview pointer to Tab view object
|
||||
* @param id index of a tab to load
|
||||
* @param anim_en true: set with sliding animation; false: set immediately
|
||||
*/
|
||||
void lv_tabview_set_tab_act(lv_obj_t * tabview, uint16_t id, bool anim_en);
|
||||
|
||||
/**
|
||||
* Set an action to call when a tab is loaded (Good to create content only if required)
|
||||
* lv_tabview_get_act() still gives the current (old) tab (to remove content from here)
|
||||
* @param tabview pointer to a tabview object
|
||||
* @param action pointer to a function to call when a tab is loaded
|
||||
*/
|
||||
void lv_tabview_set_tab_load_action(lv_obj_t *tabview, lv_tabview_action_t action);
|
||||
|
||||
/**
|
||||
* Enable horizontal sliding with touch pad
|
||||
* @param tabview pointer to Tab view object
|
||||
* @param en true: enable sliding; false: disable sliding
|
||||
*/
|
||||
void lv_tabview_set_sliding(lv_obj_t * tabview, bool en);
|
||||
|
||||
/**
|
||||
* Set the animation time of tab view when a new tab is loaded
|
||||
* @param tabview pointer to Tab view object
|
||||
* @param anim_time time of animation in milliseconds
|
||||
*/
|
||||
void lv_tabview_set_anim_time(lv_obj_t * tabview, uint16_t anim_time);
|
||||
|
||||
/**
|
||||
* Set the style of a tab view
|
||||
* @param tabview pointer to a tan view object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to the new style
|
||||
*/
|
||||
void lv_tabview_set_style(lv_obj_t *tabview, lv_tabview_style_t type, lv_style_t *style);
|
||||
|
||||
/**
|
||||
* Set the position of tab select buttons
|
||||
* @param tabview pointer to a tab view object
|
||||
* @param btns_pos which button position
|
||||
*/
|
||||
void lv_tabview_set_btns_pos(lv_obj_t *tabview, lv_tabview_btns_pos_t btns_pos);
|
||||
|
||||
/**
|
||||
* Set whether tab buttons are hidden
|
||||
* @param tabview pointer to a tab view object
|
||||
* @param en whether tab buttons are hidden
|
||||
*/
|
||||
void lv_tabview_set_btns_hidden(lv_obj_t *tabview, bool en);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the index of the currently active tab
|
||||
* @param tabview pointer to Tab view object
|
||||
* @return the active tab index
|
||||
*/
|
||||
uint16_t lv_tabview_get_tab_act(const lv_obj_t * tabview);
|
||||
|
||||
/**
|
||||
* Get the number of tabs
|
||||
* @param tabview pointer to Tab view object
|
||||
* @return tab count
|
||||
*/
|
||||
uint16_t lv_tabview_get_tab_count(const lv_obj_t * tabview);
|
||||
/**
|
||||
* Get the page (content area) of a tab
|
||||
* @param tabview pointer to Tab view object
|
||||
* @param id index of the tab (>= 0)
|
||||
* @return pointer to page (lv_page) object
|
||||
*/
|
||||
lv_obj_t * lv_tabview_get_tab(const lv_obj_t * tabview, uint16_t id);
|
||||
|
||||
/**
|
||||
* Get the tab load action
|
||||
* @param tabview pointer to a tabview object
|
||||
* @param return the current tab load action
|
||||
*/
|
||||
lv_tabview_action_t lv_tabview_get_tab_load_action(const lv_obj_t *tabview);
|
||||
|
||||
/**
|
||||
* Get horizontal sliding is enabled or not
|
||||
* @param tabview pointer to Tab view object
|
||||
* @return true: enable sliding; false: disable sliding
|
||||
*/
|
||||
bool lv_tabview_get_sliding(const lv_obj_t * tabview);
|
||||
|
||||
/**
|
||||
* Get the animation time of tab view when a new tab is loaded
|
||||
* @param tabview pointer to Tab view object
|
||||
* @return time of animation in milliseconds
|
||||
*/
|
||||
uint16_t lv_tabview_get_anim_time(const lv_obj_t * tabview);
|
||||
|
||||
/**
|
||||
* Get a style of a tab view
|
||||
* @param tabview pointer to a ab view object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_tabview_get_style(const lv_obj_t *tabview, lv_tabview_style_t type);
|
||||
|
||||
/**
|
||||
* Get position of tab select buttons
|
||||
* @param tabview pointer to a ab view object
|
||||
*/
|
||||
lv_tabview_btns_pos_t lv_tabview_get_btns_pos(const lv_obj_t *tabview);
|
||||
|
||||
/**
|
||||
* Get whether tab buttons are hidden
|
||||
* @param tabview pointer to a tab view object
|
||||
* @return whether tab buttons are hidden
|
||||
*/
|
||||
bool lv_tabview_get_btns_hidden(const lv_obj_t *tabview);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_TABVIEW*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_TABVIEW_H*/
|
578
bdk/libs/lvgl/lv_objx/lv_tileview.c
Normal file
578
bdk/libs/lvgl/lv_objx/lv_tileview.c
Normal file
|
@ -0,0 +1,578 @@
|
|||
/**
|
||||
* @file lv_tileview.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_tileview.h"
|
||||
#if USE_LV_TILEVIEW != 0
|
||||
|
||||
#include "lv_cont.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#if USE_LV_ANIMATION
|
||||
# ifndef LV_TILEVIEW_ANIM_TIME
|
||||
# define LV_TILEVIEW_ANIM_TIME 300 /*Animation time loading a tile [ms] (0: no animation) */
|
||||
# endif
|
||||
#else
|
||||
# undef LV_TILEVIEW_ANIM_TIME
|
||||
# define LV_TILEVIEW_ANIM_TIME 0 /*No animations*/
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_tileview_signal(lv_obj_t * tileview, lv_signal_t sign, void * param);
|
||||
static lv_res_t lv_tileview_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, void * param);
|
||||
static lv_res_t element_signal_func(lv_obj_t * element, lv_signal_t sign, void * param);
|
||||
static void drag_end_handler(lv_obj_t * tileview);
|
||||
static bool set_valid_drag_dirs(lv_obj_t * tileview);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
static lv_signal_func_t ancestor_scrl_signal;
|
||||
static lv_design_func_t ancestor_design;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a tileview object
|
||||
* @param par pointer to an object, it will be the parent of the new tileview
|
||||
* @param copy pointer to a tileview object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created tileview
|
||||
*/
|
||||
lv_obj_t * lv_tileview_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("tileview create started");
|
||||
|
||||
/*Create the ancestor of tileview*/
|
||||
lv_obj_t * new_tileview = lv_page_create(par, copy);
|
||||
lv_mem_assert(new_tileview);
|
||||
if(new_tileview == NULL) return NULL;
|
||||
|
||||
/*Allocate the tileview type specific extended data*/
|
||||
lv_tileview_ext_t * ext = lv_obj_allocate_ext_attr(new_tileview, sizeof(lv_tileview_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_tileview);
|
||||
if(ancestor_scrl_signal == NULL) ancestor_scrl_signal = lv_obj_get_signal_func(lv_page_get_scrl(new_tileview));
|
||||
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_tileview);
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->anim_time = LV_TILEVIEW_ANIM_TIME;
|
||||
ext->action = NULL;
|
||||
ext->act_id.x = 0;
|
||||
ext->act_id.y = 0;
|
||||
ext->valid_pos = NULL;
|
||||
|
||||
/*The signal and design functions are not copied so set them here*/
|
||||
lv_obj_set_signal_func(new_tileview, lv_tileview_signal);
|
||||
lv_obj_set_signal_func(lv_page_get_scrl(new_tileview), lv_tileview_scrl_signal);
|
||||
|
||||
/*Init the new tileview*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_size(new_tileview, LV_HOR_RES, LV_VER_RES);
|
||||
lv_obj_set_drag_throw(lv_page_get_scrl(new_tileview), false);
|
||||
lv_page_set_scrl_fit(new_tileview, true, true);
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_page_set_style(new_tileview, LV_PAGE_STYLE_BG, th->tileview.bg);
|
||||
lv_page_set_style(new_tileview, LV_PAGE_STYLE_SCRL, th->tileview.scrl);
|
||||
lv_page_set_style(new_tileview, LV_PAGE_STYLE_SB, th->tileview.sb);
|
||||
} else {
|
||||
lv_page_set_style(new_tileview, LV_PAGE_STYLE_BG, &lv_style_transp_tight);
|
||||
lv_page_set_style(new_tileview, LV_PAGE_STYLE_SCRL, &lv_style_transp_tight);
|
||||
}
|
||||
}
|
||||
/*Copy an existing tileview*/
|
||||
else {
|
||||
lv_tileview_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
ext->act_id.x = copy_ext->act_id.x;
|
||||
ext->act_id.y = copy_ext->act_id.y;
|
||||
ext->action = copy_ext->action;
|
||||
ext->anim_time = copy_ext->anim_time;
|
||||
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_tileview);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("tileview created");
|
||||
|
||||
return new_tileview;
|
||||
}
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Register an object on the tileview. The register object will able to slide the tileview
|
||||
* @param element pointer to an object
|
||||
*/
|
||||
void lv_tileview_add_element(lv_obj_t * element)
|
||||
{
|
||||
lv_obj_set_free_ptr(element, lv_obj_get_signal_func(element));
|
||||
lv_obj_set_signal_func(element, element_signal_func);
|
||||
lv_obj_set_drag_parent(element, true);
|
||||
}
|
||||
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Set the valid position's indices. The scrolling will be possible only to these positions.
|
||||
* @param tileview pointer to a Tileview object
|
||||
* @param valid_pos array width the indices. E.g. `lv_point_t p[] = {{0,0}, {1,0}, {1,1}, {LV_COORD_MIN, LV_COORD_MIN}};`
|
||||
* Must be closed with `{LV_COORD_MIN, LV_COORD_MIN}`. Only the pointer is saved so can't be a local variable.
|
||||
*/
|
||||
void lv_tileview_set_valid_positions(lv_obj_t * tileview, const lv_point_t * valid_pos)
|
||||
{
|
||||
lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
|
||||
ext->valid_pos = valid_pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the tile to be shown
|
||||
* @param tileview pointer to a tileview object
|
||||
* @param x column id (0, 1, 2...)
|
||||
* @param y line id (0, 1, 2...)
|
||||
* @param anim_en true: move with animation
|
||||
*/
|
||||
void lv_tileview_set_tile_act(lv_obj_t * tileview, lv_coord_t x, lv_coord_t y, bool anim_en)
|
||||
{
|
||||
#if USE_LV_ANIMATION == 0
|
||||
anim_en = false;
|
||||
#endif
|
||||
|
||||
lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
|
||||
|
||||
|
||||
uint16_t i;
|
||||
bool valid = false;
|
||||
for(i = 0; ext->valid_pos[i].x != LV_COORD_MIN; i++) {
|
||||
if(ext->valid_pos[i].x == x && ext->valid_pos[i].y == y) {
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(valid == false) return; /*Don't load not valid tiles*/
|
||||
|
||||
lv_res_t res = LV_RES_OK;
|
||||
if(ext->action) res = ext->action(tileview, x, y);
|
||||
if(res != LV_RES_OK) return; /*Prevent the tile loading*/
|
||||
|
||||
ext->act_id.x = x;
|
||||
ext->act_id.y = y;
|
||||
|
||||
lv_coord_t x_coord = -x * lv_obj_get_width(tileview);
|
||||
lv_coord_t y_coord = -y * lv_obj_get_height(tileview);
|
||||
lv_obj_t * scrl = lv_page_get_scrl(tileview);
|
||||
if(anim_en) {
|
||||
#if USE_LV_ANIMATION
|
||||
lv_coord_t x_act = lv_obj_get_x(scrl);
|
||||
lv_coord_t y_act = lv_obj_get_y(scrl);
|
||||
|
||||
lv_anim_t a;
|
||||
a.var = scrl;
|
||||
a.fp = (lv_anim_fp_t)lv_obj_set_x;
|
||||
a.path = lv_anim_path_linear;
|
||||
a.end_cb = NULL;
|
||||
a.act_time = 0;
|
||||
a.time = ext->anim_time;
|
||||
a.playback = 0;
|
||||
a.playback_pause = 0;
|
||||
a.repeat = 0;
|
||||
a.repeat_pause = 0;
|
||||
|
||||
if(x_coord != x_act) {
|
||||
a.start = x_act;
|
||||
a.end = x_coord;
|
||||
lv_anim_create(&a);
|
||||
}
|
||||
|
||||
if(y_coord != y_act) {
|
||||
a.start = y_act;
|
||||
a.end = y_coord;
|
||||
a.fp = (lv_anim_fp_t)lv_obj_set_y;
|
||||
lv_anim_create(&a);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
lv_obj_set_pos(scrl, x_coord, y_coord);
|
||||
}
|
||||
}
|
||||
|
||||
void lv_tileview_set_tile_load_action(lv_obj_t * tileview, lv_tileview_action_t action)
|
||||
{
|
||||
lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
|
||||
ext->action = action;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a tileview.
|
||||
* @param tileview pointer to tileview object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_tileview_set_style(lv_obj_t * tileview, lv_tileview_style_t type, lv_style_t * style)
|
||||
{
|
||||
|
||||
switch(type) {
|
||||
case LV_TILEVIEW_STYLE_BG:
|
||||
lv_obj_set_style(tileview, style);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/*
|
||||
* New object specific "get" functions come here
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get style of a tileview.
|
||||
* @param tileview pointer to tileview object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
*/
|
||||
lv_style_t * lv_tileview_get_style(const lv_obj_t * tileview, lv_tileview_style_t type)
|
||||
{
|
||||
lv_style_t * style = NULL;
|
||||
switch(type) {
|
||||
case LV_TILEVIEW_STYLE_BG:
|
||||
style = lv_obj_get_style(tileview);
|
||||
break;
|
||||
default:
|
||||
style = NULL;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/*
|
||||
* New object specific "other" functions come here
|
||||
*/
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the tileview
|
||||
* @param tileview pointer to a tileview object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_tileview_signal(lv_obj_t * tileview, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(tileview, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
|
||||
if(sign == LV_SIGNAL_CLEANUP) {
|
||||
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_tileview";
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal function of the tileview scrollable
|
||||
* @param tileview pointer to the scrollable part of the tileview object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_tileview_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, void * param)
|
||||
{
|
||||
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_scrl_signal(scrl, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_obj_t * tileview = lv_obj_get_parent(scrl);
|
||||
lv_style_t * style_bg = lv_tileview_get_style(tileview, LV_TILEVIEW_STYLE_BG);
|
||||
|
||||
|
||||
/*Apply constraint on moving of the tileview*/
|
||||
if(sign == LV_SIGNAL_CORD_CHG) {
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
if(indev) {
|
||||
lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
|
||||
|
||||
/*Set horizontal drag constraint if no vertical constraint an dragged to valid x direction */
|
||||
if(ext->drag_ver == 0 &&
|
||||
((ext->drag_right_en && indev->proc.drag_sum.x <= -LV_INDEV_DRAG_LIMIT) ||
|
||||
(ext->drag_left_en && indev->proc.drag_sum.x >= LV_INDEV_DRAG_LIMIT))) {
|
||||
ext->drag_hor = 1;
|
||||
}
|
||||
/*Set vertical drag constraint if no horizontal constraint an dragged to valid y direction */
|
||||
if(ext->drag_hor == 0 &&
|
||||
((ext->drag_bottom_en && indev->proc.drag_sum.y <= -LV_INDEV_DRAG_LIMIT) ||
|
||||
(ext->drag_top_en && indev->proc.drag_sum.y >= LV_INDEV_DRAG_LIMIT))) {
|
||||
ext->drag_ver = 1;
|
||||
}
|
||||
|
||||
if(ext->drag_hor) {
|
||||
ext->page.edge_flash.top_ip = 0;
|
||||
ext->page.edge_flash.bottom_ip = 0;
|
||||
}
|
||||
|
||||
if(ext->drag_ver) {
|
||||
ext->page.edge_flash.right_ip = 0;
|
||||
ext->page.edge_flash.left_ip = 0;
|
||||
}
|
||||
|
||||
lv_coord_t x = lv_obj_get_x(scrl);
|
||||
lv_coord_t y = lv_obj_get_y(scrl);
|
||||
lv_coord_t h = lv_obj_get_height(tileview);
|
||||
lv_coord_t w = lv_obj_get_width(tileview);
|
||||
if(ext->drag_top_en == 0) {
|
||||
if(y > -(ext->act_id.y * h) && indev->proc.vect.y > 0 && ext->drag_hor == 0) {
|
||||
if(ext->page.edge_flash.enabled &&
|
||||
ext->page.edge_flash.left_ip == 0 && ext->page.edge_flash.right_ip == 0 &&
|
||||
ext->page.edge_flash.top_ip == 0 && ext->page.edge_flash.bottom_ip == 0) {
|
||||
ext->page.edge_flash.top_ip = 1;
|
||||
lv_page_start_edge_flash(tileview);
|
||||
}
|
||||
|
||||
lv_obj_set_y(scrl, -ext->act_id.y * h + style_bg->body.padding.ver);
|
||||
}
|
||||
}
|
||||
if(ext->drag_bottom_en == 0 && indev->proc.vect.y < 0 && ext->drag_hor == 0) {
|
||||
if(y < -(ext->act_id.y * h)) {
|
||||
if(ext->page.edge_flash.enabled &&
|
||||
ext->page.edge_flash.left_ip == 0 && ext->page.edge_flash.right_ip == 0 &&
|
||||
ext->page.edge_flash.top_ip == 0 && ext->page.edge_flash.bottom_ip == 0) {
|
||||
ext->page.edge_flash.bottom_ip = 1;
|
||||
lv_page_start_edge_flash(tileview);
|
||||
}
|
||||
}
|
||||
|
||||
lv_obj_set_y(scrl, -ext->act_id.y * h + style_bg->body.padding.ver);
|
||||
}
|
||||
if(ext->drag_left_en == 0) {
|
||||
if(x > -(ext->act_id.x * w) && indev->proc.vect.x > 0 && ext->drag_ver == 0) {
|
||||
if(ext->page.edge_flash.enabled &&
|
||||
ext->page.edge_flash.left_ip == 0 && ext->page.edge_flash.right_ip == 0 &&
|
||||
ext->page.edge_flash.top_ip == 0 && ext->page.edge_flash.bottom_ip == 0) {
|
||||
ext->page.edge_flash.left_ip = 1;
|
||||
lv_page_start_edge_flash(tileview);
|
||||
}
|
||||
|
||||
lv_obj_set_x(scrl, -ext->act_id.x * w + style_bg->body.padding.hor);
|
||||
}
|
||||
}
|
||||
if(ext->drag_right_en == 0 && indev->proc.vect.x < 0 && ext->drag_ver == 0) {
|
||||
if(x < -(ext->act_id.x * w)) {
|
||||
if(ext->page.edge_flash.enabled &&
|
||||
ext->page.edge_flash.left_ip == 0 && ext->page.edge_flash.right_ip == 0 &&
|
||||
ext->page.edge_flash.top_ip == 0 && ext->page.edge_flash.bottom_ip == 0) {
|
||||
ext->page.edge_flash.right_ip = 1;
|
||||
lv_page_start_edge_flash(tileview);
|
||||
}
|
||||
}
|
||||
|
||||
lv_obj_set_x(scrl, -ext->act_id.x * w + style_bg->body.padding.hor);
|
||||
}
|
||||
|
||||
/*Apply the drag constraints*/
|
||||
if(ext->drag_ver == 0) lv_obj_set_y(scrl, - ext->act_id.y * lv_obj_get_height(tileview) + style_bg->body.padding.ver);
|
||||
if(ext->drag_hor == 0) lv_obj_set_x(scrl, - ext->act_id.x * lv_obj_get_width(tileview) + style_bg->body.padding.hor);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is applied called for the elements of the tileview. Used when the element is
|
||||
* @param element
|
||||
* @param sign
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
static lv_res_t element_signal_func(lv_obj_t * element, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
lv_signal_func_t sign_func = lv_obj_get_free_ptr(element);
|
||||
res = sign_func(element, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
/*Initialize some variables on PRESS*/
|
||||
if(sign == LV_SIGNAL_PRESSED) {
|
||||
/*Get the tileview from the element*/
|
||||
lv_obj_t * tileview = lv_obj_get_parent(element);
|
||||
while(tileview) {
|
||||
if(lv_obj_get_signal_func(tileview) != lv_tileview_signal) tileview = lv_obj_get_parent(tileview);
|
||||
else break;
|
||||
}
|
||||
|
||||
if(tileview) {
|
||||
lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
|
||||
ext->drag_hor = 0;
|
||||
ext->drag_ver = 0;
|
||||
set_valid_drag_dirs(tileview);
|
||||
}
|
||||
}
|
||||
|
||||
/*Animate the tabview to the correct location on RELEASE*/
|
||||
else if(sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_RELEASED) {
|
||||
|
||||
/*Get the tileview from the element*/
|
||||
lv_obj_t * tileview = lv_obj_get_parent(element);
|
||||
while(tileview) {
|
||||
if(lv_obj_get_signal_func(tileview) != lv_tileview_signal) tileview = lv_obj_get_parent(tileview);
|
||||
else break;
|
||||
}
|
||||
|
||||
if(tileview) {
|
||||
/* If the element was dragged and it moved the tileview finish the drag manually to
|
||||
* let the tileview to finish the move.*/
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
|
||||
if(indev->proc.drag_in_prog && (ext->drag_hor || ext->drag_ver)) {
|
||||
|
||||
lv_obj_t * drag_obj = element;
|
||||
while(lv_obj_get_drag_parent(drag_obj)) {
|
||||
drag_obj = lv_obj_get_parent(drag_obj);
|
||||
if(drag_obj == NULL) break;
|
||||
}
|
||||
indev->proc.drag_in_prog = 0;
|
||||
if(drag_obj) drag_obj->signal_func(drag_obj, LV_SIGNAL_DRAG_END, NULL);
|
||||
}
|
||||
|
||||
drag_end_handler(tileview);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the user releases an element of the tileview after dragging it.
|
||||
* @param tileview pointer to a tileview object
|
||||
*/
|
||||
static void drag_end_handler(lv_obj_t * tileview)
|
||||
{
|
||||
lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
lv_point_t point_act;
|
||||
lv_indev_get_point(indev, &point_act);
|
||||
lv_obj_t * scrl = lv_page_get_scrl(tileview);
|
||||
lv_point_t p;
|
||||
|
||||
p.x = - (scrl->coords.x1 - LV_HOR_RES / 2);
|
||||
p.y = - (scrl->coords.y1 - LV_VER_RES / 2);
|
||||
|
||||
/*From the drag vector (drag throw) predict the end position*/
|
||||
if(ext->drag_hor) {
|
||||
lv_point_t vect;
|
||||
lv_indev_get_vect(indev, &vect);
|
||||
lv_coord_t predict = 0;
|
||||
|
||||
while(vect.x != 0) {
|
||||
predict += vect.x;
|
||||
vect.x = vect.x * (100 - LV_INDEV_DRAG_THROW) / 100;
|
||||
}
|
||||
|
||||
p.x -= predict;
|
||||
}
|
||||
else if(ext->drag_ver) {
|
||||
lv_point_t vect;
|
||||
lv_indev_get_vect(indev, &vect);
|
||||
lv_coord_t predict = 0;
|
||||
|
||||
while(vect.y != 0) {
|
||||
predict += vect.y;
|
||||
vect.y = vect.y * (100 - LV_INDEV_DRAG_THROW) / 100;
|
||||
}
|
||||
|
||||
p.y -= predict;
|
||||
}
|
||||
|
||||
/*Get the index of the tile*/
|
||||
p.x = p.x / lv_obj_get_width(tileview);
|
||||
p.y = p.y / lv_obj_get_height(tileview);
|
||||
|
||||
/*Max +- move*/
|
||||
lv_coord_t x_move = p.x - ext->act_id.x;
|
||||
lv_coord_t y_move = p.y - ext->act_id.y;
|
||||
if(x_move < -1) x_move = -1;
|
||||
if(x_move > 1) x_move = 1;
|
||||
if(y_move < -1) y_move = -1;
|
||||
if(y_move > 1) y_move = 1;
|
||||
|
||||
/*Set the new tile*/
|
||||
lv_tileview_set_tile_act(tileview, ext->act_id.x + x_move, ext->act_id.y + y_move,true);
|
||||
}
|
||||
|
||||
static bool set_valid_drag_dirs(lv_obj_t * tileview)
|
||||
{
|
||||
|
||||
lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
|
||||
if(ext->valid_pos == NULL) return false;
|
||||
|
||||
ext->drag_bottom_en = 0;
|
||||
ext->drag_top_en = 0;
|
||||
ext->drag_left_en = 0;
|
||||
ext->drag_right_en = 0;
|
||||
|
||||
uint16_t i;
|
||||
for(i = 0; ext->valid_pos[i].x != LV_COORD_MIN; i++) {
|
||||
if(ext->valid_pos[i].x == ext->act_id.x && ext->valid_pos[i].y == ext->act_id.y - 1) ext->drag_top_en = 1;
|
||||
if(ext->valid_pos[i].x == ext->act_id.x && ext->valid_pos[i].y == ext->act_id.y + 1) ext->drag_bottom_en = 1;
|
||||
if(ext->valid_pos[i].x == ext->act_id.x - 1 && ext->valid_pos[i].y == ext->act_id.y) ext->drag_left_en = 1;
|
||||
if(ext->valid_pos[i].x == ext->act_id.x + 1 && ext->valid_pos[i].y == ext->act_id.y) ext->drag_right_en = 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
163
bdk/libs/lvgl/lv_objx/lv_tileview.h
Normal file
163
bdk/libs/lvgl/lv_objx/lv_tileview.h
Normal file
|
@ -0,0 +1,163 @@
|
|||
/**
|
||||
* @file lv_tileview.h
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LV_TILEVIEW_H
|
||||
#define LV_TILEVIEW_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_TILEVIEW != 0
|
||||
|
||||
#include "../lv_objx/lv_page.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
|
||||
|
||||
/* parametes: pointer to a tileview object, x, y (tile coordinates to load)
|
||||
* return: LV_RES_INV: to prevent the loading of the tab; LV_RES_OK: if everything is fine*/
|
||||
typedef lv_res_t (*lv_tileview_action_t)(lv_obj_t *, lv_coord_t, lv_coord_t);
|
||||
|
||||
/*Data of tileview*/
|
||||
typedef struct {
|
||||
lv_page_ext_t page;
|
||||
/*New data for this type */
|
||||
const lv_point_t * valid_pos;
|
||||
uint16_t anim_time;
|
||||
lv_tileview_action_t action;
|
||||
lv_point_t act_id;
|
||||
uint8_t drag_top_en :1;
|
||||
uint8_t drag_bottom_en :1;
|
||||
uint8_t drag_left_en :1;
|
||||
uint8_t drag_right_en :1;
|
||||
uint8_t drag_hor :1;
|
||||
uint8_t drag_ver :1;
|
||||
} lv_tileview_ext_t;
|
||||
|
||||
|
||||
/*Styles*/
|
||||
enum {
|
||||
LV_TILEVIEW_STYLE_BG,
|
||||
};
|
||||
typedef uint8_t lv_tileview_style_t;
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a tileview objects
|
||||
* @param par pointer to an object, it will be the parent of the new tileview
|
||||
* @param copy pointer to a tileview object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created tileview
|
||||
*/
|
||||
lv_obj_t * lv_tileview_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Register an object on the tileview. The register object will able to slide the tileview
|
||||
* @param element pointer to an object
|
||||
*/
|
||||
void lv_tileview_add_element(lv_obj_t * element);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
|
||||
/**
|
||||
* Set the valid position's indices. The scrolling will be possible only to these positions.
|
||||
* @param tileview pointer to a Tileview object
|
||||
* @param valid_pos array width the indices. E.g. `lv_point_t p[] = {{0,0}, {1,0}, {1,1}, {LV_COORD_MIN, LV_COORD_MIN}};`
|
||||
* Must be closed with `{LV_COORD_MIN, LV_COORD_MIN}`. Only the pointer is saved so can't be a local variable.
|
||||
*/
|
||||
void lv_tileview_set_valid_positions(lv_obj_t * tileview, const lv_point_t * valid_pos);
|
||||
|
||||
/**
|
||||
* Set the tile to be shown
|
||||
* @param tileview pointer to a tileview object
|
||||
* @param x column id (0, 1, 2...)
|
||||
* @param y line id (0, 1, 2...)
|
||||
* @param anim_en true: move with animation
|
||||
*/
|
||||
void lv_tileview_set_tile_act(lv_obj_t * tileview, lv_coord_t x, lv_coord_t y, bool anim_en);
|
||||
|
||||
/**
|
||||
* Enable the edge flash effect. (Show an arc when the an edge is reached)
|
||||
* @param tileview pointer to a Tileview
|
||||
* @param en true or false to enable/disable end flash
|
||||
*/
|
||||
static inline void lv_tileview_set_edge_flash(lv_obj_t * tileview, bool en)
|
||||
{
|
||||
lv_page_set_edge_flash(tileview, en);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a tileview.
|
||||
* @param tileview pointer to tileview object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_tileview_set_style(lv_obj_t * tileview, lv_tileview_style_t type, lv_style_t *style);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the scroll propagation property
|
||||
* @param tileview pointer to a Tileview
|
||||
* @return true or false
|
||||
*/
|
||||
static inline bool lv_tileview_get_edge_flash(lv_obj_t * tileview)
|
||||
{
|
||||
return lv_page_get_edge_flash(tileview);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get style of a tileview.
|
||||
* @param tileview pointer to tileview object
|
||||
* @param type which style should be get
|
||||
* @return style pointer to the style
|
||||
*/
|
||||
lv_style_t * lv_tileview_get_style(const lv_obj_t * tileview, lv_tileview_style_t type);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_TILEVIEW*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_TILEVIEW_H*/
|
591
bdk/libs/lvgl/lv_objx/lv_win.c
Normal file
591
bdk/libs/lvgl/lv_objx/lv_win.c
Normal file
|
@ -0,0 +1,591 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file lv_win.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_win.h"
|
||||
#if USE_LV_WIN != 0
|
||||
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_win_signal(lv_obj_t * win, lv_signal_t sign, void * param);
|
||||
static void lv_win_realign(lv_obj_t * win);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static lv_signal_func_t ancestor_signal;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a window objects
|
||||
* @param par pointer to an object, it will be the parent of the new window
|
||||
* @param copy pointer to a window object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created window
|
||||
*/
|
||||
lv_obj_t * lv_win_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
LV_LOG_TRACE("window create started");
|
||||
|
||||
/*Create the ancestor object*/
|
||||
lv_obj_t * new_win = lv_obj_create(par, copy);
|
||||
lv_mem_assert(new_win);
|
||||
if(new_win == NULL) return NULL;
|
||||
|
||||
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_win);
|
||||
|
||||
/*Allocate the object type specific extended data*/
|
||||
lv_win_ext_t * ext = lv_obj_allocate_ext_attr(new_win, sizeof(lv_win_ext_t));
|
||||
lv_mem_assert(ext);
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
ext->page = NULL;
|
||||
ext->header = NULL;
|
||||
ext->title = NULL;
|
||||
ext->style_header = &lv_style_plain_color;
|
||||
ext->style_btn_rel = &lv_style_btn_rel;
|
||||
ext->style_btn_pr = &lv_style_btn_pr;
|
||||
ext->btn_size = (LV_DPI) / 2;
|
||||
|
||||
/*Init the new window object*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_size(new_win, LV_HOR_RES, LV_VER_RES);
|
||||
lv_obj_set_pos(new_win, 0, 0);
|
||||
lv_obj_set_style(new_win, &lv_style_pretty);
|
||||
|
||||
ext->page = lv_page_create(new_win, NULL);
|
||||
lv_obj_set_protect(ext->page, LV_PROTECT_PARENT);
|
||||
lv_page_set_sb_mode(ext->page, LV_SB_MODE_AUTO);
|
||||
lv_page_set_arrow_scroll(ext->page, true);
|
||||
|
||||
/*Create a holder for the header*/
|
||||
ext->header = lv_obj_create(new_win, NULL);
|
||||
/*Move back the header because it is automatically moved to the scrollable */
|
||||
lv_obj_set_protect(ext->header, LV_PROTECT_PARENT);
|
||||
lv_obj_set_parent(ext->header, new_win);
|
||||
lv_obj_set_width(ext->header, LV_HOR_RES - 62);////
|
||||
ext->btn_size = lv_obj_get_height(ext->header) - 3;////
|
||||
|
||||
/*Create a title on the header*/
|
||||
ext->title = lv_label_create(ext->header, NULL);
|
||||
lv_label_set_text(ext->title, "My title");
|
||||
|
||||
/*Set the default styles*/
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_win_set_style(new_win, LV_WIN_STYLE_BG, th->win.bg);
|
||||
lv_win_set_style(new_win, LV_WIN_STYLE_SB, th->win.sb);
|
||||
lv_win_set_style(new_win, LV_WIN_STYLE_HEADER, th->win.header);
|
||||
lv_win_set_style(new_win, LV_WIN_STYLE_CONTENT_BG, th->win.content.bg);
|
||||
lv_win_set_style(new_win, LV_WIN_STYLE_CONTENT_SCRL, th->win.content.scrl);
|
||||
lv_win_set_style(new_win, LV_WIN_STYLE_BTN_REL, th->win.btn.rel);
|
||||
lv_win_set_style(new_win, LV_WIN_STYLE_BTN_PR, th->win.btn.pr);
|
||||
} else {
|
||||
lv_win_set_style(new_win, LV_WIN_STYLE_BG, &lv_style_plain);
|
||||
lv_win_set_style(new_win, LV_WIN_STYLE_CONTENT_BG, &lv_style_plain);
|
||||
lv_win_set_style(new_win, LV_WIN_STYLE_CONTENT_SCRL, &lv_style_transp);
|
||||
lv_win_set_style(new_win, LV_WIN_STYLE_HEADER, &lv_style_plain_color);
|
||||
}
|
||||
|
||||
lv_obj_set_signal_func(new_win, lv_win_signal);
|
||||
lv_obj_set_size(new_win, LV_HOR_RES, LV_VER_RES);
|
||||
}
|
||||
/*Copy an existing object*/
|
||||
else {
|
||||
lv_win_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
|
||||
/*Create the objects*/
|
||||
ext->header = lv_obj_create(new_win, copy_ext->header);
|
||||
ext->title = lv_label_create(ext->header, copy_ext->title);
|
||||
ext->page = lv_page_create(new_win, copy_ext->page);
|
||||
ext->btn_size = copy_ext->btn_size;
|
||||
|
||||
/*Copy the control buttons*/
|
||||
lv_obj_t * child;
|
||||
lv_obj_t * cbtn;
|
||||
child = lv_obj_get_child_back(copy_ext->header, NULL);
|
||||
child = lv_obj_get_child_back(copy_ext->header, child); /*Sip the title*/
|
||||
while(child != NULL) {
|
||||
cbtn = lv_btn_create(ext->header, child);
|
||||
lv_img_create(cbtn, lv_obj_get_child(child, NULL));
|
||||
child = lv_obj_get_child_back(copy_ext->header, child);
|
||||
}
|
||||
|
||||
lv_obj_set_signal_func(new_win, lv_win_signal);
|
||||
|
||||
/*Refresh the style with new signal function*/
|
||||
lv_obj_refresh_style(new_win);
|
||||
}
|
||||
|
||||
lv_win_realign(new_win);
|
||||
|
||||
LV_LOG_INFO("window created");
|
||||
|
||||
return new_win;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_win_clean(lv_obj_t * obj)
|
||||
{
|
||||
lv_obj_t * scrl = lv_page_get_scrl(obj);
|
||||
lv_obj_clean(scrl);
|
||||
}
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Add control button to the header of the window
|
||||
* @param win pointer to a window object
|
||||
* @param img_src an image source ('lv_img_t' variable, path to file or a symbol)
|
||||
* @param rel_action a function pointer to call when the button is released
|
||||
* @return pointer to the created button object
|
||||
*/
|
||||
lv_obj_t * lv_win_add_btn(lv_obj_t * win, const void * img_src, const char * label_src, lv_action_t rel_action)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
|
||||
lv_obj_t * btn = lv_btn_create(ext->header, NULL);
|
||||
lv_btn_set_style(btn, LV_BTN_STYLE_REL, ext->style_btn_rel);
|
||||
lv_btn_set_style(btn, LV_BTN_STYLE_PR, ext->style_btn_pr);
|
||||
lv_obj_set_size(btn, lv_obj_get_width(btn), ext->btn_size);
|
||||
lv_btn_set_fit(btn, true, false);
|
||||
lv_btn_set_action(btn, LV_BTN_ACTION_CLICK, rel_action);
|
||||
|
||||
if (img_src)
|
||||
{
|
||||
lv_obj_t * img = lv_img_create(btn, NULL);
|
||||
lv_obj_set_click(img, false);
|
||||
lv_img_set_src(img, img_src);
|
||||
}
|
||||
else if (label_src)
|
||||
{
|
||||
lv_obj_t *label = lv_label_create(btn, NULL);
|
||||
lv_label_set_recolor(label, true);
|
||||
lv_label_set_text(label, label_src);
|
||||
}
|
||||
|
||||
lv_win_realign(win);
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* A release action which can be assigned to a window control button to close it
|
||||
* @param btn pointer to the released button
|
||||
* @return always LV_ACTION_RES_INV because the button is deleted with the window
|
||||
*/
|
||||
lv_res_t lv_win_close_action(lv_obj_t * btn)
|
||||
{
|
||||
lv_obj_t * win = lv_win_get_from_btn(btn);
|
||||
|
||||
lv_obj_del(win);
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the title of a window
|
||||
* @param win pointer to a window object
|
||||
* @param title string of the new title
|
||||
*/
|
||||
void lv_win_set_title(lv_obj_t * win, const char * title)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
|
||||
lv_label_set_text(ext->title, title);
|
||||
lv_win_realign(win);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the control button size of a window
|
||||
* @param win pointer to a window object
|
||||
* @param size control button size
|
||||
*/
|
||||
void lv_win_set_btn_size(lv_obj_t * win, lv_coord_t size)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
if(ext->btn_size == size) return;
|
||||
|
||||
ext->btn_size = size;
|
||||
|
||||
lv_win_realign(win);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the layout of the window
|
||||
* @param win pointer to a window object
|
||||
* @param layout the layout from 'lv_layout_t'
|
||||
*/
|
||||
void lv_win_set_layout(lv_obj_t * win, lv_layout_t layout)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
lv_page_set_scrl_layout(ext->page, layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scroll bar mode of a window
|
||||
* @param win pointer to a window object
|
||||
* @param sb_mode the new scroll bar mode from 'lv_sb_mode_t'
|
||||
*/
|
||||
void lv_win_set_sb_mode(lv_obj_t * win, lv_sb_mode_t sb_mode)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
lv_page_set_sb_mode(ext->page, sb_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a style of a window
|
||||
* @param win pointer to a window object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_win_set_style(lv_obj_t * win, lv_win_style_t type, lv_style_t * style)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
|
||||
switch(type) {
|
||||
case LV_WIN_STYLE_BG:
|
||||
lv_obj_set_style(win, style);
|
||||
lv_win_realign(win);
|
||||
break;
|
||||
case LV_WIN_STYLE_CONTENT_BG:
|
||||
lv_page_set_style(ext->page, LV_PAGE_STYLE_BG, style);
|
||||
break;
|
||||
case LV_WIN_STYLE_CONTENT_SCRL:
|
||||
lv_page_set_style(ext->page, LV_PAGE_STYLE_SCRL, style);
|
||||
break;
|
||||
case LV_WIN_STYLE_SB:
|
||||
lv_page_set_style(ext->page, LV_PAGE_STYLE_SB, style);
|
||||
break;
|
||||
case LV_WIN_STYLE_HEADER:
|
||||
lv_obj_set_style(ext->header, style);
|
||||
lv_win_realign(win);
|
||||
break;
|
||||
case LV_WIN_STYLE_BTN_REL:
|
||||
ext->style_btn_rel = style;
|
||||
break;
|
||||
case LV_WIN_STYLE_BTN_PR:
|
||||
ext->style_btn_pr = style;
|
||||
break;
|
||||
}
|
||||
|
||||
/*Refresh the existing buttons*/
|
||||
if(type == LV_WIN_STYLE_BTN_REL || type == LV_WIN_STYLE_BTN_PR) {
|
||||
lv_obj_t * btn;
|
||||
btn = lv_obj_get_child_back(ext->header, NULL);
|
||||
btn = lv_obj_get_child_back(ext->header, btn); /*Skip the title*/
|
||||
while(btn != NULL) {
|
||||
if(type == LV_WIN_STYLE_BTN_REL) lv_btn_set_style(btn, LV_BTN_STYLE_REL, style);
|
||||
else lv_btn_set_style(btn, LV_BTN_STYLE_PR, style);
|
||||
btn = lv_obj_get_child_back(ext->header, btn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set drag status of a window. If set to 'true' window can be dragged like on a PC.
|
||||
* @param win pointer to a window object
|
||||
* @param en whether dragging is enabled
|
||||
*/
|
||||
void lv_win_set_drag(lv_obj_t *win, bool en)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
lv_obj_t * win_header = ext->header;
|
||||
lv_obj_set_drag_parent(win_header, en);
|
||||
lv_obj_set_drag(win, en);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the title of a window
|
||||
* @param win pointer to a window object
|
||||
* @return title string of the window
|
||||
*/
|
||||
const char * lv_win_get_title(const lv_obj_t * win)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
return lv_label_get_text(ext->title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content holder object of window (`lv_page`) to allow additional customization
|
||||
* @param win pointer to a window object
|
||||
* @return the Page object where the window's content is
|
||||
*/
|
||||
lv_obj_t * lv_win_get_content(const lv_obj_t * win)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
return ext->page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the control button size of a window
|
||||
* @param win pointer to a window object
|
||||
* @return control button size
|
||||
*/
|
||||
lv_coord_t lv_win_get_btn_size(const lv_obj_t * win)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
return ext->btn_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pointer of a widow from one of its control button.
|
||||
* It is useful in the action of the control buttons where only button is known.
|
||||
* @param ctrl_btn pointer to a control button of a window
|
||||
* @return pointer to the window of 'ctrl_btn'
|
||||
*/
|
||||
lv_obj_t * lv_win_get_from_btn(const lv_obj_t * ctrl_btn)
|
||||
{
|
||||
lv_obj_t * header = lv_obj_get_parent(ctrl_btn);
|
||||
lv_obj_t * win = lv_obj_get_parent(header);
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the layout of a window
|
||||
* @param win pointer to a window object
|
||||
* @return the layout of the window (from 'lv_layout_t')
|
||||
*/
|
||||
lv_layout_t lv_win_get_layout(lv_obj_t * win)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
return lv_page_get_scrl_layout(ext->page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scroll bar mode of a window
|
||||
* @param win pointer to a window object
|
||||
* @return the scroll bar mode of the window (from 'lv_sb_mode_t')
|
||||
*/
|
||||
lv_sb_mode_t lv_win_get_sb_mode(lv_obj_t * win)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
return lv_page_get_sb_mode(ext->page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get width of the content area (page scrollable) of the window
|
||||
* @param win pointer to a window object
|
||||
* @return the width of the content_bg area
|
||||
*/
|
||||
lv_coord_t lv_win_get_width(lv_obj_t * win)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
lv_obj_t * scrl = lv_page_get_scrl(ext->page);
|
||||
lv_style_t * style_scrl = lv_obj_get_style(scrl);
|
||||
|
||||
return lv_obj_get_width(scrl) - 2 * style_scrl->body.padding.hor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a style of a window
|
||||
* @param win pointer to a button object
|
||||
* @param type which style window be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_win_get_style(const lv_obj_t * win, lv_win_style_t type)
|
||||
{
|
||||
lv_style_t * style = NULL;
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
|
||||
switch(type) {
|
||||
case LV_WIN_STYLE_BG:
|
||||
style = lv_obj_get_style(win);
|
||||
break;
|
||||
case LV_WIN_STYLE_CONTENT_BG:
|
||||
style = lv_page_get_style(ext->page, LV_PAGE_STYLE_BG);
|
||||
break;
|
||||
case LV_WIN_STYLE_CONTENT_SCRL:
|
||||
style = lv_page_get_style(ext->page, LV_PAGE_STYLE_SCRL);
|
||||
break;
|
||||
case LV_WIN_STYLE_SB:
|
||||
style = lv_page_get_style(ext->page, LV_PAGE_STYLE_SB);
|
||||
break;
|
||||
case LV_WIN_STYLE_HEADER:
|
||||
style = lv_obj_get_style(ext->header);
|
||||
break;
|
||||
case LV_WIN_STYLE_BTN_REL:
|
||||
style = ext->style_btn_rel;
|
||||
break;
|
||||
case LV_WIN_STYLE_BTN_PR:
|
||||
style = ext->style_btn_pr;
|
||||
break;
|
||||
default:
|
||||
style = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Focus on an object. It ensures that the object will be visible in the window.
|
||||
* @param win pointer to a window object
|
||||
* @param obj pointer to an object to focus (must be in the window)
|
||||
* @param anim_time scroll animation time in milliseconds (0: no animation)
|
||||
*/
|
||||
void lv_win_focus(lv_obj_t * win, lv_obj_t * obj, uint16_t anim_time)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
lv_page_focus(ext->page, obj, anim_time);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Signal function of the window
|
||||
* @param win pointer to a window object
|
||||
* @param sign a signal type from lv_signal_t enum
|
||||
* @param param pointer to a signal specific variable
|
||||
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
|
||||
*/
|
||||
static lv_res_t lv_win_signal(lv_obj_t * win, lv_signal_t sign, void * param)
|
||||
{
|
||||
lv_res_t res;
|
||||
|
||||
/* Include the ancient signal function */
|
||||
res = ancestor_signal(win, sign, param);
|
||||
if(res != LV_RES_OK) return res;
|
||||
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
if(sign == LV_SIGNAL_CHILD_CHG) { /*Move children to the page*/
|
||||
lv_obj_t * page = ext->page;
|
||||
if(page != NULL) {
|
||||
lv_obj_t * child;
|
||||
child = lv_obj_get_child(win, NULL);
|
||||
while(child != NULL) {
|
||||
if(lv_obj_is_protected(child, LV_PROTECT_PARENT) == false) {
|
||||
lv_obj_t * tmp = child;
|
||||
child = lv_obj_get_child(win, child); /*Get the next child before move this*/
|
||||
lv_obj_set_parent(tmp, page);
|
||||
} else {
|
||||
child = lv_obj_get_child(win, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_STYLE_CHG) {
|
||||
lv_win_realign(win);
|
||||
} else if(sign == LV_SIGNAL_CORD_CHG) {
|
||||
/*If the size is changed refresh the window*/
|
||||
if(lv_area_get_width(param) != lv_obj_get_width(win) ||
|
||||
lv_area_get_height(param) != lv_obj_get_height(win)) {
|
||||
lv_win_realign(win);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_CLEANUP) {
|
||||
ext->header = NULL; /*These objects were children so they are already invalid*/
|
||||
ext->page = NULL;
|
||||
ext->title = NULL;
|
||||
} else if(sign == LV_SIGNAL_CONTROLL) {
|
||||
/*Forward all the control signals to the page*/
|
||||
ext->page->signal_func(ext->page, sign, param);
|
||||
} else if(sign == LV_SIGNAL_GET_TYPE) {
|
||||
lv_obj_type_t * buf = param;
|
||||
uint8_t i;
|
||||
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
|
||||
if(buf->type[i] == NULL) break;
|
||||
}
|
||||
buf->type[i] = "lv_win";
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Realign the building elements of a window
|
||||
* @param win pointer to window objectker
|
||||
*/
|
||||
static void lv_win_realign(lv_obj_t * win)
|
||||
{
|
||||
lv_win_ext_t * ext = lv_obj_get_ext_attr(win);
|
||||
|
||||
if(ext->page == NULL || ext->header == NULL || ext->title == NULL) return;
|
||||
|
||||
lv_style_t * header_style = lv_win_get_style(win, LV_WIN_STYLE_HEADER);
|
||||
lv_obj_set_size(ext->header, lv_obj_get_width(win) - 62, ext->btn_size + 2 * header_style->body.padding.ver);
|
||||
|
||||
bool first_btn = true;
|
||||
lv_obj_t * btn;
|
||||
lv_obj_t * btn_prev = NULL;
|
||||
/*Refresh the size of all control buttons*/
|
||||
btn = lv_obj_get_child_back(ext->header, NULL);
|
||||
btn = lv_obj_get_child_back(ext->header, btn); /*Skip the title*/
|
||||
while(btn != NULL) {
|
||||
lv_obj_set_size(btn, lv_obj_get_width(btn), ext->btn_size);
|
||||
if(first_btn) {
|
||||
lv_obj_align(btn, ext->header, LV_ALIGN_IN_RIGHT_MID, - header_style->body.padding.hor, 0);
|
||||
first_btn = false;
|
||||
} else {
|
||||
lv_obj_align(btn, btn_prev, LV_ALIGN_OUT_LEFT_MID, - header_style->body.padding.inner, 0);
|
||||
}
|
||||
btn_prev = btn;
|
||||
btn = lv_obj_get_child_back(ext->header, btn);
|
||||
}
|
||||
|
||||
|
||||
lv_obj_align(ext->title, NULL, LV_ALIGN_IN_LEFT_MID, ext->style_header->body.padding.hor, 0);
|
||||
|
||||
lv_obj_set_pos(ext->header, 31, 0);
|
||||
|
||||
lv_obj_set_size(ext->page, lv_obj_get_width(win), lv_obj_get_height(win) - lv_obj_get_height(ext->header));
|
||||
lv_obj_align(ext->page, ext->header, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
298
bdk/libs/lvgl/lv_objx/lv_win.h
Normal file
298
bdk/libs/lvgl/lv_objx/lv_win.h
Normal file
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file lv_win.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_WIN_H
|
||||
#define LV_WIN_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_WIN != 0
|
||||
|
||||
/*Testing of dependencies*/
|
||||
#if USE_LV_BTN == 0
|
||||
#error "lv_win: lv_btn is required. Enable it in lv_conf.h (USE_LV_BTN 1) "
|
||||
#endif
|
||||
|
||||
#if USE_LV_LABEL == 0
|
||||
#error "lv_win: lv_label is required. Enable it in lv_conf.h (USE_LV_LABEL 1) "
|
||||
#endif
|
||||
|
||||
#if USE_LV_IMG == 0
|
||||
#error "lv_win: lv_img is required. Enable it in lv_conf.h (USE_LV_IMG 1) "
|
||||
#endif
|
||||
|
||||
|
||||
#if USE_LV_PAGE == 0
|
||||
#error "lv_win: lv_page is required. Enable it in lv_conf.h (USE_LV_PAGE 1) "
|
||||
#endif
|
||||
|
||||
#include "../lv_core/lv_obj.h"
|
||||
#include "lv_cont.h"
|
||||
#include "lv_btn.h"
|
||||
#include "lv_label.h"
|
||||
#include "lv_img.h"
|
||||
#include "lv_page.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Data of window*/
|
||||
typedef struct
|
||||
{
|
||||
/*Ext. of ancestor*/
|
||||
/*New data for this type */
|
||||
lv_obj_t * page; /*Pointer to a page which holds the content*/
|
||||
lv_obj_t * header; /*Pointer to the header container of the window*/
|
||||
lv_obj_t * title; /*Pointer to the title label of the window*/
|
||||
lv_style_t * style_header; /*Style of the header container*/
|
||||
lv_style_t * style_btn_rel; /*Control button releases style*/
|
||||
lv_style_t * style_btn_pr; /*Control button pressed style*/
|
||||
lv_coord_t btn_size; /*Size of the control buttons (square)*/
|
||||
} lv_win_ext_t;
|
||||
|
||||
enum {
|
||||
LV_WIN_STYLE_BG,
|
||||
LV_WIN_STYLE_CONTENT_BG,
|
||||
LV_WIN_STYLE_CONTENT_SCRL,
|
||||
LV_WIN_STYLE_SB,
|
||||
LV_WIN_STYLE_HEADER,
|
||||
LV_WIN_STYLE_BTN_REL,
|
||||
LV_WIN_STYLE_BTN_PR,
|
||||
};
|
||||
typedef uint8_t lv_win_style_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create a window objects
|
||||
* @param par pointer to an object, it will be the parent of the new window
|
||||
* @param copy pointer to a window object, if not NULL then the new object will be copied from it
|
||||
* @return pointer to the created window
|
||||
*/
|
||||
lv_obj_t * lv_win_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
|
||||
/**
|
||||
* Delete all children of the scrl object, without deleting scrl child.
|
||||
* @param obj pointer to an object
|
||||
*/
|
||||
void lv_win_clean(lv_obj_t *obj);
|
||||
|
||||
/*======================
|
||||
* Add/remove functions
|
||||
*=====================*/
|
||||
|
||||
/**
|
||||
* Add control button to the header of the window
|
||||
* @param win pointer to a window object
|
||||
* @param img_src an image source ('lv_img_t' variable, path to file or a symbol)
|
||||
* @param rel_action a function pointer to call when the button is released
|
||||
* @return pointer to the created button object
|
||||
*/
|
||||
lv_obj_t * lv_win_add_btn(lv_obj_t * win, const void * img_src, const char * label_src, lv_action_t rel_action);
|
||||
|
||||
/*=====================
|
||||
* Setter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* A release action which can be assigned to a window control button to close it
|
||||
* @param btn pointer to the released button
|
||||
* @return always LV_ACTION_RES_INV because the button is deleted with the window
|
||||
*/
|
||||
lv_res_t lv_win_close_action(lv_obj_t * btn);
|
||||
|
||||
/**
|
||||
* Set the title of a window
|
||||
* @param win pointer to a window object
|
||||
* @param title string of the new title
|
||||
*/
|
||||
void lv_win_set_title(lv_obj_t * win, const char * title);
|
||||
|
||||
/**
|
||||
* Set the control button size of a window
|
||||
* @param win pointer to a window object
|
||||
* @return control button size
|
||||
*/
|
||||
void lv_win_set_btn_size(lv_obj_t * win, lv_coord_t size);
|
||||
|
||||
/**
|
||||
* Set the layout of the window
|
||||
* @param win pointer to a window object
|
||||
* @param layout the layout from 'lv_layout_t'
|
||||
*/
|
||||
void lv_win_set_layout(lv_obj_t *win, lv_layout_t layout);
|
||||
|
||||
/**
|
||||
* Set the scroll bar mode of a window
|
||||
* @param win pointer to a window object
|
||||
* @param sb_mode the new scroll bar mode from 'lv_sb_mode_t'
|
||||
*/
|
||||
void lv_win_set_sb_mode(lv_obj_t *win, lv_sb_mode_t sb_mode);
|
||||
|
||||
/**
|
||||
* Set a style of a window
|
||||
* @param win pointer to a window object
|
||||
* @param type which style should be set
|
||||
* @param style pointer to a style
|
||||
*/
|
||||
void lv_win_set_style(lv_obj_t *win, lv_win_style_t type, lv_style_t *style);
|
||||
|
||||
/**
|
||||
* Set drag status of a window. If set to 'true' window can be dragged like on a PC.
|
||||
* @param win pointer to a window object
|
||||
* @param en whether dragging is enabled
|
||||
*/
|
||||
void lv_win_set_drag(lv_obj_t *win, bool en);
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Get the title of a window
|
||||
* @param win pointer to a window object
|
||||
* @return title string of the window
|
||||
*/
|
||||
const char * lv_win_get_title(const lv_obj_t * win);
|
||||
|
||||
/**
|
||||
* Get the content holder object of window (`lv_page`) to allow additional customization
|
||||
* @param win pointer to a window object
|
||||
* @return the Page object where the window's content is
|
||||
*/
|
||||
lv_obj_t * lv_win_get_content(const lv_obj_t * win);
|
||||
|
||||
/**
|
||||
* Get the control button size of a window
|
||||
* @param win pointer to a window object
|
||||
* @return control button size
|
||||
*/
|
||||
lv_coord_t lv_win_get_btn_size(const lv_obj_t * win);
|
||||
|
||||
/**
|
||||
* Get the pointer of a widow from one of its control button.
|
||||
* It is useful in the action of the control buttons where only button is known.
|
||||
* @param ctrl_btn pointer to a control button of a window
|
||||
* @return pointer to the window of 'ctrl_btn'
|
||||
*/
|
||||
lv_obj_t * lv_win_get_from_btn(const lv_obj_t * ctrl_btn);
|
||||
|
||||
/**
|
||||
* Get the layout of a window
|
||||
* @param win pointer to a window object
|
||||
* @return the layout of the window (from 'lv_layout_t')
|
||||
*/
|
||||
lv_layout_t lv_win_get_layout(lv_obj_t *win);
|
||||
|
||||
/**
|
||||
* Get the scroll bar mode of a window
|
||||
* @param win pointer to a window object
|
||||
* @return the scroll bar mode of the window (from 'lv_sb_mode_t')
|
||||
*/
|
||||
lv_sb_mode_t lv_win_get_sb_mode(lv_obj_t *win);
|
||||
|
||||
/**
|
||||
* Get width of the content area (page scrollable) of the window
|
||||
* @param win pointer to a window object
|
||||
* @return the width of the content area
|
||||
*/
|
||||
lv_coord_t lv_win_get_width(lv_obj_t * win);
|
||||
|
||||
/**
|
||||
* Get a style of a window
|
||||
* @param win pointer to a button object
|
||||
* @param type which style window be get
|
||||
* @return style pointer to a style
|
||||
*/
|
||||
lv_style_t * lv_win_get_style(const lv_obj_t *win, lv_win_style_t type);
|
||||
|
||||
/**
|
||||
* Get drag status of a window. If set to 'true' window can be dragged like on a PC.
|
||||
* @param win pointer to a window object
|
||||
* @return whether window is draggable
|
||||
*/
|
||||
static inline bool lv_win_get_drag(const lv_obj_t *win)
|
||||
{
|
||||
return lv_obj_get_drag(win);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
/**
|
||||
* Focus on an object. It ensures that the object will be visible in the window.
|
||||
* @param win pointer to a window object
|
||||
* @param obj pointer to an object to focus (must be in the window)
|
||||
* @param anim_time scroll animation time in milliseconds (0: no animation)
|
||||
*/
|
||||
void lv_win_focus(lv_obj_t * win, lv_obj_t * obj, uint16_t anim_time);
|
||||
|
||||
/**
|
||||
* Scroll the window horizontally
|
||||
* @param win pointer to a window object
|
||||
* @param dist the distance to scroll (< 0: scroll right; > 0 scroll left)
|
||||
*/
|
||||
static inline void lv_win_scroll_hor(lv_obj_t * win, lv_coord_t dist)
|
||||
{
|
||||
lv_win_ext_t * ext = (lv_win_ext_t *)lv_obj_get_ext_attr(win);
|
||||
lv_page_scroll_hor(ext->page, dist);
|
||||
}
|
||||
/**
|
||||
* Scroll the window vertically
|
||||
* @param win pointer to a window object
|
||||
* @param dist the distance to scroll (< 0: scroll down; > 0 scroll up)
|
||||
*/
|
||||
static inline void lv_win_scroll_ver(lv_obj_t * win, lv_coord_t dist)
|
||||
{
|
||||
lv_win_ext_t * ext = (lv_win_ext_t *)lv_obj_get_ext_attr(win);
|
||||
lv_page_scroll_ver(ext->page, dist);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*USE_LV_WIN*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_WIN_H*/
|
Loading…
Add table
Add a link
Reference in a new issue