1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-21 06:53:01 +08:00

Merge branch 'dev-5.3' of https://github.com/littlevgl/lvgl into dev-5.3

This commit is contained in:
Themba Dube 2018-11-21 15:01:35 -05:00
commit be783a65e0
14 changed files with 405 additions and 147 deletions

View File

@ -27,7 +27,7 @@ In the simplest case you need 5 things:
3. Register a function which can **read an input device**. (E.g. touch pad) 3. Register a function which can **read an input device**. (E.g. touch pad)
4. Copy `lv_conf_templ.h` as `lv_conf.h` and set at least `LV_HOR_RES`, `LV_VER_RES` and `LV_COLOR_DEPTH`. 4. Copy `lv_conf_templ.h` as `lv_conf.h` and set at least `LV_HOR_RES`, `LV_VER_RES` and `LV_COLOR_DEPTH`.
5. Call `lv_task_handler()` periodically every few milliseconds. 5. Call `lv_task_handler()` periodically every few milliseconds.
For a detailed description visit https://littlevgl.com/porting For a detailed description visit https://github.com/littlevgl/lvgl/wiki/Porting
Or check the [Porting tutorial](https://github.com/littlevgl/lv_examples/blob/master/lv_tutorial/0_porting/lv_tutorial_porting.c) Or check the [Porting tutorial](https://github.com/littlevgl/lv_examples/blob/master/lv_tutorial/0_porting/lv_tutorial_porting.c)
## Project set-up ## Project set-up

View File

@ -262,6 +262,7 @@
#if USE_LV_PRELOAD != 0 #if USE_LV_PRELOAD != 0
#define LV_PRELOAD_DEF_ARC_LENGTH 60 /*[deg]*/ #define LV_PRELOAD_DEF_ARC_LENGTH 60 /*[deg]*/
#define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/ #define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/
#define LV_PRELOAD_DEF_ANIM LV_PRELOAD_TYPE_SPINNING_ARC
#endif #endif
/************************* /*************************

View File

@ -515,10 +515,9 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p)
/* Redraw the object */ /* Redraw the object */
lv_style_t * style = lv_obj_get_style(obj); lv_style_t * style = lv_obj_get_style(obj);
if(style->body.opa != LV_OPA_TRANSP) { obj->design_func(obj, &obj_ext_mask, LV_DESIGN_DRAW_MAIN);
obj->design_func(obj, &obj_ext_mask, LV_DESIGN_DRAW_MAIN); //tick_wait_ms(100); /*DEBUG: Wait after every object draw to see the order of drawing*/
//tick_wait_ms(100); /*DEBUG: Wait after every object draw to see the order of drawing*/
}
/*Create a new 'obj_mask' without 'ext_size' because the children can't be visible there*/ /*Create a new 'obj_mask' without 'ext_size' because the children can't be visible there*/
lv_obj_get_coords(obj, &obj_area); lv_obj_get_coords(obj, &obj_area);
@ -547,8 +546,7 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p)
} }
/* If all the children are redrawn make 'post draw' design */ /* If all the children are redrawn make 'post draw' design */
if(style->body.opa != LV_OPA_TRANSP) { obj->design_func(obj, &obj_ext_mask, LV_DESIGN_DRAW_POST);
obj->design_func(obj, &obj_ext_mask, LV_DESIGN_DRAW_POST);
}
} }
} }

View File

@ -71,7 +71,7 @@ void lv_draw_rect(const lv_area_t * coords, const lv_area_t * mask, const lv_sty
lv_draw_shadow(coords, mask, style, opa_scale); lv_draw_shadow(coords, mask, style, opa_scale);
} }
#endif #endif
if(style->body.empty == 0) { if(style->body.empty == 0 && style->body.opa >= LV_OPA_MIN) {
lv_draw_rect_main_mid(coords, mask, style, opa_scale); lv_draw_rect_main_mid(coords, mask, style, opa_scale);
if(style->body.radius != 0) { if(style->body.radius != 0) {
@ -79,7 +79,7 @@ void lv_draw_rect(const lv_area_t * coords, const lv_area_t * mask, const lv_sty
} }
} }
if(style->body.border.width != 0 && style->body.border.part != LV_BORDER_NONE) { if(style->body.border.width != 0 && style->body.border.part != LV_BORDER_NONE && style->body.border.opa >= LV_OPA_MIN) {
lv_draw_rect_border_straight(coords, mask, style, opa_scale); lv_draw_rect_border_straight(coords, mask, style, opa_scale);
if(style->body.radius != 0) { if(style->body.radius != 0) {

View File

@ -196,6 +196,30 @@ int32_t lv_anim_path_ease_in_out(const lv_anim_t * a)
return new_value; return new_value;
} }
/**
* Calculate the current value of an animation with overshoot at the end
* @param a pointer to an animation
* @return the current value to set
*/
int32_t lv_anim_path_overshoot(const lv_anim_t * a)
{
/*Calculate the current step*/
uint32_t t;
if(a->time == a->act_time) t = 1024;
else t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time;
int32_t step = lv_bezier3(t, 0, 600, 1300, 1024);
int32_t new_value;
new_value = (int32_t) step * (a->end - a->start);
new_value = new_value >> 10;
new_value += a->start;
return new_value;
}
/** /**
* Calculate the current value of an animation applying step characteristic. * Calculate the current value of an animation applying step characteristic.
* (Set end value on the end of the animation) * (Set end value on the end of the animation)

View File

@ -129,6 +129,13 @@ int32_t lv_anim_path_linear(const lv_anim_t *a);
*/ */
int32_t lv_anim_path_ease_in_out(const lv_anim_t *a); int32_t lv_anim_path_ease_in_out(const lv_anim_t *a);
/**
* Calculate the current value of an animation with overshoot at the end
* @param a pointer to an animation
* @return the current value to set
*/
int32_t lv_anim_path_overshoot(const lv_anim_t * a);
/** /**
* Calculate the current value of an animation applying step characteristic. * Calculate the current value of an animation applying step characteristic.
* (Set end value on the end of the animation) * (Set end value on the end of the animation)

View File

@ -340,16 +340,27 @@ lv_btnm_action_t lv_btnm_get_action(const lv_obj_t * btnm)
return ext->action; 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 * Get the toggled button
* @param btnm pointer to button matrix object * @param btnm pointer to button matrix object
* @return index of the currently toggled button (0: if unset) * @return index of the currently toggled button (LV_BTNM_PR_NONE: if unset)
*/ */
uint16_t lv_btnm_get_toggled(const lv_obj_t * btnm) uint16_t lv_btnm_get_toggled(const lv_obj_t * btnm)
{ {
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm); lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
if(ext->toggle == 0) return 0; if(ext->toggle == 0) return LV_BTNM_PR_NONE;
else return ext->btn_id_tgl; else return ext->btn_id_tgl;
} }
@ -581,7 +592,7 @@ static lv_res_t lv_btnm_signal(lv_obj_t * btnm, lv_signal_t sign, void * param)
} }
#if USE_LV_GROUP #if USE_LV_GROUP
/*Leave the clicked button as pressed if this the focused object in a 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); lv_group_t * g = lv_obj_get_group(btnm);
if(lv_group_get_focused(g) != btnm) { if(lv_group_get_focused(g) != btnm) {
ext->btn_id_pr = LV_BTNM_PR_NONE; ext->btn_id_pr = LV_BTNM_PR_NONE;

View File

@ -147,11 +147,17 @@ const char ** lv_btnm_get_map(const lv_obj_t * btnm);
*/ */
lv_btnm_action_t lv_btnm_get_action(const lv_obj_t * btnm); 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 * Get the toggled button
* @param btnm pointer to button matrix object * @param btnm pointer to button matrix object
* @return index of the currently toggled button (0: if unset) * @return index of the currently toggled button (LV_BTNM_PR_NONE: if unset)
*/ */
uint16_t lv_btnm_get_toggled(const lv_obj_t * btnm); uint16_t lv_btnm_get_toggled(const lv_obj_t * btnm);

View File

@ -34,6 +34,7 @@ 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_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_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_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 VARIABLES
@ -460,6 +461,7 @@ static bool lv_chart_design(lv_obj_t * chart, const lv_area_t * mask, lv_design_
if(ext->type & LV_CHART_TYPE_LINE) lv_chart_draw_lines(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_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_POINT) lv_chart_draw_points(chart, mask);
if(ext->type & LV_CHART_TYPE_VERTICAL_LINE) lv_chart_draw_vertical_lines(chart, mask);
} }
return true; return true;
} }
@ -718,4 +720,79 @@ static void lv_chart_draw_cols(lv_obj_t * chart, const lv_area_t * mask)
} }
} }
} }
/**
* 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);
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_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;
if(ext->point_cnt == w)
{
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++;
}
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;
}
}
else
{
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;
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(ser->points[i - 1] >= 0 && ser->points[i] >= 0)
{
lv_draw_line(&p1, &p2, mask, &style, opa_scale);
}
}
}
}
}
#endif #endif

View File

@ -49,7 +49,7 @@ typedef struct
uint8_t hdiv_cnt; /*Number of horizontal division lines*/ uint8_t hdiv_cnt; /*Number of horizontal division lines*/
uint8_t vdiv_cnt; /*Number of vertical division lines*/ uint8_t vdiv_cnt; /*Number of vertical division lines*/
uint16_t point_cnt; /*Point number in a data line*/ uint16_t point_cnt; /*Point number in a data line*/
uint8_t type :3; /*Line, column or point chart (from 'lv_chart_type_t')*/ uint8_t type :4; /*Line, column or point chart (from 'lv_chart_type_t')*/
struct { struct {
lv_coord_t width; /*Line width or point radius*/ lv_coord_t width; /*Line width or point radius*/
uint8_t num; /*Number of data lines in dl_ll*/ uint8_t num; /*Number of data lines in dl_ll*/
@ -64,6 +64,7 @@ enum
LV_CHART_TYPE_LINE = 0x01, LV_CHART_TYPE_LINE = 0x01,
LV_CHART_TYPE_COLUMN = 0x02, LV_CHART_TYPE_COLUMN = 0x02,
LV_CHART_TYPE_POINT = 0x04, LV_CHART_TYPE_POINT = 0x04,
LV_CHART_TYPE_VERTICAL_LINE = 0x08,
}; };
typedef uint8_t lv_chart_type_t; typedef uint8_t lv_chart_type_t;

View File

@ -24,6 +24,12 @@
#ifndef LV_PRELOAD_DEF_SPIN_TIME #ifndef LV_PRELOAD_DEF_SPIN_TIME
# define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/ # define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/
#endif #endif
#ifndef LV_PRELOAD_DEF_ANIM
# define LV_PRELOAD_DEF_ANIM LV_PRELOAD_TYPE_SPINNING_ARC /*animation type*/
#endif
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
@ -73,26 +79,12 @@ lv_obj_t * lv_preload_create(lv_obj_t * par, const lv_obj_t * copy)
/*Initialize the allocated 'ext' */ /*Initialize the allocated 'ext' */
ext->arc_length = LV_PRELOAD_DEF_ARC_LENGTH; 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*/ /*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_signal_func(new_preload, lv_preload_signal);
lv_obj_set_design_func(new_preload, lv_preload_design); lv_obj_set_design_func(new_preload, lv_preload_design);
#if USE_LV_ANIMATION
lv_anim_t a;
a.var = new_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 = LV_PRELOAD_DEF_SPIN_TIME;
a.playback = 0;
a.playback_pause = 0;
a.repeat = 1;
a.repeat_pause = 0;
lv_anim_create(&a);
#endif
/*Init the new pre loader pre loader*/ /*Init the new pre loader pre loader*/
if(copy == NULL) { if(copy == NULL) {
@ -106,6 +98,8 @@ lv_obj_t * lv_preload_create(lv_obj_t * par, const lv_obj_t * copy)
lv_obj_set_style(new_preload, &lv_style_pretty_color); lv_obj_set_style(new_preload, &lv_style_pretty_color);
} }
ext->time = LV_PRELOAD_DEF_SPIN_TIME;
} }
/*Copy an existing pre loader*/ /*Copy an existing pre loader*/
else { else {
@ -116,6 +110,8 @@ lv_obj_t * lv_preload_create(lv_obj_t * par, const lv_obj_t * copy)
lv_obj_refresh_style(new_preload); lv_obj_refresh_style(new_preload);
} }
lv_preload_set_animation_type(new_preload, ext->anim_type);
LV_LOG_INFO("preload created"); LV_LOG_INFO("preload created");
@ -148,22 +144,7 @@ void lv_preload_set_spin_time(lv_obj_t * preload, uint16_t time)
lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload); lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload);
ext->time = time; ext->time = time;
#if USE_LV_ANIMATION lv_preload_set_animation_type(preload, ext->anim_type);
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 = time;
a.playback = 0;
a.playback_pause = 0;
a.repeat = 1;
a.repeat_pause = 0;
lv_anim_create(&a);
#endif
} }
/*===================== /*=====================
* Setter functions * Setter functions
@ -178,12 +159,85 @@ void lv_preload_set_spin_time(lv_obj_t * preload, uint16_t time)
void lv_preload_set_style(lv_obj_t * preload, lv_preload_style_t type, lv_style_t * style) void lv_preload_set_style(lv_obj_t * preload, lv_preload_style_t type, lv_style_t * style)
{ {
switch(type) { switch(type) {
case LV_PRELOAD_STYLE_MAIN: case LV_PRELOAD_STYLE_MAIN:
lv_arc_set_style(preload, LV_ARC_STYLE_MAIN, style); lv_arc_set_style(preload, LV_ARC_STYLE_MAIN, style);
break; 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 * Getter functions
*====================*/ *====================*/
@ -220,17 +274,28 @@ lv_style_t * lv_preload_get_style(const lv_obj_t * preload, lv_preload_style_t t
lv_style_t * style = NULL; lv_style_t * style = NULL;
switch(type) { switch(type) {
case LV_PRELOAD_STYLE_MAIN: case LV_PRELOAD_STYLE_MAIN:
style = lv_arc_get_style(preload, LV_ARC_STYLE_MAIN); style = lv_arc_get_style(preload, LV_ARC_STYLE_MAIN);
break; break;
default: default:
style = NULL; style = NULL;
break; break;
} }
return style; 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 * Other functions
*====================*/ *====================*/

View File

@ -43,6 +43,7 @@ extern "C" {
enum { enum {
LV_PRELOAD_TYPE_SPINNING_ARC, LV_PRELOAD_TYPE_SPINNING_ARC,
LV_PRELOAD_TYPE_FILLSPIN_ARC,
}; };
typedef uint8_t lv_preloader_type_t; typedef uint8_t lv_preloader_type_t;
@ -52,6 +53,7 @@ typedef struct {
/*New data for this type */ /*New data for this type */
uint16_t arc_length; /*Length of the spinning indicator in degree*/ uint16_t arc_length; /*Length of the spinning indicator in degree*/
uint16_t time; /*Time of one round*/ uint16_t time; /*Time of one round*/
lv_preloader_type_t anim_type; /*Type of the arc animation*/
} lv_preload_ext_t; } lv_preload_ext_t;
@ -103,6 +105,13 @@ void lv_preload_set_spin_time(lv_obj_t * preload, uint16_t time);
* */ * */
void lv_preload_set_style(lv_obj_t * preload, lv_preload_style_t type, lv_style_t *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 * Getter functions
*====================*/ *====================*/
@ -127,6 +136,13 @@ uint16_t lv_preload_get_spin_time(const lv_obj_t * preload);
* */ * */
lv_style_t * lv_preload_get_style(const lv_obj_t * preload, lv_preload_style_t type); 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 * Other functions
*====================*/ *====================*/

View File

@ -16,13 +16,12 @@
#endif #endif
#include "../lv_themes/lv_theme.h" #include "../lv_themes/lv_theme.h"
#include "../lv_misc/lv_math.h"
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define LV_SWITCH_SLIDER_ANIM_MAX 1000
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
@ -31,6 +30,7 @@
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param); 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 VARIABLES
@ -81,6 +81,7 @@ lv_obj_t * lv_sw_create(lv_obj_t * par, const lv_obj_t * copy)
lv_slider_set_range(new_sw, 0, 1); lv_slider_set_range(new_sw, 0, 1);
lv_obj_set_size(new_sw, 2 * LV_DPI / 3, LV_DPI / 3); lv_obj_set_size(new_sw, 2 * LV_DPI / 3, LV_DPI / 3);
lv_slider_set_knob_in(new_sw, true); lv_slider_set_knob_in(new_sw, true);
lv_slider_set_range(new_sw, 0, LV_SWITCH_SLIDER_ANIM_MAX);
/*Set the default styles*/ /*Set the default styles*/
lv_theme_t * th = lv_theme_get_current(); lv_theme_t * th = lv_theme_get_current();
@ -99,9 +100,12 @@ lv_obj_t * lv_sw_create(lv_obj_t * par, const lv_obj_t * copy)
lv_sw_ext_t * copy_ext = lv_obj_get_ext_attr(copy); lv_sw_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
ext->style_knob_off = copy_ext->style_knob_off; ext->style_knob_off = copy_ext->style_knob_off;
ext->style_knob_on = copy_ext->style_knob_on; ext->style_knob_on = copy_ext->style_knob_on;
ext->anim_time = copy_ext->anim_time;
if(lv_sw_get_state(new_sw)) lv_slider_set_style(new_sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_on); 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); else lv_slider_set_style(new_sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off);
/*Refresh the style with new signal function*/ /*Refresh the style with new signal function*/
lv_obj_refresh_style(new_sw); lv_obj_refresh_style(new_sw);
} }
@ -115,44 +119,15 @@ lv_obj_t * lv_sw_create(lv_obj_t * par, const lv_obj_t * copy)
* Setter functions * Setter functions
*====================*/ *====================*/
static void lv_sw_clear_anim(lv_obj_t *sw)
{
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
ext->anim_act = 0;
}
/** /**
* Turn ON the switch * Turn ON the switch
* @param sw pointer to a switch object * @param sw pointer to a switch object
*/ */
void lv_sw_on(lv_obj_t * sw) void lv_sw_on(lv_obj_t * sw)
{ {
if(lv_sw_get_state(sw)) return; /*Do nothing is already turned on*/
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
#if USE_LV_ANIMATION lv_slider_set_value(sw, LV_SWITCH_SLIDER_ANIM_MAX);
if(lv_sw_get_anim_time(sw) > 0) {
if(ext->anim_act) {
lv_anim_del(sw, NULL);
ext->anim_act = 0;
}
ext->cur_anim.var = sw;
ext->cur_anim.start = lv_slider_get_value(sw);
ext->cur_anim.end = LV_SWITCH_SLIDER_ANIM_MAX;
ext->cur_anim.fp = (lv_anim_fp_t)lv_slider_set_value;
ext->cur_anim.path = lv_anim_path_linear;
ext->cur_anim.end_cb = (lv_anim_cb_t)lv_sw_clear_anim;
ext->cur_anim.act_time = 0;
ext->cur_anim.time = lv_sw_get_anim_time(sw);
ext->cur_anim.playback = 0;
ext->cur_anim.playback_pause = 0;
ext->cur_anim.repeat = 0;
ext->cur_anim.repeat_pause = 0;
ext->anim_act = 1;
lv_anim_create(&ext->cur_anim);
} else /* continues below if statement */
#endif
lv_slider_set_value(sw, 1);
lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_on); lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_on);
} }
@ -162,10 +137,36 @@ void lv_sw_on(lv_obj_t * sw)
*/ */
void lv_sw_off(lv_obj_t * sw) void lv_sw_off(lv_obj_t * sw)
{ {
if(!lv_sw_get_state(sw)) return; /*Do nothing is already turned off*/
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
lv_slider_set_value(sw, 0); lv_slider_set_value(sw, 0);
lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off);
}
/**
* 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); lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off);
} }
@ -197,15 +198,13 @@ void lv_sw_set_style(lv_obj_t * sw, lv_sw_style_t type, lv_style_t * style)
} }
} }
void lv_sw_set_anim_time(lv_obj_t *sw, uint16_t anim_time) void lv_sw_set_anim_time(lv_obj_t *sw, uint16_t anim_time)
{ {
#if USE_LV_ANIMATION == 0
anim_time = 0;
#endif
lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
ext->anim_time = anim_time; ext->anim_time = anim_time;
if(anim_time > 0) {
lv_slider_set_range(sw, 0, LV_SWITCH_SLIDER_ANIM_MAX);
} else
lv_slider_set_range(sw, 0, 1);
} }
/*===================== /*=====================
@ -246,8 +245,13 @@ lv_style_t * lv_sw_get_style(const lv_obj_t * sw, lv_sw_style_t type)
uint16_t lv_sw_get_anim_time(const lv_obj_t *sw) 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); lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw);
return ext->anim_time; return ext->anim_time;
#else
return 0;
#endif
} }
/********************** /**********************
@ -271,13 +275,6 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param)
if(sign == LV_SIGNAL_PRESSING) old_val = ext->slider.drag_value; if(sign == LV_SIGNAL_PRESSING) old_val = ext->slider.drag_value;
else old_val = lv_slider_get_value(sw); else old_val = lv_slider_get_value(sw);
#if USE_LV_ANIMATION
if(lv_sw_get_anim_time(sw) > 0) {
/* Overwrite old_val */
old_val = lv_sw_get_state(sw) ? LV_SWITCH_SLIDER_ANIM_MAX : 0;
}
#endif
/*Do not let the slider to call the callback. The Switch will do it if required*/ /*Do not let the slider to call the callback. The Switch will do it if required*/
lv_action_t slider_action = ext->slider.action; lv_action_t slider_action = ext->slider.action;
ext->slider.action = NULL; ext->slider.action = NULL;
@ -289,58 +286,80 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param)
if(sign == LV_SIGNAL_CLEANUP) { if(sign == LV_SIGNAL_CLEANUP) {
/*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/ /*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/
} else if(sign == LV_SIGNAL_PRESSING) { }
int16_t act_val = ext->slider.drag_value; else if(sign == LV_SIGNAL_PRESSED) {
if(act_val != old_val) ext->changed = 1;
#if USE_LV_ANIMATION /*Save the x coordinate of the pressed point to see if the switch was slid*/
if(lv_sw_get_anim_time(sw) > 0) { lv_indev_t * indev = lv_indev_get_act();
/* Keep forcing the slider to old_val */ if(indev) {
lv_slider_set_value(sw, old_val); lv_point_t p;
lv_indev_get_point(indev, &p);
ext->start_x = p.x;
} }
#endif ext->slided = 0;
} else if(sign == LV_SIGNAL_PRESS_LOST) {
ext->changed = 0; ext->changed = 0;
if(lv_sw_get_state(sw)) lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_on); }
else lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off); else if(sign == LV_SIGNAL_PRESSING) {
} else if(sign == LV_SIGNAL_RELEASED) { /*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);
lv_sw_anim_to_value(sw, LV_SWITCH_SLIDER_ANIM_MAX);
}
else {
lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off);
lv_sw_anim_to_value(sw, 0);
}
}
else if(sign == LV_SIGNAL_RELEASED) {
/*If not dragged then toggle the switch*/
if(ext->changed == 0) { if(ext->changed == 0) {
if(lv_sw_get_state(sw)) lv_sw_off_anim(sw);
else lv_sw_on_anim(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); int16_t v = lv_slider_get_value(sw);
if(v == 0) lv_slider_set_value(sw, 1); if(v > LV_SWITCH_SLIDER_ANIM_MAX / 2) lv_sw_on_anim(sw);
else lv_slider_set_value(sw, 0); else lv_sw_off_anim(sw);
if(slider_action != NULL) res = slider_action(sw);
} }
#if USE_LV_ANIMATION
else if(lv_sw_get_anim_time(sw) > 0) {
if(old_val == 0) {
lv_slider_set_value(sw, 0);
lv_bar_set_value(sw, 0);
lv_sw_on(sw);
} else {
lv_slider_set_value(sw, LV_SWITCH_SLIDER_ANIM_MAX);
lv_sw_off(sw);
}
}
#endif
if(lv_sw_get_state(sw)) lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_on);
else lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off);
ext->changed = 0;
if(slider_action != NULL) res = slider_action(sw);
} else if(sign == LV_SIGNAL_CONTROLL) { } else if(sign == LV_SIGNAL_CONTROLL) {
char c = *((char *)param); char c = *((char *)param);
if(c == LV_GROUP_KEY_ENTER) { if(c == LV_GROUP_KEY_ENTER) {
if(old_val) lv_sw_off(sw); if(old_val) lv_sw_off_anim(sw);
else lv_sw_on(sw); else lv_sw_on_anim(sw);
if(slider_action) res = slider_action(sw); if(slider_action) res = slider_action(sw);
} else if(c == LV_GROUP_KEY_UP || c == LV_GROUP_KEY_RIGHT) { } else if(c == LV_GROUP_KEY_UP || c == LV_GROUP_KEY_RIGHT) {
lv_sw_on(sw); lv_sw_on_anim(sw);
if(slider_action) res = slider_action(sw); if(slider_action) res = slider_action(sw);
} else if(c == LV_GROUP_KEY_DOWN || c == LV_GROUP_KEY_LEFT) { } else if(c == LV_GROUP_KEY_DOWN || c == LV_GROUP_KEY_LEFT) {
lv_sw_off(sw); lv_sw_off_anim(sw);
if(slider_action) res = slider_action(sw); if(slider_action) res = slider_action(sw);
} }
} else if(sign == LV_SIGNAL_GET_EDITABLE) { } else if(sign == LV_SIGNAL_GET_EDITABLE) {
@ -361,4 +380,24 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param)
return res; return res;
} }
static void lv_sw_anim_to_value(lv_obj_t * sw, int16_t value)
{
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

View File

@ -32,6 +32,7 @@ extern "C" {
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#define LV_SWITCH_SLIDER_ANIM_MAX 1000
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@ -41,13 +42,13 @@ typedef struct
{ {
lv_slider_ext_t slider; /*Ext. of ancestor*/ lv_slider_ext_t slider; /*Ext. of ancestor*/
/*New data for this type */ /*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_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_style_t *style_knob_on; /*Style of the knob when the switch is ON (NULL to use the same as OFF)*/
uint8_t changed :1; /*Indicates the switch explicitly changed by drag*/ 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 #if USE_LV_ANIMATION
uint16_t anim_time; /*switch animation time */ uint16_t anim_time; /*switch animation time */
lv_anim_t cur_anim; /*current active animation */
uint8_t anim_act :1;
#endif #endif
} lv_sw_ext_t; } lv_sw_ext_t;
@ -87,6 +88,18 @@ void lv_sw_on(lv_obj_t *sw);
*/ */
void lv_sw_off(lv_obj_t *sw); void lv_sw_off(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);
/** /**
* Set a function which will be called when the switch is toggled by the user * Set a function which will be called when the switch is toggled by the user
* @param sw pointer to switch object * @param sw pointer to switch object
@ -126,7 +139,7 @@ void lv_sw_set_anim_time(lv_obj_t *sw, uint16_t anim_time);
*/ */
static inline bool lv_sw_get_state(const lv_obj_t *sw) static inline bool lv_sw_get_state(const lv_obj_t *sw)
{ {
return lv_bar_get_value(sw) == 0 ? false : true; return lv_bar_get_value(sw) < LV_SWITCH_SLIDER_ANIM_MAX / 2 ? false : true;
} }
/** /**