Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
CTCaer
GitHub Repository: CTCaer/hekate
Path: blob/master/bdk/libs/lvgl/lv_objx/lv_btn.c
1476 views
1
/**
2
* @file lv_btn.c
3
*
4
*/
5
6
/*********************
7
* INCLUDES
8
*********************/
9
10
#include "lv_btn.h"
11
#if USE_LV_BTN != 0
12
13
#include <string.h>
14
#include "../lv_core/lv_group.h"
15
#include "../lv_draw/lv_draw.h"
16
#include "../lv_themes/lv_theme.h"
17
#include "../lv_misc/lv_area.h"
18
#include "../lv_misc/lv_color.h"
19
#include "../lv_misc/lv_math.h"
20
21
/*********************
22
* DEFINES
23
*********************/
24
#define LV_BTN_INK_VALUE_MAX 256
25
#define LV_BTN_INK_VALUE_MAX_SHIFT 8
26
27
/**********************
28
* TYPEDEFS
29
**********************/
30
31
/**********************
32
* STATIC PROTOTYPES
33
**********************/
34
static bool lv_btn_design(lv_obj_t * btn, const lv_area_t * mask, lv_design_mode_t mode);
35
static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param);
36
37
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
38
static void lv_btn_ink_effect_anim(lv_obj_t * btn, int32_t val);
39
static void lv_btn_ink_effect_anim_ready(void * p);
40
#endif
41
42
/**********************
43
* STATIC VARIABLES
44
**********************/
45
static lv_signal_func_t ancestor_signal;
46
static lv_design_func_t ancestor_design;
47
48
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
49
static lv_coord_t ink_act_value;
50
static lv_obj_t * ink_obj;
51
static lv_btn_state_t ink_bg_state;
52
static lv_btn_state_t ink_top_state;
53
static bool ink_ready;
54
static bool ink_playback;
55
static lv_point_t ink_point;
56
#endif
57
58
/**********************
59
* MACROS
60
**********************/
61
62
/**********************
63
* GLOBAL FUNCTIONS
64
**********************/
65
66
/**
67
* Create a button objects
68
* @param par pointer to an object, it will be the parent of the new button
69
* @param copy pointer to a button object, if not NULL then the new object will be copied from it
70
* @return pointer to the created button
71
*/
72
lv_obj_t * lv_btn_create(lv_obj_t * par, const lv_obj_t * copy)
73
{
74
LV_LOG_TRACE("button create started");
75
76
lv_obj_t * new_btn;
77
78
new_btn = lv_cont_create(par, copy);
79
lv_mem_assert(new_btn);
80
if(new_btn == NULL) return NULL;
81
82
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(new_btn);
83
if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_func(new_btn);
84
85
/*Allocate the extended data*/
86
lv_btn_ext_t * ext = lv_obj_allocate_ext_attr(new_btn, sizeof(lv_btn_ext_t));
87
lv_mem_assert(ext);
88
if(ext == NULL) return NULL;
89
90
ext->state = LV_BTN_STATE_REL;
91
92
ext->actions[LV_BTN_ACTION_PR] = NULL;
93
ext->actions[LV_BTN_ACTION_CLICK] = NULL;
94
ext->actions[LV_BTN_ACTION_LONG_PR] = NULL;
95
ext->actions[LV_BTN_ACTION_LONG_PR_REPEAT] = NULL;
96
97
ext->styles[LV_BTN_STATE_REL] = &lv_style_btn_rel;
98
ext->styles[LV_BTN_STATE_PR] = &lv_style_btn_pr;
99
ext->styles[LV_BTN_STATE_TGL_REL] = &lv_style_btn_tgl_rel;
100
ext->styles[LV_BTN_STATE_TGL_PR] = &lv_style_btn_tgl_pr;
101
ext->styles[LV_BTN_STATE_INA] = &lv_style_btn_ina;
102
103
ext->long_pr_action_executed = 0;
104
ext->toggle = 0;
105
ext->idx = 0;
106
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
107
ext->ink_in_time = 0;
108
ext->ink_wait_time = 0;
109
ext->ink_out_time = 0;
110
#endif
111
112
lv_obj_set_signal_func(new_btn, lv_btn_signal);
113
lv_obj_set_design_func(new_btn, lv_btn_design);
114
115
/*If no copy do the basic initialization*/
116
if(copy == NULL) {
117
/*Set layout if the button is not a screen*/
118
if(par != NULL) {
119
lv_btn_set_layout(new_btn, LV_LAYOUT_CENTER);
120
}
121
122
lv_obj_set_click(new_btn, true); /*Be sure the button is clickable*/
123
124
/*Set the default styles*/
125
lv_theme_t * th = lv_theme_get_current();
126
if(th) {
127
lv_btn_set_style(new_btn, LV_BTN_STYLE_REL, th->btn.rel);
128
lv_btn_set_style(new_btn, LV_BTN_STYLE_PR, th->btn.pr);
129
lv_btn_set_style(new_btn, LV_BTN_STYLE_TGL_REL, th->btn.tgl_rel);
130
lv_btn_set_style(new_btn, LV_BTN_STYLE_TGL_PR, th->btn.tgl_pr);
131
lv_btn_set_style(new_btn, LV_BTN_STYLE_INA, th->btn.ina);
132
} else {
133
lv_obj_set_style(new_btn, ext->styles[LV_BTN_STATE_REL]);
134
}
135
}
136
/*Copy 'copy'*/
137
else {
138
lv_btn_ext_t * copy_ext = lv_obj_get_ext_attr(copy);
139
ext->state = copy_ext->state;
140
ext->toggle = copy_ext->toggle;
141
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
142
ext->ink_in_time = copy_ext->ink_in_time;
143
ext->ink_wait_time = copy_ext->ink_wait_time;
144
ext->ink_out_time = copy_ext->ink_out_time;
145
#endif
146
memcpy(ext->actions, copy_ext->actions, sizeof(ext->actions));
147
memcpy(ext->styles, copy_ext->styles, sizeof(ext->styles));
148
149
/*Refresh the style with new signal function*/
150
lv_obj_refresh_style(new_btn);
151
}
152
153
LV_LOG_INFO("button created");
154
155
return new_btn;
156
}
157
158
/*=====================
159
* Setter functions
160
*====================*/
161
162
/**
163
* Enable the toggled states
164
* @param btn pointer to a button object
165
* @param tgl true: enable toggled states, false: disable
166
*/
167
void lv_btn_set_toggle(lv_obj_t * btn, bool tgl)
168
{
169
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
170
171
ext->toggle = tgl != false ? 1 : 0;
172
}
173
174
/**
175
* Set the state of the button
176
* @param btn pointer to a button object
177
* @param state the new state of the button (from lv_btn_state_t enum)
178
*/
179
void lv_btn_set_state(lv_obj_t * btn, lv_btn_state_t state)
180
{
181
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
182
if(ext->state != state) {
183
ext->state = state;
184
lv_obj_set_style(btn, ext->styles[state]);
185
}
186
}
187
188
/**
189
* Toggle the state of the button (ON->OFF, OFF->ON)
190
* @param btn pointer to a button object
191
*/
192
void lv_btn_toggle(lv_obj_t * btn)
193
{
194
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
195
switch(ext->state) {
196
case LV_BTN_STATE_REL:
197
lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
198
break;
199
case LV_BTN_STATE_PR:
200
lv_btn_set_state(btn, LV_BTN_STATE_TGL_PR);
201
break;
202
case LV_BTN_STATE_TGL_REL:
203
lv_btn_set_state(btn, LV_BTN_STATE_REL);
204
break;
205
case LV_BTN_STATE_TGL_PR:
206
lv_btn_set_state(btn, LV_BTN_STATE_PR);
207
break;
208
default:
209
break;
210
}
211
}
212
213
/**
214
* Set a function to call when a button event happens
215
* @param btn pointer to a button object
216
* @param action type of event form 'lv_action_t' (press, release, long press, long press repeat)
217
*/
218
void lv_btn_set_action(lv_obj_t * btn, lv_btn_action_t type, lv_action_t action)
219
{
220
if(type >= LV_BTN_ACTION_NUM) return;
221
222
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
223
ext->actions[type] = action;
224
}
225
226
/**
227
* Set time of the ink effect (draw a circle on click to animate in the new state)
228
* @param btn pointer to a button object
229
* @param time the time of the ink animation
230
*/
231
void lv_btn_set_ink_in_time(lv_obj_t * btn, uint16_t time)
232
{
233
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
234
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
235
ext->ink_in_time = time;
236
#else
237
(void)btn; /*Unused*/
238
(void)time; /*Unused*/
239
LV_LOG_WARN("`lv_btn_set_ink_ink_time` has no effect if LV_BTN_INK_EFEFCT or USE_LV_ANIMATION is disabled")
240
#endif
241
}
242
243
/**
244
* Set the wait time before the ink disappears
245
* @param btn pointer to a button object
246
* @param time the time of the ink animation
247
*/
248
void lv_btn_set_ink_wait_time(lv_obj_t * btn, uint16_t time)
249
{
250
251
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
252
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
253
ext->ink_wait_time = time;
254
#else
255
(void)btn; /*Unused*/
256
(void)time; /*Unused*/
257
LV_LOG_WARN("`lv_btn_set_ink_wait_time` has no effect if LV_BTN_INK_EFEFCT or USE_LV_ANIMATION is disabled")
258
#endif
259
}
260
261
/**
262
* Set time of the ink out effect (animate to the released state)
263
* @param btn pointer to a button object
264
* @param time the time of the ink animation
265
*/
266
void lv_btn_set_ink_out_time(lv_obj_t * btn, uint16_t time)
267
{
268
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
269
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
270
ext->ink_out_time = time;
271
#else
272
(void)btn; /*Unused*/
273
(void)time; /*Unused*/
274
LV_LOG_WARN("`lv_btn_set_ink_out_time` has no effect if LV_BTN_INK_EFEFCT or USE_LV_ANIMATION is disabled")
275
#endif
276
}
277
278
/**
279
* Set a style of a button
280
* @param btn pointer to a button object
281
* @param type which style should be set
282
* @param style pointer to a style
283
*/
284
void lv_btn_set_style(lv_obj_t * btn, lv_btn_style_t type, lv_style_t * style)
285
{
286
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
287
288
switch(type) {
289
case LV_BTN_STYLE_REL:
290
ext->styles[LV_BTN_STATE_REL] = style;
291
break;
292
case LV_BTN_STYLE_PR:
293
ext->styles[LV_BTN_STATE_PR] = style;
294
break;
295
case LV_BTN_STYLE_TGL_REL:
296
ext->styles[LV_BTN_STATE_TGL_REL] = style;
297
break;
298
case LV_BTN_STYLE_TGL_PR:
299
ext->styles[LV_BTN_STATE_TGL_PR] = style;
300
break;
301
case LV_BTN_STYLE_INA:
302
ext->styles[LV_BTN_STATE_INA] = style;
303
break;
304
}
305
306
/*Refresh the object with the new style*/
307
lv_obj_set_style(btn, ext->styles[ext->state]);
308
}
309
310
311
/*=====================
312
* Getter functions
313
*====================*/
314
315
/**
316
* Get the current state of the button
317
* @param btn pointer to a button object
318
* @return the state of the button (from lv_btn_state_t enum)
319
*/
320
lv_btn_state_t lv_btn_get_state(const lv_obj_t * btn)
321
{
322
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
323
return ext->state;
324
}
325
326
/**
327
* Get the toggle enable attribute of the button
328
* @param btn pointer to a button object
329
* @return ture: toggle enabled, false: disabled
330
*/
331
bool lv_btn_get_toggle(const lv_obj_t * btn)
332
{
333
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
334
335
return ext->toggle != 0 ? true : false;
336
}
337
338
/**
339
* Get the release action of a button
340
* @param btn pointer to a button object
341
* @return pointer to the release action function
342
*/
343
lv_action_t lv_btn_get_action(const lv_obj_t * btn, lv_btn_action_t type)
344
{
345
if(type >= LV_BTN_ACTION_NUM) return NULL;
346
347
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
348
return ext->actions[type];
349
}
350
351
/**
352
* Get time of the ink in effect (draw a circle on click to animate in the new state)
353
* @param btn pointer to a button object
354
* @return the time of the ink animation
355
*/
356
uint16_t lv_btn_get_ink_in_time(const lv_obj_t * btn)
357
{
358
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
359
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
360
return ext->ink_in_time;
361
#else
362
(void)btn; /*Unused*/
363
return 0;
364
#endif
365
}
366
367
368
/**
369
* Get the wait time before the ink disappears
370
* @param btn pointer to a button object
371
* @return the time of the ink animation
372
*/
373
uint16_t lv_btn_get_ink_wait_time(const lv_obj_t * btn)
374
{
375
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
376
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
377
return ext->ink_wait_time;
378
#else
379
(void)btn; /*Unused*/
380
return 0;
381
#endif
382
}
383
/**
384
* Get time of the ink out effect (animate to the releases state)
385
* @param btn pointer to a button object
386
* @return the time of the ink animation
387
*/
388
uint16_t lv_btn_get_ink_out_time(const lv_obj_t * btn)
389
{
390
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
391
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
392
return ext->ink_in_time;
393
#else
394
(void)btn; /*Unused*/
395
return 0;
396
#endif
397
}
398
399
/**
400
* Get a style of a button
401
* @param btn pointer to a button object
402
* @param type which style should be get
403
* @return style pointer to a style
404
*/
405
lv_style_t * lv_btn_get_style(const lv_obj_t * btn, lv_btn_style_t type)
406
{
407
lv_style_t * style = NULL;
408
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
409
410
switch(type) {
411
case LV_BTN_STYLE_REL:
412
style = ext->styles[LV_BTN_STATE_REL];
413
break;
414
case LV_BTN_STYLE_PR:
415
style = ext->styles[LV_BTN_STATE_PR];
416
break;
417
case LV_BTN_STYLE_TGL_REL:
418
style = ext->styles[LV_BTN_STATE_TGL_REL];
419
break;
420
case LV_BTN_STYLE_TGL_PR:
421
style = ext->styles[LV_BTN_STATE_TGL_PR];
422
break;
423
case LV_BTN_STYLE_INA:
424
style = ext->styles[LV_BTN_STATE_INA];
425
break;
426
default:
427
style = NULL;
428
break;
429
}
430
431
return style;
432
}
433
434
/**********************
435
* STATIC FUNCTIONS
436
**********************/
437
438
439
/**
440
* Handle the drawing related tasks of the drop down lists
441
* @param btn pointer to an object
442
* @param mask the object will be drawn only in this area
443
* @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area
444
* (return 'true' if yes)
445
* LV_DESIGN_DRAW: draw the object (always return 'true')
446
* LV_DESIGN_DRAW_POST: drawing after every children are drawn
447
* @param return true/false, depends on 'mode'
448
*/
449
static bool lv_btn_design(lv_obj_t * btn, const lv_area_t * mask, lv_design_mode_t mode)
450
{
451
if(mode == LV_DESIGN_COVER_CHK) {
452
return false;
453
} else if(mode == LV_DESIGN_DRAW_MAIN) {
454
455
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
456
if(btn != ink_obj) {
457
ancestor_design(btn, mask, mode);
458
} else {
459
lv_opa_t opa_scale = lv_obj_get_opa_scale(btn);
460
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
461
462
/*Draw the normal button*/
463
if(ink_playback == false) {
464
lv_style_t style_tmp;
465
lv_style_copy(&style_tmp, ext->styles[ink_bg_state]);
466
style_tmp.body.shadow.width = ext->styles[ink_top_state]->body.shadow.width;
467
lv_draw_rect(&btn->coords, mask, &style_tmp, opa_scale);
468
469
lv_coord_t w = lv_obj_get_width(btn);
470
lv_coord_t h = lv_obj_get_height(btn);
471
lv_coord_t r_max = LV_MATH_MIN(w, h) / 2;
472
473
/*In the first part of the animation increase the size of the circle (ink effect) */
474
lv_area_t cir_area;
475
476
lv_coord_t coord_state = ink_act_value < LV_BTN_INK_VALUE_MAX / 2 ? ink_act_value : LV_BTN_INK_VALUE_MAX / 2;
477
lv_point_t p_act;
478
p_act.x = ink_point.x;
479
p_act.y = ink_point.y;
480
lv_coord_t x_err = (btn->coords.x1 + w / 2) - p_act.x;
481
lv_coord_t y_err = (btn->coords.y1 + h / 2) - p_act.y;
482
483
p_act.x += (x_err * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1);
484
p_act.y += (y_err * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1);
485
486
lv_coord_t half_side = LV_MATH_MAX(w, h) / 2;
487
cir_area.x1 = p_act.x - ((half_side * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
488
cir_area.y1 = p_act.y - ((half_side * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
489
cir_area.x2 = p_act.x + ((half_side * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
490
cir_area.y2 = p_act.y + ((half_side * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
491
492
lv_area_intersect(&cir_area, &btn->coords, &cir_area); /*Limit the area. (It might be too big on the smaller side)*/
493
494
/*In the second part animate the radius. Circle -> body.radius*/
495
lv_coord_t r_state = ink_act_value > LV_BTN_INK_VALUE_MAX / 2 ? ink_act_value - LV_BTN_INK_VALUE_MAX / 2 : 0;
496
497
lv_style_copy(&style_tmp, ext->styles[ink_top_state]);
498
style_tmp.body.radius = r_max + (((ext->styles[ink_bg_state]->body.radius - r_max) * r_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
499
style_tmp.body.border.width = 0;
500
501
/*Draw the circle*/
502
lv_draw_rect(&cir_area, mask, &style_tmp, opa_scale);
503
} else {
504
lv_style_t res;
505
lv_style_copy(&res, ext->styles[ink_bg_state]);
506
lv_style_mix(ext->styles[ink_bg_state], ext->styles[ink_top_state], &res, ink_act_value);
507
lv_draw_rect(&btn->coords, mask, &res, opa_scale);
508
509
}
510
}
511
#else
512
ancestor_design(btn, mask, mode);
513
#endif
514
} else if(mode == LV_DESIGN_DRAW_POST) {
515
ancestor_design(btn, mask, mode);
516
}
517
518
return true;
519
}
520
521
/**
522
* Signal function of the button
523
* @param btn pointer to a button object
524
* @param sign a signal type from lv_signal_t enum
525
* @param param pointer to a signal specific variable
526
* @return LV_RES_OK: the object is not deleted in the function; LV_RES_INV: the object is deleted
527
*/
528
static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param)
529
{
530
lv_res_t res;
531
532
/* Include the ancient signal function */
533
res = ancestor_signal(btn, sign, param);
534
if(res != LV_RES_OK) return res;
535
536
lv_btn_ext_t * ext = lv_obj_get_ext_attr(btn);
537
lv_btn_state_t state = lv_btn_get_state(btn);
538
bool tgl = lv_btn_get_toggle(btn);
539
540
if(sign == LV_SIGNAL_PRESSED) {
541
/*Refresh the state*/
542
if(ext->state == LV_BTN_STATE_REL) {
543
lv_btn_set_state(btn, LV_BTN_STATE_PR);
544
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
545
ink_bg_state = LV_BTN_STATE_REL;
546
ink_top_state = LV_BTN_STATE_PR;
547
#endif
548
} else if(ext->state == LV_BTN_STATE_TGL_REL) {
549
lv_btn_set_state(btn, LV_BTN_STATE_TGL_PR);
550
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
551
ink_bg_state = LV_BTN_STATE_TGL_REL;
552
ink_top_state = LV_BTN_STATE_TGL_PR;
553
#endif
554
}
555
556
ext->long_pr_action_executed = 0;
557
558
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
559
/*Forget the old inked button*/
560
if(ink_obj != NULL && ink_obj != btn) {
561
lv_anim_del(ink_obj, (lv_anim_fp_t)lv_btn_ink_effect_anim);
562
lv_obj_invalidate(ink_obj);
563
ink_obj = NULL;
564
}
565
/*Save the new data for inking and start it's animation if enabled*/
566
if(ext->ink_in_time > 0) {
567
ink_obj = btn;
568
ink_playback = false;
569
ink_ready = false;
570
lv_indev_get_point(lv_indev_get_act(), &ink_point);
571
572
lv_anim_t a;
573
a.var = btn;
574
a.start = 0;
575
a.end = LV_BTN_INK_VALUE_MAX;
576
a.fp = (lv_anim_fp_t)lv_btn_ink_effect_anim;
577
a.path = lv_anim_path_linear;
578
a.end_cb = lv_btn_ink_effect_anim_ready;
579
a.act_time = 0;
580
a.time = ext->ink_in_time;
581
a.playback = 0;
582
a.playback_pause = 0;
583
a.repeat = 0;
584
a.repeat_pause = 0;
585
lv_anim_create(&a);
586
}
587
#endif
588
/*Call the press action, 'param' is the caller indev_proc*/
589
if(ext->actions[LV_BTN_ACTION_PR] && state != LV_BTN_STATE_INA) {
590
res = ext->actions[LV_BTN_ACTION_PR](btn);
591
}
592
} else if(sign == LV_SIGNAL_PRESS_LOST) {
593
/*Refresh the state*/
594
if(ext->state == LV_BTN_STATE_PR) lv_btn_set_state(btn, LV_BTN_STATE_REL);
595
else if(ext->state == LV_BTN_STATE_TGL_PR) lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
596
} else if(sign == LV_SIGNAL_PRESSING) {
597
/*When the button begins to drag revert pressed states to released*/
598
if(lv_indev_is_dragging(param) != false) {
599
if(ext->state == LV_BTN_STATE_PR) lv_btn_set_state(btn, LV_BTN_STATE_REL);
600
else if(ext->state == LV_BTN_STATE_TGL_PR) lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
601
}
602
} else if(sign == LV_SIGNAL_RELEASED) {
603
/*If not dragged and it was not long press action then
604
*change state and run the action*/
605
if(lv_indev_is_dragging(param) == false && ext->long_pr_action_executed == 0) {
606
if(ext->state == LV_BTN_STATE_PR && tgl == false) {
607
lv_btn_set_state(btn, LV_BTN_STATE_REL);
608
} else if(ext->state == LV_BTN_STATE_TGL_PR && tgl == false) {
609
lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
610
} else if(ext->state == LV_BTN_STATE_PR && tgl == true) {
611
lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
612
} else if(ext->state == LV_BTN_STATE_TGL_PR && tgl == true) {
613
lv_btn_set_state(btn, LV_BTN_STATE_REL);
614
}
615
616
if(ext->actions[LV_BTN_ACTION_CLICK] && state != LV_BTN_STATE_INA) {
617
res = ext->actions[LV_BTN_ACTION_CLICK](btn);
618
}
619
} else { /*If dragged change back the state*/
620
if(ext->state == LV_BTN_STATE_PR) {
621
lv_btn_set_state(btn, LV_BTN_STATE_REL);
622
} else if(ext->state == LV_BTN_STATE_TGL_PR) {
623
lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
624
}
625
}
626
627
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
628
/*Draw the toggled state in the inking instead*/
629
if(ext->toggle) {
630
ink_top_state = ext->state;
631
}
632
/*If not a toggle button and the "IN" inking is ready then start an "OUT" inking*/
633
else if(ink_ready && ext->ink_out_time > 0) {
634
ink_obj = btn;
635
ink_playback = true; /*It is the playback. If not set `lv_btn_ink_effect_anim_ready` will start its own playback*/
636
lv_indev_get_point(lv_indev_get_act(), &ink_point);
637
638
lv_anim_t a;
639
a.var = ink_obj;
640
a.start = LV_BTN_INK_VALUE_MAX;
641
a.end = 0;
642
a.fp = (lv_anim_fp_t)lv_btn_ink_effect_anim;
643
a.path = lv_anim_path_linear;
644
a.end_cb = lv_btn_ink_effect_anim_ready;
645
a.act_time = 0;
646
a.time = ext->ink_out_time;
647
a.playback = 0;
648
a.playback_pause = 0;
649
a.repeat = 0;
650
a.repeat_pause = 0;
651
lv_anim_create(&a);
652
}
653
#endif
654
} else if(sign == LV_SIGNAL_LONG_PRESS) {
655
if(ext->actions[LV_BTN_ACTION_LONG_PR] && state != LV_BTN_STATE_INA) {
656
ext->long_pr_action_executed = 1;
657
res = ext->actions[LV_BTN_ACTION_LONG_PR](btn);
658
}
659
} else if(sign == LV_SIGNAL_LONG_PRESS_REP) {
660
if(ext->actions[LV_BTN_ACTION_LONG_PR_REPEAT] && state != LV_BTN_STATE_INA) {
661
res = ext->actions[LV_BTN_ACTION_LONG_PR_REPEAT](btn);
662
}
663
} else if(sign == LV_SIGNAL_CONTROLL) {
664
char c = *((char *)param);
665
if(c == LV_GROUP_KEY_RIGHT || c == LV_GROUP_KEY_UP) {
666
if(lv_btn_get_toggle(btn) != false) lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
667
if(ext->actions[LV_BTN_ACTION_CLICK] && lv_btn_get_state(btn) != LV_BTN_STATE_INA) {
668
res = ext->actions[LV_BTN_ACTION_CLICK](btn);
669
}
670
} else if(c == LV_GROUP_KEY_LEFT || c == LV_GROUP_KEY_DOWN) {
671
if(lv_btn_get_toggle(btn) != false) lv_btn_set_state(btn, LV_BTN_STATE_REL);
672
if(ext->actions[LV_BTN_ACTION_CLICK] && lv_btn_get_state(btn) != LV_BTN_STATE_INA) {
673
res = ext->actions[LV_BTN_ACTION_CLICK](btn);
674
}
675
} else if(c == LV_GROUP_KEY_ENTER) {
676
if(!ext->long_pr_action_executed) {
677
if(lv_btn_get_toggle(btn)) {
678
if(state == LV_BTN_STATE_REL || state == LV_BTN_STATE_PR) lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
679
else if(state == LV_BTN_STATE_TGL_REL || state == LV_BTN_STATE_TGL_PR) lv_btn_set_state(btn, LV_BTN_STATE_REL);
680
} else {
681
if(state == LV_BTN_STATE_REL || state == LV_BTN_STATE_PR) lv_btn_set_state(btn, LV_BTN_STATE_REL);
682
else if(state == LV_BTN_STATE_TGL_REL || state == LV_BTN_STATE_TGL_PR) lv_btn_set_state(btn, LV_BTN_STATE_TGL_REL);
683
}
684
if(ext->actions[LV_BTN_ACTION_CLICK] && state != LV_BTN_STATE_INA) {
685
res = ext->actions[LV_BTN_ACTION_CLICK](btn);
686
}
687
}
688
if(res != LV_RES_INV) {
689
ext->long_pr_action_executed = 0;
690
}
691
}
692
} else if(sign == LV_SIGNAL_CLEANUP) {
693
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
694
if(btn == ink_obj) {
695
lv_anim_del(ink_obj, (lv_anim_fp_t)lv_btn_ink_effect_anim);
696
ink_obj = NULL;
697
}
698
#endif
699
} else if(sign == LV_SIGNAL_GET_TYPE) {
700
lv_obj_type_t * buf = param;
701
uint8_t i;
702
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
703
if(buf->type[i] == NULL) break;
704
}
705
buf->type[i] = "lv_btn";
706
}
707
708
return res;
709
}
710
711
#if USE_LV_ANIMATION && LV_BTN_INK_EFFECT
712
713
/**
714
* The animator function of inking. CAlled to increase the radius of ink
715
* @param btn pointer to the animated button
716
* @param val the new radius
717
*/
718
static void lv_btn_ink_effect_anim(lv_obj_t * btn, int32_t val)
719
{
720
if(btn) {
721
ink_act_value = val;
722
lv_obj_invalidate(btn);
723
}
724
}
725
726
/**
727
* Called to clean up when the ink animation is ready
728
* @param p unused
729
*/
730
static void lv_btn_ink_effect_anim_ready(void * p)
731
{
732
(void) p; /*Unused*/
733
734
lv_btn_ext_t * ext = lv_obj_get_ext_attr(ink_obj);
735
lv_btn_state_t state = lv_btn_get_state(ink_obj);
736
737
lv_obj_invalidate(ink_obj);
738
ink_ready = true;
739
740
if((state == LV_BTN_STATE_REL || state == LV_BTN_STATE_TGL_REL) && ext->toggle == 0 && ink_playback == false) {
741
lv_anim_t a;
742
a.var = ink_obj;
743
a.start = LV_BTN_INK_VALUE_MAX;
744
a.end = 0;
745
a.fp = (lv_anim_fp_t)lv_btn_ink_effect_anim;
746
a.path = lv_anim_path_linear;
747
a.end_cb = lv_btn_ink_effect_anim_ready;
748
a.act_time = -ext->ink_wait_time;
749
a.time = ext->ink_out_time;
750
a.playback = 0;
751
a.playback_pause = 0;
752
a.repeat = 0;
753
a.repeat_pause = 0;
754
lv_anim_create(&a);
755
756
ink_playback = true;
757
} else {
758
ink_obj = NULL;
759
}
760
}
761
#endif /*USE_LV_ANIMATION*/
762
763
#endif
764
765