1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <private/xyanimation_p.h>
5#include <private/xychart_p.h>
6#include <QtCore/QDebug>
7
8
9QT_BEGIN_NAMESPACE
10
11XYAnimation::XYAnimation(XYChart *item, int duration, QEasingCurve &curve)
12 : ChartAnimation(item),
13 m_type(NewAnimation),
14 m_dirty(false),
15 m_index(-1),
16 m_item(item)
17{
18 setDuration(duration);
19 setEasingCurve(curve);
20}
21
22XYAnimation::~XYAnimation()
23{
24}
25
26void XYAnimation::setup(const QList<QPointF> &oldPoints, const QList<QPointF> &newPoints, int index)
27{
28 m_type = NewAnimation;
29
30 if (state() != QAbstractAnimation::Stopped) {
31 stop();
32 m_dirty = false;
33 }
34
35 if (!m_dirty) {
36 m_dirty = true;
37 m_oldPoints = oldPoints;
38 }
39
40 m_newPoints = newPoints;
41
42 int x = m_oldPoints.size();
43 int y = m_newPoints.size();
44 int diff = x - y;
45 int requestedDiff = oldPoints.size() - y;
46
47 // m_oldPoints can be whatever between 0 and actual points count if new animation setup
48 // interrupts a previous animation, so only do remove and add animations if both
49 // stored diff and requested diff indicate add or remove. Also ensure that index is not
50 // invalid.
51 if (diff == 1 && requestedDiff == 1 && index >= 0 && y > 0 && index <= y) {
52 //remove point
53 m_newPoints.insert(i: index, t: index > 0 ? newPoints[index - 1] : newPoints[index]);
54 m_index = index;
55 m_type = RemovePointAnimation;
56 }
57
58 if (diff == -1 && requestedDiff == -1 && index >= 0 && index <= x) {
59 //add point
60 m_oldPoints.insert(i: index, t: index > 0 ? newPoints[index - 1] : newPoints[index]);
61 m_index = index;
62 m_type = AddPointAnimation;
63 }
64
65 x = m_oldPoints.size();
66 y = m_newPoints.size();
67
68 if (x != y)
69 m_type = NewAnimation;
70 else if (m_type == NewAnimation)
71 m_type = ReplacePointAnimation;
72
73 setKeyValueAt(step: 0.0, value: QVariant::fromValue(value: m_oldPoints));
74 setKeyValueAt(step: 1.0, value: QVariant::fromValue(value: m_newPoints));
75}
76
77QVariant XYAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress) const
78{
79 const auto startList = qvariant_cast<QList<QPointF>>(v: start);
80 const auto endList = qvariant_cast<QList<QPointF>>(v: end);
81 QList<QPointF> result;
82
83 switch (m_type) {
84
85 case ReplacePointAnimation:
86 case AddPointAnimation:
87 case RemovePointAnimation: {
88 if (startList.size() != endList.size())
89 break;
90
91 for (int i = 0; i < startList.size(); i++) {
92 qreal x = startList[i].x() + ((endList[i].x() - startList[i].x()) * progress);
93 qreal y = startList[i].y() + ((endList[i].y() - startList[i].y()) * progress);
94 result << QPointF(x, y);
95 }
96
97 }
98 break;
99 case NewAnimation: {
100 for (int i = 0; i < endList.size() * qBound(min: qreal(0), val: progress, max: qreal(1)); i++)
101 result << endList[i];
102 }
103 break;
104 default:
105 qWarning() << "Unknown type of animation";
106 break;
107 }
108
109 return QVariant::fromValue(value: result);
110}
111
112void XYAnimation::updateCurrentValue(const QVariant &value)
113{
114 if (state() != QAbstractAnimation::Stopped) { //workaround
115
116 const auto list = qvariant_cast<QList<QPointF>>(v: value);
117 m_item->setGeometryPoints(list);
118 m_item->updateGeometry();
119 m_item->setDirty(true);
120 m_dirty = false;
121
122 }
123}
124
125void XYAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
126{
127 if (oldState == QAbstractAnimation::Running && newState == QAbstractAnimation::Stopped) {
128 if (m_item->isDirty() && m_type == RemovePointAnimation) {
129 if (!m_newPoints.isEmpty())
130 m_newPoints.remove(i: m_index);
131 m_item->setGeometryPoints(m_newPoints);
132 }
133 }
134}
135
136QT_END_NAMESPACE
137
138#include "moc_chartanimation_p.cpp"
139

source code of qtcharts/src/charts/animations/xyanimation.cpp