xremote_app.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*!
  2. * @file flipper-xremote/xremote_app.c
  3. @license This project is released under the GNU GPLv3 License
  4. * @copyright (c) 2023 Sandro Kalatozishvili (s.kalatoz@gmail.com)
  5. *
  6. * @brief Shared functionality and data types between the apps.
  7. */
  8. #include "xremote_app.h"
  9. XRemoteAppContext* xremote_app_context_alloc(void *arg)
  10. {
  11. XRemoteAppContext* ctx = malloc(sizeof(XRemoteAppContext));
  12. ctx->gui = furi_record_open(RECORD_GUI);
  13. ctx->notifications = furi_record_open(RECORD_NOTIFICATION);
  14. ctx->view_dispatcher = view_dispatcher_alloc();
  15. ctx->arg = arg;
  16. view_dispatcher_enable_queue(ctx->view_dispatcher);
  17. view_dispatcher_attach_to_gui(ctx->view_dispatcher, ctx->gui, ViewDispatcherTypeFullscreen);
  18. return ctx;
  19. }
  20. void xremote_app_context_free(XRemoteAppContext* ctx)
  21. {
  22. xremote_app_assert_void(ctx);
  23. notification_internal_message(ctx->notifications, &sequence_reset_blue);
  24. view_dispatcher_free(ctx->view_dispatcher);
  25. furi_record_close(RECORD_NOTIFICATION);
  26. furi_record_close(RECORD_GUI);
  27. free(ctx);
  28. }
  29. void xremote_app_view_alloc(XRemoteApp *app, uint32_t view_id, XRemoteViewAllocator allocator)
  30. {
  31. furi_assert(app);
  32. xremote_app_assert_void(app->app_ctx);
  33. if (app->view_id == view_id &&
  34. app->view_ctx != NULL) return;
  35. xremote_app_view_free(app);
  36. app->view_id = view_id;
  37. app->view_ctx = allocator(app->app_ctx->notifications);
  38. View* app_view = xremote_view_get_view(app->view_ctx);
  39. ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
  40. view_dispatcher_add_view(view_disp, app->view_id, app_view);
  41. }
  42. void xremote_app_view_free(XRemoteApp* app)
  43. {
  44. xremote_app_assert_void(app);
  45. if (app->app_ctx != NULL && app->view_id != XRemoteViewNone)
  46. {
  47. ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
  48. view_dispatcher_remove_view(view_disp, app->view_id);
  49. app->view_id = XRemoteViewNone;
  50. }
  51. if (app->view_ctx != NULL)
  52. {
  53. xremote_view_free(app->view_ctx);
  54. app->view_ctx = NULL;
  55. }
  56. }
  57. bool xremote_app_has_view(XRemoteApp *app, uint32_t view_id)
  58. {
  59. xremote_app_assert(app, false);
  60. return (app->view_id == view_id ||
  61. app->submenu_id == view_id);
  62. }
  63. void xremote_app_switch_to_view(XRemoteApp *app, uint32_t view_id)
  64. {
  65. furi_assert(app);
  66. xremote_app_assert_void(app->app_ctx);
  67. ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
  68. view_dispatcher_switch_to_view(view_disp, view_id);
  69. }
  70. void xremote_app_switch_to_submenu(XRemoteApp *app)
  71. {
  72. furi_assert(app);
  73. xremote_app_assert_void(app->app_ctx);
  74. ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
  75. view_dispatcher_switch_to_view(view_disp, app->submenu_id);
  76. }
  77. void xremote_app_submenu_add(XRemoteApp* app, const char *name, uint32_t index, SubmenuItemCallback callback)
  78. {
  79. furi_assert(app);
  80. xremote_app_assert_void(app->submenu);
  81. submenu_add_item(app->submenu, name, index, callback, app);
  82. }
  83. void xremote_app_submenu_alloc(XRemoteApp* app, uint32_t index, ViewNavigationCallback prev_cb)
  84. {
  85. furi_assert(app);
  86. app->submenu = submenu_alloc();
  87. app->submenu_id = index;
  88. submenu_set_orientation(app->submenu, ViewOrientationVertical);
  89. view_set_previous_callback(submenu_get_view(app->submenu), prev_cb);
  90. ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
  91. view_dispatcher_add_view(view_disp, app->submenu_id, submenu_get_view(app->submenu));
  92. }
  93. void xremote_app_submenu_free(XRemoteApp *app)
  94. {
  95. xremote_app_assert_void(app);
  96. /* Remove submenu view from dispatcher */
  97. if (app->submenu_id != XRemoteViewNone && app->app_ctx != NULL)
  98. {
  99. ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
  100. view_dispatcher_remove_view(view_disp, app->submenu_id);
  101. app->submenu_id = XRemoteViewNone;
  102. }
  103. /* Free submenu */
  104. if (app->submenu != NULL)
  105. {
  106. submenu_free(app->submenu);
  107. app->submenu = NULL;
  108. }
  109. }
  110. void xremote_app_view_set_previous_callback(XRemoteApp* app, ViewNavigationCallback callback)
  111. {
  112. furi_assert(app);
  113. xremote_app_assert_void(app->view_ctx);
  114. View* view = xremote_view_get_view(app->view_ctx);
  115. view_set_previous_callback(view, callback);
  116. }
  117. void xremote_app_set_view_context(XRemoteApp* app, void *context, XRemoteViewClearCallback on_clear)
  118. {
  119. furi_assert(app);
  120. xremote_app_assert_void(app->view_ctx);
  121. xremote_view_set_context(app->view_ctx, context, on_clear);
  122. }
  123. void xremote_app_set_user_context(XRemoteApp* app, void *context, XRemoteAppClearCallback on_clear)
  124. {
  125. furi_assert(app);
  126. app->on_clear = on_clear;
  127. app->context = context;
  128. }
  129. void xremote_app_user_context_free(XRemoteApp* app)
  130. {
  131. furi_assert(app);
  132. xremote_app_assert_void(app->context);
  133. xremote_app_assert_void(app->on_clear);
  134. app->on_clear(app->context);
  135. app->on_clear = NULL;
  136. app->context = NULL;
  137. }
  138. XRemoteApp* xremote_app_alloc(XRemoteAppContext *ctx)
  139. {
  140. furi_assert(ctx);
  141. XRemoteApp* app = malloc(sizeof(XRemoteApp));
  142. app->submenu_id = XRemoteViewNone;
  143. app->view_id = XRemoteViewNone;
  144. app->app_ctx = ctx;
  145. app->submenu = NULL;
  146. app->view_ctx = NULL;
  147. app->on_clear = NULL;
  148. app->context = NULL;
  149. return app;
  150. }
  151. void xremote_app_free(XRemoteApp* app)
  152. {
  153. xremote_app_assert_void(app);
  154. xremote_app_submenu_free(app);
  155. xremote_app_view_free(app);
  156. if (app->on_clear != NULL)
  157. app->on_clear(app->context);
  158. free(app);
  159. }