diff --git a/docs/widgets/switch.rst b/docs/widgets/switch.rst index 4b0c445bf..938b48873 100644 --- a/docs/widgets/switch.rst +++ b/docs/widgets/switch.rst @@ -10,6 +10,8 @@ Overview The Switch looks like a little slider and can be used to turn something on and off. +Vertical Switch can be created if the width of the object is smaller than its height. + .. _lv_switch_parts_and_styles: Parts and Styles @@ -43,6 +45,12 @@ To get the current state of the switch (with ``true`` being on), use Call :cpp:expr:`lv_obj_add_state(obj, LV_STATE_CHECKED)` to turn it on, or :cpp:expr:`lv_obj_remove_state(obj, LV_STATE_CHECKED)` to turn it off. +Change orientation +------------------ + +:cpp:expr:`lv_switch_set_orientation(obj, LV_SWITCH_ORIENTATION_VERTICAL)` change orientation, default orientation is :cpp:enumerator:`LV_SWITCH_ORIENTATION_AUTO`, adaptive based on the width and height of the object. + + .. _lv_switch_events: Events diff --git a/examples/widgets/lv_example_widgets.h b/examples/widgets/lv_example_widgets.h index 8b4848d17..a52ed9016 100644 --- a/examples/widgets/lv_example_widgets.h +++ b/examples/widgets/lv_example_widgets.h @@ -136,6 +136,7 @@ void lv_example_spinbox_1(void); void lv_example_spinner_1(void); void lv_example_switch_1(void); +void lv_example_switch_2(void); void lv_example_table_1(void); void lv_example_table_2(void); diff --git a/examples/widgets/switch/index.rst b/examples/widgets/switch/index.rst index 07ee12670..060102614 100644 --- a/examples/widgets/switch/index.rst +++ b/examples/widgets/switch/index.rst @@ -5,3 +5,10 @@ Simple Switch .. lv_example:: widgets/switch/lv_example_switch_1 :language: c + +Switch Orientation +------------------- + +.. lv_example:: widgets/switch/lv_example_switch_2 + :language: c + diff --git a/examples/widgets/switch/lv_example_switch_2.c b/examples/widgets/switch/lv_example_switch_2.c new file mode 100644 index 000000000..1e3512fc9 --- /dev/null +++ b/examples/widgets/switch/lv_example_switch_2.c @@ -0,0 +1,32 @@ +#include "../../lv_examples.h" +#if LV_USE_SWITCH && LV_BUILD_EXAMPLES + +static void event_handler(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * obj = lv_event_get_target(e); + if(code == LV_EVENT_VALUE_CHANGED) { + LV_UNUSED(obj); + LV_LOG_USER("State: %s\n", lv_obj_has_state(obj, LV_STATE_CHECKED) ? "On" : "Off"); + } +} + +void lv_example_switch_2(void) +{ + lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + + lv_obj_t * sw; + + sw = lv_switch_create(lv_screen_active()); + lv_obj_set_size(sw, 30, 60); + lv_obj_add_event_cb(sw, event_handler, LV_EVENT_ALL, NULL); + + sw = lv_switch_create(lv_screen_active()); + lv_obj_set_size(sw, 30, 60); + lv_switch_set_orientation(sw, LV_SWITCH_ORIENTATION_VERTICAL); + lv_obj_add_state(sw, LV_STATE_CHECKED); + lv_obj_add_event_cb(sw, event_handler, LV_EVENT_ALL, NULL); +} + +#endif diff --git a/src/widgets/switch/lv_switch.c b/src/widgets/switch/lv_switch.c index 89b4b6363..6603f20c8 100644 --- a/src/widgets/switch/lv_switch.c +++ b/src/widgets/switch/lv_switch.c @@ -49,6 +49,7 @@ static void draw_main(lv_event_t * e); static void lv_switch_anim_exec_cb(void * sw, int32_t value); static void lv_switch_trigger_anim(lv_obj_t * obj); static void lv_switch_anim_completed(lv_anim_t * a); + /********************** * STATIC VARIABLES **********************/ @@ -80,6 +81,31 @@ lv_obj_t * lv_switch_create(lv_obj_t * parent) return obj; } +/*===================== + * Setter functions + *====================*/ + +void lv_switch_set_orientation(lv_obj_t * obj, lv_switch_orientation_t orientation) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_switch_t * sw = (lv_switch_t *)obj; + + sw->orientation = orientation; + lv_obj_invalidate(obj); +} + +/*===================== + * Getter functions + *====================*/ + +lv_switch_orientation_t lv_switch_get_orientation(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_switch_t * sw = (lv_switch_t *)obj; + + return sw->orientation; +} + /********************** * STATIC FUNCTIONS **********************/ @@ -92,6 +118,7 @@ static void lv_switch_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj lv_switch_t * sw = (lv_switch_t *)obj; sw->anim_state = LV_SWITCH_ANIM_STATE_INV; + sw->orientation = LV_SWITCH_ORIENTATION_AUTO; lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLLABLE); lv_obj_add_flag(obj, LV_OBJ_FLAG_CHECKABLE); @@ -163,28 +190,67 @@ static void draw_main(lv_event_t * e) lv_draw_rect(layer, &draw_indic_dsc, &indic_area); /*Draw the knob*/ - int32_t anim_value_x = 0; - int32_t knob_size = lv_obj_get_height(obj); - int32_t anim_length = lv_area_get_width(&obj->coords) - knob_size; - - if(LV_SWITCH_IS_ANIMATING(sw)) { - /* Use the animation's coordinate */ - anim_value_x = (anim_length * sw->anim_state) / LV_SWITCH_ANIM_STATE_END; - } - else { - /* Use LV_STATE_CHECKED to decide the coordinate */ - bool chk = lv_obj_get_state(obj) & LV_STATE_CHECKED; - anim_value_x = chk ? anim_length : 0; - } - - if(LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN)) { - anim_value_x = anim_length - anim_value_x; - } - lv_area_t knob_area; lv_area_copy(&knob_area, &obj->coords); - knob_area.x1 += anim_value_x; - knob_area.x2 = knob_area.x1 + (knob_size > 0 ? knob_size - 1 : 0); + + int32_t switch_w = lv_area_get_width(&obj->coords); + int32_t switch_h = lv_area_get_height(&obj->coords); + bool hor = false; + + switch(sw->orientation) { + case LV_SWITCH_ORIENTATION_HORIZONTAL: + hor = true; + break; + case LV_SWITCH_ORIENTATION_VERTICAL: + hor = false; + break; + case LV_SWITCH_ORIENTATION_AUTO: + default: + hor = (switch_w >= switch_h); + break; + } + + if(hor) { + int32_t anim_value_x = 0; + int32_t knob_size = lv_obj_get_height(obj); + int32_t anim_length = lv_area_get_width(&obj->coords) - knob_size; + if(LV_SWITCH_IS_ANIMATING(sw)) { + /* Use the animation's coordinate */ + anim_value_x = (anim_length * sw->anim_state) / LV_SWITCH_ANIM_STATE_END; + } + else { + /* Use LV_STATE_CHECKED to decide the coordinate */ + bool chk = lv_obj_get_state(obj) & LV_STATE_CHECKED; + anim_value_x = chk ? anim_length : 0; + } + + if(LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN)) { + anim_value_x = anim_length - anim_value_x; + } + knob_area.x1 += anim_value_x; + knob_area.x2 = knob_area.x1 + (knob_size > 0 ? knob_size - 1 : 0); + } + else { + int32_t anim_value_y = 0; + int32_t knob_size = lv_obj_get_width(obj); + int32_t anim_length = lv_area_get_height(&obj->coords) - knob_size; + if(LV_SWITCH_IS_ANIMATING(sw)) { + /* Use the animation's coordinate */ + anim_value_y = (anim_length * sw->anim_state) / LV_SWITCH_ANIM_STATE_END; + } + else { + /* Use LV_STATE_CHECKED to decide the coordinate */ + bool chk = lv_obj_get_state(obj) & LV_STATE_CHECKED; + anim_value_y = chk ? anim_length : 0; + } + + if(LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN)) { + anim_value_y = anim_length - anim_value_y; + } + + knob_area.y2 -= anim_value_y; + knob_area.y1 = knob_area.y2 - (knob_size > 0 ? knob_size - 1 : 0); + } int32_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); int32_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); diff --git a/src/widgets/switch/lv_switch.h b/src/widgets/switch/lv_switch.h index 989a3dd1b..3cc0d2846 100644 --- a/src/widgets/switch/lv_switch.h +++ b/src/widgets/switch/lv_switch.h @@ -28,6 +28,16 @@ extern "C" { LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_switch_class; +/********************** + * TYPEDEFS + **********************/ + +typedef enum { + LV_SWITCH_ORIENTATION_AUTO, + LV_SWITCH_ORIENTATION_HORIZONTAL, + LV_SWITCH_ORIENTATION_VERTICAL +} lv_switch_orientation_t; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -39,6 +49,28 @@ LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_switch_class; */ lv_obj_t * lv_switch_create(lv_obj_t * parent); +/*===================== + * Setter functions + *====================*/ + +/** + * Set the orientation of switch. + * @param obj pointer to switch object + * @param orientation switch orientation from `lv_switch_orientation_t` + */ +void lv_switch_set_orientation(lv_obj_t * obj, lv_switch_orientation_t orientation); + +/*===================== + * Getter functions + *====================*/ + +/** + * Get the orientation of switch. + * @param obj pointer to switch object + * @return switch orientation from ::lv_switch_orientation_t + */ +lv_switch_orientation_t lv_switch_get_orientation(lv_obj_t * obj); + /********************** * MACROS **********************/ diff --git a/src/widgets/switch/lv_switch_private.h b/src/widgets/switch/lv_switch_private.h index f7bf77e97..66e90d324 100644 --- a/src/widgets/switch/lv_switch_private.h +++ b/src/widgets/switch/lv_switch_private.h @@ -34,6 +34,7 @@ extern "C" { struct _lv_switch_t { lv_obj_t obj; int32_t anim_state; + lv_switch_orientation_t orientation : 3; /**< Orientation of switch*/ }; diff --git a/tests/ref_imgs/widgets/switch_1.png b/tests/ref_imgs/widgets/switch_1.png new file mode 100644 index 000000000..108009aee Binary files /dev/null and b/tests/ref_imgs/widgets/switch_1.png differ diff --git a/tests/src/test_cases/widgets/test_switch.c b/tests/src/test_cases/widgets/test_switch.c index aff45bf73..8ffa58731 100644 --- a/tests/src/test_cases/widgets/test_switch.c +++ b/tests/src/test_cases/widgets/test_switch.c @@ -133,4 +133,33 @@ void test_switch_should_state_change_when_event_bubbling_is_enabled(void) TEST_ASSERT(lv_obj_has_state(sw, LV_STATE_CHECKED)); } + +void test_screeshots(void) +{ + lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + lv_obj_clean(scr); + + sw = lv_switch_create(lv_screen_active()); + + sw = lv_switch_create(lv_screen_active()); + lv_obj_add_state(sw, LV_STATE_CHECKED); + + sw = lv_switch_create(lv_screen_active()); + + sw = lv_switch_create(lv_screen_active()); + lv_obj_add_state(sw, LV_STATE_CHECKED | LV_STATE_DISABLED); + + sw = lv_switch_create(lv_screen_active()); + lv_switch_set_orientation(sw, LV_SWITCH_ORIENTATION_VERTICAL); + lv_obj_set_size(sw, 50, 100); + + sw = lv_switch_create(lv_screen_active()); + lv_switch_set_orientation(sw, LV_SWITCH_ORIENTATION_VERTICAL); + lv_obj_add_state(sw, LV_STATE_CHECKED); + lv_obj_set_size(sw, 50, 100); + + TEST_ASSERT_EQUAL_SCREENSHOT("widgets/switch_1.png"); +} + #endif