1 /****************************************************************************
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the demonstration applications of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #ifdef QT_OPENGL_SUPPORT
46 #include "arthurwidgets.h"
47 #include "hoverpoints.h"
51 HoverPoints::HoverPoints(QWidget
*widget
, PointShape shape
)
55 widget
->installEventFilter(this);
56 widget
->setAttribute(Qt::WA_AcceptTouchEvents
);
58 m_connectionType
= CurveConnection
;
61 m_pointPen
= QPen(QColor(255, 255, 255, 191), 1);
62 m_connectionPen
= QPen(QColor(255, 255, 255, 127), 2);
63 m_pointBrush
= QBrush(QColor(191, 191, 191, 127));
64 m_pointSize
= QSize(11, 11);
69 connect(this, SIGNAL(pointsChanged(const QPolygonF
&)),
70 m_widget
, SLOT(update()));
74 void HoverPoints::setEnabled(bool enabled
)
76 if (m_enabled
!= enabled
) {
83 bool HoverPoints::eventFilter(QObject
*object
, QEvent
*event
)
85 if (object
== m_widget
&& m_enabled
) {
86 switch (event
->type()) {
88 case QEvent::MouseButtonPress
:
90 if (!m_fingerPointMapping
.isEmpty())
92 QMouseEvent
*me
= (QMouseEvent
*) event
;
94 QPointF clickPos
= me
->pos();
96 for (int i
=0; i
<m_points
.size(); ++i
) {
98 if (m_shape
== CircleShape
)
99 path
.addEllipse(pointBoundingRect(i
));
101 path
.addRect(pointBoundingRect(i
));
103 if (path
.contains(clickPos
)) {
109 if (me
->button() == Qt::LeftButton
) {
114 // Insert sort for x or y
115 if (m_sortType
== XSort
) {
116 for (int i
=0; i
<m_points
.size(); ++i
)
117 if (m_points
.at(i
).x() > clickPos
.x()) {
121 } else if (m_sortType
== YSort
) {
122 for (int i
=0; i
<m_points
.size(); ++i
)
123 if (m_points
.at(i
).y() > clickPos
.y()) {
129 m_points
.insert(pos
, clickPos
);
130 m_locks
.insert(pos
, 0);
131 m_currentIndex
= pos
;
134 m_currentIndex
= index
;
138 } else if (me
->button() == Qt::RightButton
) {
139 if (index
>= 0 && m_editable
) {
140 if (m_locks
[index
] == 0) {
141 m_locks
.remove(index
);
142 m_points
.remove(index
);
152 case QEvent::MouseButtonRelease
:
153 if (!m_fingerPointMapping
.isEmpty())
158 case QEvent::MouseMove
:
159 if (!m_fingerPointMapping
.isEmpty())
161 if (m_currentIndex
>= 0)
162 movePoint(m_currentIndex
, ((QMouseEvent
*)event
)->pos());
164 case QEvent::TouchBegin
:
165 case QEvent::TouchUpdate
:
167 const QTouchEvent
*const touchEvent
= static_cast<const QTouchEvent
*>(event
);
168 const QList
<QTouchEvent::TouchPoint
> points
= touchEvent
->touchPoints();
169 const qreal pointSize
= qMax(m_pointSize
.width(), m_pointSize
.height());
170 foreach (const QTouchEvent::TouchPoint
&touchPoint
, points
) {
171 const int id
= touchPoint
.id();
172 switch (touchPoint
.state()) {
173 case Qt::TouchPointPressed
:
175 // find the point, move it
176 QSet
<int> activePoints
= QSet
<int>::fromList(m_fingerPointMapping
.values());
177 int activePoint
= -1;
179 const int pointsCount
= m_points
.size();
180 const int activePointCount
= activePoints
.size();
181 if (pointsCount
== 2 && activePointCount
== 1) { // only two points
182 activePoint
= activePoints
.contains(0) ? 1 : 0;
184 for (int i
=0; i
<pointsCount
; ++i
) {
185 if (activePoints
.contains(i
))
188 qreal d
= QLineF(touchPoint
.pos(), m_points
.at(i
)).length();
189 if ((distance
< 0 && d
< 12 * pointSize
) || d
< distance
) {
196 if (activePoint
!= -1) {
197 m_fingerPointMapping
.insert(touchPoint
.id(), activePoint
);
198 movePoint(activePoint
, touchPoint
.pos());
202 case Qt::TouchPointReleased
:
204 // move the point and release
205 QHash
<int,int>::iterator it
= m_fingerPointMapping
.find(id
);
206 movePoint(it
.value(), touchPoint
.pos());
207 m_fingerPointMapping
.erase(it
);
210 case Qt::TouchPointMoved
:
213 const int pointIdx
= m_fingerPointMapping
.value(id
, -1);
214 if (pointIdx
>= 0) // do we track this point?
215 movePoint(pointIdx
, touchPoint
.pos());
222 if (m_fingerPointMapping
.isEmpty()) {
230 case QEvent::TouchEnd
:
231 if (m_fingerPointMapping
.isEmpty()) {
240 QResizeEvent
*e
= (QResizeEvent
*) event
;
241 if (e
->oldSize().width() == 0 || e
->oldSize().height() == 0)
243 qreal stretch_x
= e
->size().width() / qreal(e
->oldSize().width());
244 qreal stretch_y
= e
->size().height() / qreal(e
->oldSize().height());
245 for (int i
=0; i
<m_points
.size(); ++i
) {
246 QPointF p
= m_points
[i
];
247 movePoint(i
, QPointF(p
.x() * stretch_x
, p
.y() * stretch_y
), false);
256 QWidget
*that_widget
= m_widget
;
258 QApplication::sendEvent(object
, event
);
259 m_widget
= that_widget
;
261 #ifdef QT_OPENGL_SUPPORT
262 ArthurFrame
*af
= qobject_cast
<ArthurFrame
*>(that_widget
);
263 if (af
&& af
->usesOpenGL())
264 af
->glWidget()->swapBuffers();
277 void HoverPoints::paintPoints()
280 #ifdef QT_OPENGL_SUPPORT
281 ArthurFrame
*af
= qobject_cast
<ArthurFrame
*>(m_widget
);
282 if (af
&& af
->usesOpenGL())
283 p
.begin(af
->glWidget());
290 p
.setRenderHint(QPainter::Antialiasing
);
292 if (m_connectionPen
.style() != Qt::NoPen
&& m_connectionType
!= NoConnection
) {
293 p
.setPen(m_connectionPen
);
295 if (m_connectionType
== CurveConnection
) {
297 path
.moveTo(m_points
.at(0));
298 for (int i
=1; i
<m_points
.size(); ++i
) {
299 QPointF p1
= m_points
.at(i
-1);
300 QPointF p2
= m_points
.at(i
);
301 qreal distance
= p2
.x() - p1
.x();
303 path
.cubicTo(p1
.x() + distance
/ 2, p1
.y(),
304 p1
.x() + distance
/ 2, p2
.y(),
309 p
.drawPolyline(m_points
);
313 p
.setPen(m_pointPen
);
314 p
.setBrush(m_pointBrush
);
316 for (int i
=0; i
<m_points
.size(); ++i
) {
317 QRectF bounds
= pointBoundingRect(i
);
318 if (m_shape
== CircleShape
)
319 p
.drawEllipse(bounds
);
325 static QPointF
bound_point(const QPointF
&point
, const QRectF
&bounds
, int lock
)
329 qreal left
= bounds
.left();
330 qreal right
= bounds
.right();
331 qreal top
= bounds
.top();
332 qreal bottom
= bounds
.bottom();
334 if (p
.x() < left
|| (lock
& HoverPoints::LockToLeft
)) p
.setX(left
);
335 else if (p
.x() > right
|| (lock
& HoverPoints::LockToRight
)) p
.setX(right
);
337 if (p
.y() < top
|| (lock
& HoverPoints::LockToTop
)) p
.setY(top
);
338 else if (p
.y() > bottom
|| (lock
& HoverPoints::LockToBottom
)) p
.setY(bottom
);
343 void HoverPoints::setPoints(const QPolygonF
&points
)
345 if (points
.size() != m_points
.size())
346 m_fingerPointMapping
.clear();
348 for (int i
=0; i
<points
.size(); ++i
)
349 m_points
<< bound_point(points
.at(i
), boundingRect(), 0);
352 if (m_points
.size() > 0) {
353 m_locks
.resize(m_points
.size());
360 void HoverPoints::movePoint(int index
, const QPointF
&point
, bool emitUpdate
)
362 m_points
[index
] = bound_point(point
, boundingRect(), m_locks
.at(index
));
368 inline static bool x_less_than(const QPointF
&p1
, const QPointF
&p2
)
370 return p1
.x() < p2
.x();
374 inline static bool y_less_than(const QPointF
&p1
, const QPointF
&p2
)
376 return p1
.y() < p2
.y();
379 void HoverPoints::firePointChange()
381 // printf("HoverPoints::firePointChange(), current=%d\n", m_currentIndex);
383 if (m_sortType
!= NoSort
) {
386 if (m_currentIndex
!= -1) {
387 oldCurrent
= m_points
[m_currentIndex
];
390 if (m_sortType
== XSort
)
391 qSort(m_points
.begin(), m_points
.end(), x_less_than
);
392 else if (m_sortType
== YSort
)
393 qSort(m_points
.begin(), m_points
.end(), y_less_than
);
395 // Compensate for changed order...
396 if (m_currentIndex
!= -1) {
397 for (int i
=0; i
<m_points
.size(); ++i
) {
398 if (m_points
[i
] == oldCurrent
) {
405 // printf(" - firePointChange(), current=%d\n", m_currentIndex);
409 // for (int i=0; i<m_points.size(); ++i) {
410 // printf(" - point(%2d)=[%.2f, %.2f], lock=%d\n",
411 // i, m_points.at(i).x(), m_points.at(i).y(), m_locks.at(i));
414 emit
pointsChanged(m_points
);