| 1 | // Aseprite |
| 2 | // Copyright (C) 2022 Igara Studio S.A. |
| 3 | // |
| 4 | // This program is distributed under the terms of |
| 5 | // the End-User License Agreement for Aseprite. |
| 6 | |
| 7 | #ifndef APP_UI_EDITOR_DELAYED_MOUSE_MOVE_STATE_H_INCLUDED |
| 8 | #define APP_UI_EDITOR_DELAYED_MOUSE_MOVE_STATE_H_INCLUDED |
| 9 | #pragma once |
| 10 | |
| 11 | #include "app/ui/editor/standby_state.h" |
| 12 | #include "ui/timer.h" |
| 13 | |
| 14 | #include <limits> |
| 15 | |
| 16 | namespace ui { |
| 17 | class MouseMessage; |
| 18 | } |
| 19 | |
| 20 | namespace app { |
| 21 | class Editor; |
| 22 | |
| 23 | class DelayedMouseMoveDelegate { |
| 24 | public: |
| 25 | virtual ~DelayedMouseMoveDelegate() { } |
| 26 | virtual void onCommitMouseMove(Editor* editor, |
| 27 | const gfx::PointF& spritePos) = 0; |
| 28 | }; |
| 29 | |
| 30 | // Helper class to group several onMouseMove() calls into one |
| 31 | // onCommitMouseMove(). Useful in Linux as mouse movement messages |
| 32 | // are queued a high speed (so we can group several mouse messages |
| 33 | // for tools that use only the last position and have a heavy |
| 34 | // calculation per mouse position, e.g. pixel transformations, |
| 35 | // drawing with Line, Rectangle, etc.). |
| 36 | class DelayedMouseMove { |
| 37 | public: |
| 38 | // The "interval" is given in milliseconds, and can be zero if we |
| 39 | // want to disable the delay between onMouseMove() -> onCommitMouseMove() |
| 40 | DelayedMouseMove(DelayedMouseMoveDelegate* delegate, |
| 41 | Editor* editor, |
| 42 | const int interval); |
| 43 | |
| 44 | // In case the event wasn't started with onMouseDown() we can |
| 45 | // initialize the sprite position directly (e.g. starting a line |
| 46 | // from last painted point with Shift+click with Pencil tool). |
| 47 | void initSpritePos(const gfx::PointF& pos); |
| 48 | |
| 49 | void onMouseDown(const ui::MouseMessage* msg); |
| 50 | bool onMouseMove(const ui::MouseMessage* msg); |
| 51 | void onMouseUp(const ui::MouseMessage* msg); |
| 52 | |
| 53 | // Forces stopping the timer so we don't receive a Tick event in |
| 54 | // case that we've just removed/delete some structure that is |
| 55 | // needed in onCommitMouseMove(). |
| 56 | void stopTimer(); |
| 57 | |
| 58 | const gfx::PointF& spritePos() const; |
| 59 | |
| 60 | private: |
| 61 | void commitMouseMove(); |
| 62 | bool updateSpritePos(const ui::MouseMessage* msg); |
| 63 | |
| 64 | DelayedMouseMoveDelegate* m_delegate; |
| 65 | Editor* m_editor; |
| 66 | ui::Timer m_timer; |
| 67 | |
| 68 | // Position of the mouse in the canvas to avoid redrawing when the |
| 69 | // mouse position changes (only we redraw when the canvas position |
| 70 | // changes). |
| 71 | gfx::PointF m_spritePos; |
| 72 | }; |
| 73 | |
| 74 | } // namespace app |
| 75 | |
| 76 | #endif // APP_UI_EDITOR_DELAYED_MOUSE_MOVE_STATE_H_INCLUDED |
| 77 | |