| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the Qt Charts module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 or (at your option) any later version |
| ** approved by the KDE Free Qt Foundation. The licenses are as published by |
| ** the Free Software Foundation and appearing in the file LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include <private/xyanimation_p.h> |
| #include <private/xychart_p.h> |
| #include <QtCore/QDebug> |
| |
| Q_DECLARE_METATYPE(QVector<QPointF>) |
| |
| QT_CHARTS_BEGIN_NAMESPACE |
| |
| XYAnimation::XYAnimation(XYChart *item, int duration, QEasingCurve &curve) |
| : ChartAnimation(item), |
| m_type(NewAnimation), |
| m_dirty(false), |
| m_index(-1), |
| m_item(item) |
| { |
| setDuration(duration); |
| setEasingCurve(curve); |
| } |
| |
| XYAnimation::~XYAnimation() |
| { |
| } |
| |
| void XYAnimation::setup(const QVector<QPointF> &oldPoints, const QVector<QPointF> &newPoints, int index) |
| { |
| m_type = NewAnimation; |
| |
| if (state() != QAbstractAnimation::Stopped) { |
| stop(); |
| m_dirty = false; |
| } |
| |
| if (!m_dirty) { |
| m_dirty = true; |
| m_oldPoints = oldPoints; |
| } |
| |
| m_newPoints = newPoints; |
| |
| int x = m_oldPoints.count(); |
| int y = m_newPoints.count(); |
| int diff = x - y; |
| int requestedDiff = oldPoints.count() - y; |
| |
| // m_oldPoints can be whatever between 0 and actual points count if new animation setup |
| // interrupts a previous animation, so only do remove and add animations if both |
| // stored diff and requested diff indicate add or remove. Also ensure that index is not |
| // invalid. |
| if (diff == 1 && requestedDiff == 1 && index >= 0 && y > 0 && index <= y) { |
| //remove point |
| m_newPoints.insert(index, index > 0 ? newPoints[index - 1] : newPoints[index]); |
| m_index = index; |
| m_type = RemovePointAnimation; |
| } |
| |
| if (diff == -1 && requestedDiff == -1 && index >= 0 && index <= x) { |
| //add point |
| m_oldPoints.insert(index, index > 0 ? newPoints[index - 1] : newPoints[index]); |
| m_index = index; |
| m_type = AddPointAnimation; |
| } |
| |
| x = m_oldPoints.count(); |
| y = m_newPoints.count(); |
| |
| if (x != y) |
| m_type = NewAnimation; |
| else if (m_type == NewAnimation) |
| m_type = ReplacePointAnimation; |
| |
| setKeyValueAt(0.0, QVariant::fromValue(m_oldPoints)); |
| setKeyValueAt(1.0, QVariant::fromValue(m_newPoints)); |
| } |
| |
| QVariant XYAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress) const |
| { |
| QVector<QPointF> startVector = qvariant_cast<QVector<QPointF> >(start); |
| QVector<QPointF> endVector = qvariant_cast<QVector<QPointF> >(end); |
| QVector<QPointF> result; |
| |
| switch (m_type) { |
| |
| case ReplacePointAnimation: |
| case AddPointAnimation: |
| case RemovePointAnimation: { |
| if (startVector.count() != endVector.count()) |
| break; |
| |
| for (int i = 0; i < startVector.count(); i++) { |
| qreal x = startVector[i].x() + ((endVector[i].x() - startVector[i].x()) * progress); |
| qreal y = startVector[i].y() + ((endVector[i].y() - startVector[i].y()) * progress); |
| result << QPointF(x, y); |
| } |
| |
| } |
| break; |
| case NewAnimation: { |
| for (int i = 0; i < endVector.count() * qBound(qreal(0), progress, qreal(1)); i++) |
| result << endVector[i]; |
| } |
| break; |
| default: |
| qWarning() << "Unknown type of animation"; |
| break; |
| } |
| |
| return QVariant::fromValue(result); |
| } |
| |
| void XYAnimation::updateCurrentValue(const QVariant &value) |
| { |
| if (state() != QAbstractAnimation::Stopped) { //workaround |
| |
| QVector<QPointF> vector = qvariant_cast<QVector<QPointF> >(value); |
| m_item->setGeometryPoints(vector); |
| m_item->updateGeometry(); |
| m_item->setDirty(true); |
| m_dirty = false; |
| |
| } |
| } |
| |
| void XYAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) |
| { |
| if (oldState == QAbstractAnimation::Running && newState == QAbstractAnimation::Stopped) { |
| if (m_item->isDirty() && m_type == RemovePointAnimation) { |
| if (!m_newPoints.isEmpty()) |
| m_newPoints.remove(m_index); |
| m_item->setGeometryPoints(m_newPoints); |
| } |
| } |
| } |
| |
| QT_CHARTS_END_NAMESPACE |
| |
| #include "moc_chartanimation_p.cpp" |