##// END OF EJS Templates
prevents flipping in xyseries animation
Michal Klocek -
r1220:8dbddb2db883
parent child
Show More
@@ -1,211 +1,210
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "chartanimator_p.h"
21 #include "chartanimator_p.h"
22 #include "axisanimation_p.h"
22 #include "axisanimation_p.h"
23 #include "xyanimation_p.h"
23 #include "xyanimation_p.h"
24 #include "splineanimation_p.h"
24 #include "splineanimation_p.h"
25 #include "xychart_p.h"
25 #include "xychart_p.h"
26 #include "pieanimation_p.h"
26 #include "pieanimation_p.h"
27 #include "baranimation_p.h"
27 #include "baranimation_p.h"
28 #include "barchartitem_p.h"
28 #include "barchartitem_p.h"
29 #include "areachartitem_p.h"
29 #include "areachartitem_p.h"
30 #include "splinechartitem_p.h"
30 #include "splinechartitem_p.h"
31 #include "scatterchartitem_p.h"
31 #include "scatterchartitem_p.h"
32 #include <QTimer>
32 #include <QTimer>
33
33
34 Q_DECLARE_METATYPE(QVector<QPointF>)
34 Q_DECLARE_METATYPE(QVector<QPointF>)
35 Q_DECLARE_METATYPE(QVector<qreal>)
35 Q_DECLARE_METATYPE(QVector<qreal>)
36 Q_DECLARE_METATYPE(QVector<QRectF>)
36 Q_DECLARE_METATYPE(QVector<QRectF>)
37
37
38 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 QTCOMMERCIALCHART_BEGIN_NAMESPACE
39
39
40 ChartAnimator::ChartAnimator(QObject *parent):QObject(parent),
40 ChartAnimator::ChartAnimator(QObject *parent):QObject(parent),
41 m_state(ShowState)
41 m_state(ShowState)
42 {
42 {
43 }
43 }
44
44
45 ChartAnimator::~ChartAnimator()
45 ChartAnimator::~ChartAnimator()
46 {
46 {
47 }
47 }
48
48
49 void ChartAnimator::addAnimation(ChartAxis *item)
49 void ChartAnimator::addAnimation(ChartAxis *item)
50 {
50 {
51 ChartAnimation *animation = m_animations.value(item);
51 ChartAnimation *animation = m_animations.value(item);
52
52
53 if (!animation) {
53 if (!animation) {
54 animation = new AxisAnimation(item);
54 animation = new AxisAnimation(item);
55 m_animations.insert(item, animation);
55 m_animations.insert(item, animation);
56 }
56 }
57
57
58 item->setAnimator(this);
58 item->setAnimator(this);
59 }
59 }
60
60
61 void ChartAnimator::addAnimation(PieChartItem *item)
61 void ChartAnimator::addAnimation(PieChartItem *item)
62 {
62 {
63 ChartAnimation *animation = m_animations.value(item);
63 ChartAnimation *animation = m_animations.value(item);
64
64
65 if (!animation) {
65 if (!animation) {
66 animation = new PieAnimation(item);
66 animation = new PieAnimation(item);
67 m_animations.insert(item, animation);
67 m_animations.insert(item, animation);
68 }
68 }
69
69
70 item->setAnimator(this);
70 item->setAnimator(this);
71 }
71 }
72
72
73 void ChartAnimator::addAnimation(BarChartItem *item)
73 void ChartAnimator::addAnimation(BarChartItem *item)
74 {
74 {
75 ChartAnimation *animation = m_animations.value(item);
75 ChartAnimation *animation = m_animations.value(item);
76
76
77 if (!animation) {
77 if (!animation) {
78 animation = new BarAnimation(item);
78 animation = new BarAnimation(item);
79 m_animations.insert(item, animation);
79 m_animations.insert(item, animation);
80 }
80 }
81
81
82 item->setAnimator(this);
82 item->setAnimator(this);
83 }
83 }
84
84
85
85
86 void ChartAnimator::removeAnimation(Chart *item)
86 void ChartAnimator::removeAnimation(Chart *item)
87 {
87 {
88 item->setAnimator(0);
88 item->setAnimator(0);
89 m_animations.remove(item);
89 m_animations.remove(item);
90 }
90 }
91
91
92 void ChartAnimator::updateLayout(ChartAxis *item , QVector<qreal> &newLayout)
92 void ChartAnimator::updateLayout(ChartAxis *item , QVector<qreal> &newLayout)
93 {
93 {
94 AxisAnimation *animation = static_cast<AxisAnimation*>(m_animations.value(item));
94 AxisAnimation *animation = static_cast<AxisAnimation*>(m_animations.value(item));
95
95
96 Q_ASSERT(animation);
96 Q_ASSERT(animation);
97
97
98 QVector<qreal> oldLayout = item->layout();
98 QVector<qreal> oldLayout = item->layout();
99
99
100 if (newLayout.count() == 0)
100 if (newLayout.count() == 0)
101 return;
101 return;
102
102
103 switch (m_state) {
103 switch (m_state) {
104 case ZoomOutState: {
104 case ZoomOutState: {
105 QRectF rect = item->geometry();
105 QRectF rect = item->geometry();
106 oldLayout.resize(newLayout.count());
106 oldLayout.resize(newLayout.count());
107
107
108 for(int i = 0, j = oldLayout.count() - 1; i < (oldLayout.count() + 1) / 2; ++i, --j) {
108 for(int i = 0, j = oldLayout.count() - 1; i < (oldLayout.count() + 1) / 2; ++i, --j) {
109 oldLayout[i] = item->axisType() == ChartAxis::X_AXIS ? rect.left() : rect.bottom();
109 oldLayout[i] = item->axisType() == ChartAxis::X_AXIS ? rect.left() : rect.bottom();
110 oldLayout[j] = item->axisType() == ChartAxis::X_AXIS ? rect.right() : rect.top();
110 oldLayout[j] = item->axisType() == ChartAxis::X_AXIS ? rect.right() : rect.top();
111 }
111 }
112 }
112 }
113 break;
113 break;
114 case ZoomInState: {
114 case ZoomInState: {
115 int index = qMin(oldLayout.count() * (item->axisType() == ChartAxis::X_AXIS ? m_point.x() : (1 - m_point.y())), newLayout.count() - 1.0);
115 int index = qMin(oldLayout.count() * (item->axisType() == ChartAxis::X_AXIS ? m_point.x() : (1 - m_point.y())), newLayout.count() - 1.0);
116 oldLayout.resize(newLayout.count());
116 oldLayout.resize(newLayout.count());
117
117
118 for(int i = 0; i < oldLayout.count(); i++)
118 for(int i = 0; i < oldLayout.count(); i++)
119 oldLayout[i]= oldLayout[index];
119 oldLayout[i]= oldLayout[index];
120 }
120 }
121 break;
121 break;
122 case ScrollDownState:
122 case ScrollDownState:
123 case ScrollRightState: {
123 case ScrollRightState: {
124 oldLayout.resize(newLayout.count());
124 oldLayout.resize(newLayout.count());
125
125
126 for(int i = 0, j = i + 1; i < oldLayout.count() - 1; ++i, ++j)
126 for(int i = 0, j = i + 1; i < oldLayout.count() - 1; ++i, ++j)
127 oldLayout[i]= oldLayout[j];
127 oldLayout[i]= oldLayout[j];
128 }
128 }
129 break;
129 break;
130 case ScrollUpState:
130 case ScrollUpState:
131 case ScrollLeftState: {
131 case ScrollLeftState: {
132 oldLayout.resize(newLayout.count());
132 oldLayout.resize(newLayout.count());
133
133
134 for(int i = oldLayout.count() - 1, j = i - 1; i > 0; --i, --j)
134 for(int i = oldLayout.count() - 1, j = i - 1; i > 0; --i, --j)
135 oldLayout[i]= oldLayout[j];
135 oldLayout[i]= oldLayout[j];
136 }
136 }
137 break;
137 break;
138 default: {
138 default: {
139 oldLayout.resize(newLayout.count());
139 oldLayout.resize(newLayout.count());
140 QRectF rect = item->geometry();
140 QRectF rect = item->geometry();
141 for(int i = 0, j = oldLayout.count() - 1; i < oldLayout.count(); ++i, --j)
141 for(int i = 0, j = oldLayout.count() - 1; i < oldLayout.count(); ++i, --j)
142 oldLayout[i] = item->axisType() == ChartAxis::X_AXIS ? rect.left() : rect.top();
142 oldLayout[i] = item->axisType() == ChartAxis::X_AXIS ? rect.left() : rect.top();
143 }
143 }
144 break;
144 break;
145 }
145 }
146
146
147
147
148 if (animation->state() != QAbstractAnimation::Stopped)
148 if (animation->state() != QAbstractAnimation::Stopped)
149 animation->stop();
149 animation->stop();
150
150
151 animation->setDuration(ChartAnimationDuration);
151 animation->setDuration(ChartAnimationDuration);
152 animation->setEasingCurve(QEasingCurve::OutQuart);
152 animation->setEasingCurve(QEasingCurve::OutQuart);
153 QVariantAnimation::KeyValues value;
153 QVariantAnimation::KeyValues value;
154 animation->setKeyValues(value); //workaround for wrong interpolation call
154 animation->setKeyValues(value); //workaround for wrong interpolation call
155 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
155 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
156 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
156 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
157
157
158 QTimer::singleShot(0, animation, SLOT(start()));
158 QTimer::singleShot(0, animation, SLOT(start()));
159 }
159 }
160
160
161 void ChartAnimator::addAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData, bool startupAnimation)
161 void ChartAnimator::addAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData, bool startupAnimation)
162 {
162 {
163 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
163 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
164 Q_ASSERT(animation);
164 Q_ASSERT(animation);
165 animation->addSlice(sliceItem, sliceData, startupAnimation);
165 animation->addSlice(sliceItem, sliceData, startupAnimation);
166 }
166 }
167
167
168 void ChartAnimator::removeAnimation(PieChartItem *item, PieSliceItem *sliceItem)
168 void ChartAnimator::removeAnimation(PieChartItem *item, PieSliceItem *sliceItem)
169 {
169 {
170 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
170 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
171 Q_ASSERT(animation);
171 Q_ASSERT(animation);
172 animation->removeSlice(sliceItem);
172 animation->removeSlice(sliceItem);
173 }
173 }
174
174
175 void ChartAnimator::updateAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData)
175 void ChartAnimator::updateAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData)
176 {
176 {
177 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
177 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
178 Q_ASSERT(animation);
178 Q_ASSERT(animation);
179 animation->updateValue(sliceItem, sliceData);
179 animation->updateValue(sliceItem, sliceData);
180 }
180 }
181
181
182 void ChartAnimator::updateLayout(BarChartItem *item, const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout)
182 void ChartAnimator::updateLayout(BarChartItem *item, const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout)
183 {
183 {
184 BarAnimation *animation = static_cast<BarAnimation *>(m_animations.value(item));
184 BarAnimation *animation = static_cast<BarAnimation *>(m_animations.value(item));
185 Q_ASSERT(animation);
185 Q_ASSERT(animation);
186 animation->setDuration(ChartAnimationDuration);
186 animation->setDuration(ChartAnimationDuration);
187 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
187 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
188 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
188 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
189 QTimer::singleShot(0, animation, SLOT(start()));
189 QTimer::singleShot(0, animation, SLOT(start()));
190 }
190 }
191
191
192
192
193 void ChartAnimator::setState(State state, const QPointF &point)
193 void ChartAnimator::setState(State state, const QPointF &point)
194 {
194 {
195 m_state = state;
195 m_state = state;
196 m_point = point;
196 m_point = point;
197 }
197 }
198
198
199 void ChartAnimator::startAnimation(XYAnimation* animation)
199 void ChartAnimator::startAnimation(XYAnimation* animation)
200 {
200 {
201 Q_ASSERT(animation);
201 Q_ASSERT(animation);
202 if (animation->state() != QAbstractAnimation::Stopped)
202 if (animation->state() != QAbstractAnimation::Stopped) animation->stop();
203 animation->stop();
204 animation->setDuration(ChartAnimationDuration);
203 animation->setDuration(ChartAnimationDuration);
205 animation->setEasingCurve(QEasingCurve::OutQuart);
204 animation->setEasingCurve(QEasingCurve::OutQuart);
206 QTimer::singleShot(0, animation, SLOT(start()));
205 QTimer::singleShot(0, animation, SLOT(start()));
207 }
206 }
208
207
209 #include "moc_chartanimator_p.cpp"
208 #include "moc_chartanimator_p.cpp"
210
209
211 QTCOMMERCIALCHART_END_NAMESPACE
210 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,117 +1,120
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "xyanimation_p.h"
21 #include "xyanimation_p.h"
22 #include "xychart_p.h"
22 #include "xychart_p.h"
23 #include <QDebug>
23 #include <QDebug>
24
24
25 Q_DECLARE_METATYPE(QVector<QPointF>)
25 Q_DECLARE_METATYPE(QVector<QPointF>)
26
26
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28
28
29 XYAnimation::XYAnimation(XYChart *item):ChartAnimation(item),
29 XYAnimation::XYAnimation(XYChart *item):ChartAnimation(item),
30 m_item(item),
30 m_item(item),
31 m_dirty(false),
31 m_dirty(false),
32 m_type(MoveDownAnimation)
32 m_type(MoveDownAnimation)
33 {
33 {
34 }
34 }
35
35
36 XYAnimation::~XYAnimation()
36 XYAnimation::~XYAnimation()
37 {
37 {
38 }
38 }
39
39
40 void XYAnimation::setAnimationType(Animation type)
40 void XYAnimation::setAnimationType(Animation type)
41 {
41 {
42 if (state() != QAbstractAnimation::Stopped) stop();
42 m_type=type;
43 m_type=type;
43 }
44 }
44
45
45 void XYAnimation::setValues(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
46 void XYAnimation::setValues(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
46 {
47 {
48 if (state() != QAbstractAnimation::Stopped) stop();
49
47 int x = oldPoints.count();
50 int x = oldPoints.count();
48 int y = newPoints.count();
51 int y = newPoints.count();
49
52
50 if (x != y && abs(x - y) != 1) {
53 if (x != y && abs(x - y) != 1) {
51 m_oldPoints = newPoints;
54 m_oldPoints = newPoints;
52 oldPoints.resize(newPoints.size());
55 oldPoints.resize(newPoints.size());
53 setKeyValueAt(0.0, qVariantFromValue(oldPoints));
56 setKeyValueAt(0.0, qVariantFromValue(oldPoints));
54 setKeyValueAt(1.0, qVariantFromValue(newPoints));
57 setKeyValueAt(1.0, qVariantFromValue(newPoints));
55 m_dirty = false;
58 m_dirty = false;
56 }
59 }
57 else {
60 else {
58 if (m_dirty) {
61 if (m_dirty) {
59 m_oldPoints = oldPoints;
62 m_oldPoints = oldPoints;
60 m_dirty = false;
63 m_dirty = false;
61 }
64 }
62 oldPoints = newPoints;
65 oldPoints = newPoints;
63 if (y < x)
66 if (y < x)
64 m_oldPoints.remove(index); //remove
67 m_oldPoints.remove(index); //remove
65 if (y > x)
68 if (y > x)
66 m_oldPoints.insert(index, x > 0 ? m_oldPoints[index-1] : newPoints[index]); //add
69 m_oldPoints.insert(index, x > 0 ? m_oldPoints[index-1] : newPoints[index]); //add
67 setKeyValueAt(0.0, qVariantFromValue(m_oldPoints));
70 setKeyValueAt(0.0, qVariantFromValue(m_oldPoints));
68 setKeyValueAt(1.0, qVariantFromValue(newPoints));
71 setKeyValueAt(1.0, qVariantFromValue(newPoints));
69 Q_ASSERT(m_oldPoints.count() == newPoints.count());
72 Q_ASSERT(m_oldPoints.count() == newPoints.count());
70 }
73 }
71 }
74 }
72
75
73 QVariant XYAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress ) const
76 QVariant XYAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress ) const
74 {
77 {
75 QVector<QPointF> startVector = qVariantValue<QVector<QPointF> >(start);
78 QVector<QPointF> startVector = qVariantValue<QVector<QPointF> >(start);
76 QVector<QPointF> endVector = qVariantValue<QVector<QPointF> >(end);
79 QVector<QPointF> endVector = qVariantValue<QVector<QPointF> >(end);
77 QVector<QPointF> result;
80 QVector<QPointF> result;
78
81
79 switch (m_type) {
82 switch (m_type) {
80
83
81 case MoveDownAnimation: {
84 case MoveDownAnimation: {
82
85
83 if (startVector.count() != endVector.count())
86 if (startVector.count() != endVector.count())
84 break;
87 break;
85
88
86 for(int i = 0; i < startVector.count(); i++) {
89 for(int i = 0; i < startVector.count(); i++) {
87 qreal x = startVector[i].x() + ((endVector[i].x() - startVector[i].x()) * progress);
90 qreal x = startVector[i].x() + ((endVector[i].x() - startVector[i].x()) * progress);
88 qreal y = startVector[i].y() + ((endVector[i].y() - startVector[i].y()) * progress);
91 qreal y = startVector[i].y() + ((endVector[i].y() - startVector[i].y()) * progress);
89 result << QPointF(x, y);
92 result << QPointF(x, y);
90 }
93 }
91
94
92 }
95 }
93 break;
96 break;
94 case LineDrawAnimation: {
97 case LineDrawAnimation: {
95 for(int i = 0; i < endVector.count() * qBound(qreal(0), progress, qreal(1)); i++)
98 for(int i = 0; i < endVector.count() * qBound(qreal(0), progress, qreal(1)); i++)
96 result << endVector[i];
99 result << endVector[i];
97 }
100 }
98 break;
101 break;
99 default:
102 default:
100 qWarning() << "Unknown type of animation";
103 qWarning() << "Unknown type of animation";
101 break;
104 break;
102 }
105 }
103
106
104 return qVariantFromValue(result);
107 return qVariantFromValue(result);
105 }
108 }
106
109
107 void XYAnimation::updateCurrentValue (const QVariant &value)
110 void XYAnimation::updateCurrentValue (const QVariant &value)
108 {
111 {
109 if(state()!=QAbstractAnimation::Stopped){ //workaround
112 if(state()!=QAbstractAnimation::Stopped){ //workaround
110 m_dirty = true;
113 m_dirty = true;
111 QVector<QPointF> vector = qVariantValue<QVector<QPointF> >(value);
114 QVector<QPointF> vector = qVariantValue<QVector<QPointF> >(value);
112 m_item->setGeometryPoints(vector);
115 m_item->setGeometryPoints(vector);
113 m_item->updateGeometry();
116 m_item->updateGeometry();
114 }
117 }
115 }
118 }
116
119
117 QTCOMMERCIALCHART_END_NAMESPACE
120 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,304 +1,304
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "xychart_p.h"
21 #include "xychart_p.h"
22 #include "qxyseries.h"
22 #include "qxyseries.h"
23 #include "qxyseries_p.h"
23 #include "qxyseries_p.h"
24 #include "chartpresenter_p.h"
24 #include "chartpresenter_p.h"
25 #include "chartanimator_p.h"
25 #include "chartanimator_p.h"
26 #include <QPainter>
26 #include <QPainter>
27 #include <QAbstractItemModel>
27 #include <QAbstractItemModel>
28 #include "qxymodelmapper.h"
28 #include "qxymodelmapper.h"
29
29
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
31
32 //TODO: optimize : remove points which are not visible
32 //TODO: optimize : remove points which are not visible
33
33
34 XYChart::XYChart(QXYSeries *series, ChartPresenter *presenter):Chart(presenter),
34 XYChart::XYChart(QXYSeries *series, ChartPresenter *presenter):Chart(presenter),
35 m_minX(0),
35 m_minX(0),
36 m_maxX(0),
36 m_maxX(0),
37 m_minY(0),
37 m_minY(0),
38 m_maxY(0),
38 m_maxY(0),
39 m_series(series),
39 m_series(series),
40 m_animation(0)
40 m_animation(0)
41 {
41 {
42 QObject::connect(series->d_func(),SIGNAL(pointReplaced(int)),this,SLOT(handlePointReplaced(int)));
42 QObject::connect(series->d_func(),SIGNAL(pointReplaced(int)),this,SLOT(handlePointReplaced(int)));
43 QObject::connect(series->d_func(),SIGNAL(pointAdded(int)),this,SLOT(handlePointAdded(int)));
43 QObject::connect(series->d_func(),SIGNAL(pointAdded(int)),this,SLOT(handlePointAdded(int)));
44 QObject::connect(series->d_func(),SIGNAL(pointsAdded(int, int)),this,SLOT(handlePointsAdded(int, int)));
44 QObject::connect(series->d_func(),SIGNAL(pointsAdded(int, int)),this,SLOT(handlePointsAdded(int, int)));
45 QObject::connect(series->d_func(),SIGNAL(pointRemoved(int)),this,SLOT(handlePointRemoved(int)));
45 QObject::connect(series->d_func(),SIGNAL(pointRemoved(int)),this,SLOT(handlePointRemoved(int)));
46 QObject::connect(series->d_func(),SIGNAL(pointsRemoved(int, int)),this,SLOT(handlePointsRemoved(int, int)));
46 QObject::connect(series->d_func(),SIGNAL(pointsRemoved(int, int)),this,SLOT(handlePointsRemoved(int, int)));
47 QObject::connect(series->d_func(),SIGNAL(reinitialized()),this,SLOT(handleReinitialized()));
47 QObject::connect(series->d_func(),SIGNAL(reinitialized()),this,SLOT(handleReinitialized()));
48 QObject::connect(this,SIGNAL(clicked(QPointF)),series,SIGNAL(clicked(QPointF)));
48 QObject::connect(this,SIGNAL(clicked(QPointF)),series,SIGNAL(clicked(QPointF)));
49 }
49 }
50
50
51 void XYChart::setGeometryPoints(QVector<QPointF>& points)
51 void XYChart::setGeometryPoints(QVector<QPointF>& points)
52 {
52 {
53 m_points = points;
53 m_points = points;
54 }
54 }
55
55
56 void XYChart::setClipRect(const QRectF &rect)
56 void XYChart::setClipRect(const QRectF &rect)
57 {
57 {
58 m_clipRect = rect;
58 m_clipRect = rect;
59 }
59 }
60
60
61 void XYChart::setAnimation(XYAnimation* animation)
61 void XYChart::setAnimation(XYAnimation* animation)
62 {
62 {
63 m_animation=animation;
63 m_animation=animation;
64 }
64 }
65
65
66 QPointF XYChart::calculateGeometryPoint(const QPointF &point) const
66 QPointF XYChart::calculateGeometryPoint(const QPointF &point) const
67 {
67 {
68 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
68 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
69 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
69 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
70 qreal x = (point.x() - m_minX)* deltaX;
70 qreal x = (point.x() - m_minX)* deltaX;
71 qreal y = (point.y() - m_minY)*-deltaY + m_size.height();
71 qreal y = (point.y() - m_minY)*-deltaY + m_size.height();
72 return QPointF(x,y);
72 return QPointF(x,y);
73 }
73 }
74
74
75 QPointF XYChart::calculateGeometryPoint(int index) const
75 QPointF XYChart::calculateGeometryPoint(int index) const
76 {
76 {
77 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
77 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
78 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
78 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
79 const QList<QPointF>& vector = m_series->points();
79 const QList<QPointF>& vector = m_series->points();
80 qreal x = (vector[index].x() - m_minX)* deltaX;
80 qreal x = (vector[index].x() - m_minX)* deltaX;
81 qreal y = (vector[index].y() - m_minY)*-deltaY + m_size.height();
81 qreal y = (vector[index].y() - m_minY)*-deltaY + m_size.height();
82 return QPointF(x,y);
82 return QPointF(x,y);
83 }
83 }
84
84
85 QVector<QPointF> XYChart::calculateGeometryPoints() const
85 QVector<QPointF> XYChart::calculateGeometryPoints() const
86 {
86 {
87 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
87 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
88 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
88 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
89
89
90 QVector<QPointF> result;
90 QVector<QPointF> result;
91 result.resize(m_series->count());
91 result.resize(m_series->count());
92 const QList<QPointF>& vector = m_series->points();
92 const QList<QPointF>& vector = m_series->points();
93 for (int i = 0; i < m_series->count(); ++i) {
93 for (int i = 0; i < m_series->count(); ++i) {
94 qreal x = (vector[i].x() - m_minX)* deltaX;
94 qreal x = (vector[i].x() - m_minX)* deltaX;
95 qreal y = (vector[i].y() - m_minY)*-deltaY + m_size.height();
95 qreal y = (vector[i].y() - m_minY)*-deltaY + m_size.height();
96 result[i].setX(x);
96 result[i].setX(x);
97 result[i].setY(y);
97 result[i].setY(y);
98 }
98 }
99 return result;
99 return result;
100 }
100 }
101
101
102 QPointF XYChart::calculateDomainPoint(const QPointF &point) const
102 QPointF XYChart::calculateDomainPoint(const QPointF &point) const
103 {
103 {
104 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
104 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
105 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
105 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
106 qreal x = point.x()/deltaX +m_minX;
106 qreal x = point.x()/deltaX +m_minX;
107 qreal y = (point.y()-m_size.height())/(-deltaY)+ m_minY;
107 qreal y = (point.y()-m_size.height())/(-deltaY)+ m_minY;
108 return QPointF(x,y);
108 return QPointF(x,y);
109 }
109 }
110
110
111 void XYChart::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints,int index)
111 void XYChart::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints,int index)
112 {
112 {
113 if (m_animation) {
113 if (m_animation) {
114 m_animation->setValues(oldPoints, newPoints, index);
114 m_animation->setValues(oldPoints, newPoints, index);
115 animator()->startAnimation(m_animation);
115 animator()->startAnimation(m_animation);
116 }
116 }
117 else {
117 else {
118 setGeometryPoints(newPoints);
118 setGeometryPoints(newPoints);
119 updateGeometry();
119 updateGeometry();
120 }
120 }
121 }
121 }
122
122
123 //handlers
123 //handlers
124
124
125 void XYChart::handlePointAdded(int index)
125 void XYChart::handlePointAdded(int index)
126 {
126 {
127 if (m_series->model() == 0) {
127 if (m_series->model() == 0) {
128 Q_ASSERT(index<m_series->count());
128 Q_ASSERT(index<m_series->count());
129 Q_ASSERT(index>=0);
129 Q_ASSERT(index>=0);
130 }
130 }
131
131
132 QVector<QPointF> points = m_points;
132 QVector<QPointF> points = m_points;
133 QPointF point;
133 QPointF point;
134 point = calculateGeometryPoint(index);
134 point = calculateGeometryPoint(index);
135 points.insert(index, point);
135 points.insert(index, point);
136
136
137 if(m_animation) {
137 if(m_animation) {
138 m_animation->setAnimationType(XYAnimation::LineDrawAnimation);
138 m_animation->setAnimationType(XYAnimation::LineDrawAnimation);
139 }
139 }
140
140
141 updateChart(m_points,points,index);
141 updateChart(m_points,points,index);
142 }
142 }
143
143
144 void XYChart::handlePointsAdded(int start, int end)
144 void XYChart::handlePointsAdded(int start, int end)
145 {
145 {
146 if (m_series->model() == 0) {
146 if (m_series->model() == 0) {
147 for (int i = start; i <= end; i++)
147 for (int i = start; i <= end; i++)
148 handlePointAdded(i);
148 handlePointAdded(i);
149 }
149 }
150 else {
150 else {
151 int mapFirst = m_series->modelMapper()->first();
151 int mapFirst = m_series->modelMapper()->first();
152 int mapCount = m_series->modelMapper()->count();
152 int mapCount = m_series->modelMapper()->count();
153 if (mapCount != -1 && start >= mapFirst + mapCount) {
153 if (mapCount != -1 && start >= mapFirst + mapCount) {
154 return;
154 return;
155 }
155 }
156 else {
156 else {
157 int addedCount = end - start + 1;
157 int addedCount = end - start + 1;
158 if (mapCount != -1 && addedCount > mapCount)
158 if (mapCount != -1 && addedCount > mapCount)
159 addedCount = mapCount;
159 addedCount = mapCount;
160 int first = qMax(start, mapFirst); // get the index of the first item that will be added
160 int first = qMax(start, mapFirst); // get the index of the first item that will be added
161 int last = qMin(first + addedCount - 1, mapCount + mapFirst - 1);// get the index of the last item that will be added
161 int last = qMin(first + addedCount - 1, mapCount + mapFirst - 1);// get the index of the last item that will be added
162 for (int i = first; i <= last; i++) {
162 for (int i = first; i <= last; i++) {
163 handlePointAdded(i - mapFirst);
163 handlePointAdded(i - mapFirst);
164 }
164 }
165 // the map is limited therefore the items that are now outside the map
165 // the map is limited therefore the items that are now outside the map
166 // need to be removed from the drawn points
166 // need to be removed from the drawn points
167 if (mapCount != -1 && m_points.size() > mapCount)
167 if (mapCount != -1 && m_points.size() > mapCount)
168 for (int i = m_points.size() - 1; i >= mapCount; i--)
168 for (int i = m_points.size() - 1; i >= mapCount; i--)
169 handlePointRemoved(i);
169 handlePointRemoved(i);
170 }
170 }
171 }
171 }
172 }
172 }
173
173
174 void XYChart::handlePointRemoved(int index)
174 void XYChart::handlePointRemoved(int index)
175 {
175 {
176 if (m_series->model() == 0) {
176 if (m_series->model() == 0) {
177 Q_ASSERT(index<m_series->count() + 1);
177 Q_ASSERT(index<m_series->count() + 1);
178 Q_ASSERT(index>=0);
178 Q_ASSERT(index>=0);
179 }
179 }
180 QVector<QPointF> points = m_points;
180 QVector<QPointF> points = m_points;
181 points.remove(index);
181 points.remove(index);
182
182
183 if(m_animation) {
183 if(m_animation) {
184 m_animation->setAnimationType(XYAnimation::LineDrawAnimation);
184 m_animation->setAnimationType(XYAnimation::LineDrawAnimation);
185 }
185 }
186
186
187 updateChart(m_points,points,index);
187 updateChart(m_points,points,index);
188 }
188 }
189
189
190 void XYChart::handlePointsRemoved(int start, int end)
190 void XYChart::handlePointsRemoved(int start, int end)
191 {
191 {
192 Q_UNUSED(start)
192 Q_UNUSED(start)
193 Q_UNUSED(end)
193 Q_UNUSED(end)
194 if (m_series->model() == 0) {
194 if (m_series->model() == 0) {
195 for (int i = end; i >= start; i--)
195 for (int i = end; i >= start; i--)
196 handlePointRemoved(i);
196 handlePointRemoved(i);
197 }
197 }
198 else {
198 else {
199 // series uses model as a data source
199 // series uses model as a data source
200 int mapFirst = m_series->modelMapper()->first();
200 int mapFirst = m_series->modelMapper()->first();
201 int mapCount = m_series->modelMapper()->count();
201 int mapCount = m_series->modelMapper()->count();
202 int removedCount = end - start + 1;
202 int removedCount = end - start + 1;
203 if (mapCount != -1 && start >= mapFirst + mapCount) {
203 if (mapCount != -1 && start >= mapFirst + mapCount) {
204 return;
204 return;
205 }
205 }
206 else {
206 else {
207 int toRemove = qMin(m_points.size(), removedCount); // first find how many items can actually be removed
207 int toRemove = qMin(m_points.size(), removedCount); // first find how many items can actually be removed
208 int first = qMax(start, mapFirst);// get the index of the first item that will be removed.
208 int first = qMax(start, mapFirst);// get the index of the first item that will be removed.
209 int last = qMin(first + toRemove - 1, m_points.size() + mapFirst - 1);// get the index of the last item that will be removed.
209 int last = qMin(first + toRemove - 1, m_points.size() + mapFirst - 1);// get the index of the last item that will be removed.
210 if (last - first == 0) {
210 if (last - first == 0) {
211 for (int i = last; i >= first; i--) {
211 for (int i = last; i >= first; i--) {
212 handlePointRemoved(i - mapFirst);
212 handlePointRemoved(i - mapFirst);
213
213
214 }
214 }
215 }
215 }
216 else {
216 else {
217 QVector<QPointF> points = m_points;
217 QVector<QPointF> points = m_points;
218 for (int i = last; i >= first; i--)
218 for (int i = last; i >= first; i--)
219 points.remove(i - mapFirst);
219 points.remove(i - mapFirst);
220 setGeometryPoints(points);
220 setGeometryPoints(points);
221 updateGeometry();
221 updateGeometry();
222 }
222 }
223 if (mapCount != -1) {
223 if (mapCount != -1) {
224 int itemsAvailable; // check how many are available to be added
224 int itemsAvailable; // check how many are available to be added
225 if (m_series->modelMapper()->orientation() == Qt::Vertical)
225 if (m_series->modelMapper()->orientation() == Qt::Vertical)
226 itemsAvailable = m_series->model()->rowCount() - mapFirst - m_points.size();
226 itemsAvailable = m_series->model()->rowCount() - mapFirst - m_points.size();
227 else
227 else
228 itemsAvailable = m_series->model()->columnCount() - mapFirst - m_points.size();
228 itemsAvailable = m_series->model()->columnCount() - mapFirst - m_points.size();
229 int toBeAdded = qMin(itemsAvailable, mapCount - m_points.size());// add not more items than there is space left to be filled.
229 int toBeAdded = qMin(itemsAvailable, mapCount - m_points.size());// add not more items than there is space left to be filled.
230 int currentSize = m_points.size();
230 int currentSize = m_points.size();
231 if (toBeAdded > 0)
231 if (toBeAdded > 0)
232 for (int i = m_points.size(); i < currentSize + toBeAdded; i++) {
232 for (int i = m_points.size(); i < currentSize + toBeAdded; i++) {
233 handlePointAdded(i);
233 handlePointAdded(i);
234 }
234 }
235 }
235 }
236 }
236 }
237 }
237 }
238
238
239 }
239 }
240
240
241 void XYChart::handlePointReplaced(int index)
241 void XYChart::handlePointReplaced(int index)
242 {
242 {
243 Q_ASSERT(index<m_series->count());
243 Q_ASSERT(index<m_series->count());
244 Q_ASSERT(index>=0);
244 Q_ASSERT(index>=0);
245 QPointF point = calculateGeometryPoint(index);
245 QPointF point = calculateGeometryPoint(index);
246 QVector<QPointF> points = m_points;
246 QVector<QPointF> points = m_points;
247 points.replace(index,point);
247 points.replace(index,point);
248
248
249 if(m_animation) {
249 if(m_animation) {
250 m_animation->setAnimationType(XYAnimation::MoveDownAnimation);
250 m_animation->setAnimationType(XYAnimation::MoveDownAnimation);
251 }
251 }
252
252
253 updateChart(m_points,points,index);
253 updateChart(m_points,points,index);
254 }
254 }
255
255
256 void XYChart::handleReinitialized()
256 void XYChart::handleReinitialized()
257 {
257 {
258 QVector<QPointF> points = calculateGeometryPoints();
258 QVector<QPointF> points = calculateGeometryPoints();
259
259
260 if(m_animation) {
260 if(m_animation) {
261 m_animation->setAnimationType(XYAnimation::LineDrawAnimation);
261 m_animation->setAnimationType(XYAnimation::LineDrawAnimation);
262 }
262 }
263
263
264 updateChart(m_points,points);
264 updateChart(m_points,points);
265 }
265 }
266
266
267 void XYChart::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
267 void XYChart::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
268 {
268 {
269 m_minX=minX;
269 m_minX=minX;
270 m_maxX=maxX;
270 m_maxX=maxX;
271 m_minY=minY;
271 m_minY=minY;
272 m_maxY=maxY;
272 m_maxY=maxY;
273 if (isEmpty()) return;
273 if (isEmpty()) return;
274 QVector<QPointF> points = calculateGeometryPoints();
274 QVector<QPointF> points = calculateGeometryPoints();
275
275
276 if(m_animation) {
276 if(m_animation) {
277 m_animation->setAnimationType(XYAnimation::LineDrawAnimation);
277 m_animation->setAnimationType(XYAnimation::MoveDownAnimation);
278 }
278 }
279 updateChart(m_points,points);
279 updateChart(m_points,points);
280 }
280 }
281
281
282 void XYChart::handleGeometryChanged(const QRectF &rect)
282 void XYChart::handleGeometryChanged(const QRectF &rect)
283 {
283 {
284 Q_ASSERT(rect.isValid());
284 Q_ASSERT(rect.isValid());
285 m_size=rect.size();
285 m_size=rect.size();
286 m_clipRect=rect.translated(-rect.topLeft());
286 m_clipRect=rect.translated(-rect.topLeft());
287 m_origin=rect.topLeft();
287 m_origin=rect.topLeft();
288
288
289 if (isEmpty()) return;
289 if (isEmpty()) return;
290 QVector<QPointF> points = calculateGeometryPoints();
290 QVector<QPointF> points = calculateGeometryPoints();
291 if(m_animation) {
291 if(m_animation) {
292 m_animation->setAnimationType(XYAnimation::LineDrawAnimation);
292 m_animation->setAnimationType(XYAnimation::LineDrawAnimation);
293 }
293 }
294 updateChart(m_points,points);
294 updateChart(m_points,points);
295 }
295 }
296
296
297 bool XYChart::isEmpty()
297 bool XYChart::isEmpty()
298 {
298 {
299 return !m_clipRect.isValid() || qFuzzyIsNull(m_maxX - m_minX) || qFuzzyIsNull(m_maxY - m_minY) || m_series->points().isEmpty();
299 return !m_clipRect.isValid() || qFuzzyIsNull(m_maxX - m_minX) || qFuzzyIsNull(m_maxY - m_minY) || m_series->points().isEmpty();
300 }
300 }
301
301
302 #include "moc_xychart_p.cpp"
302 #include "moc_xychart_p.cpp"
303
303
304 QTCOMMERCIALCHART_END_NAMESPACE
304 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now