1 // Aseprite
2 // Copyright (C) 2017 David Capello
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/moving_slice_state.h"
12
13 #include "app/cmd/set_slice_key.h"
14 #include "app/context_access.h"
15 #include "app/transaction.h"
16 #include "app/ui/editor/editor.h"
17 #include "app/ui/status_bar.h"
18 #include "app/ui_context.h"
19 #include "doc/slice.h"
20 #include "ui/message.h"
21
22 #include <cmath>
23
24 namespace app {
25
26 using namespace ui;
27
MovingSliceState(Editor * editor,MouseMessage * msg,const EditorHit & hit)28 MovingSliceState::MovingSliceState(Editor* editor, MouseMessage* msg,
29 const EditorHit& hit)
30 : m_hit(hit)
31 {
32 m_mouseStart = editor->screenToEditor(msg->position());
33
34 auto keyPtr = m_hit.slice()->getByFrame(editor->frame());
35 ASSERT(keyPtr);
36 if (keyPtr)
37 m_keyStart = m_key = *keyPtr;
38
39 editor->captureMouse();
40 }
41
onMouseUp(Editor * editor,MouseMessage * msg)42 bool MovingSliceState::onMouseUp(Editor* editor, MouseMessage* msg)
43 {
44 {
45 ContextWriter writer(UIContext::instance(), 1000);
46 Transaction transaction(writer.context(), "Slice Movement", ModifyDocument);
47
48 doc::SliceKey newKey = m_key;
49 m_hit.slice()->insert(editor->frame(), m_keyStart);
50
51 transaction.execute(new cmd::SetSliceKey(m_hit.slice(),
52 editor->frame(),
53 newKey));
54 transaction.commit();
55 }
56
57 editor->backToPreviousState();
58 editor->releaseMouse();
59 return true;
60 }
61
onMouseMove(Editor * editor,MouseMessage * msg)62 bool MovingSliceState::onMouseMove(Editor* editor, MouseMessage* msg)
63 {
64 gfx::Point newCursorPos = editor->screenToEditor(msg->position());
65 gfx::Point delta = newCursorPos - m_mouseStart;
66
67 m_key = m_keyStart;
68 gfx::Rect rc =
69 (m_hit.type() == EditorHit::SliceCenter ? m_key.center():
70 m_key.bounds());
71
72 // Move slice
73 if (m_hit.border() == (CENTER | MIDDLE)) {
74 rc.x += delta.x;
75 rc.y += delta.y;
76 }
77 else {
78 if (m_hit.border() & LEFT) {
79 rc.x += delta.x;
80 rc.w -= delta.x;
81 if (rc.w < 1) {
82 rc.x += rc.w-1;
83 rc.w = 1;
84 }
85 }
86 if (m_hit.border() & TOP) {
87 rc.y += delta.y;
88 rc.h -= delta.y;
89 if (rc.h < 1) {
90 rc.y += rc.h-1;
91 rc.h = 1;
92 }
93 }
94 if (m_hit.border() & RIGHT) {
95 rc.w += delta.x;
96 if (rc.w < 1)
97 rc.w = 1;
98 }
99 if (m_hit.border() & BOTTOM) {
100 rc.h += delta.y;
101 if (rc.h < 1)
102 rc.h = 1;
103 }
104 }
105
106 if (m_hit.type() == EditorHit::SliceCenter)
107 m_key.setCenter(rc);
108 else
109 m_key.setBounds(rc);
110
111 // Update the slice key
112 m_hit.slice()->insert(editor->frame(), m_key);
113
114 // Redraw the editor.
115 editor->invalidate();
116
117 // Use StandbyState implementation
118 return StandbyState::onMouseMove(editor, msg);
119 }
120
onSetCursor(Editor * editor,const gfx::Point & mouseScreenPos)121 bool MovingSliceState::onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos)
122 {
123 switch (m_hit.border()) {
124 case TOP | LEFT:
125 editor->showMouseCursor(kSizeNWCursor);
126 break;
127 case TOP:
128 editor->showMouseCursor(kSizeNCursor);
129 break;
130 case TOP | RIGHT:
131 editor->showMouseCursor(kSizeNECursor);
132 break;
133 case LEFT:
134 editor->showMouseCursor(kSizeWCursor);
135 break;
136 case RIGHT:
137 editor->showMouseCursor(kSizeECursor);
138 break;
139 case BOTTOM | LEFT:
140 editor->showMouseCursor(kSizeSWCursor);
141 break;
142 case BOTTOM:
143 editor->showMouseCursor(kSizeSCursor);
144 break;
145 case BOTTOM | RIGHT:
146 editor->showMouseCursor(kSizeSECursor);
147 break;
148 }
149 return true;
150 }
151
152 } // namespace app
153