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#ifdef HAVE_CONFIG_H
8#include "config.h"
9#endif
10
11#include "app/ui/editor/delayed_mouse_move.h"
12
13#include "app/ui/editor/editor.h"
14
15namespace app {
16
17DelayedMouseMove::DelayedMouseMove(DelayedMouseMoveDelegate* delegate,
18 Editor* editor,
19 const int interval)
20 : m_delegate(delegate)
21 , m_editor(editor)
22 , m_timer(interval)
23 , m_spritePos(std::numeric_limits<double>::min(),
24 std::numeric_limits<double>::min())
25{
26 ASSERT(m_delegate);
27 m_timer.Tick.connect([this] { commitMouseMove(); });
28}
29
30void DelayedMouseMove::initSpritePos(const gfx::PointF& pos)
31{
32 m_spritePos = pos;
33}
34
35void DelayedMouseMove::onMouseDown(const ui::MouseMessage* msg)
36{
37 updateSpritePos(msg);
38}
39
40bool DelayedMouseMove::onMouseMove(const ui::MouseMessage* msg)
41{
42 if (!updateSpritePos(msg))
43 return false;
44
45 if (!m_timer.isRunning()) {
46 if (m_timer.interval() > 0) {
47 m_timer.start();
48 }
49 else {
50 // Commit immediately
51 commitMouseMove();
52 }
53 }
54 return true;
55}
56
57void DelayedMouseMove::onMouseUp(const ui::MouseMessage* msg)
58{
59 if (updateSpritePos(msg))
60 commitMouseMove();
61}
62
63void DelayedMouseMove::stopTimer()
64{
65 if (m_timer.isRunning())
66 m_timer.stop();
67}
68
69void DelayedMouseMove::commitMouseMove()
70{
71 if (m_timer.isRunning())
72 m_timer.stop();
73
74 m_delegate->onCommitMouseMove(m_editor, spritePos());
75}
76
77const gfx::PointF& DelayedMouseMove::spritePos() const
78{
79 ASSERT(m_spritePos.x != std::numeric_limits<double>::min() &&
80 m_spritePos.y != std::numeric_limits<double>::min());
81 return m_spritePos;
82}
83
84bool DelayedMouseMove::updateSpritePos(const ui::MouseMessage* msg)
85{
86 // The autoScroll() function controls the "infinite scroll" when we
87 // touch the viewport borders.
88 const gfx::Point mousePos = m_editor->autoScroll(msg, AutoScroll::MouseDir);
89 const gfx::PointF spritePos = m_editor->screenToEditorF(mousePos);
90
91 // Avoid redrawing everything if the position in the canvas didn't
92 // change.
93 if (m_spritePos != spritePos) {
94 m_spritePos = spritePos;
95 return true;
96 }
97 else
98 return false;
99}
100
101} // namespace app
102