cligui_main.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #include "cligui_main_i.h"
  2. #include "cli_control.h"
  3. #include "text_input.h"
  4. #include "console_output.h"
  5. #include <loader/loader_i.h>
  6. static bool cligui_custom_event_cb(void* context, uint32_t event) {
  7. UNUSED(event);
  8. CliguiApp* app = context;
  9. UNUSED(app);
  10. return true;
  11. }
  12. static bool cligui_back_event_cb(void* context) {
  13. CliguiApp* app = context;
  14. UNUSED(app);
  15. return true;
  16. }
  17. static void cligui_tick_event_cb(void* context) {
  18. CliguiApp* app = context;
  19. size_t available = furi_stream_buffer_bytes_available(app->data->streams.app_rx);
  20. for(size_t i = 0; i < available; i++) {
  21. char c = 0;
  22. size_t len = furi_stream_buffer_receive(app->data->streams.app_rx, &c, 1, 100);
  23. if(len > 0) {
  24. furi_string_push_back(app->text_box_store, c);
  25. }
  26. }
  27. if(available > 0) {
  28. text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store));
  29. }
  30. // Set input header stuff
  31. size_t len = furi_string_size(app->text_box_store);
  32. size_t idx = len - 2;
  33. while(idx > 0) {
  34. if(furi_string_get_char(app->text_box_store, idx) == '\n') {
  35. idx++;
  36. break;
  37. }
  38. idx--;
  39. }
  40. text_input_set_header_text(app->text_input, furi_string_get_cstr(app->text_box_store) + idx);
  41. UNUSED(app);
  42. }
  43. ViewPortInputCallback prev_input_callback;
  44. volatile bool persistent_exit = false;
  45. static void input_callback_wrapper(InputEvent* event, void* context) {
  46. CliguiApp* app = context;
  47. if(event->type == InputTypeLong && event->key == InputKeyBack) {
  48. persistent_exit = false;
  49. view_dispatcher_stop(app->view_dispatcher);
  50. }
  51. if(event->type == InputTypeLong && event->key == InputKeyOk) {
  52. if(app->data->state == ViewConsoleOutput) {
  53. persistent_exit = true;
  54. view_dispatcher_stop(app->view_dispatcher);
  55. }
  56. }
  57. if(app->data->state == ViewTextInput) {
  58. text_input_input_handler(app, event);
  59. } else {
  60. console_output_input_handler(app, event);
  61. }
  62. prev_input_callback(event, app->view_dispatcher);
  63. }
  64. int32_t cligui_main(void* p) {
  65. UNUSED(p);
  66. // Unlock loader-lock and save app thread
  67. FuriThread* temp_save_appthr;
  68. Loader* loader = furi_record_open(RECORD_LOADER);
  69. temp_save_appthr = loader->app.thread;
  70. loader->app.thread = NULL;
  71. furi_record_close(RECORD_LOADER);
  72. CliguiApp* cligui = malloc(sizeof(CliguiApp));
  73. cligui->data = malloc(sizeof(CliguiData));
  74. latch_tx_handler();
  75. cligui->data->streams.app_tx = rx_stream;
  76. cligui->data->streams.app_rx = tx_stream;
  77. cligui->gui = furi_record_open(RECORD_GUI);
  78. cligui->view_dispatcher = view_dispatcher_alloc();
  79. cligui->view_dispatcher_i = (ViewDispatcher_internal*)(cligui->view_dispatcher);
  80. prev_input_callback =
  81. ((ViewPort_internal*)cligui->view_dispatcher_i->view_port)->input_callback;
  82. view_port_input_callback_set(
  83. cligui->view_dispatcher_i->view_port, input_callback_wrapper, cligui);
  84. view_dispatcher_enable_queue(cligui->view_dispatcher);
  85. view_dispatcher_set_event_callback_context(cligui->view_dispatcher, cligui);
  86. view_dispatcher_set_custom_event_callback(cligui->view_dispatcher, cligui_custom_event_cb);
  87. view_dispatcher_set_navigation_event_callback(cligui->view_dispatcher, cligui_back_event_cb);
  88. view_dispatcher_set_tick_event_callback(cligui->view_dispatcher, cligui_tick_event_cb, 100);
  89. view_dispatcher_attach_to_gui(
  90. cligui->view_dispatcher, cligui->gui, ViewDispatcherTypeFullscreen);
  91. view_dispatcher_send_to_front(cligui->view_dispatcher);
  92. cligui->text_box = text_box_alloc();
  93. view_dispatcher_add_view(
  94. cligui->view_dispatcher, ViewConsoleOutput, text_box_get_view(cligui->text_box));
  95. cligui->text_box_store = furi_string_alloc();
  96. furi_string_reserve(cligui->text_box_store, TEXT_BOX_STORE_SIZE);
  97. furi_string_set_char(cligui->text_box_store, 0, 0);
  98. text_box_set_text(cligui->text_box, furi_string_get_cstr(cligui->text_box_store));
  99. text_box_set_focus(cligui->text_box, TextBoxFocusEnd);
  100. cligui->text_input = text_input_alloc();
  101. text_input_set_result_callback(
  102. cligui->text_input,
  103. text_input_result_callback,
  104. cligui,
  105. cligui->text_input_store,
  106. TEXT_INPUT_STORE_SIZE,
  107. true);
  108. view_dispatcher_add_view(
  109. cligui->view_dispatcher, ViewTextInput, text_input_get_view(cligui->text_input));
  110. view_dispatcher_switch_to_view(cligui->view_dispatcher, ViewTextInput);
  111. cligui->data->state = ViewTextInput;
  112. view_dispatcher_run(cligui->view_dispatcher);
  113. view_dispatcher_remove_view(cligui->view_dispatcher, ViewConsoleOutput);
  114. view_dispatcher_remove_view(cligui->view_dispatcher, ViewTextInput);
  115. text_box_free(cligui->text_box);
  116. furi_string_free(cligui->text_box_store);
  117. text_input_free(cligui->text_input);
  118. view_dispatcher_free(cligui->view_dispatcher);
  119. unlatch_tx_handler(persistent_exit);
  120. furi_record_close(RECORD_GUI);
  121. free(cligui->data);
  122. free(cligui);
  123. // We restoring previous app thread here, we love kostily and velosipedy, bydlo kod forever!
  124. loader = furi_record_open(RECORD_LOADER);
  125. loader->app.thread = temp_save_appthr;
  126. furi_record_close(RECORD_LOADER);
  127. return 0;
  128. }