blob: 1507c77a7183be294d20043daba3b00e59f47f7a [file] [log] [blame]
Robert Bieber83c60a12010-08-03 22:29:26 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 Robert Bieber
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
Robert Bieber10b9e3b2010-08-05 22:31:46 +000022#include <QGraphicsSceneMouseEvent>
Robert Bieber83c60a12010-08-03 22:29:26 +000023#include <QPainter>
24#include <QDebug>
25
Robert Bieber76d13772010-08-06 20:06:56 +000026#include <cmath>
27
Robert Bieber83c60a12010-08-03 22:29:26 +000028#include "rbmovable.h"
29
Robert Bieber10b9e3b2010-08-05 22:31:46 +000030const double RBMovable::handleSize = 7;
31
Robert Bieber83c60a12010-08-03 22:29:26 +000032RBMovable::RBMovable(QGraphicsItem* parent)
Robert Bieber10b9e3b2010-08-05 22:31:46 +000033 : QGraphicsItem(parent), dragMode(None)
Robert Bieber83c60a12010-08-03 22:29:26 +000034{
35 setFlags(ItemIsMovable | ItemIsSelectable | ItemSendsGeometryChanges);
36}
37
38RBMovable::~RBMovable()
39{
40}
41
42void RBMovable::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
43 QWidget *widget)
44{
45 if(isSelected())
46 {
47 painter->setBrush(Qt::NoBrush);
48 QPen pen;
49 pen.setStyle(Qt::DashLine);
50 pen.setColor(Qt::green);
51 painter->setPen(pen);
52 painter->drawRect(boundingRect());
Robert Bieber10b9e3b2010-08-05 22:31:46 +000053
54 painter->fillRect(topLeftHandle(), Qt::green);
55 painter->fillRect(topRightHandle(), Qt::green);
56 painter->fillRect(bottomLeftHandle(), Qt::green);
57 painter->fillRect(bottomRightHandle(), Qt::green);
Robert Bieber83c60a12010-08-03 22:29:26 +000058 }
59}
60
61QVariant RBMovable::itemChange(GraphicsItemChange change, const QVariant &value)
62{
63 if(change == ItemPositionChange)
64 {
65 QPointF pos = value.toPointF();
66 QRectF bound = parentItem()->boundingRect();
67
Robert Bieber76d13772010-08-06 20:06:56 +000068 pos.setX(qMax(0., floor(pos.x())));
Robert Bieber83c60a12010-08-03 22:29:26 +000069 pos.setX(qMin(pos.x(), bound.width() - boundingRect().width()));
70
Robert Bieber76d13772010-08-06 20:06:56 +000071 pos.setY(qMax(0., floor(pos.y())));
Robert Bieber83c60a12010-08-03 22:29:26 +000072 pos.setY(qMin(pos.y(), bound.height() - boundingRect().height()));
73
Robert Bieber83c60a12010-08-03 22:29:26 +000074
75 return pos;
76 }
77
78 return QGraphicsItem::itemChange(change, value);
79}
80
Robert Bieber49865b22010-08-04 09:16:52 +000081void RBMovable::mousePressEvent(QGraphicsSceneMouseEvent *event)
82{
Robert Bieber10b9e3b2010-08-05 22:31:46 +000083 if(!isSelected())
84 {
85 QGraphicsItem::mousePressEvent(event);
86 return;
87 }
88
89 if(topLeftHandle().contains(event->pos()))
90 {
91 dragStartClick = event->pos() + pos();
92 dragStartPos = pos();
93 dragStartSize = boundingRect();
94
95 dWidthMin = -1. * pos().x();
96 dWidthMax = boundingRect().width() - childrenBoundingRect().right();
97
98 dHeightMin = -1. * pos().y();
99 dHeightMax = boundingRect().height() - childrenBoundingRect().bottom();
100
101 dragMode = TopLeft;
102 }
103 else if(topRightHandle().contains(event->pos()))
104 {
105 dragStartClick = event->pos() + pos();
106 dragStartPos = pos();
107 dragStartSize = boundingRect();
108
109 dWidthMin = childrenBoundingRect().width() - boundingRect().width();
110 dWidthMin = qMax(dWidthMin, -1. * size.width());
111 dWidthMax = parentItem()->boundingRect().width()
112 - boundingRect().width() - pos().x();
113
114 dHeightMin = -1. * pos().y();
115 dHeightMax = boundingRect().height() - childrenBoundingRect().bottom();
116 dHeightMax = qMin(dHeightMax, boundingRect().height());
117
118 dragMode = TopRight;
119 }
120 else if(bottomLeftHandle().contains(event->pos()))
121 {
122 dragStartClick = event->pos() + pos();
123 dragStartPos = pos();
124 dragStartSize = boundingRect();
125
126 dWidthMin = -1. * pos().x();
127 dWidthMax = boundingRect().width() - childrenBoundingRect().right();
128 dWidthMax = qMin(dWidthMax, size.width());
129
130 dHeightMin = -1. * (boundingRect().height()
131 - childrenBoundingRect().bottom());
132 dHeightMin = qMax(dHeightMin, -1. * boundingRect().height());
133
134 dragMode = BottomLeft;
135 }
136 else if(bottomRightHandle().contains(event->pos()))
137 {
138 dragStartClick = event->pos() + pos();
139 dragStartPos = pos();
140 dragStartSize = boundingRect();
141
142 dWidthMin = -1. * (boundingRect().width()
143 - childrenBoundingRect().right());
144 dWidthMin = qMax(dWidthMin, -1. * boundingRect().width());
145 dWidthMax = parentItem()->boundingRect().width() -
146 boundingRect().width() - pos().x();
147
148 dHeightMin = -1. * (boundingRect().height()
149 - childrenBoundingRect().bottom());
150 dHeightMin = qMax(dHeightMin, -1. * boundingRect().height());
151 dHeightMax = parentItem()->boundingRect().height() -
152 boundingRect().height() - pos().y();
153
154 dragMode = BottomRight;
155 }
156 else
157 {
158 QGraphicsItem::mousePressEvent(event);
159 }
160}
161
162void RBMovable::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
163{
164
165 QPointF absPos;
166 QPointF dPos;
167 QPointF dMouse;
168 switch(dragMode)
169 {
170 case None:
171 QGraphicsItem::mouseMoveEvent(event);
172 break;
173
174 case TopLeft:
175 /* Dragging from the top left corner */
176 absPos = event->pos() + pos();
Robert Bieber76d13772010-08-06 20:06:56 +0000177 dMouse = QPointF(floor(absPos.x() - dragStartClick.x()),
178 floor(absPos.y() - dragStartClick.y()));
Robert Bieber10b9e3b2010-08-05 22:31:46 +0000179
180 dPos.setX(qMin(dMouse.x(), dWidthMax));
181 dPos.setX(qMax(dPos.x(), dWidthMin));
182
183 dPos.setY(qMin(dMouse.y(), dHeightMax));
184 dPos.setY(qMax(dPos.y(), dHeightMin));
185
186 prepareGeometryChange();
187
188 setPos(dragStartPos + dPos);
189
190 size.setWidth(dragStartSize.width() - dPos.x());
191 size.setHeight(dragStartSize.height() - dPos.y());
192
193 break;
194
195 case TopRight:
196 /* Dragging from the top right corner */
197 absPos = event->pos() + pos();
Robert Bieber76d13772010-08-06 20:06:56 +0000198 dMouse = QPointF(floor(absPos.x() - dragStartClick.x()),
199 floor(absPos.y() - dragStartClick.y()));
Robert Bieber10b9e3b2010-08-05 22:31:46 +0000200
201 dPos.setX(qMin(dMouse.x(), dWidthMax));
202 dPos.setX(qMax(dPos.x(), dWidthMin));
203
204 dPos.setY(qMin(dMouse.y(), dHeightMax));
205 dPos.setY(qMax(dPos.y(), dHeightMin));
206
207 prepareGeometryChange();
208
209 setPos(dragStartPos.x(), dragStartPos.y() + dPos.y());
210
211 size.setWidth(dragStartSize.width() + dPos.x());
212 size.setHeight(dragStartSize.height() - dPos.y());
213
214 break;
215
216 case BottomLeft:
217 /* Dragging from the bottom left corner */
218 absPos = event->pos() + pos();
Robert Bieber76d13772010-08-06 20:06:56 +0000219 dMouse = QPointF(floor(absPos.x() - dragStartClick.x()),
220 floor(absPos.y() - dragStartClick.y()));
Robert Bieber10b9e3b2010-08-05 22:31:46 +0000221
222 dPos.setX(qMin(dMouse.x(), dWidthMax));
223 dPos.setX(qMax(dPos.x(), dWidthMin));
224
225 dPos.setY(qMin(dMouse.y(), dHeightMax));
226 dPos.setY(qMax(dPos.y(), dHeightMin));
227
228 prepareGeometryChange();
229 setPos(dragStartPos.x() + dPos.x(), dragStartPos.y());
230 size.setHeight(dragStartSize.height() + dPos.y());
231 size.setWidth(dragStartSize.width() - dPos.x());
232
233 break;
234
235 case BottomRight:
236 /* Dragging from the bottom right corner */
237 absPos = event->pos() + pos();
Robert Bieber76d13772010-08-06 20:06:56 +0000238 dMouse = QPointF(floor(absPos.x() - dragStartClick.x()),
239 floor(absPos.y() - dragStartClick.y()));
Robert Bieber10b9e3b2010-08-05 22:31:46 +0000240
241 dPos.setX(qMin(dMouse.x(), dWidthMax));
242 dPos.setX(qMax(dPos.x(), dWidthMin));
243
244 dPos.setY(qMin(dMouse.y(), dHeightMax));
245 dPos.setY(qMax(dPos.y(), dHeightMin));
246
247 prepareGeometryChange();
248
249 size.setWidth(dragStartSize.width() + dPos.x());
250 size.setHeight(dragStartSize.height() + dPos.y());
251
252 break;
253 }
Robert Bieber49865b22010-08-04 09:16:52 +0000254}
255
256void RBMovable::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
257{
258 QGraphicsItem::mouseReleaseEvent(event);
Robert Bieber10b9e3b2010-08-05 22:31:46 +0000259
260 dragMode = None;
261
Robert Bieber49865b22010-08-04 09:16:52 +0000262 if(isSelected())
263 {
264 saveGeometry();
Robert Bieber49865b22010-08-04 09:16:52 +0000265 }
266}
Robert Bieber10b9e3b2010-08-05 22:31:46 +0000267
268QRectF RBMovable::topLeftHandle()
269{
270 QRectF bounds = boundingRect();
271 double width = qMin(bounds.width() / 2. - .5, handleSize);
272 double height = qMin(bounds.height() / 2. - .5, handleSize);
273 double size = qMin(width, height);
274
275 return QRectF(0, 0, size, size);
276}
277
278QRectF RBMovable::topRightHandle()
279{
280 QRectF bounds = boundingRect();
281 double width = qMin(bounds.width() / 2. - .5, handleSize);
282 double height = qMin(bounds.height() / 2. - .5, handleSize);
283 double size = qMin(width, height);
284
285 return QRectF(bounds.width() - size, 0, size, size);
286}
287
288QRectF RBMovable::bottomLeftHandle()
289{
290 QRectF bounds = boundingRect();
291 double width = qMin(bounds.width() / 2. - .5, handleSize);
292 double height = qMin(bounds.height() / 2. - .5, handleSize);
293 double size = qMin(width, height);
294
295 return QRectF(0, bounds.height() - size, size, size);
296}
297
298QRectF RBMovable::bottomRightHandle()
299{
300 QRectF bounds = boundingRect();
301 double width = qMin(bounds.width() / 2. - .5, handleSize);
302 double height = qMin(bounds.height() / 2. - .5, handleSize);
303 double size = qMin(width, height);
304
305 return QRectF(bounds.width() - size, bounds.height() - size, size, size);
306}