view_holder.c 4.1 KB

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