From e6214480c4ef47cb4620e5c451d6d77130bf2ebd Mon Sep 17 00:00:00 2001 From: Themba Dube Date: Wed, 14 Nov 2018 20:09:09 -0500 Subject: [PATCH 1/9] Very rough prototype of animated switch --- lv_objx/lv_sw.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ lv_objx/lv_sw.h | 24 ++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/lv_objx/lv_sw.c b/lv_objx/lv_sw.c index 98c20ea85..83c084fa0 100644 --- a/lv_objx/lv_sw.c +++ b/lv_objx/lv_sw.c @@ -7,6 +7,7 @@ * INCLUDES *********************/ #include "lv_sw.h" + #if USE_LV_SW != 0 /*Testing of dependencies*/ @@ -20,6 +21,8 @@ * DEFINES *********************/ +#define LV_SWITCH_SLIDER_ANIM_MAX 1000 + /********************** * TYPEDEFS **********************/ @@ -66,6 +69,7 @@ lv_obj_t * lv_sw_create(lv_obj_t * par, const lv_obj_t * copy) /*Initialize the allocated 'ext' */ ext->changed = 0; + ext->anim_time = 0; ext->style_knob_off = ext->slider.style_knob; ext->style_knob_on = ext->slider.style_knob; @@ -111,6 +115,12 @@ lv_obj_t * lv_sw_create(lv_obj_t * par, const lv_obj_t * copy) * 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 * @param sw pointer to a switch object @@ -120,6 +130,28 @@ 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); +#if USE_LV_ANIMATION + 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); } @@ -165,6 +197,17 @@ 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) +{ + lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); + 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); +} + /*===================== * Getter functions *====================*/ @@ -200,6 +243,13 @@ lv_style_t * lv_sw_get_style(const lv_obj_t * sw, lv_sw_style_t type) return style; } + +uint16_t lv_sw_get_anim_time(const lv_obj_t *sw) +{ + lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); + return ext->anim_time; +} + /********************** * STATIC FUNCTIONS **********************/ @@ -217,9 +267,17 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param) /*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); +#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*/ lv_action_t slider_action = ext->slider.action; ext->slider.action = NULL; @@ -234,6 +292,12 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param) } else if(sign == LV_SIGNAL_PRESSING) { int16_t act_val = ext->slider.drag_value; if(act_val != old_val) ext->changed = 1; +#if USE_LV_ANIMATION + if(lv_sw_get_anim_time(sw) > 0) { + /* Keep forcing the slider to old_val */ + lv_slider_set_value(sw, old_val); + } +#endif } else if(sign == LV_SIGNAL_PRESS_LOST) { ext->changed = 0; if(lv_sw_get_state(sw)) lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_on); @@ -244,6 +308,18 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param) if(v == 0) lv_slider_set_value(sw, 1); else lv_slider_set_value(sw, 0); } +#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); diff --git a/lv_objx/lv_sw.h b/lv_objx/lv_sw.h index 3834c7287..58f6d3f30 100644 --- a/lv_objx/lv_sw.h +++ b/lv_objx/lv_sw.h @@ -44,6 +44,11 @@ typedef struct 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)*/ uint8_t changed :1; /*Indicates the switch explicitly changed by drag*/ +#if USE_LV_ANIMATION + uint16_t anim_time; /*switch animation time */ + lv_anim_t cur_anim; /*current active animation */ + uint8_t anim_act :1; +#endif } lv_sw_ext_t; enum { @@ -100,6 +105,16 @@ static inline void lv_sw_set_action(lv_obj_t * sw, lv_action_t action) */ 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 *====================*/ @@ -132,6 +147,15 @@ static inline lv_action_t lv_sw_get_action(const lv_obj_t * slider) */ lv_style_t * lv_sw_get_style(const lv_obj_t *sw, lv_sw_style_t type); +#if USE_LV_ANIMATION +/** + * 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); +#endif + /********************** * MACROS **********************/ From 1da612e8a0bef388b74ddc5dd140c3a5e6b6cea1 Mon Sep 17 00:00:00 2001 From: Themba Dube Date: Wed, 14 Nov 2018 20:20:35 -0500 Subject: [PATCH 2/9] Prevent switch from jumping when clicked --- lv_objx/lv_sw.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lv_objx/lv_sw.c b/lv_objx/lv_sw.c index 83c084fa0..fe551e325 100644 --- a/lv_objx/lv_sw.c +++ b/lv_objx/lv_sw.c @@ -296,12 +296,20 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param) if(lv_sw_get_anim_time(sw) > 0) { /* Keep forcing the slider to old_val */ lv_slider_set_value(sw, old_val); + ext->slider.drag_value = old_val; } #endif } else if(sign == LV_SIGNAL_PRESS_LOST) { 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); +#if USE_LV_ANIMATION + if(lv_sw_get_anim_time(sw) > 0) { + /* Keep forcing the slider to old_val */ + lv_slider_set_value(sw, old_val); + ext->slider.drag_value = old_val; + } +#endif } else if(sign == LV_SIGNAL_RELEASED) { if(ext->changed == 0) { int16_t v = lv_slider_get_value(sw); From 65d6c82f81a4170b97ade69ab487db2272718174 Mon Sep 17 00:00:00 2001 From: Themba Dube Date: Wed, 14 Nov 2018 20:24:13 -0500 Subject: [PATCH 3/9] Add off animation and correct initial switch state --- lv_objx/lv_sw.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/lv_objx/lv_sw.c b/lv_objx/lv_sw.c index fe551e325..e08c7601d 100644 --- a/lv_objx/lv_sw.c +++ b/lv_objx/lv_sw.c @@ -165,6 +165,28 @@ 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); +#if USE_LV_ANIMATION + 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_SWITCH_SLIDER_ANIM_MAX; + ext->cur_anim.end = 0; + 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, 0); lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off); } @@ -197,16 +219,20 @@ void lv_sw_set_style(lv_obj_t * sw, lv_sw_style_t type, lv_style_t * style) } } - +#if USE_LV_ANIMATION void lv_sw_set_anim_time(lv_obj_t *sw, uint16_t anim_time) { lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); + bool sw_state = lv_sw_get_state(sw); + uint16_t max = anim_time > 0 ? LV_SWITCH_SLIDER_ANIM_MAX : 1; 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); + lv_slider_set_value(sw, sw_state ? max : 0); } +#endif /*===================== * Getter functions @@ -244,11 +270,13 @@ lv_style_t * lv_sw_get_style(const lv_obj_t * sw, lv_sw_style_t type) return style; } +#if USE_LV_ANIMATION uint16_t lv_sw_get_anim_time(const lv_obj_t *sw) { lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); return ext->anim_time; } +#endif /********************** * STATIC FUNCTIONS From 938819a8b886113e20609ad608326de3da1d7610 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 16 Nov 2018 17:42:29 +0100 Subject: [PATCH 4/9] lv_sw: simplify animation --- lv_objx/lv_sw.c | 174 +++++++++++++++--------------------------------- lv_objx/lv_sw.h | 8 +-- 2 files changed, 57 insertions(+), 125 deletions(-) diff --git a/lv_objx/lv_sw.c b/lv_objx/lv_sw.c index e08c7601d..15b3b2da9 100644 --- a/lv_objx/lv_sw.c +++ b/lv_objx/lv_sw.c @@ -20,7 +20,6 @@ /********************* * DEFINES *********************/ - #define LV_SWITCH_SLIDER_ANIM_MAX 1000 /********************** @@ -31,6 +30,7 @@ * 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 @@ -68,7 +68,7 @@ lv_obj_t * lv_sw_create(lv_obj_t * par, const lv_obj_t * copy) if(ext == NULL) return NULL; /*Initialize the allocated 'ext' */ - ext->changed = 0; + ext->tmp_state = 0; ext->anim_time = 0; ext->style_knob_off = ext->slider.style_knob; ext->style_knob_on = ext->slider.style_knob; @@ -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_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(); @@ -115,44 +116,17 @@ lv_obj_t * lv_sw_create(lv_obj_t * par, const lv_obj_t * copy) * 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 * @param sw pointer to a switch object */ 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); -#if USE_LV_ANIMATION - 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); + + 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); } @@ -162,32 +136,10 @@ void lv_sw_on(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); -#if USE_LV_ANIMATION - 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_SWITCH_SLIDER_ANIM_MAX; - ext->cur_anim.end = 0; - 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, 0); + 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); } @@ -219,20 +171,14 @@ void lv_sw_set_style(lv_obj_t * sw, lv_sw_style_t type, lv_style_t * style) } } -#if USE_LV_ANIMATION void lv_sw_set_anim_time(lv_obj_t *sw, uint16_t anim_time) { - lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); - bool sw_state = lv_sw_get_state(sw); - uint16_t max = anim_time > 0 ? LV_SWITCH_SLIDER_ANIM_MAX : 1; - 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); - lv_slider_set_value(sw, sw_state ? max : 0); -} +#if USE_LV_ANIMATION == 0 + anim_time = 0; #endif + lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); + ext->anim_time = anim_time; +} /*===================== * Getter functions @@ -270,13 +216,16 @@ lv_style_t * lv_sw_get_style(const lv_obj_t * sw, lv_sw_style_t type) return style; } -#if USE_LV_ANIMATION 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 @@ -299,13 +248,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; 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*/ lv_action_t slider_action = ext->slider.action; ext->slider.action = NULL; @@ -317,52 +259,24 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param) if(sign == LV_SIGNAL_CLEANUP) { /*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/ - } else if(sign == LV_SIGNAL_PRESSING) { - int16_t act_val = ext->slider.drag_value; - if(act_val != old_val) ext->changed = 1; -#if USE_LV_ANIMATION - if(lv_sw_get_anim_time(sw) > 0) { - /* Keep forcing the slider to old_val */ - lv_slider_set_value(sw, old_val); - ext->slider.drag_value = old_val; - } -#endif - } else if(sign == LV_SIGNAL_PRESS_LOST) { - ext->changed = 0; + } + else if(sign == LV_SIGNAL_PRESSED) { + ext->tmp_state = lv_sw_get_state(sw); + } + 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); else lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off); -#if USE_LV_ANIMATION - if(lv_sw_get_anim_time(sw) > 0) { - /* Keep forcing the slider to old_val */ - lv_slider_set_value(sw, old_val); - ext->slider.drag_value = old_val; + } + else if(sign == LV_SIGNAL_RELEASED) { + int16_t v = lv_slider_get_value(sw); + if(v > LV_SWITCH_SLIDER_ANIM_MAX / 2) { + lv_sw_on(sw); + if(ext->tmp_state == 0 && slider_action != NULL) res = slider_action(sw); } -#endif - } else if(sign == LV_SIGNAL_RELEASED) { - if(ext->changed == 0) { - int16_t v = lv_slider_get_value(sw); - if(v == 0) lv_slider_set_value(sw, 1); - else lv_slider_set_value(sw, 0); + else { + lv_sw_off(sw); + if(ext->tmp_state && 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) { @@ -397,4 +311,24 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param) 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 diff --git a/lv_objx/lv_sw.h b/lv_objx/lv_sw.h index 58f6d3f30..2d198170b 100644 --- a/lv_objx/lv_sw.h +++ b/lv_objx/lv_sw.h @@ -41,13 +41,11 @@ 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)*/ - uint8_t changed :1; /*Indicates the switch explicitly changed by drag*/ + 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)*/ + uint8_t tmp_state :1; /*Saves the initial state of the switch when it begins to drag*/ #if USE_LV_ANIMATION uint16_t anim_time; /*switch animation time */ - lv_anim_t cur_anim; /*current active animation */ - uint8_t anim_act :1; #endif } lv_sw_ext_t; From 07f2e18dfc2d84b1b45e67d9ed4bc210fdf16f5d Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 16 Nov 2018 18:36:12 +0100 Subject: [PATCH 5/9] lv_sw: animation fixes --- lv_objx/lv_sw.c | 46 ++++++++++++++++++++++++++++++++-------------- lv_objx/lv_sw.h | 5 +++-- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/lv_objx/lv_sw.c b/lv_objx/lv_sw.c index 15b3b2da9..e143ca585 100644 --- a/lv_objx/lv_sw.c +++ b/lv_objx/lv_sw.c @@ -20,7 +20,6 @@ /********************* * DEFINES *********************/ -#define LV_SWITCH_SLIDER_ANIM_MAX 1000 /********************** * TYPEDEFS @@ -68,7 +67,7 @@ lv_obj_t * lv_sw_create(lv_obj_t * par, const lv_obj_t * copy) if(ext == NULL) return NULL; /*Initialize the allocated 'ext' */ - ext->tmp_state = 0; + ext->changed = 0; ext->anim_time = 0; ext->style_knob_off = ext->slider.style_knob; ext->style_knob_on = ext->slider.style_knob; @@ -260,23 +259,42 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param) if(sign == LV_SIGNAL_CLEANUP) { /*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/ } - else if(sign == LV_SIGNAL_PRESSED) { - ext->tmp_state = lv_sw_get_state(sw); + else if(sign == LV_SIGNAL_PRESSING) { + 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; + } + printf("tmp: %d\n", ext->changed); } 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); - else lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off); - } - else if(sign == LV_SIGNAL_RELEASED) { - int16_t v = lv_slider_get_value(sw); - if(v > LV_SWITCH_SLIDER_ANIM_MAX / 2) { - lv_sw_on(sw); - if(ext->tmp_state == 0 && slider_action != NULL) res = slider_action(sw); + 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_sw_off(sw); - if(ext->tmp_state && slider_action != NULL) res = slider_action(sw); + lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off); + lv_sw_anim_to_value(sw, 0); } + ext->changed = 0; + } + 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(sw); + else lv_sw_on(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(sw); + else lv_sw_off(sw); + + if(slider_action != NULL) res = slider_action(sw); + } + + ext->changed = 0; } else if(sign == LV_SIGNAL_CONTROLL) { diff --git a/lv_objx/lv_sw.h b/lv_objx/lv_sw.h index 2d198170b..87a62c8cc 100644 --- a/lv_objx/lv_sw.h +++ b/lv_objx/lv_sw.h @@ -32,6 +32,7 @@ extern "C" { /********************* * DEFINES *********************/ +#define LV_SWITCH_SLIDER_ANIM_MAX 1000 /********************** * TYPEDEFS @@ -43,7 +44,7 @@ typedef struct /*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)*/ - uint8_t tmp_state :1; /*Saves the initial state of the switch when it begins to drag*/ + uint8_t changed :1; /*Indicates the switch explicitly changed by drag*/ #if USE_LV_ANIMATION uint16_t anim_time; /*switch animation time */ #endif @@ -124,7 +125,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) { - return lv_bar_get_value(sw) == 0 ? false : true; + return lv_bar_get_value(sw) < LV_SWITCH_SLIDER_ANIM_MAX / 2 ? false : true; } /** From bf557a1bb0ad6e83e7dbac2eb9e6ae286aaddaa2 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 19 Nov 2018 06:35:11 +0100 Subject: [PATCH 6/9] lv_sw: add comment --- lv_objx/lv_sw.c | 3 +-- lv_objx/lv_sw.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lv_objx/lv_sw.c b/lv_objx/lv_sw.c index e143ca585..52f5a389c 100644 --- a/lv_objx/lv_sw.c +++ b/lv_objx/lv_sw.c @@ -264,9 +264,8 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param) if((old_val < threshold && ext->slider.drag_value > threshold) || (old_val > threshold && ext->slider.drag_value < threshold)) { - ext->changed = 1; + ext->changed = 1; /*If explicitly changed don't need to be toggled on release*/ } - printf("tmp: %d\n", ext->changed); } else if(sign == LV_SIGNAL_PRESS_LOST) { if(lv_sw_get_state(sw)) { diff --git a/lv_objx/lv_sw.h b/lv_objx/lv_sw.h index 87a62c8cc..ba22c677f 100644 --- a/lv_objx/lv_sw.h +++ b/lv_objx/lv_sw.h @@ -44,7 +44,7 @@ typedef struct /*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)*/ - uint8_t changed :1; /*Indicates the switch explicitly changed by drag*/ + uint8_t changed :1; /*Indicates the switch state explicitly changed by drag*/ #if USE_LV_ANIMATION uint16_t anim_time; /*switch animation time */ #endif From 892f2be48743bf3a3bc6d0cd9c705fec261265fb Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 19 Nov 2018 07:00:17 +0100 Subject: [PATCH 7/9] add lv_btnm_get_pressed --- lv_objx/lv_btnm.c | 17 ++++++++++++++--- lv_objx/lv_btnm.h | 8 +++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/lv_objx/lv_btnm.c b/lv_objx/lv_btnm.c index 3326f2e96..73a96e39d 100644 --- a/lv_objx/lv_btnm.c +++ b/lv_objx/lv_btnm.c @@ -340,16 +340,27 @@ lv_btnm_action_t lv_btnm_get_action(const lv_obj_t * 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 (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) { 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; } @@ -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 - /*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); if(lv_group_get_focused(g) != btnm) { ext->btn_id_pr = LV_BTNM_PR_NONE; diff --git a/lv_objx/lv_btnm.h b/lv_objx/lv_btnm.h index 91214e40f..a1c7c2097 100644 --- a/lv_objx/lv_btnm.h +++ b/lv_objx/lv_btnm.h @@ -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); +/** + * 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 (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); From 5416c2b7787dce8796b6b6172d7de5bc7162f291 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 20 Nov 2018 07:33:32 +0100 Subject: [PATCH 8/9] lv_sw: aniamtion improvements --- lv_objx/lv_sw.c | 82 ++++++++++++++++++++++++++++++++++++++++--------- lv_objx/lv_sw.h | 14 +++++++++ 2 files changed, 81 insertions(+), 15 deletions(-) diff --git a/lv_objx/lv_sw.c b/lv_objx/lv_sw.c index 52f5a389c..570a6c4f4 100644 --- a/lv_objx/lv_sw.c +++ b/lv_objx/lv_sw.c @@ -16,6 +16,7 @@ #endif #include "../lv_themes/lv_theme.h" +#include "../lv_misc/lv_math.h" /********************* * DEFINES @@ -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); ext->style_knob_off = copy_ext->style_knob_off; 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); 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); } @@ -122,9 +126,7 @@ lv_obj_t * lv_sw_create(lv_obj_t * par, const lv_obj_t * copy) void lv_sw_on(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_value(sw, LV_SWITCH_SLIDER_ANIM_MAX); lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_on); } @@ -134,6 +136,32 @@ void lv_sw_on(lv_obj_t * sw) * @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); +} + +/** + * 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); @@ -259,12 +287,39 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param) 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; /*If explicitly changed don't need to be toggled on release*/ + ext->changed = 1; } } else if(sign == LV_SIGNAL_PRESS_LOST) { @@ -276,38 +331,35 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param) lv_slider_set_style(sw, LV_SLIDER_STYLE_KNOB, ext->style_knob_off); lv_sw_anim_to_value(sw, 0); } - ext->changed = 0; } 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(sw); - else lv_sw_on(sw); + 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); - if(v > LV_SWITCH_SLIDER_ANIM_MAX / 2) lv_sw_on(sw); - else lv_sw_off(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); } - ext->changed = 0; - } else if(sign == LV_SIGNAL_CONTROLL) { char c = *((char *)param); if(c == LV_GROUP_KEY_ENTER) { - if(old_val) lv_sw_off(sw); - else lv_sw_on(sw); + 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(sw); + 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(sw); + lv_sw_off_anim(sw); if(slider_action) res = slider_action(sw); } } else if(sign == LV_SIGNAL_GET_EDITABLE) { diff --git a/lv_objx/lv_sw.h b/lv_objx/lv_sw.h index ba22c677f..1eee3a50e 100644 --- a/lv_objx/lv_sw.h +++ b/lv_objx/lv_sw.h @@ -44,7 +44,9 @@ typedef struct /*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 @@ -86,6 +88,18 @@ void lv_sw_on(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 * @param sw pointer to switch object From c5845869857b8edda207d31a47d8a6e3bf0d3d41 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Wed, 21 Nov 2018 14:00:19 +0100 Subject: [PATCH 9/9] lv_refr/draw: enable the drawing even with body.opa == LV_OPA_TRANSP E.g. labels don't care with body paramters --- lv_core/lv_refr.c | 12 +++++------- lv_draw/lv_draw_rect.c | 4 ++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/lv_core/lv_refr.c b/lv_core/lv_refr.c index 93a81c34c..766c6e2e9 100644 --- a/lv_core/lv_refr.c +++ b/lv_core/lv_refr.c @@ -515,10 +515,9 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p) /* Redraw the object */ 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); - //tick_wait_ms(100); /*DEBUG: Wait after every object draw to see the order of drawing*/ - } + 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*/ + /*Create a new 'obj_mask' without 'ext_size' because the children can't be visible there*/ 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(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); + } } diff --git a/lv_draw/lv_draw_rect.c b/lv_draw/lv_draw_rect.c index b62ccab51..5b4ef1665 100644 --- a/lv_draw/lv_draw_rect.c +++ b/lv_draw/lv_draw_rect.c @@ -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); } #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); 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); if(style->body.radius != 0) {