paint.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #include <furi.h>
  2. #include <furi_hal.h>
  3. #include <gui/gui.h>
  4. #include <input/input.h>
  5. #include <notification/notification.h>
  6. #include <notification/notification_messages.h>
  7. #include <stdbool.h> // Header-file for boolean data-type.
  8. typedef struct selected_position {
  9. int x;
  10. int y;
  11. } selected_position;
  12. typedef struct {
  13. FuriMutex* mutex;
  14. selected_position selected;
  15. bool board[32][16];
  16. bool isDrawing;
  17. } PaintData;
  18. void paint_draw_callback(Canvas* canvas, void* ctx) {
  19. furi_assert(ctx);
  20. const PaintData* paint_state = ctx;
  21. furi_mutex_acquire(paint_state->mutex, FuriWaitForever);
  22. canvas_clear(canvas);
  23. canvas_set_color(canvas, ColorBlack);
  24. //draw the canvas(32x16) on screen(144x64) using 4x4 tiles
  25. for(int y = 0; y < 16; y++) {
  26. for(int x = 0; x < 32; x++) {
  27. if(paint_state->board[x][y]) {
  28. canvas_draw_box(canvas, x * 4, y * 4, 4, 4);
  29. }
  30. }
  31. }
  32. //draw cursor as a 4x4 black box with a 2x2 white box inside
  33. canvas_set_color(canvas, ColorBlack);
  34. canvas_draw_box(canvas, paint_state->selected.x * 4, paint_state->selected.y * 4, 4, 4);
  35. canvas_set_color(canvas, ColorWhite);
  36. canvas_draw_box(
  37. canvas, paint_state->selected.x * 4 + 1, paint_state->selected.y * 4 + 1, 2, 2);
  38. //release the mutex
  39. furi_mutex_release(paint_state->mutex);
  40. }
  41. void paint_input_callback(InputEvent* input_event, void* ctx) {
  42. furi_assert(ctx);
  43. FuriMessageQueue* event_queue = ctx;
  44. furi_message_queue_put(event_queue, input_event, FuriWaitForever);
  45. }
  46. int32_t paint_app(void* p) {
  47. UNUSED(p);
  48. FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
  49. PaintData* paint_state = malloc(sizeof(PaintData));
  50. paint_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
  51. if(!paint_state->mutex) {
  52. FURI_LOG_E("paint", "cannot create mutex\r\n");
  53. free(paint_state);
  54. return -1;
  55. }
  56. // Configure view port
  57. ViewPort* view_port = view_port_alloc();
  58. view_port_draw_callback_set(view_port, paint_draw_callback, paint_state);
  59. view_port_input_callback_set(view_port, paint_input_callback, event_queue);
  60. // Register view port in GUI
  61. Gui* gui = furi_record_open(RECORD_GUI);
  62. gui_add_view_port(gui, view_port, GuiLayerFullscreen);
  63. //NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
  64. InputEvent event;
  65. while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) {
  66. //break out of the loop if the back key is pressed
  67. if(event.type == InputTypeShort && event.key == InputKeyBack) {
  68. break;
  69. }
  70. //check the key pressed and change x and y accordingly
  71. if(event.type == InputTypeShort) {
  72. switch(event.key) {
  73. case InputKeyUp:
  74. paint_state->selected.y -= 1;
  75. break;
  76. case InputKeyDown:
  77. paint_state->selected.y += 1;
  78. break;
  79. case InputKeyLeft:
  80. paint_state->selected.x -= 1;
  81. break;
  82. case InputKeyRight:
  83. paint_state->selected.x += 1;
  84. break;
  85. case InputKeyOk:
  86. paint_state->board[paint_state->selected.x][paint_state->selected.y] =
  87. !paint_state->board[paint_state->selected.x][paint_state->selected.y];
  88. break;
  89. default:
  90. break;
  91. }
  92. //check if cursor position is out of bounds and reset it to the closest position
  93. if(paint_state->selected.x < 0) {
  94. paint_state->selected.x = 0;
  95. }
  96. if(paint_state->selected.x > 31) {
  97. paint_state->selected.x = 31;
  98. }
  99. if(paint_state->selected.y < 0) {
  100. paint_state->selected.y = 0;
  101. }
  102. if(paint_state->selected.y > 15) {
  103. paint_state->selected.y = 15;
  104. }
  105. if(paint_state->isDrawing == true) {
  106. paint_state->board[paint_state->selected.x][paint_state->selected.y] = true;
  107. }
  108. view_port_update(view_port);
  109. }
  110. if(event.key == InputKeyBack && event.type == InputTypeLong) {
  111. paint_state->board[1][1] = true;
  112. for(int y = 0; y < 16; y++) {
  113. for(int x = 0; x < 32; x++) {
  114. paint_state->board[x][y] = false;
  115. }
  116. }
  117. view_port_update(view_port);
  118. }
  119. if(event.key == InputKeyOk && event.type == InputTypeLong) {
  120. paint_state->isDrawing = !paint_state->isDrawing;
  121. paint_state->board[paint_state->selected.x][paint_state->selected.y] = true;
  122. view_port_update(view_port);
  123. }
  124. }
  125. gui_remove_view_port(gui, view_port);
  126. view_port_free(view_port);
  127. furi_message_queue_free(event_queue);
  128. furi_mutex_free(paint_state->mutex);
  129. furi_record_close(RECORD_NOTIFICATION);
  130. furi_record_close(RECORD_GUI);
  131. free(paint_state);
  132. return 0;
  133. }