##// END OF EJS Templates
Refactor graphical side of pie to simplify the implementation.
Jani Honkonen -
r1074:22571433397b
parent child
Show More
@@ -1,301 +1,294
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 "xychartitem_p.h"
25 #include "xychartitem_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 const static int duration = 1000;
40 const static int duration = 1000;
41
41
42 ChartAnimator::ChartAnimator(QObject *parent):QObject(parent),
42 ChartAnimator::ChartAnimator(QObject *parent):QObject(parent),
43 m_state(ShowState)
43 m_state(ShowState)
44 {
44 {
45 }
45 }
46
46
47 ChartAnimator::~ChartAnimator()
47 ChartAnimator::~ChartAnimator()
48 {
48 {
49 }
49 }
50
50
51 void ChartAnimator::addAnimation(ChartAxis *item)
51 void ChartAnimator::addAnimation(ChartAxis *item)
52 {
52 {
53 ChartAnimation *animation = m_animations.value(item);
53 ChartAnimation *animation = m_animations.value(item);
54
54
55 if (!animation) {
55 if (!animation) {
56 animation = new AxisAnimation(item);
56 animation = new AxisAnimation(item);
57 m_animations.insert(item, animation);
57 m_animations.insert(item, animation);
58 }
58 }
59
59
60 item->setAnimator(this);
60 item->setAnimator(this);
61 }
61 }
62
62
63 void ChartAnimator::addAnimation(SplineChartItem *item)
63 void ChartAnimator::addAnimation(SplineChartItem *item)
64 {
64 {
65 ChartAnimation *animation = m_animations.value(item);
65 ChartAnimation *animation = m_animations.value(item);
66
66
67 if (!animation) {
67 if (!animation) {
68 animation = new SplineAnimation(item);
68 animation = new SplineAnimation(item);
69 m_animations.insert(item, animation);
69 m_animations.insert(item, animation);
70 }
70 }
71
71
72 item->setAnimator(this);
72 item->setAnimator(this);
73 }
73 }
74
74
75 void ChartAnimator::addAnimation(ScatterChartItem *item)
75 void ChartAnimator::addAnimation(ScatterChartItem *item)
76 {
76 {
77 ChartAnimation *animation = m_animations.value(item);
77 ChartAnimation *animation = m_animations.value(item);
78
78
79 if (!animation) {
79 if (!animation) {
80 animation = new XYAnimation(item);
80 animation = new XYAnimation(item);
81 m_animations.insert(item, animation);
81 m_animations.insert(item, animation);
82 }
82 }
83
83
84 item->setAnimator(this);
84 item->setAnimator(this);
85 }
85 }
86
86
87 void ChartAnimator::addAnimation(LineChartItem *item)
87 void ChartAnimator::addAnimation(LineChartItem *item)
88 {
88 {
89 ChartAnimation *animation = m_animations.value(item);
89 ChartAnimation *animation = m_animations.value(item);
90
90
91 if (!animation) {
91 if (!animation) {
92 animation = new XYAnimation(item);
92 animation = new XYAnimation(item);
93 m_animations.insert(item, animation);
93 m_animations.insert(item, animation);
94 }
94 }
95
95
96 item->setAnimator(this);
96 item->setAnimator(this);
97 }
97 }
98
98
99 void ChartAnimator::addAnimation(PieChartItem *item)
99 void ChartAnimator::addAnimation(PieChartItem *item)
100 {
100 {
101 ChartAnimation *animation = m_animations.value(item);
101 ChartAnimation *animation = m_animations.value(item);
102
102
103 if (!animation) {
103 if (!animation) {
104 animation = new PieAnimation(item);
104 animation = new PieAnimation(item);
105 m_animations.insert(item, animation);
105 m_animations.insert(item, animation);
106 }
106 }
107
107
108 item->setAnimator(this);
108 item->setAnimator(this);
109 }
109 }
110
110
111 void ChartAnimator::addAnimation(BarChartItem *item)
111 void ChartAnimator::addAnimation(BarChartItem *item)
112 {
112 {
113 ChartAnimation *animation = m_animations.value(item);
113 ChartAnimation *animation = m_animations.value(item);
114
114
115 if (!animation) {
115 if (!animation) {
116 animation = new BarAnimation(item);
116 animation = new BarAnimation(item);
117 m_animations.insert(item, animation);
117 m_animations.insert(item, animation);
118 }
118 }
119
119
120 item->setAnimator(this);
120 item->setAnimator(this);
121 }
121 }
122
122
123
123
124 void ChartAnimator::removeAnimation(Chart *item)
124 void ChartAnimator::removeAnimation(Chart *item)
125 {
125 {
126 item->setAnimator(0);
126 item->setAnimator(0);
127 m_animations.remove(item);
127 m_animations.remove(item);
128 }
128 }
129
129
130 void ChartAnimator::updateLayout(ChartAxis *item , QVector<qreal> &newLayout)
130 void ChartAnimator::updateLayout(ChartAxis *item , QVector<qreal> &newLayout)
131 {
131 {
132 AxisAnimation *animation = static_cast<AxisAnimation*>(m_animations.value(item));
132 AxisAnimation *animation = static_cast<AxisAnimation*>(m_animations.value(item));
133
133
134 Q_ASSERT(animation);
134 Q_ASSERT(animation);
135
135
136 QVector<qreal> oldLayout = item->layout();
136 QVector<qreal> oldLayout = item->layout();
137
137
138 if (newLayout.count() == 0)
138 if (newLayout.count() == 0)
139 return;
139 return;
140
140
141 switch (m_state) {
141 switch (m_state) {
142 case ZoomOutState: {
142 case ZoomOutState: {
143 QRectF rect = item->geometry();
143 QRectF rect = item->geometry();
144 oldLayout.resize(newLayout.count());
144 oldLayout.resize(newLayout.count());
145
145
146 for(int i = 0, j = oldLayout.count() - 1; i < (oldLayout.count() + 1) / 2; ++i, --j) {
146 for(int i = 0, j = oldLayout.count() - 1; i < (oldLayout.count() + 1) / 2; ++i, --j) {
147 oldLayout[i] = item->axisType() == ChartAxis::X_AXIS ? rect.left() : rect.bottom();
147 oldLayout[i] = item->axisType() == ChartAxis::X_AXIS ? rect.left() : rect.bottom();
148 oldLayout[j] = item->axisType() == ChartAxis::X_AXIS ? rect.right() : rect.top();
148 oldLayout[j] = item->axisType() == ChartAxis::X_AXIS ? rect.right() : rect.top();
149 }
149 }
150 }
150 }
151 break;
151 break;
152 case ZoomInState: {
152 case ZoomInState: {
153 int index = qMin(oldLayout.count() * (item->axisType() == ChartAxis::X_AXIS ? m_point.x() : (1 - m_point.y())), newLayout.count() - 1.0);
153 int index = qMin(oldLayout.count() * (item->axisType() == ChartAxis::X_AXIS ? m_point.x() : (1 - m_point.y())), newLayout.count() - 1.0);
154 oldLayout.resize(newLayout.count());
154 oldLayout.resize(newLayout.count());
155
155
156 for(int i = 0; i < oldLayout.count(); i++)
156 for(int i = 0; i < oldLayout.count(); i++)
157 oldLayout[i]= oldLayout[index];
157 oldLayout[i]= oldLayout[index];
158 }
158 }
159 break;
159 break;
160 case ScrollDownState:
160 case ScrollDownState:
161 case ScrollRightState: {
161 case ScrollRightState: {
162 oldLayout.resize(newLayout.count());
162 oldLayout.resize(newLayout.count());
163
163
164 for(int i = 0, j = i + 1; i < oldLayout.count() - 1; ++i, ++j)
164 for(int i = 0, j = i + 1; i < oldLayout.count() - 1; ++i, ++j)
165 oldLayout[i]= oldLayout[j];
165 oldLayout[i]= oldLayout[j];
166 }
166 }
167 break;
167 break;
168 case ScrollUpState:
168 case ScrollUpState:
169 case ScrollLeftState: {
169 case ScrollLeftState: {
170 oldLayout.resize(newLayout.count());
170 oldLayout.resize(newLayout.count());
171
171
172 for(int i = oldLayout.count() - 1, j = i - 1; i > 0; --i, --j)
172 for(int i = oldLayout.count() - 1, j = i - 1; i > 0; --i, --j)
173 oldLayout[i]= oldLayout[j];
173 oldLayout[i]= oldLayout[j];
174 }
174 }
175 break;
175 break;
176 default: {
176 default: {
177 oldLayout.resize(newLayout.count());
177 oldLayout.resize(newLayout.count());
178 QRectF rect = item->geometry();
178 QRectF rect = item->geometry();
179 for(int i = 0, j = oldLayout.count() - 1; i < oldLayout.count(); ++i, --j)
179 for(int i = 0, j = oldLayout.count() - 1; i < oldLayout.count(); ++i, --j)
180 oldLayout[i] = item->axisType() == ChartAxis::X_AXIS ? rect.left() : rect.top();
180 oldLayout[i] = item->axisType() == ChartAxis::X_AXIS ? rect.left() : rect.top();
181 }
181 }
182 break;
182 break;
183 }
183 }
184
184
185
185
186 if (animation->state() != QAbstractAnimation::Stopped)
186 if (animation->state() != QAbstractAnimation::Stopped)
187 animation->stop();
187 animation->stop();
188
188
189 animation->setDuration(duration);
189 animation->setDuration(duration);
190 animation->setEasingCurve(QEasingCurve::OutQuart);
190 animation->setEasingCurve(QEasingCurve::OutQuart);
191 QVariantAnimation::KeyValues value;
191 QVariantAnimation::KeyValues value;
192 animation->setKeyValues(value); //workaround for wrong interpolation call
192 animation->setKeyValues(value); //workaround for wrong interpolation call
193 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
193 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
194 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
194 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
195
195
196 QTimer::singleShot(0, animation, SLOT(start()));
196 QTimer::singleShot(0, animation, SLOT(start()));
197 }
197 }
198
198
199 void ChartAnimator::updateLayout(SplineChartItem *item, QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, QVector<QPointF> &oldControlPoints, QVector<QPointF> &newControlPoints, int index)
199 void ChartAnimator::updateLayout(SplineChartItem *item, QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, QVector<QPointF> &oldControlPoints, QVector<QPointF> &newControlPoints, int index)
200 {
200 {
201 SplineAnimation *animation = static_cast<SplineAnimation *>(m_animations.value(item));
201 SplineAnimation *animation = static_cast<SplineAnimation *>(m_animations.value(item));
202
202
203 Q_ASSERT(animation);
203 Q_ASSERT(animation);
204
204
205 if (newPoints.count() < 2 || newControlPoints.count() < 2)
205 if (newPoints.count() < 2 || newControlPoints.count() < 2)
206 return;
206 return;
207
207
208 bool empty = oldPoints.count() == 0;
208 bool empty = oldPoints.count() == 0;
209
209
210
210
211 if (animation->state() != QAbstractAnimation::Stopped)
211 if (animation->state() != QAbstractAnimation::Stopped)
212 animation->stop();
212 animation->stop();
213
213
214 animation->setDuration(duration);
214 animation->setDuration(duration);
215 if (!empty)
215 if (!empty)
216 animation->setAnimationType(ChartAnimation::MoveDownAnimation);
216 animation->setAnimationType(ChartAnimation::MoveDownAnimation);
217 else
217 else
218 animation->setAnimationType(ChartAnimation::LineDrawAnimation);
218 animation->setAnimationType(ChartAnimation::LineDrawAnimation);
219
219
220 animation->setEasingCurve(QEasingCurve::OutQuart);
220 animation->setEasingCurve(QEasingCurve::OutQuart);
221 animation->setValues(oldPoints, newPoints, oldControlPoints, newControlPoints, index);
221 animation->setValues(oldPoints, newPoints, oldControlPoints, newControlPoints, index);
222
222
223 QTimer::singleShot(0, animation, SLOT(start()));
223 QTimer::singleShot(0, animation, SLOT(start()));
224 }
224 }
225
225
226
226
227 void ChartAnimator::updateLayout(XYChartItem *item, QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
227 void ChartAnimator::updateLayout(XYChartItem *item, QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
228 {
228 {
229 XYAnimation *animation = static_cast<XYAnimation *>(m_animations.value(item));
229 XYAnimation *animation = static_cast<XYAnimation *>(m_animations.value(item));
230
230
231 Q_ASSERT(animation);
231 Q_ASSERT(animation);
232
232
233 if (newPoints.count() == 0)
233 if (newPoints.count() == 0)
234 return;
234 return;
235
235
236 bool empty = oldPoints.count() == 0;
236 bool empty = oldPoints.count() == 0;
237
237
238
238
239 if (animation->state() != QAbstractAnimation::Stopped)
239 if (animation->state() != QAbstractAnimation::Stopped)
240 animation->stop();
240 animation->stop();
241
241
242 animation->setDuration(duration);
242 animation->setDuration(duration);
243 if (!empty)
243 if (!empty)
244 animation->setAnimationType(ChartAnimation::MoveDownAnimation);
244 animation->setAnimationType(ChartAnimation::MoveDownAnimation);
245 else
245 else
246 animation->setAnimationType(ChartAnimation::LineDrawAnimation);
246 animation->setAnimationType(ChartAnimation::LineDrawAnimation);
247
247
248 animation->setEasingCurve(QEasingCurve::OutQuart);
248 animation->setEasingCurve(QEasingCurve::OutQuart);
249 animation->setValues(oldPoints, newPoints, index);
249 animation->setValues(oldPoints, newPoints, index);
250
250
251 QTimer::singleShot(0, animation, SLOT(start()));
251 QTimer::singleShot(0, animation, SLOT(start()));
252 }
252 }
253
253
254 void ChartAnimator::addAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData, bool isEmpty)
254 void ChartAnimator::addAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData, bool startupAnimation)
255 {
255 {
256 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
256 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
257 Q_ASSERT(animation);
257 Q_ASSERT(animation);
258 animation->addSlice(sliceItem, sliceData, isEmpty);
258 animation->addSlice(sliceItem, sliceData, startupAnimation);
259 }
259 }
260
260
261 void ChartAnimator::removeAnimation(PieChartItem *item, PieSliceItem *sliceItem)
261 void ChartAnimator::removeAnimation(PieChartItem *item, PieSliceItem *sliceItem)
262 {
262 {
263 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
263 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
264 Q_ASSERT(animation);
264 Q_ASSERT(animation);
265 animation->removeSlice(sliceItem);
265 animation->removeSlice(sliceItem);
266 }
266 }
267
267
268 void ChartAnimator::updateLayout(PieChartItem *item, const PieLayout &layout)
268 void ChartAnimator::updateAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData)
269 {
270 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
271 Q_ASSERT(animation);
272 animation->updateValues(layout);
273 }
274
275 void ChartAnimator::updateLayout(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData)
276 {
269 {
277 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
270 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
278 Q_ASSERT(animation);
271 Q_ASSERT(animation);
279 animation->updateValue(sliceItem, sliceData);
272 animation->updateValue(sliceItem, sliceData);
280 }
273 }
281
274
282 void ChartAnimator::updateLayout(BarChartItem *item, const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout)
275 void ChartAnimator::updateLayout(BarChartItem *item, const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout)
283 {
276 {
284 BarAnimation *animation = static_cast<BarAnimation *>(m_animations.value(item));
277 BarAnimation *animation = static_cast<BarAnimation *>(m_animations.value(item));
285 Q_ASSERT(animation);
278 Q_ASSERT(animation);
286 animation->setDuration(duration);
279 animation->setDuration(duration);
287 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
280 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
288 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
281 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
289 QTimer::singleShot(0, animation, SLOT(start()));
282 QTimer::singleShot(0, animation, SLOT(start()));
290 }
283 }
291
284
292
285
293 void ChartAnimator::setState(State state, const QPointF &point)
286 void ChartAnimator::setState(State state, const QPointF &point)
294 {
287 {
295 m_state = state;
288 m_state = state;
296 m_point = point;
289 m_point = point;
297 }
290 }
298
291
299 #include "moc_chartanimator_p.cpp"
292 #include "moc_chartanimator_p.cpp"
300
293
301 QTCOMMERCIALCHART_END_NAMESPACE
294 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,79 +1,78
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 #ifndef CHARTANIMATOR_P_H
21 #ifndef CHARTANIMATOR_P_H
22 #define CHARTANIMATOR_P_H
22 #define CHARTANIMATOR_P_H
23
23
24 #include "qchartglobal.h"
24 #include "qchartglobal.h"
25 #include "chartanimation_p.h"
25 #include "chartanimation_p.h"
26 #include "piechartitem_p.h"
26 #include "piechartitem_p.h"
27 #include "barchartitem_p.h"
27 #include "barchartitem_p.h"
28 #include <QPointF>
28 #include <QPointF>
29
29
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
31
32 class ChartItem;
32 class ChartItem;
33 class ChartAxis;
33 class ChartAxis;
34 class AreaChartItem;
34 class AreaChartItem;
35 class SplineChartItem;
35 class SplineChartItem;
36 class ScatterChartItem;
36 class ScatterChartItem;
37 class LineChartItem;
37 class LineChartItem;
38 class XYChartItem;
38 class XYChartItem;
39
39
40 class ChartAnimator : public QObject
40 class ChartAnimator : public QObject
41 {
41 {
42 Q_OBJECT
42 Q_OBJECT
43 public:
43 public:
44 enum State{ShowState, ScrollUpState, ScrollDownState, ScrollLeftState, ScrollRightState, ZoomInState, ZoomOutState};
44 enum State{ShowState, ScrollUpState, ScrollDownState, ScrollLeftState, ScrollRightState, ZoomInState, ZoomOutState};
45
45
46 ChartAnimator(QObject *parent = 0);
46 ChartAnimator(QObject *parent = 0);
47 virtual ~ChartAnimator();
47 virtual ~ChartAnimator();
48
48
49 void addAnimation(ChartAxis *item);
49 void addAnimation(ChartAxis *item);
50 void addAnimation(PieChartItem *item);
50 void addAnimation(PieChartItem *item);
51 void addAnimation(ScatterChartItem *item);
51 void addAnimation(ScatterChartItem *item);
52 void addAnimation(LineChartItem *item);
52 void addAnimation(LineChartItem *item);
53 void addAnimation(SplineChartItem *item);
53 void addAnimation(SplineChartItem *item);
54 void addAnimation(BarChartItem *item);
54 void addAnimation(BarChartItem *item);
55 void removeAnimation(Chart *item);
55 void removeAnimation(Chart *item);
56
56
57 void animationStarted();
57 void animationStarted();
58 void updateLayout(XYChartItem *item, QVector<QPointF> &oldLayout, QVector<QPointF> &newLayout, int index);
58 void updateLayout(XYChartItem *item, QVector<QPointF> &oldLayout, QVector<QPointF> &newLayout, int index);
59 void updateLayout(SplineChartItem *item, QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, QVector<QPointF> &oldControlPoints, QVector<QPointF> &newContorlPoints, int index);
59 void updateLayout(SplineChartItem *item, QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, QVector<QPointF> &oldControlPoints, QVector<QPointF> &newContorlPoints, int index);
60 void updateLayout(ChartAxis *item, QVector<qreal> &layout);
60 void updateLayout(ChartAxis *item, QVector<qreal> &layout);
61
61
62 void addAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData, bool isEmpty);
62 void addAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData, bool isEmpty);
63 void removeAnimation(PieChartItem *item, PieSliceItem *sliceItem);
63 void removeAnimation(PieChartItem *item, PieSliceItem *sliceItem);
64 void updateLayout(PieChartItem *item, const PieLayout &layout);
64 void updateAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData);
65 void updateLayout(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData);
66
65
67 void updateLayout(BarChartItem *item, const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout);
66 void updateLayout(BarChartItem *item, const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout);
68
67
69 void setState(State state,const QPointF &point = QPointF());
68 void setState(State state,const QPointF &point = QPointF());
70
69
71 private:
70 private:
72 QMap<Chart *, ChartAnimation *> m_animations;
71 QMap<Chart *, ChartAnimation *> m_animations;
73 State m_state;
72 State m_state;
74 QPointF m_point;
73 QPointF m_point;
75 };
74 };
76
75
77 QTCOMMERCIALCHART_END_NAMESPACE
76 QTCOMMERCIALCHART_END_NAMESPACE
78
77
79 #endif
78 #endif
@@ -1,106 +1,100
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 "pieanimation_p.h"
21 #include "pieanimation_p.h"
22 #include "piesliceanimation_p.h"
22 #include "piesliceanimation_p.h"
23 #include "piechartitem_p.h"
23 #include "piechartitem_p.h"
24 #include <QParallelAnimationGroup>
24 #include <QParallelAnimationGroup>
25 #include <QTimer>
25 #include <QTimer>
26
26
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28
28
29 PieAnimation::PieAnimation(PieChartItem *item)
29 PieAnimation::PieAnimation(PieChartItem *item)
30 :ChartAnimation(item),
30 :ChartAnimation(item),
31 m_item(item)
31 m_item(item)
32 {
32 {
33 }
33 }
34
34
35 PieAnimation::~PieAnimation()
35 PieAnimation::~PieAnimation()
36 {
36 {
37 }
37 }
38
38
39 void PieAnimation::updateValues(const PieLayout &newValues)
40 {
41 foreach (PieSliceItem *s, newValues.keys())
42 updateValue(s, newValues.value(s));
43 }
44
45 void PieAnimation::updateValue(PieSliceItem *sliceItem, const PieSliceData &sliceData)
39 void PieAnimation::updateValue(PieSliceItem *sliceItem, const PieSliceData &sliceData)
46 {
40 {
47 PieSliceAnimation *animation = m_animations.value(sliceItem);
41 PieSliceAnimation *animation = m_animations.value(sliceItem);
48 Q_ASSERT(animation);
42 Q_ASSERT(animation);
49 animation->stop();
43 animation->stop();
50
44
51 animation->updateValue(sliceData);
45 animation->updateValue(sliceData);
52 animation->setDuration(1000);
46 animation->setDuration(1000);
53 animation->setEasingCurve(QEasingCurve::OutQuart);
47 animation->setEasingCurve(QEasingCurve::OutQuart);
54
48
55 QTimer::singleShot(0, animation, SLOT(start()));
49 QTimer::singleShot(0, animation, SLOT(start()));
56 }
50 }
57
51
58 void PieAnimation::addSlice(PieSliceItem *sliceItem, const PieSliceData &sliceData, bool isEmpty)
52 void PieAnimation::addSlice(PieSliceItem *sliceItem, const PieSliceData &sliceData, bool startupAnimation)
59 {
53 {
60 PieSliceAnimation *animation = new PieSliceAnimation(sliceItem);
54 PieSliceAnimation *animation = new PieSliceAnimation(sliceItem);
61 m_animations.insert(sliceItem, animation);
55 m_animations.insert(sliceItem, animation);
62
56
63 PieSliceData startValue = sliceData;
57 PieSliceData startValue = sliceData;
64 startValue.m_radius = 0;
58 startValue.m_radius = 0;
65 if (isEmpty)
59 if (startupAnimation)
66 startValue.m_startAngle = 0;
60 startValue.m_startAngle = 0;
67 else
61 else
68 startValue.m_startAngle = sliceData.m_startAngle + (sliceData.m_angleSpan / 2);
62 startValue.m_startAngle = sliceData.m_startAngle + (sliceData.m_angleSpan / 2);
69 startValue.m_angleSpan = 0;
63 startValue.m_angleSpan = 0;
70 animation->setValue(startValue, sliceData);
64 animation->setValue(startValue, sliceData);
71
65
72 animation->setDuration(1000);
66 animation->setDuration(1000);
73 animation->setEasingCurve(QEasingCurve::OutQuart);
67 animation->setEasingCurve(QEasingCurve::OutQuart);
74 QTimer::singleShot(0, animation, SLOT(start()));
68 QTimer::singleShot(0, animation, SLOT(start()));
75 }
69 }
76
70
77 void PieAnimation::removeSlice(PieSliceItem *sliceItem)
71 void PieAnimation::removeSlice(PieSliceItem *sliceItem)
78 {
72 {
79 PieSliceAnimation *animation = m_animations.value(sliceItem);
73 PieSliceAnimation *animation = m_animations.value(sliceItem);
80 Q_ASSERT(animation);
74 Q_ASSERT(animation);
81 animation->stop();
75 animation->stop();
82
76
83 PieSliceData endValue = animation->currentSliceValue();
77 PieSliceData endValue = animation->currentSliceValue();
84 endValue.m_radius = 0;
78 endValue.m_radius = 0;
85 endValue.m_startAngle = endValue.m_startAngle + endValue.m_angleSpan;
79 endValue.m_startAngle = endValue.m_startAngle + endValue.m_angleSpan;
86 endValue.m_angleSpan = 0;
80 endValue.m_angleSpan = 0;
87
81
88 animation->updateValue(endValue);
82 animation->updateValue(endValue);
89 animation->setDuration(1000);
83 animation->setDuration(1000);
90 animation->setEasingCurve(QEasingCurve::OutQuart);
84 animation->setEasingCurve(QEasingCurve::OutQuart);
91
85
92 // PieSliceItem is the parent of PieSliceAnimation so the animation will be deleted as well..
86 // PieSliceItem is the parent of PieSliceAnimation so the animation will be deleted as well..
93 connect(animation, SIGNAL(finished()), sliceItem, SLOT(deleteLater()));
87 connect(animation, SIGNAL(finished()), sliceItem, SLOT(deleteLater()));
94 m_animations.remove(sliceItem);
88 m_animations.remove(sliceItem);
95
89
96 QTimer::singleShot(0, animation, SLOT(start()));
90 QTimer::singleShot(0, animation, SLOT(start()));
97 }
91 }
98
92
99 void PieAnimation::updateCurrentValue(const QVariant &)
93 void PieAnimation::updateCurrentValue(const QVariant &)
100 {
94 {
101 // nothing to do...
95 // nothing to do...
102 }
96 }
103
97
104 #include "moc_pieanimation_p.cpp"
98 #include "moc_pieanimation_p.cpp"
105
99
106 QTCOMMERCIALCHART_END_NAMESPACE
100 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,54 +1,53
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 #ifndef PIEANIMATION_P_H
21 #ifndef PIEANIMATION_P_H
22 #define PIEANIMATION_P_H
22 #define PIEANIMATION_P_H
23
23
24 #include "chartanimation_p.h"
24 #include "chartanimation_p.h"
25 #include "piechartitem_p.h"
25 #include "piechartitem_p.h"
26 #include "piesliceanimation_p.h"
26 #include "piesliceanimation_p.h"
27
27
28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29
29
30 class PieChartItem;
30 class PieChartItem;
31
31
32 class PieAnimation : public ChartAnimation
32 class PieAnimation : public ChartAnimation
33 {
33 {
34 Q_OBJECT
34 Q_OBJECT
35
35
36 public:
36 public:
37 PieAnimation(PieChartItem *item);
37 PieAnimation(PieChartItem *item);
38 ~PieAnimation();
38 ~PieAnimation();
39 void updateValues(const PieLayout &newValues);
40 void updateValue(PieSliceItem *sliceItem, const PieSliceData &newValue);
39 void updateValue(PieSliceItem *sliceItem, const PieSliceData &newValue);
41 void addSlice(PieSliceItem *sliceItem, const PieSliceData &endValue, bool isEmpty);
40 void addSlice(PieSliceItem *sliceItem, const PieSliceData &endValue, bool startupAnimation);
42 void removeSlice(PieSliceItem *sliceItem);
41 void removeSlice(PieSliceItem *sliceItem);
43
42
44 public: // from QVariantAnimation
43 public: // from QVariantAnimation
45 void updateCurrentValue(const QVariant &value);
44 void updateCurrentValue(const QVariant &value);
46
45
47 private:
46 private:
48 PieChartItem *m_item;
47 PieChartItem *m_item;
49 QHash<PieSliceItem *, PieSliceAnimation *> m_animations;
48 QHash<PieSliceItem *, PieSliceAnimation *> m_animations;
50 };
49 };
51
50
52 QTCOMMERCIALCHART_END_NAMESPACE
51 QTCOMMERCIALCHART_END_NAMESPACE
53
52
54 #endif
53 #endif
@@ -1,127 +1,125
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 "piesliceanimation_p.h"
21 #include "piesliceanimation_p.h"
22 #include "piechartitem_p.h"
22 #include "piechartitem_p.h"
23
23
24 Q_DECLARE_METATYPE(QTCOMMERCIALCHART_NAMESPACE::PieSliceData)
24 Q_DECLARE_METATYPE(QTCOMMERCIALCHART_NAMESPACE::PieSliceData)
25
25
26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27
27
28 qreal linearPos(qreal start, qreal end, qreal pos)
28 qreal linearPos(qreal start, qreal end, qreal pos)
29 {
29 {
30 return start + ((end - start) * pos);
30 return start + ((end - start) * pos);
31 }
31 }
32
32
33 QPointF linearPos(QPointF start, QPointF end, qreal pos)
33 QPointF linearPos(QPointF start, QPointF end, qreal pos)
34 {
34 {
35 qreal x = linearPos(start.x(), end.x(), pos);
35 qreal x = linearPos(start.x(), end.x(), pos);
36 qreal y = linearPos(start.y(), end.y(), pos);
36 qreal y = linearPos(start.y(), end.y(), pos);
37 return QPointF(x, y);
37 return QPointF(x, y);
38 }
38 }
39
39
40 QPen linearPos(QPen start, QPen end, qreal pos)
40 QPen linearPos(QPen start, QPen end, qreal pos)
41 {
41 {
42 QColor c;
42 QColor c;
43 c.setRedF(linearPos(start.color().redF(), end.color().redF(), pos));
43 c.setRedF(linearPos(start.color().redF(), end.color().redF(), pos));
44 c.setGreenF(linearPos(start.color().greenF(), end.color().greenF(), pos));
44 c.setGreenF(linearPos(start.color().greenF(), end.color().greenF(), pos));
45 c.setBlueF(linearPos(start.color().blueF(), end.color().blueF(), pos));
45 c.setBlueF(linearPos(start.color().blueF(), end.color().blueF(), pos));
46 end.setColor(c);
46 end.setColor(c);
47 return end;
47 return end;
48 }
48 }
49
49
50 QBrush linearPos(QBrush start, QBrush end, qreal pos)
50 QBrush linearPos(QBrush start, QBrush end, qreal pos)
51 {
51 {
52 QColor c;
52 QColor c;
53 c.setRedF(linearPos(start.color().redF(), end.color().redF(), pos));
53 c.setRedF(linearPos(start.color().redF(), end.color().redF(), pos));
54 c.setGreenF(linearPos(start.color().greenF(), end.color().greenF(), pos));
54 c.setGreenF(linearPos(start.color().greenF(), end.color().greenF(), pos));
55 c.setBlueF(linearPos(start.color().blueF(), end.color().blueF(), pos));
55 c.setBlueF(linearPos(start.color().blueF(), end.color().blueF(), pos));
56 end.setColor(c);
56 end.setColor(c);
57 return end;
57 return end;
58 }
58 }
59
59
60 PieSliceAnimation::PieSliceAnimation(PieSliceItem *sliceItem)
60 PieSliceAnimation::PieSliceAnimation(PieSliceItem *sliceItem)
61 :QVariantAnimation(sliceItem),
61 :QVariantAnimation(sliceItem),
62 m_sliceItem(sliceItem)
62 m_sliceItem(sliceItem)
63 {
63 {
64 }
64 }
65
65
66 PieSliceAnimation::~PieSliceAnimation()
66 PieSliceAnimation::~PieSliceAnimation()
67 {
67 {
68 }
68 }
69
69
70 void PieSliceAnimation::setValue(const PieSliceData &startValue, const PieSliceData &endValue)
70 void PieSliceAnimation::setValue(const PieSliceData &startValue, const PieSliceData &endValue)
71 {
71 {
72 if (state() != QAbstractAnimation::Stopped)
72 if (state() != QAbstractAnimation::Stopped)
73 stop();
73 stop();
74
74
75 m_currentValue = startValue;
75 m_currentValue = startValue;
76
76
77 setKeyValueAt(0.0, qVariantFromValue(startValue));
77 setKeyValueAt(0.0, qVariantFromValue(startValue));
78 setKeyValueAt(1.0, qVariantFromValue(endValue));
78 setKeyValueAt(1.0, qVariantFromValue(endValue));
79 }
79 }
80
80
81 void PieSliceAnimation::updateValue(const PieSliceData &endValue)
81 void PieSliceAnimation::updateValue(const PieSliceData &endValue)
82 {
82 {
83 if (state() != QAbstractAnimation::Stopped)
83 if (state() != QAbstractAnimation::Stopped)
84 stop();
84 stop();
85
85
86 setKeyValueAt(0.0, qVariantFromValue(m_currentValue));
86 setKeyValueAt(0.0, qVariantFromValue(m_currentValue));
87 setKeyValueAt(1.0, qVariantFromValue(endValue));
87 setKeyValueAt(1.0, qVariantFromValue(endValue));
88 }
88 }
89
89
90 PieSliceData PieSliceAnimation::currentSliceValue()
90 PieSliceData PieSliceAnimation::currentSliceValue()
91 {
91 {
92 // NOTE:
92 // NOTE:
93 // We must use an internal current value because QVariantAnimation::currentValue() is updated
93 // We must use an internal current value because QVariantAnimation::currentValue() is updated
94 // before the animation is actually started. So if we get 2 updateValue() calls in a row the currentValue()
94 // before the animation is actually started. So if we get 2 updateValue() calls in a row the currentValue()
95 // will have the end value set from the first call and the second call will interpolate that instead of
95 // will have the end value set from the first call and the second call will interpolate that instead of
96 // the original current value as it was before the first call.
96 // the original current value as it was before the first call.
97 return m_currentValue;
97 return m_currentValue;
98 }
98 }
99
99
100 QVariant PieSliceAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress) const
100 QVariant PieSliceAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress) const
101 {
101 {
102 PieSliceData startValue = qVariantValue<PieSliceData>(start);
102 PieSliceData startValue = qVariantValue<PieSliceData>(start);
103 PieSliceData endValue = qVariantValue<PieSliceData>(end);
103 PieSliceData endValue = qVariantValue<PieSliceData>(end);
104
104
105 PieSliceData result;
105 PieSliceData result;
106 result = endValue;
106 result = endValue;
107 result.m_center = linearPos(startValue.m_center, endValue.m_center, progress);
107 result.m_center = linearPos(startValue.m_center, endValue.m_center, progress);
108 result.m_radius = linearPos(startValue.m_radius, endValue.m_radius, progress);
108 result.m_radius = linearPos(startValue.m_radius, endValue.m_radius, progress);
109 result.m_startAngle = linearPos(startValue.m_startAngle, endValue.m_startAngle, progress);
109 result.m_startAngle = linearPos(startValue.m_startAngle, endValue.m_startAngle, progress);
110 result.m_angleSpan = linearPos(startValue.m_angleSpan, endValue.m_angleSpan, progress);
110 result.m_angleSpan = linearPos(startValue.m_angleSpan, endValue.m_angleSpan, progress);
111 result.m_slicePen = linearPos(startValue.m_slicePen, endValue.m_slicePen, progress);
111 result.m_slicePen = linearPos(startValue.m_slicePen, endValue.m_slicePen, progress);
112 result.m_sliceBrush = linearPos(startValue.m_sliceBrush, endValue.m_sliceBrush, progress);
112 result.m_sliceBrush = linearPos(startValue.m_sliceBrush, endValue.m_sliceBrush, progress);
113
113
114 return qVariantFromValue(result);
114 return qVariantFromValue(result);
115 }
115 }
116
116
117 void PieSliceAnimation::updateCurrentValue(const QVariant &value)
117 void PieSliceAnimation::updateCurrentValue(const QVariant &value)
118 {
118 {
119 if (state() != QAbstractAnimation::Stopped) { //workaround
119 if (state() != QAbstractAnimation::Stopped) { //workaround
120 m_currentValue = qVariantValue<PieSliceData>(value);
120 m_currentValue = qVariantValue<PieSliceData>(value);
121 m_sliceItem->setSliceData(m_currentValue);
121 m_sliceItem->setLayout(m_currentValue);
122 m_sliceItem->updateGeometry();
123 m_sliceItem->update();
124 }
122 }
125 }
123 }
126
124
127 QTCOMMERCIALCHART_END_NAMESPACE
125 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,208 +1,160
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 "piechartitem_p.h"
21 #include "piechartitem_p.h"
22 #include "piesliceitem_p.h"
22 #include "piesliceitem_p.h"
23 #include "qpieslice.h"
23 #include "qpieslice.h"
24 #include "qpieseries.h"
24 #include "qpieseries.h"
25 #include "qpieseries_p.h"
25 #include "qpieseries_p.h"
26 #include "chartpresenter_p.h"
26 #include "chartpresenter_p.h"
27 #include "chartdataset_p.h"
27 #include "chartdataset_p.h"
28 #include "chartanimator_p.h"
28 #include "chartanimator_p.h"
29 #include <QPainter>
29 #include <QPainter>
30 #include <QTimer>
30 #include <QTimer>
31
31
32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33
33
34 PieChartItem::PieChartItem(QPieSeries *series, ChartPresenter* presenter)
34 PieChartItem::PieChartItem(QPieSeries *series, ChartPresenter* presenter)
35 :ChartItem(presenter),
35 :ChartItem(presenter),
36 m_series(series)
36 m_series(series)
37 {
37 {
38 Q_ASSERT(series);
38 Q_ASSERT(series);
39
39
40 QPieSeriesPrivate *d = QPieSeriesPrivate::seriesData(*series);
40 QPieSeriesPrivate *d = QPieSeriesPrivate::seriesData(*series);
41 connect(d, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>)));
41 connect(d, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>)));
42 connect(d, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>)));
42 connect(d, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>)));
43 connect(d, SIGNAL(piePositionChanged()), this, SLOT(handlePieLayoutChanged()));
43 connect(d, SIGNAL(piePositionChanged()), this, SLOT(updateLayout()));
44 connect(d, SIGNAL(pieSizeChanged()), this, SLOT(handlePieLayoutChanged()));
44 connect(d, SIGNAL(pieSizeChanged()), this, SLOT(updateLayout()));
45
45
46 QTimer::singleShot(0, this, SLOT(initialize())); // TODO: get rid of this
46 QTimer::singleShot(0, this, SLOT(initialize())); // TODO: get rid of this
47
47
48 // Note: the following does not affect as long as the item does not have anything to paint
48 // Note: the following does not affect as long as the item does not have anything to paint
49 setZValue(ChartPresenter::PieSeriesZValue);
49 setZValue(ChartPresenter::PieSeriesZValue);
50 }
50 }
51
51
52 PieChartItem::~PieChartItem()
52 PieChartItem::~PieChartItem()
53 {
53 {
54 // slices deleted automatically through QGraphicsItem
54 // slices deleted automatically through QGraphicsItem
55 }
55 }
56
56
57 void PieChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
57 void PieChartItem::handleGeometryChanged(const QRectF& rect)
58 {
58 {
59 Q_UNUSED(painter)
59 prepareGeometryChange();
60 // TODO: paint shadows for all components
60 m_rect = rect;
61 // - get paths from items & merge & offset and draw with shadow color?
61 updateLayout();
62 //painter->setBrush(QBrush(Qt::red));
63 //painter->drawRect(m_debugRect);
64 }
62 }
65
63
66 void PieChartItem::initialize()
64 void PieChartItem::initialize()
67 {
65 {
68 handleSlicesAdded(m_series->slices());
66 handleSlicesAdded(m_series->slices());
69 }
67 }
70
68
71 void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices)
69 void PieChartItem::updateLayout()
72 {
70 {
73 bool isEmpty = m_slices.isEmpty();
71 // find pie center coordinates
72 m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->horizontalPosition()));
73 m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->verticalPosition()));
74
74
75 // find maximum radius for pie
76 m_pieRadius = m_rect.height() / 2;
77 if (m_rect.width() < m_rect.height())
78 m_pieRadius = m_rect.width() / 2;
79
80 // apply size factor
81 m_pieRadius *= m_series->pieSize();
82
83 // set layouts for existing slice items
84 foreach (QPieSlice* slice, m_series->slices()) {
85 PieSliceItem *sliceItem = m_sliceItems.value(slice);
86 if (sliceItem) {
87 PieSliceData sliceData = updateSliceGeometry(slice);
88 if (animator())
89 animator()->updateAnimation(this, sliceItem, sliceData);
90 else
91 sliceItem->setLayout(sliceData);
92 }
93 }
94
95 update();
96 }
97
98 void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices)
99 {
75 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series));
100 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series));
76
101
77 foreach (QPieSlice *s, slices) {
102 bool startupAnimation = m_sliceItems.isEmpty();
78 PieSliceItem* item = new PieSliceItem(this);
79 m_slices.insert(s, item);
80 connect(s, SIGNAL(changed()), this, SLOT(handleSliceChanged()));
81 connect(item, SIGNAL(clicked(Qt::MouseButtons)), s, SIGNAL(clicked()));
82 connect(item, SIGNAL(hovered(bool)), s, SIGNAL(hovered(bool)));
83
103
84 PieSliceData data = sliceData(s);
104 foreach (QPieSlice *slice, slices) {
105 PieSliceItem* sliceItem = new PieSliceItem(this);
106 m_sliceItems.insert(slice, sliceItem);
107 connect(slice, SIGNAL(changed()), this, SLOT(handleSliceChanged()));
108 connect(sliceItem, SIGNAL(clicked(Qt::MouseButtons)), slice, SIGNAL(clicked()));
109 connect(sliceItem, SIGNAL(hovered(bool)), slice, SIGNAL(hovered(bool)));
85
110
111 PieSliceData sliceData = updateSliceGeometry(slice);
86 if (animator())
112 if (animator())
87 animator()->addAnimation(this, item, data, isEmpty);
113 animator()->addAnimation(this, sliceItem, sliceData, startupAnimation);
88 else
114 else
89 setLayout(item, data);
115 sliceItem->setLayout(sliceData);
90 }
116 }
91 }
117 }
92
118
93 void PieChartItem::handleSlicesRemoved(QList<QPieSlice*> slices)
119 void PieChartItem::handleSlicesRemoved(QList<QPieSlice*> slices)
94 {
120 {
95 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series));
121 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series));
96
122
97 foreach (QPieSlice *slice, slices) {
123 foreach (QPieSlice *slice, slices) {
98
124 PieSliceItem *sliceItem = m_sliceItems.value(slice);
99 PieSliceItem *item = m_slices.value(slice);
125 Q_ASSERT(sliceItem);
100 Q_ASSERT(item);
126 m_sliceItems.remove(slice);
101 m_slices.remove(slice);
102
127
103 if (animator())
128 if (animator())
104 animator()->removeAnimation(this, item); // animator deletes the PieSliceItem
129 animator()->removeAnimation(this, sliceItem); // animator deletes the PieSliceItem
105 else
130 else
106 delete item;
131 delete sliceItem;
107 }
132 }
108 }
133 }
109
134
110 void PieChartItem::handlePieLayoutChanged()
111 {
112 PieLayout layout = calculateLayout();
113 applyLayout(layout);
114 update();
115 }
116
117 void PieChartItem::handleSliceChanged()
135 void PieChartItem::handleSliceChanged()
118 {
136 {
119 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
137 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
120 Q_ASSERT(m_slices.contains(slice));
138 Q_ASSERT(m_sliceItems.contains(slice));
121 PieSliceData data = sliceData(slice);
122 updateLayout(m_slices.value(slice), data);
123 update();
124 }
125
126 void PieChartItem::handleDomainChanged(qreal, qreal, qreal, qreal)
127 {
128 // TODO
129 }
130
131 void PieChartItem::handleGeometryChanged(const QRectF& rect)
132 {
133 prepareGeometryChange();
134 m_rect = rect;
135 handlePieLayoutChanged();
136 }
137
138 void PieChartItem::calculatePieLayout()
139 {
140 // find pie center coordinates
141 m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->horizontalPosition()));
142 m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->verticalPosition()));
143
139
144 // find maximum radius for pie
140 PieSliceItem *sliceItem = m_sliceItems.value(slice);
145 m_pieRadius = m_rect.height() / 2;
141 PieSliceData sliceData = updateSliceGeometry(slice);
146 if (m_rect.width() < m_rect.height())
142 if (animator())
147 m_pieRadius = m_rect.width() / 2;
143 animator()->updateAnimation(this, sliceItem, sliceData);
144 else
145 sliceItem->setLayout(sliceData);
148
146
149 // apply size factor
147 update();
150 m_pieRadius *= m_series->pieSize();
151 }
148 }
152
149
153 PieSliceData PieChartItem::sliceData(QPieSlice *slice)
150 PieSliceData PieChartItem::updateSliceGeometry(QPieSlice *slice)
154 {
151 {
155 // TODO: This function is kid of useless now. Refactor.
152 PieSliceData &sliceData = PieSliceData::data(slice);
156 PieSliceData sliceData = PieSliceData::data(slice);
157 sliceData.m_center = PieSliceItem::sliceCenter(m_pieCenter, m_pieRadius, slice);
153 sliceData.m_center = PieSliceItem::sliceCenter(m_pieCenter, m_pieRadius, slice);
158 sliceData.m_radius = m_pieRadius;
154 sliceData.m_radius = m_pieRadius;
159 return sliceData;
155 return sliceData;
160 }
156 }
161
157
162 PieLayout PieChartItem::calculateLayout()
163 {
164 calculatePieLayout();
165 PieLayout layout;
166 foreach (QPieSlice* s, m_series->slices()) {
167 if (m_slices.contains(s)) // calculate layout only for those slices that are already visible
168 layout.insert(m_slices.value(s), sliceData(s));
169 }
170 return layout;
171 }
172
173 void PieChartItem::applyLayout(const PieLayout &layout)
174 {
175 if (animator())
176 animator()->updateLayout(this, layout);
177 else
178 setLayout(layout);
179 }
180
181 void PieChartItem::updateLayout(PieSliceItem *sliceItem, const PieSliceData &sliceData)
182 {
183 if (animator())
184 animator()->updateLayout(this, sliceItem, sliceData);
185 else
186 setLayout(sliceItem, sliceData);
187 }
188
189 void PieChartItem::setLayout(const PieLayout &layout)
190 {
191 foreach (PieSliceItem *item, layout.keys()) {
192 item->setSliceData(layout.value(item));
193 item->updateGeometry();
194 item->update();
195 }
196 }
197
198 void PieChartItem::setLayout(PieSliceItem *sliceItem, const PieSliceData &sliceData)
199 {
200 Q_ASSERT(sliceItem);
201 sliceItem->setSliceData(sliceData);
202 sliceItem->updateGeometry();
203 sliceItem->update();
204 }
205
206 #include "moc_piechartitem_p.cpp"
158 #include "moc_piechartitem_p.cpp"
207
159
208 QTCOMMERCIALCHART_END_NAMESPACE
160 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,77 +1,72
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 #ifndef PIECHARTITEM_H
21 #ifndef PIECHARTITEM_H
22 #define PIECHARTITEM_H
22 #define PIECHARTITEM_H
23
23
24 #include "qpieseries.h"
24 #include "qpieseries.h"
25 #include "chartitem_p.h"
25 #include "chartitem_p.h"
26 #include "piesliceitem_p.h"
26 #include "piesliceitem_p.h"
27
27
28 class QGraphicsItem;
28 class QGraphicsItem;
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 class QPieSlice;
30 class QPieSlice;
31 class ChartPresenter;
31 class ChartPresenter;
32
32
33 typedef QHash<PieSliceItem*, PieSliceData> PieLayout;
34
35 class PieChartItem : public ChartItem
33 class PieChartItem : public ChartItem
36 {
34 {
37 Q_OBJECT
35 Q_OBJECT
38
36
39 public:
37 public:
40 // TODO: use a generic data class instead of x and y
38 explicit PieChartItem(QPieSeries *series, ChartPresenter *presenter);
41 PieChartItem(QPieSeries *series, ChartPresenter *presenter);
42 ~PieChartItem();
39 ~PieChartItem();
43
40
44 public: // from QGraphicsItem
41 // from QGraphicsItem
45 QRectF boundingRect() const { return m_rect; }
42 QRectF boundingRect() const { return m_rect; }
46 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
43 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
47
44
48 public Q_SLOTS:
45 public Q_SLOTS:
46 // from Chart
47 virtual void handleGeometryChanged(const QRectF &rect);
48 // TODO: Do we have actual need for these at all? What is the use case for pie?
49 //virtual void handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY);
50 //virtual void rangeXChanged(qreal min, qreal max, int tickXCount);
51 //virtual void rangeYChanged(qreal min, qreal max, int tickYCount);
52
49 void initialize();
53 void initialize();
54 void updateLayout();
50 void handleSlicesAdded(QList<QPieSlice*> slices);
55 void handleSlicesAdded(QList<QPieSlice*> slices);
51 void handleSlicesRemoved(QList<QPieSlice*> slices);
56 void handleSlicesRemoved(QList<QPieSlice*> slices);
52 void handlePieLayoutChanged();
53 void handleSliceChanged();
57 void handleSliceChanged();
54 void handleDomainChanged(qreal, qreal, qreal, qreal);
55 void handleGeometryChanged(const QRectF& rect);
56
58
57 public:
59 private:
58 void calculatePieLayout();
60 PieSliceData updateSliceGeometry(QPieSlice *slice);
59 PieSliceData sliceData(QPieSlice *slice);
60 PieLayout calculateLayout();
61 void applyLayout(const PieLayout &layout);
62 void updateLayout(PieSliceItem *sliceItem, const PieSliceData &sliceData);
63 void setLayout(const PieLayout &layout);
64 void setLayout(PieSliceItem *sliceItem, const PieSliceData &sliceData);
65
61
66 private:
62 private:
67 friend class PieSliceItem;
63 QHash<QPieSlice*, PieSliceItem*> m_sliceItems;
68 QHash<QPieSlice*, PieSliceItem*> m_slices;
69 QPieSeries *m_series;
64 QPieSeries *m_series;
70 QRectF m_rect;
65 QRectF m_rect;
71 QPointF m_pieCenter;
66 QPointF m_pieCenter;
72 qreal m_pieRadius;
67 qreal m_pieRadius;
73 };
68 };
74
69
75 QTCOMMERCIALCHART_END_NAMESPACE
70 QTCOMMERCIALCHART_END_NAMESPACE
76
71
77 #endif // PIECHARTITEM_H
72 #endif // PIECHARTITEM_H
@@ -1,212 +1,214
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 "piesliceitem_p.h"
21 #include "piesliceitem_p.h"
22 #include "piechartitem_p.h"
22 #include "piechartitem_p.h"
23 #include "qpieseries.h"
23 #include "qpieseries.h"
24 #include "qpieslice.h"
24 #include "qpieslice.h"
25 #include "chartpresenter_p.h"
25 #include "chartpresenter_p.h"
26 #include <QPainter>
26 #include <QPainter>
27 #include <qmath.h>
27 #include <qmath.h>
28 #include <QGraphicsSceneEvent>
28 #include <QGraphicsSceneEvent>
29 #include <QTime>
29 #include <QTime>
30
30
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32
32
33 #define PI 3.14159265 // TODO: is this defined in some header?
33 #define PI 3.14159265 // TODO: is this defined in some header?
34
34
35 QPointF offset(qreal angle, qreal length)
35 QPointF offset(qreal angle, qreal length)
36 {
36 {
37 qreal dx = qSin(angle*(PI/180)) * length;
37 qreal dx = qSin(angle*(PI/180)) * length;
38 qreal dy = qCos(angle*(PI/180)) * length;
38 qreal dy = qCos(angle*(PI/180)) * length;
39 return QPointF(dx, -dy);
39 return QPointF(dx, -dy);
40 }
40 }
41
41
42 PieSliceItem::PieSliceItem(QGraphicsItem* parent)
42 PieSliceItem::PieSliceItem(QGraphicsItem* parent)
43 :QGraphicsObject(parent)
43 :QGraphicsObject(parent)
44 {
44 {
45 setAcceptHoverEvents(true);
45 setAcceptHoverEvents(true);
46 setAcceptedMouseButtons(Qt::MouseButtonMask);
46 setAcceptedMouseButtons(Qt::MouseButtonMask);
47 setZValue(ChartPresenter::PieSeriesZValue);
47 setZValue(ChartPresenter::PieSeriesZValue);
48 }
48 }
49
49
50 PieSliceItem::~PieSliceItem()
50 PieSliceItem::~PieSliceItem()
51 {
51 {
52
52
53 }
53 }
54
54
55 QRectF PieSliceItem::boundingRect() const
55 QRectF PieSliceItem::boundingRect() const
56 {
56 {
57 return m_boundingRect;
57 return m_boundingRect;
58 }
58 }
59
59
60 QPainterPath PieSliceItem::shape() const
60 QPainterPath PieSliceItem::shape() const
61 {
61 {
62 // Don't include the label and label arm.
62 // Don't include the label and label arm.
63 // This is used to detect a mouse clicks. We do not want clicks from label.
63 // This is used to detect a mouse clicks. We do not want clicks from label.
64 return m_slicePath;
64 return m_slicePath;
65 }
65 }
66
66
67 void PieSliceItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
67 void PieSliceItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
68 {
68 {
69 painter->save();
69 painter->save();
70 painter->setClipRect(parentItem()->boundingRect());
70 painter->setClipRect(parentItem()->boundingRect());
71 painter->setPen(m_data.m_slicePen);
71 painter->setPen(m_data.m_slicePen);
72 painter->setBrush(m_data.m_sliceBrush);
72 painter->setBrush(m_data.m_sliceBrush);
73 painter->drawPath(m_slicePath);
73 painter->drawPath(m_slicePath);
74 painter->restore();
74 painter->restore();
75
75
76 if (m_data.m_isLabelVisible) {
76 if (m_data.m_isLabelVisible) {
77 painter->setClipRect(parentItem()->boundingRect());
77 painter->setClipRect(parentItem()->boundingRect());
78 painter->setPen(m_data.m_labelPen);
78 painter->setPen(m_data.m_labelPen);
79 painter->drawPath(m_labelArmPath);
79 painter->drawPath(m_labelArmPath);
80 // the pen color will affect the font color as well
80 // the pen color will affect the font color as well
81 painter->setFont(m_data.m_labelFont);
81 painter->setFont(m_data.m_labelFont);
82 painter->drawText(m_labelTextRect.bottomLeft(), m_data.m_labelText);
82 painter->drawText(m_labelTextRect.bottomLeft(), m_data.m_labelText);
83 }
83 }
84 }
84 }
85
85
86 void PieSliceItem::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
86 void PieSliceItem::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
87 {
87 {
88 emit hovered(true);
88 emit hovered(true);
89 }
89 }
90
90
91 void PieSliceItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
91 void PieSliceItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
92 {
92 {
93 emit hovered(false);
93 emit hovered(false);
94 }
94 }
95
95
96 void PieSliceItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
96 void PieSliceItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
97 {
97 {
98 emit clicked(event->buttons());
98 emit clicked(event->buttons());
99 }
99 }
100
100
101 void PieSliceItem::setSliceData(PieSliceData sliceData)
101 void PieSliceItem::setLayout(const PieSliceData &sliceData)
102 {
102 {
103 m_data = sliceData;
103 m_data = sliceData;
104 updateGeometry();
105 update();
104 }
106 }
105
107
106 void PieSliceItem::updateGeometry()
108 void PieSliceItem::updateGeometry()
107 {
109 {
108 if (m_data.m_radius <= 0)
110 if (m_data.m_radius <= 0)
109 return;
111 return;
110
112
111 prepareGeometryChange();
113 prepareGeometryChange();
112
114
113 // update slice path
115 // update slice path
114 qreal centerAngle;
116 qreal centerAngle;
115 QPointF armStart;
117 QPointF armStart;
116 m_slicePath = slicePath(m_data.m_center, m_data.m_radius, m_data.m_startAngle, m_data.m_angleSpan, &centerAngle, &armStart);
118 m_slicePath = slicePath(m_data.m_center, m_data.m_radius, m_data.m_startAngle, m_data.m_angleSpan, &centerAngle, &armStart);
117
119
118 // update text rect
120 // update text rect
119 m_labelTextRect = labelTextRect(m_data.m_labelFont, m_data.m_labelText);
121 m_labelTextRect = labelTextRect(m_data.m_labelFont, m_data.m_labelText);
120
122
121 // update label arm path
123 // update label arm path
122 QPointF labelTextStart;
124 QPointF labelTextStart;
123 m_labelArmPath = labelArmPath(armStart, centerAngle, m_data.m_radius * m_data.m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart);
125 m_labelArmPath = labelArmPath(armStart, centerAngle, m_data.m_radius * m_data.m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart);
124
126
125 // update text position
127 // update text position
126 m_labelTextRect.moveBottomLeft(labelTextStart);
128 m_labelTextRect.moveBottomLeft(labelTextStart);
127
129
128 // update bounding rect
130 // update bounding rect
129 if (m_data.m_isLabelVisible)
131 if (m_data.m_isLabelVisible)
130 m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect);
132 m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect);
131 else
133 else
132 m_boundingRect = m_slicePath.boundingRect();
134 m_boundingRect = m_slicePath.boundingRect();
133 }
135 }
134
136
135 QPointF PieSliceItem::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
137 QPointF PieSliceItem::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
136 {
138 {
137 if (slice->isExploded()) {
139 if (slice->isExploded()) {
138 qreal centerAngle = slice->startAngle() + ((slice->endAngle() - slice->startAngle())/2);
140 qreal centerAngle = slice->startAngle() + ((slice->endAngle() - slice->startAngle())/2);
139 qreal len = radius * slice->explodeDistanceFactor();
141 qreal len = radius * slice->explodeDistanceFactor();
140 qreal dx = qSin(centerAngle*(PI/180)) * len;
142 qreal dx = qSin(centerAngle*(PI/180)) * len;
141 qreal dy = -qCos(centerAngle*(PI/180)) * len;
143 qreal dy = -qCos(centerAngle*(PI/180)) * len;
142 point += QPointF(dx, dy);
144 point += QPointF(dx, dy);
143 }
145 }
144 return point;
146 return point;
145 }
147 }
146
148
147 QPainterPath PieSliceItem::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal *centerAngle, QPointF* armStart)
149 QPainterPath PieSliceItem::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal *centerAngle, QPointF* armStart)
148 {
150 {
149 // calculate center angle
151 // calculate center angle
150 *centerAngle = startAngle + (angleSpan/2);
152 *centerAngle = startAngle + (angleSpan/2);
151
153
152 // calculate slice rectangle
154 // calculate slice rectangle
153 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
155 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
154
156
155 // slice path
157 // slice path
156 // TODO: draw the shape so that it might have a hole in the center
158 // TODO: draw the shape so that it might have a hole in the center
157 QPainterPath path;
159 QPainterPath path;
158 path.moveTo(rect.center());
160 path.moveTo(rect.center());
159 path.arcTo(rect, -startAngle + 90, -angleSpan);
161 path.arcTo(rect, -startAngle + 90, -angleSpan);
160 path.closeSubpath();
162 path.closeSubpath();
161
163
162 // calculate label arm start point
164 // calculate label arm start point
163 *armStart = center;
165 *armStart = center;
164 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
166 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
165
167
166 return path;
168 return path;
167 }
169 }
168
170
169 QPainterPath PieSliceItem::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF *textStart)
171 QPainterPath PieSliceItem::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF *textStart)
170 {
172 {
171 // prevent label arm pointing straight down because it will look bad
173 // prevent label arm pointing straight down because it will look bad
172 if (angle < 180 && angle > 170)
174 if (angle < 180 && angle > 170)
173 angle = 170;
175 angle = 170;
174 if (angle > 180 && angle < 190)
176 if (angle > 180 && angle < 190)
175 angle = 190;
177 angle = 190;
176
178
177 // line from slice to label
179 // line from slice to label
178 qreal dx = qSin(angle*(PI/180)) * length;
180 qreal dx = qSin(angle*(PI/180)) * length;
179 qreal dy = -qCos(angle*(PI/180)) * length;
181 qreal dy = -qCos(angle*(PI/180)) * length;
180 QPointF parm1 = start + QPointF(dx, dy);
182 QPointF parm1 = start + QPointF(dx, dy);
181
183
182 // line to underline the label
184 // line to underline the label
183 QPointF parm2 = parm1;
185 QPointF parm2 = parm1;
184 if (angle < 180) { // arm swings the other way on the left side
186 if (angle < 180) { // arm swings the other way on the left side
185 parm2 += QPointF(textWidth, 0);
187 parm2 += QPointF(textWidth, 0);
186 *textStart = parm1;
188 *textStart = parm1;
187 }
189 }
188 else {
190 else {
189 parm2 += QPointF(-textWidth,0);
191 parm2 += QPointF(-textWidth,0);
190 *textStart = parm2;
192 *textStart = parm2;
191 }
193 }
192
194
193 // elevate the text position a bit so that it does not hit the line
195 // elevate the text position a bit so that it does not hit the line
194 *textStart += QPointF(0, -3);
196 *textStart += QPointF(0, -3);
195
197
196 QPainterPath path;
198 QPainterPath path;
197 path.moveTo(start);
199 path.moveTo(start);
198 path.lineTo(parm1);
200 path.lineTo(parm1);
199 path.lineTo(parm2);
201 path.lineTo(parm2);
200
202
201 return path;
203 return path;
202 }
204 }
203
205
204 QRectF PieSliceItem::labelTextRect(QFont font, QString text)
206 QRectF PieSliceItem::labelTextRect(QFont font, QString text)
205 {
207 {
206 QFontMetricsF fm(font);
208 QFontMetricsF fm(font);
207 return fm.boundingRect(text);
209 return fm.boundingRect(text);
208 }
210 }
209
211
210 #include "moc_piesliceitem_p.cpp"
212 #include "moc_piesliceitem_p.cpp"
211
213
212 QTCOMMERCIALCHART_END_NAMESPACE
214 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,78 +1,79
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 #ifndef PIESLICEITEM_H
21 #ifndef PIESLICEITEM_H
22 #define PIESLICEITEM_H
22 #define PIESLICEITEM_H
23
23
24 #include "qchartglobal.h"
24 #include "qchartglobal.h"
25 #include "charttheme_p.h"
25 #include "charttheme_p.h"
26 #include "qpieseries.h"
26 #include "qpieseries.h"
27 #include "pieslicedata_p.h"
27 #include "pieslicedata_p.h"
28 #include <QGraphicsItem>
28 #include <QGraphicsItem>
29 #include <QRectF>
29 #include <QRectF>
30 #include <QColor>
30 #include <QColor>
31 #include <QPen>
31 #include <QPen>
32
32
33 #define PIESLICE_LABEL_GAP 5
33 #define PIESLICE_LABEL_GAP 5
34
34
35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36 class PieChartItem;
36 class PieChartItem;
37 class PieSliceLabel;
37 class PieSliceLabel;
38 class QPieSlice;
38 class QPieSlice;
39
39
40 class PieSliceItem : public QGraphicsObject
40 class PieSliceItem : public QGraphicsObject
41 {
41 {
42 Q_OBJECT
42 Q_OBJECT
43
43
44 public:
44 public:
45 PieSliceItem(QGraphicsItem* parent = 0);
45 PieSliceItem(QGraphicsItem* parent = 0);
46 ~PieSliceItem();
46 ~PieSliceItem();
47
47
48 public: // from QGraphicsItem
48 // from QGraphicsItem
49 QRectF boundingRect() const;
49 QRectF boundingRect() const;
50 QPainterPath shape() const;
50 QPainterPath shape() const;
51 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
51 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
52 void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
52 void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
53 void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
53 void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
54 void mousePressEvent(QGraphicsSceneMouseEvent *event);
54 void mousePressEvent(QGraphicsSceneMouseEvent *event);
55
55
56 void setLayout(const PieSliceData &sliceData);
57 static QPointF sliceCenter(QPointF point, qreal radius, QPieSlice *slice);
58
56 Q_SIGNALS:
59 Q_SIGNALS:
57 void clicked(Qt::MouseButtons buttons);
60 void clicked(Qt::MouseButtons buttons);
58 void hovered(bool state);
61 void hovered(bool state);
59
62
60 public:
63 private:
61 void setSliceData(PieSliceData sliceData);
62 void updateGeometry();
64 void updateGeometry();
63 static QPointF sliceCenter(QPointF point, qreal radius, QPieSlice *slice);
64 QPainterPath slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal *centerAngle, QPointF *armStart);
65 QPainterPath slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal *centerAngle, QPointF *armStart);
65 QPainterPath labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF *textStart);
66 QPainterPath labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF *textStart);
66 QRectF labelTextRect(QFont font, QString text);
67 QRectF labelTextRect(QFont font, QString text);
67
68
68 private:
69 private:
69 PieSliceData m_data;
70 PieSliceData m_data;
70 QRectF m_boundingRect;
71 QRectF m_boundingRect;
71 QPainterPath m_slicePath;
72 QPainterPath m_slicePath;
72 QPainterPath m_labelArmPath;
73 QPainterPath m_labelArmPath;
73 QRectF m_labelTextRect;
74 QRectF m_labelTextRect;
74 };
75 };
75
76
76 QTCOMMERCIALCHART_END_NAMESPACE
77 QTCOMMERCIALCHART_END_NAMESPACE
77
78
78 #endif // PIESLICEITEM_H
79 #endif // PIESLICEITEM_H
General Comments 0
You need to be logged in to leave comments. Login now