app_context.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include <gui/modules/menu.h>
  2. #include <gui/modules/popup.h>
  3. #include <gui/modules/submenu.h>
  4. #include <gui/modules/variable_item_list.h>
  5. #include "tone_gen.h"
  6. #include "app_context.h"
  7. /** custom event handler - passes the event to the scene manager */
  8. bool viewDispatcherCustomCallback(void* context, uint32_t custom_event) {
  9. furi_assert(context);
  10. struct AppContext_t* appContext = context;
  11. return scene_manager_handle_custom_event(appContext->scene_manager, custom_event);
  12. }
  13. /** navigation event handler - passes the event to the scene manager */
  14. bool viewDispatcherNavigationCallback(void* context) {
  15. furi_assert(context);
  16. struct AppContext_t* appContext = context;
  17. return scene_manager_handle_back_event(appContext->scene_manager);
  18. }
  19. AppContextStatus initializeAppContext(
  20. struct AppContext_t** context,
  21. int viewsCount,
  22. const SceneManagerHandlers* sceneManagerHandlers) {
  23. FURI_LOG_I(TAG, "Allocating memory for app context");
  24. *context = malloc(sizeof(struct AppContext_t));
  25. if(*context == NULL) {
  26. FURI_LOG_E(TAG, "Failed to allocate memory for app context");
  27. return APP_CONTEXT_CANT_ALLOCATE;
  28. }
  29. // Allocate our scene manager with the handlers provided
  30. FURI_LOG_I(TAG, "Setting up the scene manager");
  31. (*context)->scene_manager = scene_manager_alloc(sceneManagerHandlers, *context);
  32. // Now setup our view dispatchers
  33. FURI_LOG_I(TAG, "Setting up the view dispatcher");
  34. (*context)->view_dispatcher = view_dispatcher_alloc();
  35. view_dispatcher_enable_queue((*context)->view_dispatcher);
  36. FURI_LOG_I(TAG, "Setting view dispatcher callbacks");
  37. view_dispatcher_set_event_callback_context((*context)->view_dispatcher, (*context));
  38. FURI_LOG_I(TAG, "Setting view dispatcher custom event callbacks");
  39. view_dispatcher_set_custom_event_callback(
  40. (*context)->view_dispatcher, viewDispatcherCustomCallback);
  41. FURI_LOG_I(TAG, "Setting view dispatcher navigation event callbacks");
  42. view_dispatcher_set_navigation_event_callback(
  43. (*context)->view_dispatcher, viewDispatcherNavigationCallback);
  44. FURI_LOG_I(TAG, "Setting view dispatcher callbacks done");
  45. (*context)->activeViews = malloc(sizeof(struct View_t) * viewsCount);
  46. if((*context)->activeViews == NULL) {
  47. return APP_CONTEXT_CANT_ALLOCATE;
  48. }
  49. (*context)->activeViewsCount = viewsCount;
  50. return APP_CONTEXT_OK;
  51. }
  52. AppContextStatus addViewToAppContext(struct AppContext_t** context, struct View_t* view) {
  53. if(view->viewId > (*context)->activeViewsCount || view->viewId < 0) {
  54. FURI_LOG_I(TAG, "Not enough views!");
  55. return APP_CONTEXT_NOT_ENOUGH_VIEWS;
  56. }
  57. (*context)->activeViews[view->viewId] = view;
  58. switch(view->type) {
  59. case MENU:
  60. view_dispatcher_add_view(
  61. (*context)->view_dispatcher, view->viewId, menu_get_view(view->viewData));
  62. break;
  63. case SUBMENU:
  64. view_dispatcher_add_view(
  65. (*context)->view_dispatcher, view->viewId, submenu_get_view(view->viewData));
  66. break;
  67. case VIEW:
  68. view_dispatcher_add_view((*context)->view_dispatcher, view->viewId, view->viewData);
  69. break;
  70. case VARIABLE_ITEM_LIST:
  71. view_dispatcher_add_view(
  72. (*context)->view_dispatcher,
  73. view->viewId,
  74. variable_item_list_get_view(view->viewData));
  75. break;
  76. case POPUP:
  77. view_dispatcher_add_view(
  78. (*context)->view_dispatcher, view->viewId, popup_get_view(view->viewData));
  79. break;
  80. }
  81. return APP_CONTEXT_OK;
  82. }
  83. AppContextStatus freeAppContextViews(struct AppContext_t** context) {
  84. FURI_LOG_I(TAG, "Freeing views");
  85. for(int i = 0; i < (*context)->activeViewsCount; i++) {
  86. struct View_t* view = (*context)->activeViews[i];
  87. if(view != NULL) {
  88. view_dispatcher_remove_view((*context)->view_dispatcher, view->viewId);
  89. switch(view->type) {
  90. case MENU:
  91. menu_free(view->viewData);
  92. break;
  93. case SUBMENU:
  94. submenu_free(view->viewData);
  95. break;
  96. case VIEW:
  97. view_free(view->viewData);
  98. break;
  99. case VARIABLE_ITEM_LIST:
  100. variable_item_list_free(view->viewData);
  101. break;
  102. case POPUP:
  103. popup_free(view->viewData);
  104. break;
  105. }
  106. free(view);
  107. }
  108. }
  109. FURI_LOG_I(TAG, "Removing all views from list");
  110. free((*context)->activeViews);
  111. (*context)->activeViewsCount = 0;
  112. return APP_CONTEXT_OK;
  113. }
  114. AppContextStatus freeAppContext(struct AppContext_t** context) {
  115. FURI_LOG_I(TAG, "Ensuring views are free'd");
  116. AppContextStatus result = freeAppContextViews(context);
  117. if(result != APP_CONTEXT_OK) {
  118. return APP_CONTEXT_CANT_FREE_VIEWS;
  119. }
  120. FURI_LOG_I(TAG, "Freeing the scene");
  121. scene_manager_free((*context)->scene_manager);
  122. FURI_LOG_I(TAG, "Freeing the view dispatcher");
  123. view_dispatcher_free((*context)->view_dispatcher);
  124. FURI_LOG_I(TAG, "Freeing the app context");
  125. free((*context));
  126. return APP_CONTEXT_OK;
  127. }