diff --git a/lv_objx/lv_sw.c b/lv_objx/lv_sw.c index 52f5a389c1..570a6c4f4a 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 ba22c677f3..1eee3a50e3 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