widget.c 5.5 KB

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