flipp_pomodoro_timer_view.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #include "flipp_pomodoro_timer_view.h"
  2. #include <furi.h>
  3. #include <gui/gui.h>
  4. #include <gui/elements.h>
  5. #include <gui/view.h>
  6. #include "../helpers/debug.h"
  7. #include "../flipp_pomodoro_app.h"
  8. #include "../modules/flipp_pomodoro.h"
  9. // Auto-compiled icons
  10. #include "flipp_pomodoro_icons.h"
  11. enum
  12. {
  13. ViewInputConsumed = true,
  14. ViewInputNotConusmed = false,
  15. };
  16. struct FlippPomodoroTimerView
  17. {
  18. View *view;
  19. FlippPomodoroTimerViewInputCb right_cb;
  20. void *right_cb_ctx;
  21. };
  22. typedef struct
  23. {
  24. IconAnimation *icon;
  25. FlippPomodoroState *state;
  26. } FlippPomodoroTimerViewModel;
  27. static const Icon *stage_background_image[] = {
  28. [Work] = &A_flipp_pomodoro_focus_64,
  29. [Rest] = &A_flipp_pomodoro_rest_64,
  30. };
  31. static void flipp_pomodoro_view_timer_draw_countdown(Canvas *canvas, TimeDifference remaining_time)
  32. {
  33. canvas_set_font(canvas, FontBigNumbers);
  34. const uint8_t right_border_margin = 1;
  35. const uint8_t countdown_box_height = canvas_height(canvas) * 0.4;
  36. const uint8_t countdown_box_width = canvas_width(canvas) * 0.5;
  37. const uint8_t countdown_box_x = canvas_width(canvas) - countdown_box_width - right_border_margin;
  38. const uint8_t countdown_box_y = 0;
  39. elements_bold_rounded_frame(canvas,
  40. countdown_box_x,
  41. countdown_box_y,
  42. countdown_box_width,
  43. countdown_box_height);
  44. FuriString *timer_string = furi_string_alloc();
  45. furi_string_printf(timer_string, "%02u:%02u", remaining_time.minutes, remaining_time.seconds);
  46. const char *remaining_stage_time_string = furi_string_get_cstr(timer_string);
  47. canvas_draw_str_aligned(
  48. canvas,
  49. countdown_box_x + (countdown_box_width / 2),
  50. countdown_box_y + (countdown_box_height / 2),
  51. AlignCenter,
  52. AlignCenter,
  53. remaining_stage_time_string);
  54. furi_string_free(timer_string);
  55. };
  56. static void flipp_pomodoro_view_timer_draw_callback(Canvas *canvas, void *_model)
  57. {
  58. if (!_model)
  59. {
  60. return;
  61. };
  62. FlippPomodoroTimerViewModel *model = _model;
  63. canvas_clear(canvas);
  64. if (model->icon)
  65. {
  66. canvas_draw_icon_animation(canvas, 0, 0, model->icon);
  67. }
  68. flipp_pomodoro_view_timer_draw_countdown(
  69. canvas,
  70. flipp_pomodoro__stage_remaining_duration(model->state));
  71. canvas_set_font(canvas, FontSecondary);
  72. elements_button_right(canvas, flipp_pomodoro__next_stage_label(model->state));
  73. };
  74. bool flipp_pomodoro_view_timer_input_callback(InputEvent *event, void *ctx)
  75. {
  76. furi_assert(ctx);
  77. furi_assert(event);
  78. FlippPomodoroTimerView *timer = ctx;
  79. const bool should_trigger_right_event_cb = (event->type == InputTypePress) &&
  80. (event->key == InputKeyRight) &&
  81. (timer->right_cb != NULL);
  82. if (should_trigger_right_event_cb)
  83. {
  84. furi_assert(timer->right_cb);
  85. furi_assert(timer->right_cb_ctx);
  86. timer->right_cb(timer->right_cb_ctx);
  87. return ViewInputConsumed;
  88. };
  89. return ViewInputNotConusmed;
  90. };
  91. View *flipp_pomodoro_view_timer_get_view(FlippPomodoroTimerView *timer)
  92. {
  93. furi_assert(timer);
  94. return timer->view;
  95. };
  96. void flipp_pomodoro_view_timer_assign_animation(View *view)
  97. {
  98. with_view_model(
  99. view,
  100. FlippPomodoroTimerViewModel * model,
  101. {
  102. furi_assert(model->state);
  103. if (model->icon)
  104. {
  105. icon_animation_free(model->icon);
  106. }
  107. model->icon = icon_animation_alloc(
  108. stage_background_image[flipp_pomodoro__get_stage(model->state)]);
  109. view_tie_icon_animation(view, model->icon);
  110. icon_animation_start(model->icon);
  111. },
  112. true);
  113. }
  114. FlippPomodoroTimerView *flipp_pomodoro_view_timer_alloc()
  115. {
  116. FlippPomodoroTimerView *timer = malloc(sizeof(FlippPomodoroTimerView));
  117. timer->view = view_alloc();
  118. view_allocate_model(timer->view, ViewModelTypeLockFree, sizeof(FlippPomodoroTimerViewModel));
  119. view_set_context(flipp_pomodoro_view_timer_get_view(timer), timer);
  120. view_set_draw_callback(timer->view, flipp_pomodoro_view_timer_draw_callback);
  121. view_set_input_callback(timer->view, flipp_pomodoro_view_timer_input_callback);
  122. return timer;
  123. };
  124. void flipp_pomodoro_view_timer_set_on_right_cb(FlippPomodoroTimerView *timer, FlippPomodoroTimerViewInputCb right_cb, void *right_cb_ctx)
  125. {
  126. furi_assert(right_cb);
  127. furi_assert(right_cb_ctx);
  128. timer->right_cb = right_cb;
  129. timer->right_cb_ctx = right_cb_ctx;
  130. };
  131. void flipp_pomodoro_view_timer_set_state(View *view, FlippPomodoroState *state)
  132. {
  133. furi_assert(view);
  134. furi_assert(state);
  135. with_view_model(
  136. view,
  137. FlippPomodoroTimerViewModel * model,
  138. {
  139. model->state = state;
  140. },
  141. false);
  142. flipp_pomodoro_view_timer_assign_animation(view);
  143. };
  144. void flipp_pomodoro_view_timer_free(FlippPomodoroTimerView *timer)
  145. {
  146. furi_assert(timer);
  147. with_view_model(
  148. timer->view,
  149. FlippPomodoroTimerViewModel * model,
  150. {
  151. icon_animation_free(model->icon);
  152. },
  153. false);
  154. view_free(timer->view);
  155. free(timer);
  156. };