##// END OF EJS Templates
Refactor spline animation handling...
Michal Klocek -
r1770:6ebf2349194b
parent child
Show More
@@ -1,237 +1,212
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "splineanimation_p.h"
22 22 #include "splinechartitem_p.h"
23 23 #include <QDebug>
24 24
25 25 Q_DECLARE_METATYPE(QVector<QPointF>)
26 26 Q_DECLARE_METATYPE(SplineVector)
27 27
28 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 29
30 30 SplineAnimation::SplineAnimation(SplineChartItem* item):XYAnimation(item),
31 m_item(item)
31 m_item(item),
32 m_valid(false)
32 33 {
33 34 }
34 35
35 36 SplineAnimation::~SplineAnimation()
36 37 {
37 38 }
38 39
39 40 void SplineAnimation::setup(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, QVector<QPointF> &oldControlPoints, QVector<QPointF> &newControlPoints, int index)
40 41 {
41 Q_ASSERT(newPoints.count() * 2 - 2 == newControlPoints.count());
42 if(newPoints.count() * 2 - 2 != newControlPoints.count() || newControlPoints.count() < 2){
43 m_valid=false;
44 m_dirty=false;
45 m_item->setGeometryPoints(newPoints);
46 m_item->setControlGeometryPoints(newControlPoints);
47 m_item->setDirty(false);
48 m_item->updateGeometry();
49 return;
50 }
42 51
43 52 m_type = NewAnimation;
44 53
45 54 if (state() != QAbstractAnimation::Stopped) {
46 55 stop();
47 56 m_dirty=false;
48 57 }
49 58
50 59 if(!m_dirty) {
51 60 m_dirty = true;
52 61 m_oldSpline.first = oldPoints;
53 62 m_oldSpline.second = oldControlPoints;
54 63 }
55 64
56 65 m_newSpline.first=newPoints;
57 66 m_newSpline.second=newControlPoints;
58 67
68
59 69 int x = m_oldSpline.first.count();
60 70 int y = m_newSpline.first.count();
61 71
62 72 if(x - y == 1 && index >= 0 && y>0) {
63 73 //remove point
64 74 if(index>0){
65 75 m_newSpline.first.insert(index, newPoints[index-1]);
66 76 m_newSpline.second.insert((index -1) * 2, newPoints[index-1] );
67 77 m_newSpline.second.insert((index -1) * 2 + 1, newPoints[index-1]);
68 78 }else{
69 79 m_newSpline.first.insert(index, newPoints[index]);
70 80 m_newSpline.second.insert(index * 2, newPoints[index] );
71 81 m_newSpline.second.insert(index * 2 + 1, newPoints[index]);
72 82 }
73 83 m_index=index;
74 84 m_type = RemovePointAnimation;
75 85 }
76 86
77 87 if(x - y == -1 && index >= 0) {
78 88 //add point
79 89 if(index>0){
80 90 m_oldSpline.first.insert(index, newPoints[index-1]);
81 91 m_oldSpline.second.insert((index - 1) * 2, newPoints[index-1]);
82 92 m_oldSpline.second.insert((index - 1) * 2 + 1, newPoints[index-1]);
83 93 }else{
84 94 m_oldSpline.first.insert(index, newPoints[index]);
85 95 m_oldSpline.second.insert((index - 1) * 2, newPoints[index]);
86 96 m_oldSpline.second.insert((index - 1) * 2 + 1, newPoints[index]);
87 97 }
88 98 m_index=index;
89 99 m_type = AddPointAnimation;
90 100 }
91 101
92 102 x = m_oldSpline.first.count();
93 103 y = m_newSpline.first.count();
94 104
95 105 if(x != y)
96 106 {
97 107 m_type = NewAnimation;
98 108 }
99 109 else if(m_type == NewAnimation)
100 110 {
101 111 m_type = ReplacePointAnimation;
102 112 }
103 113
104 114
105 115 setKeyValueAt(0.0, qVariantFromValue(m_oldSpline));
106 116 setKeyValueAt(1.0, qVariantFromValue(m_newSpline));
107 /*
108 int x = oldPoints.count();
109 int y = newPoints.count();
110
111 Q_ASSERT(newPoints.count() * 2 - 2 == newControlPoints.count());
112
113 if (x != y && abs(x - y) != 1) {
114 m_oldSpline.first = newPoints;
115 m_oldSpline.second = newControlPoints;
116 oldPoints.resize(newPoints.size());
117 oldControlPoints.resize(newControlPoints.size());
118 SplineVector oldPair;
119 oldPair.first = oldPoints;
120 oldPair.second = oldControlPoints;
121 SplineVector newPair;
122 newPair.first = newPoints;
123 newPair.second = newControlPoints;
124 setKeyValueAt(0.0, qVariantFromValue(oldPair));
125 setKeyValueAt(1.0, qVariantFromValue(newPair));
126 m_dirty = false;
127 }
128 else {
129 if(m_dirty) {
130 m_oldSpline.first = oldPoints;
131 m_oldSpline.second = oldControlPoints;
132 m_dirty = false;
133 }
134 oldPoints = newPoints;
135 oldControlPoints = newControlPoints;
136 if (y < x) {
137 m_oldSpline.first.remove(index); //remove
138 m_oldSpline.second.remove(index * 2);
139 m_oldSpline.second.remove(index * 2);
140 }
141 if (y > x) {
142 m_oldSpline.first.insert(index, x > 0 ? m_oldSpline.first[index-1] : newPoints[index]); //add
143 m_oldSpline.second.insert((index - 1) * 2, x > 1 ? m_oldSpline.second[(index-2)*2] : newControlPoints[(index - 1) * 2]); //add
144 m_oldSpline.second.insert((index - 1) * 2 + 1, x > 1 ? m_oldSpline.second[(index - 2) * 2 + 1] : newControlPoints[(index - 1) * 2 + 1]); //add
145 }
146 SplineVector newPair;
147 newPair.first=newPoints;
148 newPair.second=newControlPoints;
149 setKeyValueAt(0.0, qVariantFromValue(m_oldSpline));
150 setKeyValueAt(1.0, qVariantFromValue(newPair));
151 }
152 */
117
118 m_valid=true;
153 119
154 120 }
155 121
156 122 QVariant SplineAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress ) const
157 123 {
158 124
159 125 SplineVector startPair = qVariantValue< SplineVector >(start);
160 126 SplineVector endPair = qVariantValue< SplineVector >(end);
161 127 SplineVector result;
162 128
163 129 switch (animationType()) {
164 130
165 131 case RemovePointAnimation:
166 132 case AddPointAnimation:
167 133 case ReplacePointAnimation:
168 134 {
169 135 if (startPair.first.count() != endPair.first.count())
170 136 break;
171 137 Q_ASSERT(startPair.first.count() * 2 - 2 == startPair.second.count());
172 138 Q_ASSERT(endPair.first.count() * 2 - 2 == endPair.second.count());
173 139 for(int i = 0; i < endPair.first.count(); i++) {
174 140 qreal x = startPair.first[i].x() + ((endPair.first[i].x() - startPair.first[i].x()) * progress);
175 141 qreal y = startPair.first[i].y() + ((endPair.first[i].y() - startPair.first[i].y()) * progress);
176 142 result.first << QPointF(x,y);
177 143 if (i + 1 >= endPair.first.count())
178 144 continue;
179 145 x = startPair.second[i * 2].x() + ((endPair.second[i * 2].x() - startPair.second[i * 2].x()) * progress);
180 146 y = startPair.second[i * 2].y() + ((endPair.second[i * 2].y() - startPair.second[i * 2].y()) * progress);
181 147 result.second << QPoint(x,y);
182 148 x = startPair.second[i * 2 + 1].x() + ((endPair.second[i * 2 + 1].x() - startPair.second[i * 2 + 1].x()) * progress);
183 149 y = startPair.second[i * 2 + 1].y() + ((endPair.second[i * 2 + 1].y() - startPair.second[i * 2 + 1].y()) * progress);
184 150 result.second << QPoint(x,y);
185 151 }
186 152
187 153 }
188 154 break;
189 155 case NewAnimation: {
190 156 Q_ASSERT(endPair.first.count() * 2 - 2 == endPair.second.count());
191 157 int count = endPair.first.count()* qBound(qreal(0), progress, qreal(1));
192 158 for(int i = 0; i < count; i++) {
193 159 result.first << endPair.first[i];
194 160 if(i + 1 == count)
195 161 break;
196 162 result.second << endPair.second[2 * i];
197 163 result.second << endPair.second[2 * i + 1];
198 164 }
199 165 }
200 166 break;
201 167 default:
202 168 qWarning() << "Unknown type of animation";
203 169 break;
204 170 }
205 171
206 172 return qVariantFromValue(result);
207 173 }
208 174
209 175 void SplineAnimation::updateCurrentValue (const QVariant &value )
210 176 {
211 if (state() != QAbstractAnimation::Stopped) { //workaround
177 if (state() != QAbstractAnimation::Stopped && m_valid) { //workaround
212 178 QPair<QVector<QPointF >, QVector<QPointF > > pair = qVariantValue< QPair< QVector<QPointF>, QVector<QPointF> > >(value);
213 179 m_item->setGeometryPoints(pair.first);
214 180 m_item->setControlGeometryPoints(pair.second);
215 181 m_item->updateGeometry();
216 182 m_item->setDirty(true);
217 183 m_dirty = false;
218 184 }
219 185 }
220 186
221 187 void SplineAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
222 188 {
189 XYAnimation::updateState(newState, oldState);
190
223 191 if(oldState == QAbstractAnimation::Running && newState == QAbstractAnimation::Stopped)
224 192 {
225 193 if(m_item->isDirty() && m_type==RemovePointAnimation) {
226 194 if(!m_newSpline.first.isEmpty()) {
227 195 m_newSpline.first.remove(m_index);
228 196 m_newSpline.second.remove((m_index-1) * 2);
229 197 m_newSpline.second.remove((m_index-1) * 2);
230 198 }
231 199 m_item->setGeometryPoints(m_newSpline.first);
232 200 m_item->setControlGeometryPoints(m_newSpline.second);
233 201 }
234 202 }
203
204 if(oldState == QAbstractAnimation::Stopped && newState == QAbstractAnimation::Running)
205 {
206 if(!m_valid) {
207 stop();
208 }
209 }
235 210 }
236 211
237 212 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,61 +1,62
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef SPLINEANIMATION_P_H
31 31 #define SPLINEANIMATION_P_H
32 32 #include "xyanimation_p.h"
33 33 #include <QPointF>
34 34
35 35 typedef QPair<QVector<QPointF >, QVector<QPointF > > SplineVector;
36 36
37 37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 38
39 39 class SplineChartItem;
40 40
41 41 class SplineAnimation : public XYAnimation
42 42 {
43 43 public:
44 44 SplineAnimation(SplineChartItem *item);
45 45 ~SplineAnimation();
46 46 void setup(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, QVector<QPointF> &oldContorlPoints, QVector<QPointF> &newControlPoints, int index = -1);
47 47
48 48 protected:
49 49 QVariant interpolated(const QVariant &start, const QVariant &end, qreal progress) const;
50 50 void updateCurrentValue(const QVariant &value);
51 51 void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
52 52
53 53 private:
54 54 SplineVector m_oldSpline;
55 55 SplineVector m_newSpline;
56 56 SplineChartItem *m_item;
57 bool m_valid;
57 58 };
58 59
59 60 QTCOMMERCIALCHART_END_NAMESPACE
60 61
61 62 #endif
@@ -1,177 +1,172
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "splinechartitem_p.h"
22 22 #include "qsplineseries_p.h"
23 23 #include "chartpresenter_p.h"
24 24 #include "splineanimation_p.h"
25 25 #include <QPainter>
26 26 #include <QGraphicsSceneMouseEvent>
27 27
28 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 29
30 30 SplineChartItem::SplineChartItem(QSplineSeries *series, ChartPresenter *presenter) :
31 31 XYChart(series, presenter),
32 32 QGraphicsItem(presenter ? presenter->rootItem() : 0),
33 33 m_series(series),
34 34 m_pointsVisible(false),
35 35 m_animation(0)
36 36 {
37 37 setZValue(ChartPresenter::SplineChartZValue);
38 38 QObject::connect(m_series->d_func(),SIGNAL(updated()),this,SLOT(handleUpdated()));
39 39 QObject::connect(series, SIGNAL(visibleChanged()), this, SLOT(handleUpdated()));
40 40 handleUpdated();
41 41 }
42 42
43 43 QRectF SplineChartItem::boundingRect() const
44 44 {
45 45 return m_rect;
46 46 }
47 47
48 48 QPainterPath SplineChartItem::shape() const
49 49 {
50 50 return m_path;
51 51 }
52 52
53 53 void SplineChartItem::setAnimation(SplineAnimation* animation)
54 54 {
55 55 m_animation=animation;
56 56 XYChart::setAnimation(animation);
57 57 }
58 58
59 59 ChartAnimation* SplineChartItem::animation() const
60 60 {
61 61 return m_animation;
62 62 }
63 63
64 64 void SplineChartItem::setControlGeometryPoints(QVector<QPointF>& points)
65 65 {
66 66 m_controlPoints=points;
67 67 }
68 68
69 69 QVector<QPointF> SplineChartItem::controlGeometryPoints() const
70 70 {
71 71 return m_controlPoints;
72 72 }
73 73
74 74 void SplineChartItem::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints,int index)
75 75 {
76 76 QVector<QPointF> controlPoints;
77 77
78 78 if(newPoints.count()>=2) {
79 79 controlPoints.resize(newPoints.count()*2-2);
80 80 }
81 81
82 82 for (int i = 0; i < newPoints.size() - 1; i++) {
83 83 controlPoints[2*i] = calculateGeometryControlPoint(2 * i);
84 84 controlPoints[2 * i + 1] = calculateGeometryControlPoint(2 * i + 1);
85 85 }
86 86
87 if (controlPoints.count()<2) {
88 setGeometryPoints(newPoints);
89 setControlGeometryPoints(controlPoints);
90 updateGeometry();
91 return;
87 if (m_animation) {
88 m_animation->setup(oldPoints,newPoints,m_controlPoints,controlPoints,index);
92 89 }
93 90
91 setGeometryPoints(newPoints);
92 setControlGeometryPoints(controlPoints);
93 setDirty(false);
94
94 95 if (m_animation) {
95 m_animation->setup(oldPoints,newPoints,m_controlPoints,controlPoints,index);
96 setGeometryPoints(newPoints);
97 setDirty(false);
98 96 presenter()->startAnimation(m_animation);
99 }
100 else {
101 setGeometryPoints(newPoints);
102 setControlGeometryPoints(controlPoints);
97 } else {
103 98 updateGeometry();
104 99 }
105 100 }
106 101
107 102 QPointF SplineChartItem::calculateGeometryControlPoint(int index) const
108 103 {
109 104 return XYChart::calculateGeometryPoint(m_series->d_func()->controlPoint(index));
110 105 }
111 106
112 107 void SplineChartItem::updateGeometry()
113 108 {
114 109 const QVector<QPointF> &points = geometryPoints();
115 110 const QVector<QPointF> &controlPoints = controlGeometryPoints();
116 111
117 112 if ((points.size()<2) || (controlPoints.size()<2)) {
118 113 prepareGeometryChange();
119 114 m_path = QPainterPath();
120 115 m_rect = QRect();
121 116 return;
122 117 }
123 118
124 119 Q_ASSERT(points.count()*2-2 == controlPoints.count());
125 120
126 121 QPainterPath splinePath(points.at(0));
127 122
128 123 for (int i = 0; i < points.size() - 1; i++) {
129 124 const QPointF& point = points.at(i + 1);
130 125 splinePath.cubicTo(controlPoints[2*i],controlPoints[2 * i + 1],point);
131 126 }
132 127
133 128 prepareGeometryChange();
134 129 m_path = splinePath;
135 130 m_rect = splinePath.boundingRect();
136 131 setPos(origin());
137 132 }
138 133
139 134 //handlers
140 135
141 136 void SplineChartItem::handleUpdated()
142 137 {
143 138 setVisible(m_series->isVisible());
144 139 m_pointsVisible = m_series->pointsVisible();
145 140 m_linePen = m_series->pen();
146 141 m_pointPen = m_series->pen();
147 142 m_pointPen.setWidthF(2*m_pointPen.width());
148 143 update();
149 144 }
150 145
151 146 //painter
152 147
153 148 void SplineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
154 149 {
155 150 Q_UNUSED(widget)
156 151 Q_UNUSED(option)
157 152
158 153 painter->save();
159 154 painter->setClipRect(clipRect());
160 155 painter->setPen(m_linePen);
161 156 painter->drawPath(m_path);
162 157 if (m_pointsVisible) {
163 158 painter->setPen(m_pointPen);
164 159 painter->drawPoints(geometryPoints());
165 160 }
166 161 painter->restore();
167 162 }
168 163
169 164 void SplineChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
170 165 {
171 166 emit XYChart::clicked(calculateDomainPoint(event->pos()));
172 167 QGraphicsItem::mousePressEvent(event);
173 168 }
174 169
175 170 #include "moc_splinechartitem_p.cpp"
176 171
177 172 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now