view_holder.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #include "view_holder.h"
  2. #include <gui/view_i.h>
  3. #define TAG "ViewHolder"
  4. struct ViewHolder {
  5. View* view;
  6. ViewPort* view_port;
  7. Gui* gui;
  8. FreeCallback free_callback;
  9. void* free_context;
  10. BackCallback back_callback;
  11. void* back_context;
  12. uint8_t ongoing_input;
  13. };
  14. static void view_holder_draw_callback(Canvas* canvas, void* context);
  15. static void view_holder_input_callback(InputEvent* event, void* context);
  16. ViewHolder* view_holder_alloc() {
  17. ViewHolder* view_holder = malloc(sizeof(ViewHolder));
  18. view_holder->view_port = view_port_alloc();
  19. view_port_draw_callback_set(view_holder->view_port, view_holder_draw_callback, view_holder);
  20. view_port_input_callback_set(view_holder->view_port, view_holder_input_callback, view_holder);
  21. view_port_enabled_set(view_holder->view_port, false);
  22. return view_holder;
  23. }
  24. void view_holder_free(ViewHolder* view_holder) {
  25. furi_assert(view_holder);
  26. if(view_holder->gui) {
  27. gui_remove_view_port(view_holder->gui, view_holder->view_port);
  28. }
  29. view_port_free(view_holder->view_port);
  30. if(view_holder->free_callback) {
  31. view_holder->free_callback(view_holder->free_context);
  32. }
  33. free(view_holder);
  34. }
  35. void view_holder_set_view(ViewHolder* view_holder, View* view) {
  36. furi_assert(view_holder);
  37. if(view_holder->view) {
  38. if(view_holder->view->exit_callback) {
  39. view_holder->view->exit_callback(view_holder->view->context);
  40. }
  41. view_set_update_callback(view_holder->view, NULL);
  42. view_set_update_callback_context(view_holder->view, NULL);
  43. }
  44. view_holder->view = view;
  45. if(view_holder->view) {
  46. view_set_update_callback(view_holder->view, view_holder_update);
  47. view_set_update_callback_context(view_holder->view, view_holder);
  48. if(view_holder->view->enter_callback) {
  49. view_holder->view->enter_callback(view_holder->view->context);
  50. }
  51. }
  52. }
  53. void view_holder_set_free_callback(
  54. ViewHolder* view_holder,
  55. FreeCallback free_callback,
  56. void* free_context) {
  57. furi_assert(view_holder);
  58. view_holder->free_callback = free_callback;
  59. view_holder->free_context = free_context;
  60. }
  61. void* view_holder_get_free_context(ViewHolder* view_holder) {
  62. return view_holder->free_context;
  63. }
  64. void view_holder_set_back_callback(
  65. ViewHolder* view_holder,
  66. BackCallback back_callback,
  67. void* back_context) {
  68. furi_assert(view_holder);
  69. view_holder->back_callback = back_callback;
  70. view_holder->back_context = back_context;
  71. }
  72. void view_holder_attach_to_gui(ViewHolder* view_holder, Gui* gui) {
  73. furi_assert(gui);
  74. furi_assert(view_holder);
  75. view_holder->gui = gui;
  76. gui_add_view_port(gui, view_holder->view_port, GuiLayerFullscreen);
  77. }
  78. void view_holder_start(ViewHolder* view_holder) {
  79. view_port_enabled_set(view_holder->view_port, true);
  80. }
  81. void view_holder_stop(ViewHolder* view_holder) {
  82. while(view_holder->ongoing_input) furi_delay_tick(1);
  83. view_port_enabled_set(view_holder->view_port, false);
  84. }
  85. void view_holder_update(View* view, void* context) {
  86. furi_assert(view);
  87. furi_assert(context);
  88. ViewHolder* view_holder = context;
  89. if(view == view_holder->view) {
  90. view_port_update(view_holder->view_port);
  91. }
  92. }
  93. static void view_holder_draw_callback(Canvas* canvas, void* context) {
  94. ViewHolder* view_holder = context;
  95. if(view_holder->view) {
  96. view_draw(view_holder->view, canvas);
  97. }
  98. }
  99. static void view_holder_input_callback(InputEvent* event, void* context) {
  100. ViewHolder* view_holder = context;
  101. uint8_t key_bit = (1 << event->key);
  102. if(event->type == InputTypePress) {
  103. view_holder->ongoing_input |= key_bit;
  104. } else if(event->type == InputTypeRelease) {
  105. view_holder->ongoing_input &= ~key_bit;
  106. } else if(!(view_holder->ongoing_input & key_bit)) {
  107. FURI_LOG_W(
  108. TAG,
  109. "non-complementary input, discarding key: %s, type: %s",
  110. input_get_key_name(event->key),
  111. input_get_type_name(event->type));
  112. return;
  113. }
  114. bool is_consumed = false;
  115. if(view_holder->view) {
  116. is_consumed = view_input(view_holder->view, event);
  117. }
  118. if(!is_consumed && event->type == InputTypeShort) {
  119. if(event->key == InputKeyBack) {
  120. if(view_holder->back_callback) {
  121. view_holder->back_callback(view_holder->back_context);
  122. }
  123. }
  124. }
  125. }