view_controller.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #pragma once
  2. #include "view_modules/generic_view_module.h"
  3. #include <map>
  4. #include <furi/check.h>
  5. #include <gui/view_dispatcher.h>
  6. #include <callback-connector.h>
  7. #include "typeindex_no_rtti.hpp"
  8. /**
  9. * @brief Controller for switching application views and handling inputs and events
  10. *
  11. * @tparam TApp application class
  12. * @tparam TViewModules variadic list of ViewModules
  13. */
  14. template <typename TApp, typename... TViewModules> class ViewController {
  15. public:
  16. ViewController() {
  17. event_queue = osMessageQueueNew(10, sizeof(typename TApp::Event), NULL);
  18. view_dispatcher = view_dispatcher_alloc();
  19. previous_view_callback_pointer = cbc::obtain_connector(
  20. this, &ViewController<TApp, TViewModules...>::previous_view_callback);
  21. [](...) {
  22. }((this->add_view(ext::make_type_index<TViewModules>().hash_code(), new TViewModules()),
  23. 0)...);
  24. gui = static_cast<Gui*>(furi_record_open("gui"));
  25. view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen);
  26. };
  27. ~ViewController() {
  28. for(auto& it : holder) {
  29. view_dispatcher_remove_view(view_dispatcher, static_cast<uint32_t>(it.first));
  30. delete it.second;
  31. }
  32. view_dispatcher_free(view_dispatcher);
  33. osMessageQueueDelete(event_queue);
  34. }
  35. /**
  36. * @brief Get ViewModule pointer
  37. *
  38. * @tparam T Concrete ViewModule class
  39. * @return T* ViewModule pointer
  40. */
  41. template <typename T> T* get() {
  42. uint32_t view_index = ext::make_type_index<T>().hash_code();
  43. furi_check(holder.count(view_index) != 0);
  44. return static_cast<T*>(holder[view_index]);
  45. }
  46. /**
  47. * @brief Get ViewModule pointer by cast
  48. *
  49. * @tparam T Concrete ViewModule class
  50. * @return T* ViewModule pointer
  51. */
  52. template <typename T> operator T*() {
  53. uint32_t view_index = ext::make_type_index<T>().hash_code();
  54. furi_check(holder.count(view_index) != 0);
  55. return static_cast<T*>(holder[view_index]);
  56. }
  57. /**
  58. * @brief Switch view to ViewModule
  59. *
  60. * @tparam T Concrete ViewModule class
  61. * @return T* ViewModule pointer
  62. */
  63. template <typename T> void switch_to() {
  64. uint32_t view_index = ext::make_type_index<T>().hash_code();
  65. furi_check(holder.count(view_index) != 0);
  66. view_dispatcher_switch_to_view(view_dispatcher, view_index);
  67. }
  68. /**
  69. * @brief Receive event from app event queue
  70. *
  71. * @param event event pointer
  72. */
  73. void receive_event(typename TApp::Event* event) {
  74. if(osMessageQueueGet(event_queue, event, NULL, 100) != osOK) {
  75. event->type = TApp::EventType::Tick;
  76. }
  77. }
  78. /**
  79. * @brief Send event to app event queue
  80. *
  81. * @param event event pointer
  82. */
  83. void send_event(typename TApp::Event* event) {
  84. osStatus_t result = osMessageQueuePut(event_queue, event, 0, osWaitForever);
  85. furi_check(result == osOK);
  86. }
  87. private:
  88. /**
  89. * @brief ViewModulesHolder
  90. *
  91. */
  92. std::map<size_t, GenericViewModule*> holder;
  93. /**
  94. * @brief App event queue
  95. *
  96. */
  97. osMessageQueueId_t event_queue;
  98. /**
  99. * @brief Main ViewDispatcher pointer
  100. *
  101. */
  102. ViewDispatcher* view_dispatcher;
  103. /**
  104. * @brief Gui record pointer
  105. *
  106. */
  107. Gui* gui;
  108. /**
  109. * @brief Previous view callback fn pointer
  110. *
  111. */
  112. ViewNavigationCallback previous_view_callback_pointer;
  113. /**
  114. * @brief Previous view callback fn
  115. *
  116. * @param context not used
  117. * @return uint32_t VIEW_IGNORE
  118. */
  119. uint32_t previous_view_callback(void* context) {
  120. (void)context;
  121. typename TApp::Event event;
  122. event.type = TApp::EventType::Back;
  123. if(event_queue != NULL) {
  124. send_event(&event);
  125. }
  126. return VIEW_IGNORE;
  127. }
  128. /**
  129. * @brief Add ViewModule to holder
  130. *
  131. * @param view_index view index in holder
  132. * @param view_module view module pointer
  133. */
  134. void add_view(size_t view_index, GenericViewModule* view_module) {
  135. furi_check(holder.count(view_index) == 0);
  136. holder[view_index] = view_module;
  137. View* view = view_module->get_view();
  138. view_dispatcher_add_view(view_dispatcher, static_cast<uint32_t>(view_index), view);
  139. view_set_previous_callback(view, previous_view_callback_pointer);
  140. }
  141. };