gui.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #include "gui.h"
  2. #include "gui_i.h"
  3. #include <flipper.h>
  4. #include <flipper_v2.h>
  5. #include <stdio.h>
  6. #include <m-array.h>
  7. #include "gui_event.h"
  8. #include "canvas.h"
  9. #include "canvas_i.h"
  10. #include "widget.h"
  11. #include "widget_i.h"
  12. ARRAY_DEF(WidgetArray, Widget*, M_PTR_OPLIST);
  13. struct Gui {
  14. GuiEvent* event;
  15. CanvasApi* canvas_api;
  16. WidgetArray_t widgets_status_bar;
  17. WidgetArray_t widgets;
  18. WidgetArray_t widgets_fs;
  19. WidgetArray_t widgets_dialog;
  20. };
  21. void gui_add_widget(GuiApi* gui_api, Widget* widget, WidgetLayer layer) {
  22. assert(gui_api);
  23. assert(gui_api->gui);
  24. // TODO add mutex on widget array
  25. WidgetArray_t* widget_array = NULL;
  26. switch(layer) {
  27. case WidgetLayerStatusBar:
  28. widget_array = &gui_api->gui->widgets_status_bar;
  29. break;
  30. case WidgetLayerMain:
  31. widget_array = &gui_api->gui->widgets;
  32. break;
  33. case WidgetLayerFullscreen:
  34. widget_array = &gui_api->gui->widgets_fs;
  35. break;
  36. case WidgetLayerDialog:
  37. widget_array = &gui_api->gui->widgets_dialog;
  38. break;
  39. default:
  40. break;
  41. }
  42. assert(widget);
  43. assert(widget_array);
  44. gui_event_lock(gui_api->gui->event);
  45. WidgetArray_push_back((struct WidgetArray_s*)widget_array, widget);
  46. widget_gui_set(widget, gui_api->gui);
  47. gui_event_unlock(gui_api->gui->event);
  48. gui_update(gui_api->gui);
  49. }
  50. void gui_update(Gui* gui) {
  51. assert(gui);
  52. GuiMessage message;
  53. message.type = GuiMessageTypeRedraw;
  54. gui_event_messsage_send(gui->event, &message);
  55. }
  56. Widget* gui_widget_find_enabled(WidgetArray_t array) {
  57. size_t widgets_count = WidgetArray_size(array);
  58. for(size_t i = 0; i < widgets_count; i++) {
  59. Widget* widget = *WidgetArray_get(array, widgets_count - i - 1);
  60. if(widget_is_enabled(widget)) {
  61. return widget;
  62. }
  63. }
  64. return NULL;
  65. }
  66. bool gui_redraw_fs(Gui* gui) {
  67. canvas_frame_set(gui->canvas_api, 0, 0, 128, 64);
  68. Widget* widget = gui_widget_find_enabled(gui->widgets_fs);
  69. if(widget) {
  70. widget_draw(widget, gui->canvas_api);
  71. return true;
  72. } else {
  73. return false;
  74. }
  75. }
  76. void gui_redraw_status_bar(Gui* gui) {
  77. canvas_frame_set(gui->canvas_api, 0, 0, 128, 64);
  78. Widget* widget = gui_widget_find_enabled(gui->widgets_status_bar);
  79. if(widget) widget_draw(widget, gui->canvas_api);
  80. }
  81. void gui_redraw_normal(Gui* gui) {
  82. canvas_frame_set(gui->canvas_api, 0, 9, 128, 55);
  83. Widget* widget = gui_widget_find_enabled(gui->widgets);
  84. if(widget) widget_draw(widget, gui->canvas_api);
  85. }
  86. void gui_redraw_dialogs(Gui* gui) {
  87. canvas_frame_set(gui->canvas_api, 10, 20, 118, 44);
  88. Widget* widget = gui_widget_find_enabled(gui->widgets_dialog);
  89. if(widget) widget_draw(widget, gui->canvas_api);
  90. }
  91. void gui_redraw(Gui* gui) {
  92. assert(gui);
  93. if(!gui_redraw_fs(gui)) {
  94. gui_redraw_status_bar(gui);
  95. gui_redraw_normal(gui);
  96. }
  97. gui_redraw_dialogs(gui);
  98. canvas_commit(gui->canvas_api);
  99. }
  100. void gui_input(Gui* gui, InputEvent* input_event) {
  101. assert(gui);
  102. Widget* widget = gui_widget_find_enabled(gui->widgets_dialog);
  103. if(!widget) widget = gui_widget_find_enabled(gui->widgets_fs);
  104. if(!widget) widget = gui_widget_find_enabled(gui->widgets);
  105. if(widget) {
  106. widget_input(widget, input_event);
  107. }
  108. }
  109. Gui* gui_alloc() {
  110. Gui* gui = furi_alloc(sizeof(Gui));
  111. // Initialize widget arrays
  112. WidgetArray_init(gui->widgets_status_bar);
  113. WidgetArray_init(gui->widgets);
  114. WidgetArray_init(gui->widgets_fs);
  115. WidgetArray_init(gui->widgets_dialog);
  116. // Event dispatcher
  117. gui->event = gui_event_alloc();
  118. // Drawing canvas api
  119. gui->canvas_api = canvas_api_init();
  120. return gui;
  121. }
  122. void gui_task(void* p) {
  123. Gui* gui = gui_alloc();
  124. GuiApi gui_api = {
  125. .add_widget = gui_add_widget,
  126. .gui = gui,
  127. };
  128. // Create FURI record
  129. if(!furi_create("gui", &gui_api)) {
  130. printf("[gui_task] cannot create the gui record\n");
  131. furiac_exit(NULL);
  132. }
  133. furiac_ready();
  134. // Forever dispatch
  135. while(1) {
  136. GuiMessage message = gui_event_message_next(gui->event);
  137. if(message.type == GuiMessageTypeRedraw) {
  138. gui_redraw(gui);
  139. } else if(message.type == GuiMessageTypeInput) {
  140. gui_input(gui, &message.input);
  141. }
  142. }
  143. }