1 /*
2 * Copyright (C) 2020 Damir Porobic <damir.porobic@gmx.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include "SnippingAreaResizer.h"
21
SnippingAreaResizer(KsnipConfig * config,QObject * parent)22 SnippingAreaResizer::SnippingAreaResizer(KsnipConfig *config, QObject *parent) :
23 QObject(parent),
24 mConfig(config),
25 mIsActive(false),
26 mIsGrabbed(false),
27 mGrabbedHandleIndex(-1),
28 mControlPressed(false),
29 mAltPressed(false)
30 {
31
32 const auto width = 15;
33 mHandles.append(QRectF(0, 0, width, width));
34 mHandles.append(QRectF(0, 0, width, width));
35 mHandles.append(QRectF(0, 0, width, width));
36 mHandles.append(QRectF(0, 0, width, width));
37 mHandles.append(QRectF(0, 0, width, width));
38 mHandles.append(QRectF(0, 0, width, width));
39 mHandles.append(QRectF(0, 0, width, width));
40 mHandles.append(QRectF(0, 0, width, width));
41 }
42
activate(const QRectF & rect,const QPointF & pos)43 void SnippingAreaResizer::activate(const QRectF &rect, const QPointF &pos)
44 {
45 mIsActive = true;
46 mCurrentRect = rect;
47 mColor = mConfig->snippingAdornerColor();
48 updateHandlePositions();
49 updateCursor(pos.toPoint());
50 }
51
deactivate()52 void SnippingAreaResizer::deactivate()
53 {
54 mIsActive = false;
55 mIsGrabbed = false;
56 mGrabbedHandleIndex = -1;
57 }
58
paint(QPainter * painter)59 void SnippingAreaResizer::paint(QPainter *painter)
60 {
61 if(mIsActive) {
62 painter->setRenderHint(QPainter::Antialiasing);
63 painter->setBrush(Qt::NoBrush);
64 painter->setPen(QPen(mColor, 2, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin));
65 painter->drawRect(mCurrentRect);
66 painter->setBrush(mColor);
67 for(const auto handle : mHandles) {
68 painter->drawEllipse(handle);
69 }
70 }
71 }
72
isActive() const73 bool SnippingAreaResizer::isActive() const
74 {
75 return mIsActive;
76 }
77
handleMousePress(QMouseEvent * event)78 void SnippingAreaResizer::handleMousePress(QMouseEvent *event)
79 {
80 if(mIsActive) {
81 auto pos = event->pos();
82 for(const auto handle : mHandles) {
83 if(handle.contains(pos)) {
84 mIsGrabbed = true;
85 mGrabOffset = pos - handle.center();
86 mGrabbedHandleIndex = mHandles.indexOf(handle);
87 break;
88 }
89 }
90
91 if(!mIsGrabbed && mCurrentRect.contains(pos)) {
92 mIsGrabbed = true;
93 mGrabOffset = pos - mCurrentRect.topLeft();
94 }
95 }
96 }
97
handleMouseRelease(QMouseEvent * event)98 void SnippingAreaResizer::handleMouseRelease(QMouseEvent *event)
99 {
100 Q_UNUSED(event)
101
102 if(mIsActive && mIsGrabbed) {
103 mIsGrabbed = false;
104 mGrabOffset = {};
105 mGrabbedHandleIndex = -1;
106 }
107 }
108
handleMouseMove(QMouseEvent * event)109 void SnippingAreaResizer::handleMouseMove(QMouseEvent *event)
110 {
111 if (mIsActive) {
112 if (mIsGrabbed) {
113 updateCurrentRect(event->pos());
114 } else {
115 updateCursor(event->pos());
116 }
117 }
118 }
119
handleKeyPress(QKeyEvent * event)120 void SnippingAreaResizer::handleKeyPress(QKeyEvent *event)
121 {
122 if (event->key() == Qt::Key_Control) {
123 mControlPressed = true;
124 } else if (event->key() == Qt::Key_Alt) {
125 mAltPressed = true;
126 }
127
128 if (mIsActive) {
129 arrowKeyPressed(event);
130 notifyRectChanged();
131 }
132 }
133
arrowKeyPressed(const QKeyEvent * event)134 void SnippingAreaResizer::arrowKeyPressed(const QKeyEvent *event)
135 {
136 if (event->key() == Qt::Key_Up) {
137 arrowUpPressed();
138 } else if (event->key() == Qt::Key_Down) {
139 arrowDownPressed();
140 } else if (event->key() == Qt::Key_Left) {
141 arrowLeftPressed();
142 } else if (event->key() == Qt::Key_Right) {
143 arrowRightPressed();
144 }
145 }
146
handleKeyRelease(QKeyEvent * event)147 void SnippingAreaResizer::handleKeyRelease(QKeyEvent *event)
148 {
149 if(event->key() == Qt::Key_Control) {
150 mControlPressed = false;
151 } else if(event->key() == Qt::Key_Alt) {
152 mAltPressed = false;
153 }
154 }
155
updateCursor(const QPoint & pos)156 void SnippingAreaResizer::updateCursor(const QPoint &pos)
157 {
158 if (mHandles[1].contains(pos) || mHandles[5].contains(pos)) {
159 emit cursorChanged(Qt::SizeVerCursor);
160 } else if (mHandles[3].contains(pos) || mHandles[7].contains(pos)) {
161 emit cursorChanged(Qt::SizeHorCursor);
162 } else if (mHandles[0].contains(pos) || mHandles[2].contains(pos) || mHandles[4].contains(pos) || mHandles[6].contains(pos) || mCurrentRect.contains(pos)) {
163 emit cursorChanged(Qt::SizeAllCursor);
164 } else {
165 emit cursorChanged(Qt::ArrowCursor);
166 }
167 }
168
updateCurrentRect(const QPoint & point)169 void SnippingAreaResizer::updateCurrentRect(const QPoint &point)
170 {
171 if(mGrabbedHandleIndex == -1){
172 mCurrentRect.moveTo(point - mGrabOffset);
173 } else if(mGrabbedHandleIndex == 0){
174 mCurrentRect.setTopLeft(point - mGrabOffset);
175 } else if(mGrabbedHandleIndex == 1){
176 mCurrentRect.setTop((point - mGrabOffset).y());
177 } else if(mGrabbedHandleIndex == 2){
178 mCurrentRect.setTopRight(point - mGrabOffset);
179 } else if(mGrabbedHandleIndex == 3){
180 mCurrentRect.setRight((point - mGrabOffset).x());
181 } else if(mGrabbedHandleIndex == 4){
182 mCurrentRect.setBottomRight(point - mGrabOffset);
183 } else if(mGrabbedHandleIndex == 5){
184 mCurrentRect.setBottom((point - mGrabOffset).y());
185 } else if(mGrabbedHandleIndex == 6){
186 mCurrentRect.setBottomLeft(point - mGrabOffset);
187 } else if(mGrabbedHandleIndex == 7){
188 mCurrentRect.setLeft((point - mGrabOffset).x());
189 }
190
191 notifyRectChanged();
192 }
193
notifyRectChanged()194 void SnippingAreaResizer::notifyRectChanged()
195 {
196 updateHandlePositions();
197 emit rectChanged(mCurrentRect.normalized());
198 }
199
updateHandlePositions()200 void SnippingAreaResizer::updateHandlePositions()
201 {
202 mHandles[0].moveCenter(RectHelper::topLeft(mCurrentRect));
203 mHandles[1].moveCenter(RectHelper::top(mCurrentRect));
204 mHandles[2].moveCenter(RectHelper::topRight(mCurrentRect));
205 mHandles[3].moveCenter(RectHelper::right(mCurrentRect));
206 mHandles[4].moveCenter(RectHelper::bottomRight(mCurrentRect));
207 mHandles[5].moveCenter(RectHelper::bottom(mCurrentRect));
208 mHandles[6].moveCenter(RectHelper::bottomLeft(mCurrentRect));
209 mHandles[7].moveCenter(RectHelper::left(mCurrentRect));
210 }
211
arrowRightPressed()212 void SnippingAreaResizer::arrowRightPressed()
213 {
214 if (mControlPressed) {
215 mCurrentRect.setLeft(mCurrentRect.left() + 1);
216 } else if (mAltPressed) {
217 mCurrentRect.setRight(mCurrentRect.right() + 1);
218 } else {
219 mCurrentRect.moveRight(mCurrentRect.right() + 1);
220 }
221 }
222
arrowLeftPressed()223 void SnippingAreaResizer::arrowLeftPressed()
224 {
225 if (mControlPressed) {
226 mCurrentRect.setLeft(mCurrentRect.left() - 1);
227 } else if (mAltPressed) {
228 mCurrentRect.setRight(mCurrentRect.right() - 1);
229 } else {
230 mCurrentRect.moveLeft(mCurrentRect.left() - 1);
231 }
232 }
233
arrowDownPressed()234 void SnippingAreaResizer::arrowDownPressed()
235 {
236 if (mControlPressed) {
237 mCurrentRect.setTop(mCurrentRect.top() + 1);
238 } else if (mAltPressed) {
239 mCurrentRect.setBottom(mCurrentRect.bottom() + 1);
240 } else {
241 mCurrentRect.moveBottom(mCurrentRect.bottom() + 1);
242 }
243 }
244
arrowUpPressed()245 void SnippingAreaResizer::arrowUpPressed()
246 {
247 if (mControlPressed) {
248 mCurrentRect.setTop(mCurrentRect.top() - 1);
249 } else if (mAltPressed) {
250 mCurrentRect.setBottom(mCurrentRect.bottom() - 1);
251 } else {
252 mCurrentRect.moveTop(mCurrentRect.top() - 1);
253 }
254 }
255