xremote_common_view.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*!
  2. * @file flipper-xremote/views/xremote_common_view.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 Common view and canvas functionality shared between the pages.
  7. */
  8. #include "xremote_common_view.h"
  9. #include "../infrared/infrared_remote.h"
  10. #include "../xremote_app.h"
  11. struct XRemoteView {
  12. XRemoteViewClearCallback on_clear;
  13. NotificationApp* notifications;
  14. View* view;
  15. void *context;
  16. };
  17. const NotificationSequence g_sequence_blink_purple_50 = {
  18. &message_red_255,
  19. &message_blue_255,
  20. &message_delay_50,
  21. NULL,
  22. };
  23. XRemoteView* xremote_view_alloc(NotificationApp* notifications, ViewInputCallback input_cb, ViewDrawCallback draw_cb)
  24. {
  25. XRemoteView* remote_view = malloc(sizeof(XRemoteView));
  26. remote_view->view = view_alloc();
  27. remote_view->notifications = notifications;
  28. remote_view->context = NULL;
  29. remote_view->on_clear = NULL;
  30. view_set_orientation(remote_view->view, ViewOrientationVertical);
  31. view_allocate_model(remote_view->view, ViewModelTypeLocking, sizeof(XRemoteViewModel));
  32. view_set_input_callback(remote_view->view, input_cb);
  33. view_set_draw_callback(remote_view->view, draw_cb);
  34. view_set_context(remote_view->view, remote_view);
  35. return remote_view;
  36. }
  37. void xremote_view_clear_context(XRemoteView* rview)
  38. {
  39. furi_assert(rview);
  40. if (rview->context != NULL &&
  41. rview->on_clear != NULL)
  42. {
  43. rview->on_clear(rview->context);
  44. rview->context = NULL;
  45. }
  46. }
  47. void xremote_view_set_context(XRemoteView* rview, void *context, XRemoteViewClearCallback on_clear)
  48. {
  49. furi_assert(rview);
  50. xremote_view_clear_context(rview);
  51. rview->context = context;
  52. rview->on_clear = on_clear;
  53. }
  54. void* xremote_view_get_context(XRemoteView* rview)
  55. {
  56. furi_assert(rview);
  57. return rview->context;
  58. }
  59. void xremote_view_free(XRemoteView* rview)
  60. {
  61. furi_assert(rview);
  62. xremote_view_clear_context(rview);
  63. view_free(rview->view);
  64. free(rview);
  65. }
  66. View* xremote_view_get_view(XRemoteView* rview)
  67. {
  68. furi_assert(rview);
  69. return rview->view;
  70. }
  71. static InfraredRemoteButton* xremote_view_get_button_by_name(XRemoteView *rview, const char* name)
  72. {
  73. xremote_app_assert(rview->context, NULL);
  74. InfraredRemote* remote = (InfraredRemote*)rview->context;
  75. return infrared_remote_get_button_by_name(remote, name);
  76. }
  77. void xremote_view_send_ir(XRemoteView *rview, const char *name)
  78. {
  79. InfraredRemoteButton* button = xremote_view_get_button_by_name(rview, name);
  80. xremote_app_assert_void(button);
  81. InfraredSignal* signal = infrared_remote_button_get_signal(button);
  82. xremote_app_assert_void(signal);
  83. infrared_signal_transmit(signal);
  84. notification_message(rview->notifications, &g_sequence_blink_purple_50);
  85. }
  86. void xremote_canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, XRemoteIcon icon)
  87. {
  88. if (icon == XRemoteIconEnter)
  89. {
  90. canvas_draw_circle(canvas, x - 2, y, 4);
  91. canvas_draw_disc(canvas, x - 2, y, 2);
  92. }
  93. else if (icon == XRemoteIconBack)
  94. {
  95. canvas_draw_triangle(canvas, x - 4, y - 2, 5, 3, CanvasDirectionRightToLeft);
  96. canvas_draw_line(canvas, x + 1, y - 2, x - 5, y - 2);
  97. canvas_draw_line(canvas, x + 1, y + 3, x - 3, y + 3);
  98. canvas_draw_line(canvas, x + 3, y + 1, x + 2, y + 2);
  99. canvas_draw_line(canvas, x + 3, y, x + 2, y - 1);
  100. }
  101. else if (icon == XRemoteIconArrowUp)
  102. {
  103. canvas_draw_triangle(canvas, x - 2, y - 2, 5, 3, CanvasDirectionBottomToTop);
  104. canvas_draw_line(canvas, x - 2, y - 3, x - 2, y + 4);
  105. }
  106. else if (icon == XRemoteIconArrowDown)
  107. {
  108. canvas_draw_triangle(canvas, x - 2, y + 2, 5, 3, CanvasDirectionTopToBottom);
  109. canvas_draw_line(canvas, x - 2, y - 4, x - 2, y + 3);
  110. }
  111. else if (icon == XRemoteIconArrowLeft)
  112. {
  113. canvas_draw_triangle(canvas, x - 4, y, 5, 3, CanvasDirectionRightToLeft);
  114. canvas_draw_line(canvas, x + 2, y, x - 5, y);
  115. }
  116. else if (icon == XRemoteIconArrowRight)
  117. {
  118. canvas_draw_triangle(canvas, x, y, 5, 3, CanvasDirectionLeftToRight);
  119. canvas_draw_line(canvas, x - 6, y, x + 1, y);
  120. }
  121. else if (icon == XRemoteIconJumpForward)
  122. {
  123. canvas_draw_triangle(canvas, x - 2, y, 5, 3, CanvasDirectionLeftToRight);
  124. canvas_draw_triangle(canvas, x - 5, y, 5, 3, CanvasDirectionLeftToRight);
  125. canvas_draw_line(canvas, x + 1, y - 2, x + 1, y + 2);
  126. canvas_draw_line(canvas, x - 4, y, x, y);
  127. }
  128. else if (icon == XRemoteIconJumpBackward)
  129. {
  130. canvas_draw_triangle(canvas, x - 2, y, 5, 3, CanvasDirectionRightToLeft);
  131. canvas_draw_triangle(canvas, x + 1, y, 5, 3, CanvasDirectionRightToLeft);
  132. canvas_draw_line(canvas, x - 5, y - 2, x - 5, y + 2);
  133. canvas_draw_line(canvas, x, y, x - 4, y);
  134. }
  135. else if (icon == XRemoteIconFastForward)
  136. {
  137. canvas_draw_triangle(canvas, x - 1, y, 5, 3, CanvasDirectionLeftToRight);
  138. canvas_draw_triangle(canvas, x - 4, y, 5, 3, CanvasDirectionLeftToRight);
  139. canvas_draw_line(canvas, x - 3, y, x, y);
  140. }
  141. else if (icon == XRemoteIconFastBackward)
  142. {
  143. canvas_draw_triangle(canvas, x - 3, y, 5, 3, CanvasDirectionRightToLeft);
  144. canvas_draw_triangle(canvas, x, y, 5, 3, CanvasDirectionRightToLeft);
  145. canvas_draw_line(canvas, x - 1, y, x - 4, y);
  146. }
  147. else if (icon == XRemoteIconPlayPause)
  148. {
  149. canvas_draw_triangle(canvas, x - 5, y, 5, 3, CanvasDirectionLeftToRight);
  150. canvas_draw_dot(canvas, x - 4, y);
  151. canvas_draw_line(canvas, x - 1, y - 2, x - 1, y + 2);
  152. canvas_draw_line(canvas, x + 1, y - 2, x + 1, y + 2);
  153. }
  154. else if (icon == XRemoteIconPlay)
  155. {
  156. canvas_draw_triangle(canvas, x - 3, y, 5, 3, CanvasDirectionLeftToRight);
  157. canvas_draw_dot(canvas, x - 2, y);
  158. }
  159. else if (icon == XRemoteIconPause)
  160. {
  161. canvas_draw_line(canvas, x - 3, y - 2, x - 3, y + 2);
  162. canvas_draw_line(canvas, x - 1, y - 2, x - 1, y + 2);
  163. }
  164. else if (icon == XRemoteIconStop)
  165. {
  166. canvas_draw_box(canvas, x - 4, y - 2, 5, 5);
  167. }
  168. else if (icon == XRemoteIconOk)
  169. {
  170. canvas_draw_str(canvas, x - 7, y + 4, "OK");
  171. }
  172. }
  173. void xremote_canvas_draw_header(Canvas* canvas, const char* section)
  174. {
  175. canvas_set_font(canvas, FontPrimary);
  176. elements_multiline_text_aligned(canvas, 0, 0, AlignLeft, AlignTop, "XRemote");
  177. canvas_set_font(canvas, FontSecondary);
  178. canvas_draw_str(canvas, 0, 20, section);
  179. }
  180. void xremote_canvas_draw_exit_footer(Canvas* canvas, char *text)
  181. {
  182. canvas_set_font(canvas, FontSecondary);
  183. xremote_canvas_draw_icon(canvas, 6, 124, XRemoteIconBack);
  184. canvas_draw_str(canvas, 12, 128, text);
  185. }
  186. void xremote_canvas_draw_button(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, XRemoteIcon icon)
  187. {
  188. canvas_draw_icon(canvas, x, y, &I_Button_18x18);
  189. if (pressed)
  190. {
  191. elements_slightly_rounded_box(canvas, x + 3, y + 2, 13, 13);
  192. canvas_set_color(canvas, ColorWhite);
  193. }
  194. xremote_canvas_draw_icon(canvas, x + 11, y + 8, icon);
  195. canvas_set_color(canvas, ColorBlack);
  196. }
  197. void xremote_canvas_draw_button_wide(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, char* text, XRemoteIcon icon)
  198. {
  199. (void)icon;
  200. elements_slightly_rounded_frame(canvas, x + 4, y, 56, 15);
  201. if (pressed)
  202. {
  203. elements_slightly_rounded_box(canvas, x + 6, y + 2, 52, 11);
  204. canvas_set_color(canvas, ColorWhite);
  205. }
  206. xremote_canvas_draw_icon(canvas, x + 15, y + 7, icon);
  207. elements_multiline_text_aligned(canvas, x + 22, y + 10, AlignLeft, AlignBottom, text);
  208. canvas_set_color(canvas, ColorBlack);
  209. }
  210. void xremote_canvas_draw_frame(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, uint8_t xl, const char *text)
  211. {
  212. elements_slightly_rounded_frame(canvas, x, y, xl, 15);
  213. if (pressed)
  214. {
  215. elements_slightly_rounded_box(canvas, x + 2, y + 2, xl - 4, 11);
  216. canvas_set_color(canvas, ColorWhite);
  217. }
  218. canvas_draw_str(canvas, x + 3, y + 11, text);
  219. canvas_set_color(canvas, ColorBlack);
  220. }