acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
lv_switch.c (8747B)
1 /** 2 * @file lv_sw.c 3 * 4 */ 5 6 /********************* 7 * INCLUDES 8 *********************/ 9 #include "lv_switch.h" 10 11 #if LV_USE_SWITCH != 0 12 13 #include "../misc/lv_assert.h" 14 #include "../misc/lv_math.h" 15 #include "../misc/lv_anim.h" 16 #include "../core/lv_indev.h" 17 #include "../core/lv_disp.h" 18 #include "lv_img.h" 19 20 /********************* 21 * DEFINES 22 *********************/ 23 #define MY_CLASS &lv_switch_class 24 25 #define LV_SWITCH_IS_ANIMATING(sw) (((sw)->anim_state) != LV_SWITCH_ANIM_STATE_INV) 26 27 /** Switch animation start value. (Not the real value of the switch just indicates process animation)*/ 28 #define LV_SWITCH_ANIM_STATE_START 0 29 30 /** Switch animation end value. (Not the real value of the switch just indicates process animation)*/ 31 #define LV_SWITCH_ANIM_STATE_END 256 32 33 /** Mark no animation is in progress*/ 34 #define LV_SWITCH_ANIM_STATE_INV -1 35 36 /********************** 37 * TYPEDEFS 38 **********************/ 39 40 /********************** 41 * STATIC PROTOTYPES 42 **********************/ 43 static void lv_switch_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); 44 static void lv_switch_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); 45 static void lv_switch_event(const lv_obj_class_t * class_p, lv_event_t * e); 46 static void draw_main(lv_event_t * e); 47 48 static void lv_switch_anim_exec_cb(void * sw, int32_t value); 49 static void lv_switch_trigger_anim(lv_obj_t * obj); 50 static void lv_switch_anim_ready(lv_anim_t * a); 51 /********************** 52 * STATIC VARIABLES 53 **********************/ 54 const lv_obj_class_t lv_switch_class = { 55 .constructor_cb = lv_switch_constructor, 56 .destructor_cb = lv_switch_destructor, 57 .event_cb = lv_switch_event, 58 .width_def = (4 * LV_DPI_DEF) / 10, 59 .height_def = (4 * LV_DPI_DEF) / 17, 60 .group_def = LV_OBJ_CLASS_GROUP_DEF_TRUE, 61 .instance_size = sizeof(lv_switch_t), 62 .base_class = &lv_obj_class 63 }; 64 65 /********************** 66 * MACROS 67 **********************/ 68 69 /********************** 70 * GLOBAL FUNCTIONS 71 **********************/ 72 73 lv_obj_t * lv_switch_create(lv_obj_t * parent) 74 { 75 LV_LOG_INFO("begin"); 76 lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); 77 lv_obj_class_init_obj(obj); 78 return obj; 79 } 80 81 /********************** 82 * STATIC FUNCTIONS 83 **********************/ 84 85 static void lv_switch_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) 86 { 87 LV_UNUSED(class_p); 88 LV_TRACE_OBJ_CREATE("begin"); 89 90 lv_switch_t * sw = (lv_switch_t *)obj; 91 92 sw->anim_state = LV_SWITCH_ANIM_STATE_INV; 93 94 lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); 95 lv_obj_add_flag(obj, LV_OBJ_FLAG_CHECKABLE); 96 lv_obj_add_flag(obj, LV_OBJ_FLAG_SCROLL_ON_FOCUS); 97 98 LV_TRACE_OBJ_CREATE("finished"); 99 } 100 101 static void lv_switch_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) 102 { 103 LV_UNUSED(class_p); 104 lv_switch_t * sw = (lv_switch_t *)obj; 105 106 lv_anim_del(sw, NULL); 107 } 108 109 static void lv_switch_event(const lv_obj_class_t * class_p, lv_event_t * e) 110 { 111 LV_UNUSED(class_p); 112 113 lv_res_t res; 114 115 /*Call the ancestor's event handler*/ 116 res = lv_obj_event_base(MY_CLASS, e); 117 if(res != LV_RES_OK) return; 118 119 lv_event_code_t code = lv_event_get_code(e); 120 lv_obj_t * obj = lv_event_get_target(e); 121 122 if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { 123 lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); 124 lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); 125 lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); 126 lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); 127 128 /*The smaller size is the knob diameter*/ 129 lv_coord_t knob_size = LV_MAX4(knob_left, knob_right, knob_bottom, knob_top); 130 knob_size += _LV_SWITCH_KNOB_EXT_AREA_CORRECTION; 131 knob_size += lv_obj_calculate_ext_draw_size(obj, LV_PART_KNOB); 132 133 lv_coord_t * s = lv_event_get_param(e); 134 *s = LV_MAX(*s, knob_size); 135 *s = LV_MAX(*s, lv_obj_calculate_ext_draw_size(obj, LV_PART_INDICATOR)); 136 } 137 else if(code == LV_EVENT_VALUE_CHANGED) { 138 lv_switch_trigger_anim(obj); 139 lv_obj_invalidate(obj); 140 } 141 else if(code == LV_EVENT_DRAW_MAIN) { 142 draw_main(e); 143 } 144 } 145 146 static void draw_main(lv_event_t * e) 147 { 148 lv_obj_t * obj = lv_event_get_target(e); 149 lv_switch_t * sw = (lv_switch_t *)obj; 150 151 lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); 152 153 /*Calculate the indicator area*/ 154 lv_coord_t bg_left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN); 155 lv_coord_t bg_right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN); 156 lv_coord_t bg_top = lv_obj_get_style_pad_top(obj, LV_PART_MAIN); 157 lv_coord_t bg_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_MAIN); 158 159 /*Draw the indicator*/ 160 /*Respect the background's padding*/ 161 lv_area_t indic_area; 162 lv_area_copy(&indic_area, &obj->coords); 163 indic_area.x1 += bg_left; 164 indic_area.x2 -= bg_right; 165 indic_area.y1 += bg_top; 166 indic_area.y2 -= bg_bottom; 167 168 lv_draw_rect_dsc_t draw_indic_dsc; 169 lv_draw_rect_dsc_init(&draw_indic_dsc); 170 lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &draw_indic_dsc); 171 lv_draw_rect(draw_ctx, &draw_indic_dsc, &indic_area); 172 173 /*Draw the knob*/ 174 lv_coord_t anim_value_x = 0; 175 lv_coord_t knob_size = lv_obj_get_height(obj); 176 lv_coord_t anim_length = lv_area_get_width(&obj->coords) - knob_size; 177 178 if(LV_SWITCH_IS_ANIMATING(sw)) { 179 /* Use the animation's coordinate */ 180 anim_value_x = (anim_length * sw->anim_state) / LV_SWITCH_ANIM_STATE_END; 181 } 182 else { 183 /* Use LV_STATE_CHECKED to decide the coordinate */ 184 bool chk = lv_obj_get_state(obj) & LV_STATE_CHECKED; 185 anim_value_x = chk ? anim_length : 0; 186 } 187 188 if(LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN)) { 189 anim_value_x = anim_length - anim_value_x; 190 } 191 192 lv_area_t knob_area; 193 knob_area.x1 = obj->coords.x1 + anim_value_x; 194 knob_area.x2 = knob_area.x1 + knob_size; 195 196 knob_area.y1 = obj->coords.y1; 197 knob_area.y2 = obj->coords.y2; 198 199 lv_coord_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB); 200 lv_coord_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB); 201 lv_coord_t knob_top = lv_obj_get_style_pad_top(obj, LV_PART_KNOB); 202 lv_coord_t knob_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_KNOB); 203 204 /*Apply the paddings on the knob area*/ 205 knob_area.x1 -= knob_left; 206 knob_area.x2 += knob_right; 207 knob_area.y1 -= knob_top; 208 knob_area.y2 += knob_bottom; 209 210 lv_draw_rect_dsc_t knob_rect_dsc; 211 lv_draw_rect_dsc_init(&knob_rect_dsc); 212 lv_obj_init_draw_rect_dsc(obj, LV_PART_KNOB, &knob_rect_dsc); 213 214 lv_draw_rect(draw_ctx, &knob_rect_dsc, &knob_area); 215 } 216 217 static void lv_switch_anim_exec_cb(void * var, int32_t value) 218 { 219 lv_switch_t * sw = var; 220 sw->anim_state = value; 221 lv_obj_invalidate((lv_obj_t *)sw); 222 } 223 224 /** 225 * Resets the switch's animation state to "no animation in progress". 226 */ 227 static void lv_switch_anim_ready(lv_anim_t * a) 228 { 229 lv_switch_t * sw = a->var; 230 sw->anim_state = LV_SWITCH_ANIM_STATE_INV; 231 lv_obj_invalidate((lv_obj_t *)sw); 232 } 233 234 /** 235 * Starts an animation for the switch knob. if the anim_time style property is greater than 0 236 * @param obj the switch to animate 237 */ 238 static void lv_switch_trigger_anim(lv_obj_t * obj) 239 { 240 LV_ASSERT_OBJ(obj, MY_CLASS); 241 lv_switch_t * sw = (lv_switch_t *)obj; 242 243 uint32_t anim_dur_full = lv_obj_get_style_anim_time(obj, LV_PART_MAIN); 244 245 if(anim_dur_full > 0) { 246 bool chk = lv_obj_get_state(obj) & LV_STATE_CHECKED; 247 int32_t anim_start; 248 int32_t anim_end; 249 /*No animation in progress -> simply set the values*/ 250 if(sw->anim_state == LV_SWITCH_ANIM_STATE_INV) { 251 anim_start = chk ? LV_SWITCH_ANIM_STATE_START : LV_SWITCH_ANIM_STATE_END; 252 anim_end = chk ? LV_SWITCH_ANIM_STATE_END : LV_SWITCH_ANIM_STATE_START; 253 } 254 /*Animation in progress. Start from the animation end value*/ 255 else { 256 anim_start = sw->anim_state; 257 anim_end = chk ? LV_SWITCH_ANIM_STATE_END : LV_SWITCH_ANIM_STATE_START; 258 } 259 /*Calculate actual animation duration*/ 260 uint32_t anim_dur = (anim_dur_full * LV_ABS(anim_start - anim_end)) / LV_SWITCH_ANIM_STATE_END; 261 262 /*Stop the previous animation if it exists*/ 263 lv_anim_del(sw, NULL); 264 265 lv_anim_t a; 266 lv_anim_init(&a); 267 lv_anim_set_var(&a, sw); 268 lv_anim_set_exec_cb(&a, lv_switch_anim_exec_cb); 269 lv_anim_set_values(&a, anim_start, anim_end); 270 lv_anim_set_ready_cb(&a, lv_switch_anim_ready); 271 lv_anim_set_time(&a, anim_dur); 272 lv_anim_start(&a); 273 } 274 } 275 276 277 #endif