Kestrel Interface
Loading...
Searching...
No Matches
kest_button.c
Go to the documentation of this file.
1#include "kest_int.h"
2
3#ifndef PRINTLINES_ALLOWED
4#define PRINTLINES_ALLOWED 0
5#endif
6
8
9static const char *FNAME = "kest_active_button.c";
10
12{
13 if (!button)
14 return ERR_NULL_PTR;
15
16 button->flags = 0;
17
18 button->obj = NULL;
19 button->label = NULL;
20 button->label_text = NULL;
21 button->clicked_cb = NULL;
22 button->clicked_cb_arg = NULL;
23 button->pressing_cb = NULL;
24 button->pressing_cb_arg = NULL;
25 button->long_pressed_cb = NULL;
26 button->long_pressed_cb_arg = NULL;
27 button->released_cb = NULL;
28 button->released_cb_arg = NULL;
29
30 button->hider = NULL;
31 button->clickable = 1;
32
33 button->long_pressed = 0;
34
35 button->draggable_x = 0;
36 button->draggable_y = 0;
37
38 button->width = KEST_BUTTON_WIDTH;
39 button->height = KEST_BUTTON_HEIGHT;
40
41 button->alignment = LV_ALIGN_CENTER;
42 button->align_offs_x = 0;
43 button->align_offs_y = 0;
44
45 button->n_sub_buttons = 0;
46 for (int i = 0; i < KEST_BUTTON_MAX_SUB_BUTTONS; i++)
47 button->sub_buttons[i] = NULL;
48
49 button->opacity = 255;
50
51 return NO_ERROR;
52}
53
54kest_button *new_button(const char *label)
55{
56 kest_button *button = kest_alloc(sizeof(kest_button));
57
58 if (!button)
59 return NULL;
60
61 init_button(button);
62
63 button->label_text = label;
64
65 return button;
66}
67
68int create_button_ui(kest_button *button, lv_obj_t *parent)
69{
70 if (!button)
71 return ERR_NULL_PTR;
72
73 if (button->obj)
74 {
75 KEST_PRINTF("WARNING: attempt to call create_button_ui on a button for which button->obj is not NULL. button->obj = %p", button->obj);
76 return ERR_BAD_ARGS;
77 }
78
79 button->obj = lv_btn_create(parent);
80
81 if (!button->obj)
82 return ERR_ALLOC_FAIL;
83
84 if (button->flags & KEST_BUTTON_FLAG_HIDDEN)
85 lv_obj_add_flag(button->obj, LV_OBJ_FLAG_HIDDEN);
86 else
87 lv_obj_set_style_opa(button->obj, button->opacity, 0);
88
89 if (button->flags & KEST_BUTTON_FLAG_DISABLED)
90 lv_obj_add_state(button->obj, LV_STATE_DISABLED);
91
93 lv_obj_clear_flag(button->obj, LV_OBJ_FLAG_CLICKABLE);
94
95 if (!(button->flags & KEST_BUTTON_FLAG_NO_ALIGN))
96 lv_obj_align(button->obj, button->alignment, button->align_offs_x, button->align_offs_y);
97
98 //kest_printf("create_button_ui: button->obj = %p\n", button->obj);
99
100 button->label = lv_label_create(button->obj);
101
102 if (!button->label)
103 {
104 lv_obj_del(button->obj);
105 button->obj = NULL;
106 return ERR_ALLOC_FAIL;
107 }
108
109 int ret_val;
110 for (int i = 0; i < button->n_sub_buttons; i++)
111 {
112 if (button->sub_buttons[i])
113 {
114 if ((ret_val = create_button_ui(button->sub_buttons[i], button->obj)) != NO_ERROR)
115 {
116 lv_obj_del(button->label);
117 button->label = NULL;
118 lv_obj_del(button->obj);
119 button->obj = NULL;
120 return ret_val;
121 }
122 }
123 }
124
125 lv_obj_set_size(button->obj, button->width, button->height);
126 lv_label_set_text(button->label, button->label_text);
127 lv_obj_center(button->label);
128
129 if (button->clicked_cb)
130 lv_obj_add_event_cb(button->obj, button->clicked_cb, LV_EVENT_CLICKED, button->clicked_cb_arg);
131
132 if (button->pressing_cb)
133 lv_obj_add_event_cb(button->obj, button->pressing_cb, LV_EVENT_PRESSING, button->pressing_cb_arg);
134
135 if (button->long_pressed_cb)
136 lv_obj_add_event_cb(button->obj, button->long_pressed_cb, LV_EVENT_LONG_PRESSED, button->long_pressed_cb_arg);
137
138 if (button->released_cb)
139 lv_obj_add_event_cb(button->obj, button->released_cb, LV_EVENT_RELEASED, button->released_cb_arg);
140
141 return NO_ERROR;
142}
143
145{
146 if (!button)
147 return ERR_NULL_PTR;
148
149 if (!button->obj)
150 return ERR_BAD_ARGS;
151
152 button->label = lv_label_create(button->obj);
153 lv_obj_center(button->label);
154
155 return NO_ERROR;
156}
157
158int button_set_clicked_cb(kest_button *button, lv_event_cb_t cb, void *cb_arg)
159{
160 if (!button)
161 return ERR_NULL_PTR;
162
163 button->clicked_cb = cb;
164 button->clicked_cb_arg = cb_arg;
165
166 if (button->obj)
167 lv_obj_add_event_cb(button->obj, button->clicked_cb, LV_EVENT_CLICKED, button->clicked_cb_arg);
168
169 return NO_ERROR;
170}
171
172int button_set_pressing_cb(kest_button *button, lv_event_cb_t cb, void *cb_arg)
173{
174 if (!button)
175 return ERR_NULL_PTR;
176
177 button->pressing_cb = cb;
178 button->pressing_cb_arg = cb_arg;
179
180 if (button->obj)
181 lv_obj_add_event_cb(button->obj, button->pressing_cb, LV_EVENT_PRESSING, button->pressing_cb_arg);
182
183 return NO_ERROR;
184}
185
186int button_set_long_pressed_cb(kest_button *button, lv_event_cb_t cb, void *cb_arg)
187{
188 if (!button)
189 return ERR_NULL_PTR;
190
191 button->long_pressed_cb = cb;
192 button->long_pressed_cb_arg = cb_arg;
193
194 if (button->obj)
195 lv_obj_add_event_cb(button->obj, button->long_pressed_cb, LV_EVENT_LONG_PRESSED, button->long_pressed_cb_arg);
196
197 return NO_ERROR;
198}
199
200int button_set_released_cb(kest_button *button, lv_event_cb_t cb, void *cb_arg)
201{
202 if (!button)
203 return ERR_NULL_PTR;
204
205 button->released_cb = cb;
206 button->released_cb_arg = cb_arg;
207
208 if (button->obj)
209 lv_obj_add_event_cb(button->obj, button->released_cb, LV_EVENT_RELEASED, button->released_cb_arg);
210
211 return NO_ERROR;
212}
213
214int kest_button_set_label(kest_button *button, const char *label)
215{
216 if (!button)
217 return ERR_NULL_PTR;
218
219 button->label_text = label;
220
221 if (button->obj && label)
222 {
223 if (!button->label)
225
226 lv_label_set_text(button->label, label);
227 }
228
229 return NO_ERROR;
230}
231
232
234{
235 if (!button)
236 return ERR_NULL_PTR;
237
239
240 return NO_ERROR;
241}
242
243int kest_button_set_alignment(kest_button *button, lv_align_t align, int offs_x, int offs_y)
244{
245 if (!button)
246 return ERR_NULL_PTR;
247
249 button->alignment = align;
250
251 button->align_offs_x = offs_x;
252 button->align_offs_y = offs_y;
253
254 if (button->obj)
255 lv_obj_align(button->obj, button->alignment, offs_x, offs_y);
256
257 return NO_ERROR;
258}
259
260int kest_button_set_size(kest_button *button, int width, int height)
261{
262 if (!button)
263 return ERR_NULL_PTR;
264
265 button->width = width;
266 button->height = height;
267
268 if (button->obj)
269 lv_obj_set_size(button->obj, width, height);
270
271 return NO_ERROR;
272}
273
275{
276 if (!button || !sub_button)
277 return ERR_NULL_PTR;
278
280 return ERR_BAD_ARGS;
281
282 button->sub_buttons[button->n_sub_buttons++] = sub_button;
283
284 return NO_ERROR;
285}
286
288{
289 //kest_printf("kest_button_hide. button = %p\n", button);
290 if (!button)
291 {
292 //kest_printf("bailing\n");
293 return ERR_NULL_PTR;
294 }
295
296 //kest_printf("set hidden flag...\n");
298
299 if (button->obj)
300 {
301 //kest_printf("set hidden lv flag\n");
302 lv_obj_add_flag(button->obj, LV_OBJ_FLAG_HIDDEN);
303 }
304
305 //kest_printf("kest_button_hide done\n");
306 return NO_ERROR;
307}
308
310{
311 //kest_printf("kest_button_unhide. button = %p\n", button);
312 if (!button)
313 {
314 //kest_printf("bailing\n");
315 return ERR_NULL_PTR;
316 }
317
318 //kest_printf("unset hidden flag...\n");
319 button->flags &= (~KEST_BUTTON_FLAG_HIDDEN);
320
321 if (button->obj)
322 {
323 //kest_printf("unset hidden lv flag\n");
324 lv_obj_clear_flag(button->obj, LV_OBJ_FLAG_HIDDEN);
325 //kest_printf("restore opacity %d\n", button->opacity);
326 lv_obj_set_style_opa(button->obj, button->opacity, 0);
327 }
328
329 return NO_ERROR;
330}
331
333{
334 if (!button)
335 return ERR_NULL_PTR;
336
338
339 if (button->obj)
340 {
341 lv_obj_add_flag(button->obj, LV_OBJ_FLAG_CLICKABLE);
342 }
343
344 return NO_ERROR;
345}
346
348{
349 if (!button)
350 return ERR_NULL_PTR;
351
353
354 if (button->obj)
355 lv_obj_clear_flag(button->obj, LV_OBJ_FLAG_CLICKABLE);
356
357 return NO_ERROR;
358}
359
360int kest_button_set_opacity(kest_button *button, int opacity)
361{
362 //kest_printf("kest_button_set_opacity. button = %p, opacity = %d\n", button, opacity);
363 if (!button)
364 {
365 //kest_printf("bailing\n");
366 return ERR_NULL_PTR;
367 }
368
369 //kest_printf("store new opacity...\n");
370 button->opacity = opacity;
371
372 if (button->flags & KEST_BUTTON_FLAG_HIDDEN)
373 {
374 //kest_printf("Button is hidden. Exit\n");
375 return NO_ERROR;
376 }
377
378 if (button->obj)
379 {
380 //kest_printf("button has UI and it is not hidden. apply to lv_obj...\n");
381 lv_obj_set_style_opa(button->obj, button->opacity, 0);
382 }
383
384 //kest_printf("kest_button_set_opacity done\n");
385 return NO_ERROR;
386}
387
389{
390 if (!button)
391 return ERR_NULL_PTR;
392
394
395 if (button->obj)
396 lv_obj_clear_state(button->obj, LV_STATE_DISABLED);
397
398 return NO_ERROR;
399}
400
402{
403 //kest_printf("kest_button_disable\n");
404
405 if (!button)
406 return ERR_NULL_PTR;
407
409
410 if (button->obj)
411 {
412 lv_obj_add_state(button->obj, LV_STATE_DISABLED);
413 }
414
415 //kest_printf("kest_button_disable done\n");
416 return NO_ERROR;
417}
418
420{
421 if (!button)
422 return ERR_NULL_PTR;
423
424 if (!button->obj)
425 return ERR_BAD_ARGS;
426
427 lv_obj_clear_state(button->obj, LV_STATE_PRESSED);
428 lv_obj_clear_state(button->obj, LV_STATE_CHECKED);
429 lv_obj_clear_state(button->obj, LV_STATE_FOCUSED);
430
431 return NO_ERROR;
432}
433
435{
436 if (!button)
437 return ERR_NULL_PTR;
438
439 for (int i = 0; i < button->n_sub_buttons; i++)
441
442 if (button->label)
443 {
444 lv_obj_del(button->label);
445 button->label = NULL;
446 }
447
448 if (button->obj)
449 {
450 lv_obj_del(button->obj);
451 button->obj = NULL;
452 }
453
454 return NO_ERROR;
455}
456
457//
458// Buttons with "are you sure?" popups
459//
460
461int init_danger_button(kest_danger_button *button, void (*action_cb)(void *data), void *cb_arg, kest_ui_page *parent)
462{
463 if (!button)
464 return ERR_NULL_PTR;
465
466 init_button(&button->button);
467
468 button->parent = parent;
469 button->popup = NULL;
470
471 button->action_cb = action_cb;
472 button->cb_arg = cb_arg;
473
475
476 return NO_ERROR;
477}
478
480{
481 if (!button)
482 return ERR_NULL_PTR;
483
484 create_button_ui(&button->button, parent);
485
486 return NO_ERROR;
487}
488
490{
491 kest_danger_button *button = lv_event_get_user_data(e);
492
493 if (button->action_cb)
494 button->action_cb(button->cb_arg);
495}
496
498{
499 kest_danger_button *button = lv_event_get_user_data(e);
500
501 if (button->popup)
502 lv_msgbox_close(button->popup);
503
504 button->popup = NULL;
505}
506
508{
509 kest_danger_button *button = lv_event_get_user_data(e);
510
511 if (!button)
512 return;
513
514 if (!button->popup)
515 return;
516
517 #if LVGL_MAJOR_VERSION == 8
518 const char *button_text = lv_msgbox_get_active_btn_text(button->popup);
519
520 if (strncmp(DANGER_BUTTON_CONFIRM_TEXT, button_text, strlen(DANGER_BUTTON_CONFIRM_TEXT) + 1) == 0)
521 {
522 if (button->action_cb)
523 button->action_cb(button->cb_arg);
524 }
525
526 lv_msgbox_close(button->popup);
527 button->popup = NULL;
528 #endif
529}
530
532{
533 //kest_printf("kest_danger_button_activate_popup_cb\n");
534 kest_danger_button *button = lv_event_get_user_data(e);
535
536 if (!button)
537 {
538 //kest_printf("button is NULL! returning...\n");
539 return;
540 }
541
542 if (!button->parent)
543 {
544 //kest_printf("Button's parent is NULL! Returning\n");
545 return;
546 }
547
548 button->popup = lv_msgbox_create(button->parent->screen);
549 lv_msgbox_add_title(button->popup, button->button.label_text);
550 lv_msgbox_add_text(button->popup, "\n\tAre you sure?");
551
552 lv_obj_t *btn;
553 btn = lv_msgbox_add_footer_button(button->popup, DANGER_BUTTON_CONFIRM_TEXT);
554 lv_obj_add_event_cb(btn, kest_danger_button_confirm_cb, LV_EVENT_CLICKED, button);
556 lv_obj_align_to(btn, button->popup, LV_ALIGN_BOTTOM_LEFT, 0, -GLOBAL_PAD_WIDTH);
557 btn = lv_msgbox_add_footer_button(button->popup, DANGER_BUTTON_CANCEL_TEXT);
558 lv_obj_add_event_cb(btn, kest_danger_button_cancel_cb, LV_EVENT_CLICKED, button);
560 lv_obj_align_to(btn, button->popup, LV_ALIGN_CENTER, 0, -GLOBAL_PAD_WIDTH);
561
563
564 //kest_printf("kest_danger_button_activate_popup_cb done\n");
565}
566
567void kest_active_button_scale_cb(void *data, int32_t value)
568{
569 if (!data)
570 return;
571
572 kest_active_button *button = (kest_active_button*)data;
573
574 int32_t new_height = ((float)value / 1000.0) * button->button.height;
575 int32_t new_width = ((float)value / 1000.0) * button->button.width;
576
577 //kest_printf("kest_active_button_scale_cb. new_height = %d. new_width = %d\n", new_height, new_width);
578
579 lv_obj_set_height(button->button.obj, new_height);
580 lv_obj_set_width (button->button.obj, new_width);
581
582 button->pos_y = button->pos_y - (new_height - lv_obj_get_height(button->button.obj)) / 2;
583 button->button.align_offs_y = button->pos_y;
584
585 lv_obj_align(button->button.obj, LV_ALIGN_TOP_MID, 0, button->pos_y);
586}
587
588void kest_active_button_glide_cb(void *data, int32_t value)
589{
590 if (!data)
591 return;
592
593 kest_active_button *button = (kest_active_button*)data;
594
595 lv_obj_set_y(button->button.obj, value);
596 button->pos_y = value;
597}
598
599void kest_active_button_del_button_fade_cb(void *data, int32_t value)
600{
601 //kest_printf("kest_active_button_del_button_fade_cb. data = %p\n", data);
602 if (!data)
603 return;
604
605 kest_active_button *button = (kest_active_button*)data;
606
607 if (!button->del_button)
608 return;
609
610 //kest_printf("button->del_button->obj = %p\n", button->del_button->obj);
611
612 kest_button_set_opacity(button->del_button, value);
613 //kest_printf("kest_active_button_del_button_fade_cb done\n");
614}
615
617{
618 if (!anim)
619 return;
620
621 kest_active_button *button = (kest_active_button*)anim->user_data;
622
623 if (!button)
624 return;
625
627}
628
629void kest_active_button_delete_anim_cb(void *data, int32_t value)
630{
631 if (!data)
632 return;
633
634 kest_active_button *button = (kest_active_button*)data;
635
636 kest_button_set_opacity(&button->button, 255 * ((float)value / 100.0));
637}
638
640{
641 #ifdef ACTIVE_BUTTON_USE_SCALE_ANIM
642 if (!button)
643 return;
644
645 int initial = direction ? 1000 : 1000 * KEST_BUTTON_LP_SCALE;
646 int final = direction ? 1000 * KEST_BUTTON_LP_SCALE : 1000;
647
648 lv_anim_init (&button->scale_anim);
649 lv_anim_set_var (&button->scale_anim, button);
650 lv_anim_set_exec_cb (&button->scale_anim, kest_active_button_scale_cb);
651 lv_anim_set_time (&button->scale_anim, KEST_BUTTON_SCALE_ANIM_MS);
652 lv_anim_set_values (&button->scale_anim, initial, final);
653 lv_anim_path_ease_in_out(&button->scale_anim);
654
655 lv_anim_start(&button->scale_anim);
656 #endif
657}
658
660{
661 if (!button)
662 return;
663
664 lv_anim_init (&button->glide_anim);
665 lv_anim_set_var (&button->glide_anim, button);
666 lv_anim_set_exec_cb (&button->glide_anim, kest_active_button_glide_cb);
667 lv_anim_set_time (&button->glide_anim, KEST_BUTTON_GLIDE_ANIM_MS);
668 lv_anim_set_values (&button->glide_anim, button->pos_y, new_pos_y);
669 lv_anim_path_ease_in_out(&button->glide_anim);
670
671 lv_anim_start(&button->glide_anim);
672}
673
675{
676 if (!button)
677 return;
678
679 if (!button->del_button)
680 {
681 //kest_printf("no del button...\n");
682 return;
683 }
684
685 lv_anim_init (&button->del_button_fade);
686 lv_anim_set_var (&button->del_button_fade, button);
687 lv_anim_set_exec_cb (&button->del_button_fade, kest_active_button_del_button_fade_cb);
688 lv_anim_set_time (&button->del_button_fade, KEST_BUTTON_DEL_BTN_FADE_IN_MS);
689 lv_anim_set_values (&button->del_button_fade, 0, 255);
690
691 button->del_button_fade.user_data = (void*)button;
692
694 lv_anim_start(&button->del_button_fade);
695}
696
698{
699 lv_anim_init (&button->del_button_fade);
700 lv_anim_set_var (&button->del_button_fade, button);
701 lv_anim_set_exec_cb (&button->del_button_fade, kest_active_button_del_button_fade_cb);
702 lv_anim_set_ready_cb (&button->del_button_fade, kest_active_button_del_button_faded_out_cb);
703 lv_anim_set_time (&button->del_button_fade, KEST_BUTTON_DEL_BTN_FADE_OUT_MS);
704 lv_anim_set_values (&button->del_button_fade, 255, 0);
705
706 button->del_button_fade.user_data = (void*)button;
707
709 lv_anim_start(&button->del_button_fade);
710}
711
713{
714 kest_active_button *button = (kest_active_button*)anim->user_data;
715
718}
719
721{
722 lv_anim_init (&button->delete_anim);
723 lv_anim_set_var (&button->delete_anim, button);
724 lv_anim_set_exec_cb (&button->delete_anim, kest_active_button_delete_anim_cb);
725 lv_anim_set_ready_cb (&button->delete_anim, kest_active_button_delete_anim_ready_cb);
726 lv_anim_set_time (&button->delete_anim, KEST_BUTTON_DEL_ANIM_MS);
727 lv_anim_set_values (&button->delete_anim, 100, 0);
728
729 button->delete_anim.user_data = (void*)button;
730
731 lv_anim_start(&button->delete_anim);
732}
733
735{
736 if (!button)
737 return ERR_NULL_PTR;
738
739 if (!button->array)
740 return ERR_BAD_ARGS;
741
742 lv_coord_t new_pos_y = kest_active_button_array_index_y_position(button->array, i);
743
744 kest_active_button_trigger_glide_anim(button, new_pos_y);
745
746 button->index = i;
747
748 return NO_ERROR;
749}
750
752{
753 if (!button)
754 return ERR_NULL_PTR;
755
756 if (button->index == i)
757 return NO_ERROR;
758
759 if (!button->array)
760 return ERR_BAD_ARGS;
761
762 lv_coord_t new_pos_y = kest_active_button_array_index_y_position(button->array, i);
763
764 kest_active_button_trigger_glide_anim(button, new_pos_y);
765
766 button->index = i;
767
768 return NO_ERROR;
769}
770
772{
773 kest_active_button *button = lv_timer_get_user_data(timer);
774
776 button->del_button_remain_timer = NULL;
777}
778
780{
781 KEST_PRINTF("kest_active_button_clicked_cb\n");
782 kest_active_button *button = (kest_active_button*)lv_event_get_user_data(e);
783
784 KEST_PRINTF("button->long_pressed = %d\n", button->long_pressed);
785
786 if (!button)
787 {
788 KEST_PRINTF("Transformer widget long press callback triggered but pointer to struct not passed");
789 return;
790 }
791
792 if (button->array && button->array->clicked_cb && !button->long_pressed)
793 {
794 button->array->clicked_cb(button);
795 }
796 else
797 {
798 button->long_pressed = 0;
799 }
800}
801
803{
804 //kest_printf("kest_active_button_long_pressed_cb\n");
805 kest_active_button *button = (kest_active_button*)lv_event_get_user_data(e);
806
807 if (!button)
808 {
809 KEST_PRINTF("Transformer widget long press callback triggered but pointer to struct not passed");
810 return;
811 }
812
813 button->long_pressed = 1;
814
815
816 //kest_printf("long press detected... button->index = %d, button->prev_index = %d\n", button->index, button->prev_index);
817
818 if (button->array)
819 {
821 {
822 if (button->array->container)
823 {
824 button->array->container_scrollable = lv_obj_has_flag(button->array->container, LV_OBJ_FLAG_SCROLLABLE);
825
826 if (button->array->container_scrollable)
827 lv_obj_remove_flag(button->array->container, LV_OBJ_FLAG_SCROLLABLE);
828 }
829
830 lv_point_t touch_point;
831 lv_indev_t *indev = lv_indev_get_act();
832 lv_indev_get_point(indev, &touch_point);
833
834 lv_point_t local_point = touch_point;
835 lv_obj_t *parent = lv_obj_get_parent(button->button.obj);
836
837 lv_area_t parent_coords;
838 lv_obj_get_coords(parent, &parent_coords);
839
840 local_point.y -= parent_coords.y1;
841
842 button->relative_touch_y = local_point.y - button->pos_y;
843
844 button->prev_index = button->index;
845
847
848 lv_obj_move_foreground(button->button.obj);
849 }
850
852 {
854 }
855 }
856
857
858 //kest_printf("kest_active_button_long_pressed_cb done\n");
859}
860
862{
863 kest_active_button *button = (kest_active_button*)lv_event_get_user_data(e);
864
865 if (!button)
866 {
867 KEST_PRINTF("Transformer widget long press callback triggered but pointer to struct not passed");
868 return;
869 }
870
871 if (!button->long_pressed || !button->array || !(button->array->flags & KEST_ACTIVE_BUTTON_ARRAY_FLAG_MOVEABLE))
872 return;
873
874 lv_point_t touch_point;
875 lv_indev_t *indev = lv_indev_get_act();
876 lv_indev_get_point(indev, &touch_point);
877
878 lv_point_t local_point = touch_point;
879 lv_obj_t *parent = lv_obj_get_parent(button->button.obj);
880
881 lv_area_t parent_coords;
882 lv_obj_get_coords(parent, &parent_coords);
883
884 local_point.y -= parent_coords.y1;
885
886 button->pos_y = local_point.y - button->relative_touch_y;
887 button->button.align_offs_y = button->pos_y;
888
889 lv_obj_set_y(button->button.obj, button->pos_y);
890
891 int new_index = 0;
892 for (int i = 0; i < button->array->n_buttons; i++)
893 {
894 if (button->array->buttons[i] == button)
895 continue;
896
897 if (button->array->buttons[i]->pos_y < button->pos_y)
898 new_index++;
899 else
900 break;
901 }
902
903 if (new_index == button->index)
904 return;
905
906 if (new_index < button->index)
907 {
908 for (int i = button->index; i > new_index; i--)
909 {
910 button->array->buttons[i] = button->array->buttons[i - 1];
912 }
913
914 button->array->buttons[new_index] = button;
915 kest_active_button_set_index(button, new_index);
916 }
917 else if (new_index > button->index)
918 {
919 for (int i = button->index; i < new_index; i++)
920 {
921 button->array->buttons[i] = button->array->buttons[i + 1];
923 }
924
925 button->array->buttons[new_index] = button;
926 kest_active_button_set_index(button, new_index);
927 }
928
929 //kest_printf("new index: %d. The current array:\n", new_index);
930
931 for (int i = 0; i < button->array->n_buttons; i++)
932 {
933 //kest_printf("\t buttons[%d] = %p%s\n", i, button->array->buttons[i], (button->array->buttons[i] == button) ? " (this)" : "");
934 }
935}
936
937
939{
940 KEST_PRINTF("kest_active_button_release_cb\n");
941 kest_active_button *button = (kest_active_button*)lv_event_get_user_data(e);
942
943 if (!button)
944 {
945 return;
946 }
947
948 if (!button->array)
949 {
950 KEST_PRINTF("button has no array :(\n");
951 return;
952 }
953
954 if (button->long_pressed)
955 {
957 {
958 if (button->array->container && button->array->container_scrollable)
959 lv_obj_add_flag(button->array->container, LV_OBJ_FLAG_SCROLLABLE);
960
962
963 kest_active_button_force_index(button, button->index);
964
965 if (button->index != button->prev_index)
966 {
967 if (button->array && button->array->moved_cb)
968 {
969 button->array->moved_cb(button);
970 }
971 }
972 }
973
975 {
977 lv_timer_set_repeat_count(button->del_button_remain_timer, 1);
978
979 lv_timer_resume(button->del_button_remain_timer);
980 }
981 }
982}
983
984void kest_active_button_del_cb(lv_event_t *e)
985{
986 KEST_PRINTF("kest_active_button_del_cb\n");
987 kest_active_button *button = (kest_active_button*)lv_event_get_user_data(e);
988
990
991 lv_obj_clear_flag(button->button.obj, LV_OBJ_FLAG_CLICKABLE);
992
993 if (button->array && button->array->del_button_cb)
994 {
995 button->array->del_button_cb(button);
996 }
997}
998
1000{
1001 if (!button)
1002 return ERR_NULL_PTR;
1003
1004 init_button(&button->button);
1005
1010
1011 button->del_button = NULL;
1012
1013 button->del_button_remain_timer = NULL;
1014
1015 button->index = 0;
1016 button->prev_index = 0;
1017
1018 button->long_pressed = 0;
1019
1020 button->del_button_anims = 1;
1021
1022 return NO_ERROR;
1023}
1024
1026{
1027 //kest_printf("kest_active_button_add_del_button, button = %p\n", button);
1028 if (!button)
1029 return ERR_NULL_PTR;
1030
1031 if (button->del_button)
1032 {
1033 KEST_PRINTF("WARNING: kest_active_button_add_del_button called with button for which button->del_button is not NULL: it is %p", button->del_button);
1034 return ERR_BAD_ARGS;
1035 }
1036
1037 button->del_button = new_button(LV_SYMBOL_TRASH);
1038
1039 if (!button->del_button)
1040 return ERR_ALLOC_FAIL;
1041
1042 init_button(button->del_button);
1043 kest_button_set_label(button->del_button, LV_SYMBOL_TRASH);
1045
1046 kest_button_add_sub_button(&button->button, button->del_button);
1047
1048 kest_button_set_size(button->del_button, button->button.height, button->button.height);
1049 kest_button_set_alignment(button->del_button, LV_ALIGN_RIGHT_MID, 0, 0);
1050
1052
1053 //kest_printf("kest_active_button_add_del_button done\n");
1054 return NO_ERROR;
1055}
1056
1057void kest_active_button_set_representation(kest_active_button *button, void *representer, void *representee, void (*update)(void*, void*))
1058{
1059 if (button)
1060 {
1061 button->rep.representer = representer;
1062 button->rep.representee = representee;
1063 button->rep.update = update;
1064 }
1065}
1066
1068{
1069 if (!button)
1070 return ERR_NULL_PTR;
1071
1072 create_button_ui(&button->button, parent);
1073
1074 button->base_height = lv_obj_get_height(button->button.obj);
1075 button->base_width = lv_obj_get_width (button->button.obj);
1076
1077 /*
1078 button->button.obj = lv_btn_create(parent);
1079
1080 lv_obj_set_size(button->button.obj, KEST_BUTTON_WIDTH, KEST_BUTTON_HEIGHT);
1081
1082
1083
1084 lv_obj_align(button->button.obj, LV_ALIGN_TOP_MID, 0, button->pos_y);
1085
1086 button->button.label = lv_label_create(button->button.obj);
1087 lv_label_set_text(button->button.label, button->button.label_text);
1088 lv_obj_center(button->button.label);
1089
1090 lv_obj_add_event_cb(button->button.obj, kest_active_button_release_cb, LV_EVENT_RELEASED, button);
1091 lv_obj_add_event_cb(button->button.obj, kest_active_button_long_pressed_cb, LV_EVENT_LONG_PRESSED, button);
1092 lv_obj_add_event_cb(button->button.obj, kest_active_button_pressing_cb, LV_EVENT_PRESSING, button);
1093
1094 button->del_button = lv_btn_create(button->button.obj);
1095 lv_obj_align(button->del_button, LV_ALIGN_RIGHT_MID, 10, 0);
1096 lv_obj_set_size(button->del_button, 0.75 * KEST_BUTTON_HEIGHT, 0.75 * KEST_BUTTON_HEIGHT);
1097 lv_obj_add_event_cb(button->del_button, kest_active_button_del_cb, LV_EVENT_CLICKED, button);
1098 lv_obj_add_flag(button->del_button, LV_OBJ_FLAG_HIDDEN);
1099
1100 button->del_button->label = lv_label_create(button->del_button);
1101 lv_label_set_text(button->del_button->label, LV_SYMBOL_TRASH);
1102 lv_obj_center(button->del_button->label);
1103 */
1104
1105 return NO_ERROR;
1106}
1107
1109{
1110 if (!button)
1111 return;
1112
1113 if (button->button.obj)
1114 {
1115 lv_anim_del(button, NULL);
1116
1117 if (button->del_button_remain_timer)
1118 {
1119 lv_timer_del(button->del_button_remain_timer);
1120 button->del_button_remain_timer = NULL;
1121 }
1122
1123 if (button->array && button->array->delete_cb)
1124 button->array->delete_cb(button);
1125 }
1126
1127 kest_button_delete_ui(&button->button);
1128
1129 kest_free(button);
1130}
1131
1133{
1134 if (!button)
1135 return ERR_NULL_PTR;
1136
1137 kest_button_set_label(&button->button, text);
1138
1139 return NO_ERROR;
1140}
1141
1143{
1144 if (!button)
1145 return ERR_NULL_PTR;
1146
1147 button->base_width = w;
1148 button->base_height = h;
1149
1150 kest_button_set_size(&button->button, w, h);
1151
1152 return NO_ERROR;
1153}
1154
1156{
1157 if (!button)
1158 return ERR_NULL_PTR;
1159
1160 if (!button->del_button)
1161 return ERR_BAD_ARGS;
1162
1163 if (!button->del_button->obj)
1164 return ERR_BAD_ARGS;
1165
1166 if (!button->del_button->label)
1167 {
1169 }
1170
1171 lv_anim_del(button, kest_active_button_del_button_fade_cb);
1172
1174 kest_button_set_label(button->del_button, label);
1176 kest_button_set_opacity(button->del_button, 255);
1178
1179 button->del_button_anims = 0;
1180
1181 return NO_ERROR;
1182}
1183
1185{
1186 //kest_printf("kest_active_button_reset_del_button. button = %p\n", button);
1187 if (!button)
1188 return ERR_NULL_PTR;
1189
1190 if (!button->del_button)
1191 {
1192 //kest_printf("del button doesn't exist. bailing\n");
1193 return ERR_BAD_ARGS;
1194 }
1195
1196 if (!button->del_button->obj)
1197 {
1198 //kest_printf("del button lv_obj not created. not my job. bailing\n");
1199 return ERR_BAD_ARGS;
1200 }
1201
1202 //kest_printf("make it hidden...\n");
1204
1205 if (!button->del_button->label)
1206 {
1207 //kest_printf("del button label doesn't exist. creating...\n");
1209 }
1210
1211 //kest_printf("delete buttons's animations...\n");
1212 lv_anim_del(button, kest_active_button_del_button_fade_cb);
1213
1214 //kest_printf("reset button's state...\n");
1216 //kest_printf("set label to %s\n", LV_SYMBOL_TRASH);
1217 kest_button_set_label(button->del_button, LV_SYMBOL_TRASH);
1218 //kest_printf("make it clickable\n");
1220
1221 //kest_printf("activate animations...\n");
1222 button->del_button_anims = 1;
1223
1224 //kest_printf("kest_active_button_reset_del_button done\n");
1225 return NO_ERROR;
1226}
1227
1228
1230{
1231 if (!array)
1232 return ERR_NULL_PTR;
1233
1234 array->flags = 0;
1235
1236 array->n_buttons = 0;
1237 array->length = 0;
1238 array->buttons = NULL;
1239
1240 array->parent = NULL;
1241 array->container = NULL;
1242
1243 array->delete_cb = NULL;
1244 array->del_button_cb = NULL;
1245 array->clicked_cb = NULL;
1246 array->moved_cb = NULL;
1247
1248 array->data = NULL;
1249
1251
1254
1255 return NO_ERROR;
1256}
1257
1259{
1260 if (!array)
1261 return ERR_NULL_PTR;
1262
1263 array->buttons = kest_alloc(sizeof(kest_active_button*) * n);
1264
1265 if (!array->buttons)
1266 {
1267 return ERR_ALLOC_FAIL;
1268 }
1269
1270 for (int i = 0; i < n; i++)
1271 array->buttons[i] = NULL;
1272
1273 array->length = n;
1274
1275 return NO_ERROR;
1276}
1277
1279{
1281
1282 if (!array)
1283 return NULL;
1284
1286
1287 return array;
1288}
1289
1291{
1292 KEST_PRINTF("kest_active_button_array_append_new\n");
1293 if (!array)
1294 {
1295 //kest_printf("Returning NULL cause array = %p\n", array);
1296 return NULL;
1297 }
1298
1300
1301 if (!button)
1302 {
1303 //kest_printf("returning NULL cause button = %p\n", button);
1304 return NULL;
1305 }
1306
1308
1309 button->data = data;
1310 button->button.label_text = label;
1311
1312 int ret_val;
1313
1314 if ((ret_val = kest_active_button_array_append(button, array)) != NO_ERROR)
1315 {
1316 kest_free(button);
1317 //kest_printf("Failed to add button to array: %s\n", kest_error_code_to_string(ret_val));
1318 return NULL;
1319 }
1320
1322 {
1324 }
1325
1326 //kest_printf("returning %p\n", button);
1327 KEST_PRINTF("kest_active_button_array_append_new done\n");
1328 return button;
1329}
1330
1332{
1333 if (!button || !array)
1334 return ERR_NULL_PTR;
1335
1336 if (array->n_buttons >= array->length)
1337 {
1338 return ERR_BAD_ARGS;
1339 }
1340
1341 button->index = array->n_buttons;
1342 button->prev_index = array->n_buttons;
1343 button->array = array;
1344
1345 button->pos_y = kest_active_button_array_index_y_position(array, button->index);
1346 kest_button_set_alignment(&button->button, LV_ALIGN_TOP_MID, 0, button->pos_y);
1347
1348 kest_button_set_size(&button->button, array->button_width, array->button_height);
1349
1350 array->buttons[array->n_buttons++] = button;
1351
1352 return NO_ERROR;
1353}
1354
1355
1357{
1358 if (!array)
1359 return ERR_NULL_PTR;
1360
1361 if (index < 0 || index > array->n_buttons - 1)
1362 return ERR_BAD_ARGS;
1363
1364 array->n_buttons--;
1365
1366 array->buttons[index] = NULL;
1367
1368 for (int i = index; i < array->n_buttons; i++)
1369 {
1370 array->buttons[i] = array->buttons[i + 1];
1372 }
1373
1374 return NO_ERROR;
1375}
1376
1378{
1379 return array->base_y_pos + index * KEST_BUTTON_DISTANCE;
1380}
1381
1383{
1384 if (!array || !parent)
1385 return ERR_NULL_PTR;
1386
1387 array->container = parent;
1388 array->container_scrollable = lv_obj_has_flag(parent, LV_OBJ_FLAG_SCROLLABLE);
1389
1390 for (int i = 0; i < array->n_buttons; i++)
1391 {
1392 if (array->buttons[i]) kest_active_button_create_ui(array->buttons[i], parent);
1393 }
1394
1395 return NO_ERROR;
1396}
1397
1399{
1400 if (!array)
1401 return ERR_NULL_PTR;
1402
1403 array->button_width = w;
1404 array->button_height = h;
1405
1406 for (int i = 0; i < array->n_buttons; i++)
1407 {
1409 }
1410
1411 return NO_ERROR;
1412}
void kest_free(void *ptr)
Definition kest_alloc.c:32
void * kest_alloc(size_t size)
Definition kest_alloc.c:11
int kest_active_button_array_init(kest_active_button_array *array)
int init_button(kest_button *button)
Definition kest_button.c:11
int kest_active_button_add_del_button(kest_active_button *button)
int kest_button_disable(kest_button *button)
int kest_button_hide(kest_button *button)
int kest_button_set_opacity(kest_button *button, int opacity)
void kest_active_button_clicked_cb(lv_event_t *e)
void kest_active_button_del_button_remain_timer_cb(lv_timer_t *timer)
int init_danger_button(kest_danger_button *button, void(*action_cb)(void *data), void *cb_arg, kest_ui_page *parent)
void kest_danger_button_confirm_cb(lv_event_t *e)
int kest_active_button_force_index(kest_active_button *button, int i)
int create_button_ui(kest_button *button, lv_obj_t *parent)
Definition kest_button.c:68
void kest_active_button_delete_anim_cb(void *data, int32_t value)
void kest_danger_button_cancel_cb(lv_event_t *e)
int kest_button_create_label_ui(kest_button *button)
int kest_active_button_array_append(kest_active_button *button, kest_active_button_array *array)
int kest_button_delete_ui(kest_button *button)
int kest_active_button_array_set_dimensions(kest_active_button_array *array, int w, int h)
void kest_active_button_trigger_del_button_fade_in(kest_active_button *button)
int kest_active_button_set_dimensions(kest_active_button *button, int w, int h)
void kest_active_button_pressing_cb(lv_event_t *e)
int kest_active_button_create_ui(kest_active_button *button, lv_obj_t *parent)
int kest_active_button_set_index(kest_active_button *button, int i)
kest_active_button * kest_active_button_array_append_new(kest_active_button_array *array, void *data, char *label)
void kest_active_button_del_cb(lv_event_t *e)
int button_set_long_pressed_cb(kest_button *button, lv_event_cb_t cb, void *cb_arg)
void kest_active_button_delete_anim_ready_cb(lv_anim_t *anim)
void kest_active_button_trigger_glide_anim(kest_active_button *button, int32_t new_pos_y)
void kest_active_button_scale_cb(void *data, int32_t value)
void kest_active_button_trigger_scale_anim(kest_active_button *button, int direction)
int button_set_released_cb(kest_button *button, lv_event_cb_t cb, void *cb_arg)
int kest_button_set_clickable(kest_button *button)
int kest_active_button_array_create_ui(kest_active_button_array *array, lv_obj_t *parent)
int kest_button_enable(kest_button *button)
void kest_active_button_trigger_delete_anim(kest_active_button *button)
int kest_button_set_alignment(kest_button *button, lv_align_t align, int offs_x, int offs_y)
int kest_active_button_array_set_length(kest_active_button_array *array, int n)
int kest_active_button_change_label(kest_active_button *button, char *text)
int kest_active_button_init(kest_active_button *button)
void kest_active_button_set_representation(kest_active_button *button, void *representer, void *representee, void(*update)(void *, void *))
int button_set_clicked_cb(kest_button *button, lv_event_cb_t cb, void *cb_arg)
void kest_active_button_del_button_faded_out_cb(lv_anim_t *anim)
kest_active_button_array * kest_active_button_array_new()
void kest_active_button_glide_cb(void *data, int32_t value)
int kest_button_disable_alignment(kest_button *button)
int kest_active_button_reset_del_button(kest_active_button *button)
int kest_active_button_swap_del_button_for_persistent_unclickable(kest_active_button *button, const char *label)
int kest_active_button_array_index_y_position(kest_active_button_array *array, int index)
void kest_danger_button_value_changed_cb(lv_event_t *e)
void kest_active_button_release_cb(lv_event_t *e)
int kest_button_add_sub_button(kest_button *button, kest_button *sub_button)
int kest_button_set_label(kest_button *button, const char *label)
void kest_danger_button_activate_popup_cb(lv_event_t *e)
int kest_button_set_size(kest_button *button, int width, int height)
void kest_active_button_free(kest_active_button *button)
void kest_active_button_del_button_fade_cb(void *data, int32_t value)
int kest_button_set_unclickable(kest_button *button)
void kest_active_button_trigger_del_button_fade_out(kest_active_button *button)
int kest_button_reset_state(kest_button *button)
int kest_button_unhide(kest_button *button)
int kest_danger_button_create_ui(kest_danger_button *button, lv_obj_t *parent)
int button_set_pressing_cb(kest_button *button, lv_event_cb_t cb, void *cb_arg)
void kest_active_button_long_pressed_cb(lv_event_t *e)
kest_button * new_button(const char *label)
Definition kest_button.c:54
int kest_active_button_array_remove(kest_active_button_array *array, int index)
#define KEST_BUTTON_GLIDE_ANIM_MS
Definition kest_button.h:19
#define DANGER_BUTTON_CONFIRM_TEXT
#define KEST_BUTTON_ARRAY_BASE_Y
Definition kest_button.h:27
#define KEST_BUTTON_DEL_ANIM_MS
Definition kest_button.h:25
#define KEST_BUTTON_FLAG_HIDDEN
Definition kest_button.h:37
#define KEST_BUTTON_FLAG_DISABLED
Definition kest_button.h:38
#define KEST_BUTTON_HEIGHT
Definition kest_button.h:11
#define KEST_BUTTON_FLAG_NO_ALIGN
Definition kest_button.h:40
#define KEST_BUTTON_SCALE_EXPAND
Definition kest_button.h:14
#define DANGER_BUTTON_POPUP_BUTTON_HEIGHT
#define KEST_BUTTON_WIDTH
Definition kest_button.h:12
#define KEST_ACTIVE_BUTTON_ARRAY_FLAG_DELETEABLE
#define DANGER_BUTTON_POPUP_HEIGHT
#define KEST_BUTTON_SCALE_CONTRACT
Definition kest_button.h:15
#define DANGER_BUTTON_CANCEL_TEXT
#define KEST_BUTTON_DEL_BTN_REMAIN_MS
Definition kest_button.h:23
#define KEST_BUTTON_SCALE_ANIM_MS
Definition kest_button.h:18
#define KEST_BUTTON_DEL_BTN_FADE_IN_MS
Definition kest_button.h:21
#define DANGER_BUTTON_POPUP_WIDTH
#define KEST_BUTTON_MAX_SUB_BUTTONS
Definition kest_button.h:33
#define KEST_BUTTON_FLAG_UNCLICKABLE
Definition kest_button.h:39
#define KEST_ACTIVE_BUTTON_ARRAY_FLAG_MOVEABLE
#define KEST_BUTTON_DEL_BTN_FADE_OUT_MS
Definition kest_button.h:22
#define KEST_BUTTON_DISTANCE
Definition kest_button.h:30
#define DANGER_BUTTON_POPUP_BUTTON_WIDTH
#define KEST_BUTTON_LP_SCALE
Definition kest_button.h:17
#define ERR_ALLOC_FAIL
#define ERR_BAD_ARGS
#define NO_ERROR
#define ERR_NULL_PTR
#define IMPLEMENT_LINKED_PTR_LIST(X)
#define KEST_PRINTF(...)
Definition kest_printf.h:10
#define GLOBAL_PAD_WIDTH
Definition kest_ui.h:31
int(* moved_cb)(struct kest_active_button *button)
int(* delete_cb)(struct kest_active_button *button)
struct kest_ui_page * parent
int(* clicked_cb)(struct kest_active_button *button)
kest_active_button ** buttons
int(* del_button_cb)(struct kest_active_button *button)
kest_button * del_button
lv_timer_t * del_button_remain_timer
kest_representation rep
lv_anim_t delete_anim
kest_button button
struct kest_active_button_array * array
lv_anim_t del_button_fade
lv_align_t alignment
Definition kest_button.h:77
void * pressing_cb_arg
Definition kest_button.h:56
lv_event_cb_t pressing_cb
Definition kest_button.h:55
char * label_text
Definition kest_button.h:50
void * released_cb_arg
Definition kest_button.h:62
lv_obj_t * obj
Definition kest_button.h:48
lv_event_cb_t long_pressed_cb
Definition kest_button.h:58
void * clicked_cb_arg
Definition kest_button.h:53
lv_event_cb_t released_cb
Definition kest_button.h:61
int n_sub_buttons
Definition kest_button.h:81
struct kest_button * sub_buttons[KEST_BUTTON_MAX_SUB_BUTTONS]
Definition kest_button.h:82
lv_event_cb_t clicked_cb
Definition kest_button.h:52
lv_obj_t * label
Definition kest_button.h:49
void * long_pressed_cb_arg
Definition kest_button.h:59
kest_button button
struct kest_ui_page * parent
void(* action_cb)(void *data)
void(* update)(void *representer, void *representee)
lv_obj_t * screen
Definition kest_ui.h:89