popup.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #include "popup.h"
  2. #include <gui/elements.h>
  3. #include <furi.h>
  4. struct Popup {
  5. View* view;
  6. void* context;
  7. PopupCallback callback;
  8. osTimerId_t timer;
  9. uint32_t timer_period_in_ms;
  10. bool timer_enabled;
  11. };
  12. typedef struct {
  13. const char* text;
  14. uint8_t x;
  15. uint8_t y;
  16. Align horizontal;
  17. Align vertical;
  18. } TextElement;
  19. typedef struct {
  20. int8_t x;
  21. int8_t y;
  22. IconName name;
  23. } IconElement;
  24. typedef struct {
  25. TextElement header;
  26. TextElement text;
  27. IconElement icon;
  28. } PopupModel;
  29. static void popup_view_draw_callback(Canvas* canvas, void* _model) {
  30. PopupModel* model = _model;
  31. // Prepare canvas
  32. canvas_clear(canvas);
  33. canvas_set_color(canvas, ColorBlack);
  34. // TODO other criteria for the draw
  35. if(model->icon.x >= 0 && model->icon.y >= 0) {
  36. canvas_draw_icon_name(canvas, model->icon.x, model->icon.y, model->icon.name);
  37. }
  38. // Draw header
  39. if(model->header.text != NULL) {
  40. canvas_set_font(canvas, FontPrimary);
  41. elements_multiline_text_aligned(
  42. canvas,
  43. model->header.x,
  44. model->header.y,
  45. model->header.horizontal,
  46. model->header.vertical,
  47. model->header.text);
  48. }
  49. // Draw text
  50. if(model->text.text != NULL) {
  51. canvas_set_font(canvas, FontSecondary);
  52. elements_multiline_text_aligned(
  53. canvas,
  54. model->text.x,
  55. model->text.y,
  56. model->text.horizontal,
  57. model->text.vertical,
  58. model->text.text);
  59. }
  60. }
  61. static void popup_timer_callback(void* context) {
  62. furi_assert(context);
  63. Popup* popup = context;
  64. if(popup->callback) {
  65. popup->callback(popup->context);
  66. }
  67. }
  68. static bool popup_view_input_callback(InputEvent* event, void* context) {
  69. Popup* popup = context;
  70. bool consumed = false;
  71. // Process key presses only
  72. if(event->type == InputTypeShort && popup->callback) {
  73. popup->callback(popup->context);
  74. consumed = true;
  75. }
  76. return consumed;
  77. }
  78. void popup_start_timer(void* context) {
  79. Popup* popup = context;
  80. if(popup->timer_enabled) {
  81. uint32_t timer_period = popup->timer_period_in_ms / (1000.0f / osKernelGetTickFreq());
  82. if(timer_period == 0) timer_period = 1;
  83. if(osTimerStart(popup->timer, timer_period) != osOK) {
  84. furi_assert(0);
  85. };
  86. }
  87. }
  88. void popup_stop_timer(void* context) {
  89. Popup* popup = context;
  90. osTimerStop(popup->timer);
  91. }
  92. Popup* popup_alloc() {
  93. Popup* popup = furi_alloc(sizeof(Popup));
  94. popup->view = view_alloc();
  95. popup->timer = osTimerNew(popup_timer_callback, osTimerOnce, popup, NULL);
  96. furi_assert(popup->timer);
  97. popup->timer_period_in_ms = 1000;
  98. popup->timer_enabled = false;
  99. view_set_context(popup->view, popup);
  100. view_allocate_model(popup->view, ViewModelTypeLockFree, sizeof(PopupModel));
  101. view_set_draw_callback(popup->view, popup_view_draw_callback);
  102. view_set_input_callback(popup->view, popup_view_input_callback);
  103. view_set_enter_callback(popup->view, popup_start_timer);
  104. view_set_exit_callback(popup->view, popup_stop_timer);
  105. with_view_model(
  106. popup->view, (PopupModel * model) {
  107. model->header.text = NULL;
  108. model->header.x = 0;
  109. model->header.y = 0;
  110. model->header.horizontal = AlignLeft;
  111. model->header.vertical = AlignBottom;
  112. model->text.text = NULL;
  113. model->text.x = 0;
  114. model->text.y = 0;
  115. model->text.horizontal = AlignLeft;
  116. model->text.vertical = AlignBottom;
  117. // TODO other criteria for the draw
  118. model->icon.x = -1;
  119. model->icon.y = -1;
  120. model->icon.name = I_ButtonCenter_7x7;
  121. return true;
  122. });
  123. return popup;
  124. }
  125. void popup_free(Popup* popup) {
  126. furi_assert(popup);
  127. osTimerDelete(popup->timer);
  128. view_free(popup->view);
  129. free(popup);
  130. }
  131. View* popup_get_view(Popup* popup) {
  132. furi_assert(popup);
  133. return popup->view;
  134. }
  135. void popup_set_callback(Popup* popup, PopupCallback callback) {
  136. furi_assert(popup);
  137. popup->callback = callback;
  138. }
  139. void popup_set_context(Popup* popup, void* context) {
  140. furi_assert(popup);
  141. popup->context = context;
  142. }
  143. void popup_set_header(
  144. Popup* popup,
  145. const char* text,
  146. uint8_t x,
  147. uint8_t y,
  148. Align horizontal,
  149. Align vertical) {
  150. furi_assert(popup);
  151. with_view_model(
  152. popup->view, (PopupModel * model) {
  153. model->header.text = text;
  154. model->header.x = x;
  155. model->header.y = y;
  156. model->header.horizontal = horizontal;
  157. model->header.vertical = vertical;
  158. return true;
  159. });
  160. }
  161. void popup_set_text(
  162. Popup* popup,
  163. const char* text,
  164. uint8_t x,
  165. uint8_t y,
  166. Align horizontal,
  167. Align vertical) {
  168. furi_assert(popup);
  169. with_view_model(
  170. popup->view, (PopupModel * model) {
  171. model->text.text = text;
  172. model->text.x = x;
  173. model->text.y = y;
  174. model->text.horizontal = horizontal;
  175. model->text.vertical = vertical;
  176. return true;
  177. });
  178. }
  179. void popup_set_icon(Popup* popup, int8_t x, int8_t y, IconName name) {
  180. furi_assert(popup);
  181. with_view_model(
  182. popup->view, (PopupModel * model) {
  183. model->icon.x = x;
  184. model->icon.y = y;
  185. model->icon.name = name;
  186. return true;
  187. });
  188. }
  189. void popup_set_timeout(Popup* popup, uint32_t timeout_in_ms) {
  190. furi_assert(popup);
  191. popup->timer_period_in_ms = timeout_in_ms;
  192. }
  193. void popup_enable_timeout(Popup* popup) {
  194. popup->timer_enabled = true;
  195. }
  196. void popup_disable_timeout(Popup* popup) {
  197. popup->timer_enabled = false;
  198. }