widget.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #include <furi.h>
  2. #include "widget.h"
  3. #include <m-array.h>
  4. ARRAY_DEF(ElementArray, WidgetElement*, M_PTR_OPLIST);
  5. struct Widget {
  6. View* view;
  7. void* context;
  8. };
  9. typedef struct {
  10. ElementArray_t element;
  11. } GuiWidgetModel;
  12. static void gui_widget_view_draw_callback(Canvas* canvas, void* _model) {
  13. GuiWidgetModel* model = _model;
  14. canvas_clear(canvas);
  15. // Draw all elements
  16. ElementArray_it_t it;
  17. ElementArray_it(it, model->element);
  18. while(!ElementArray_end_p(it)) {
  19. WidgetElement* element = *ElementArray_ref(it);
  20. if(element->draw != NULL) {
  21. element->draw(canvas, element);
  22. }
  23. ElementArray_next(it);
  24. }
  25. }
  26. static bool gui_widget_view_input_callback(InputEvent* event, void* context) {
  27. Widget* widget = context;
  28. bool consumed = false;
  29. // Call all Widget Elements input handlers
  30. with_view_model(
  31. widget->view, (GuiWidgetModel * model) {
  32. ElementArray_it_t it;
  33. ElementArray_it(it, model->element);
  34. while(!ElementArray_end_p(it)) {
  35. WidgetElement* element = *ElementArray_ref(it);
  36. if(element->input != NULL) {
  37. consumed |= element->input(event, element);
  38. }
  39. ElementArray_next(it);
  40. }
  41. return true;
  42. });
  43. return consumed;
  44. }
  45. Widget* widget_alloc() {
  46. Widget* widget = malloc(sizeof(Widget));
  47. widget->view = view_alloc();
  48. view_set_context(widget->view, widget);
  49. view_allocate_model(widget->view, ViewModelTypeLocking, sizeof(GuiWidgetModel));
  50. view_set_draw_callback(widget->view, gui_widget_view_draw_callback);
  51. view_set_input_callback(widget->view, gui_widget_view_input_callback);
  52. with_view_model(
  53. widget->view, (GuiWidgetModel * model) {
  54. ElementArray_init(model->element);
  55. return true;
  56. });
  57. return widget;
  58. }
  59. void widget_reset(Widget* widget) {
  60. furi_assert(widget);
  61. with_view_model(
  62. widget->view, (GuiWidgetModel * model) {
  63. ElementArray_it_t it;
  64. ElementArray_it(it, model->element);
  65. while(!ElementArray_end_p(it)) {
  66. WidgetElement* element = *ElementArray_ref(it);
  67. furi_assert(element->free);
  68. element->free(element);
  69. ElementArray_next(it);
  70. }
  71. ElementArray_reset(model->element);
  72. return true;
  73. });
  74. }
  75. void widget_free(Widget* widget) {
  76. furi_assert(widget);
  77. // Free all elements
  78. widget_reset(widget);
  79. // Free elements container
  80. with_view_model(
  81. widget->view, (GuiWidgetModel * model) {
  82. ElementArray_clear(model->element);
  83. return true;
  84. });
  85. view_free(widget->view);
  86. free(widget);
  87. }
  88. View* widget_get_view(Widget* widget) {
  89. furi_assert(widget);
  90. return widget->view;
  91. }
  92. static void widget_add_element(Widget* widget, WidgetElement* element) {
  93. furi_assert(widget);
  94. furi_assert(element);
  95. with_view_model(
  96. widget->view, (GuiWidgetModel * model) {
  97. element->parent = widget;
  98. ElementArray_push_back(model->element, element);
  99. return true;
  100. });
  101. }
  102. void widget_add_string_multiline_element(
  103. Widget* widget,
  104. uint8_t x,
  105. uint8_t y,
  106. Align horizontal,
  107. Align vertical,
  108. Font font,
  109. const char* text) {
  110. furi_assert(widget);
  111. WidgetElement* string_multiline_element =
  112. widget_element_string_multiline_create(x, y, horizontal, vertical, font, text);
  113. widget_add_element(widget, string_multiline_element);
  114. }
  115. void widget_add_string_element(
  116. Widget* widget,
  117. uint8_t x,
  118. uint8_t y,
  119. Align horizontal,
  120. Align vertical,
  121. Font font,
  122. const char* text) {
  123. furi_assert(widget);
  124. WidgetElement* string_element =
  125. widget_element_string_create(x, y, horizontal, vertical, font, text);
  126. widget_add_element(widget, string_element);
  127. }
  128. void widget_add_text_box_element(
  129. Widget* widget,
  130. uint8_t x,
  131. uint8_t y,
  132. uint8_t width,
  133. uint8_t height,
  134. Align horizontal,
  135. Align vertical,
  136. const char* text,
  137. bool strip_to_dots) {
  138. furi_assert(widget);
  139. WidgetElement* text_box_element = widget_element_text_box_create(
  140. x, y, width, height, horizontal, vertical, text, strip_to_dots);
  141. widget_add_element(widget, text_box_element);
  142. }
  143. void widget_add_button_element(
  144. Widget* widget,
  145. GuiButtonType button_type,
  146. const char* text,
  147. ButtonCallback callback,
  148. void* context) {
  149. furi_assert(widget);
  150. WidgetElement* button_element =
  151. widget_element_button_create(button_type, text, callback, context);
  152. widget_add_element(widget, button_element);
  153. }
  154. void widget_add_icon_element(Widget* widget, uint8_t x, uint8_t y, const Icon* icon) {
  155. furi_assert(widget);
  156. furi_assert(icon);
  157. WidgetElement* icon_element = widget_element_icon_create(x, y, icon);
  158. widget_add_element(widget, icon_element);
  159. }
  160. void widget_add_frame_element(
  161. Widget* widget,
  162. uint8_t x,
  163. uint8_t y,
  164. uint8_t width,
  165. uint8_t height,
  166. uint8_t radius) {
  167. furi_assert(widget);
  168. WidgetElement* frame_element = widget_element_frame_create(x, y, width, height, radius);
  169. widget_add_element(widget, frame_element);
  170. }