diff options
Diffstat (limited to 'src/charts/animations')
21 files changed, 1761 insertions, 0 deletions
diff --git a/src/charts/animations/animations.pri b/src/charts/animations/animations.pri new file mode 100644 index 00000000..28b6db1e --- /dev/null +++ b/src/charts/animations/animations.pri @@ -0,0 +1,26 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD + +SOURCES += \ + $$PWD/axisanimation.cpp \ + $$PWD/xyanimation.cpp \ + $$PWD/pieanimation.cpp \ + $$PWD/piesliceanimation.cpp \ + $$PWD/splineanimation.cpp \ + $$PWD/baranimation.cpp \ + $$PWD/scatteranimation.cpp \ + $$PWD/boxplotanimation.cpp \ + $$PWD/boxwhiskersanimation.cpp \ + $$PWD/chartanimation.cpp + +PRIVATE_HEADERS += \ + $$PWD/axisanimation_p.h \ + $$PWD/chartanimation_p.h \ + $$PWD/xyanimation_p.h \ + $$PWD/pieanimation_p.h \ + $$PWD/piesliceanimation_p.h \ + $$PWD/splineanimation_p.h \ + $$PWD/baranimation_p.h \ + $$PWD/scatteranimation_p.h \ + $$PWD/boxplotanimation_p.h \ + $$PWD/boxwhiskersanimation_p.h diff --git a/src/charts/animations/axisanimation.cpp b/src/charts/animations/axisanimation.cpp new file mode 100644 index 00000000..ef346287 --- /dev/null +++ b/src/charts/animations/axisanimation.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "axisanimation_p.h" +#include "chartaxiselement_p.h" +#include "qabstractaxis_p.h" + +Q_DECLARE_METATYPE(QVector<qreal>) + +QT_CHARTS_BEGIN_NAMESPACE + + +AxisAnimation::AxisAnimation(ChartAxisElement *axis) + : ChartAnimation(axis), + m_axis(axis), + m_type(DefaultAnimation) +{ + setDuration(ChartAnimationDuration); + setEasingCurve(QEasingCurve::OutQuart); +} + +AxisAnimation::~AxisAnimation() +{ +} + +void AxisAnimation::setAnimationType(Animation type) +{ + if (state() != QAbstractAnimation::Stopped) + stop(); + m_type = type; +} + +void AxisAnimation::setAnimationPoint(const QPointF &point) +{ + if (state() != QAbstractAnimation::Stopped) + stop(); + m_point = point; +} + +void AxisAnimation::setValues(QVector<qreal> &oldLayout, QVector<qreal> &newLayout) +{ + if (state() != QAbstractAnimation::Stopped) stop(); + + switch (m_type) { + case ZoomOutAnimation: { + QRectF rect = m_axis->gridGeometry(); + oldLayout.resize(newLayout.count()); + + for (int i = 0, j = oldLayout.count() - 1; i < (oldLayout.count() + 1) / 2; ++i, --j) { + oldLayout[i] = m_axis->axis()->orientation() == Qt::Horizontal ? rect.left() : rect.bottom(); + oldLayout[j] = m_axis->axis()->orientation() == Qt::Horizontal ? rect.right() : rect.top(); + } + } + break; + case ZoomInAnimation: { + int index = qMin(oldLayout.count() * (m_axis->axis()->orientation() == Qt::Horizontal ? m_point.x() : (1 - m_point.y())), newLayout.count() - (qreal)1.0); + oldLayout.resize(newLayout.count()); + + for (int i = 0; i < oldLayout.count(); i++) + oldLayout[i] = oldLayout[index]; + } + break; + case MoveForwardAnimation: { + oldLayout.resize(newLayout.count()); + + for (int i = 0, j = i + 1; i < oldLayout.count() - 1; ++i, ++j) + oldLayout[i] = oldLayout[j]; + } + break; + case MoveBackwordAnimation: { + oldLayout.resize(newLayout.count()); + + for (int i = oldLayout.count() - 1, j = i - 1; i > 0; --i, --j) + oldLayout[i] = oldLayout[j]; + } + break; + default: { + oldLayout.resize(newLayout.count()); + QRectF rect = m_axis->gridGeometry(); + for (int i = 0, j = oldLayout.count() - 1; i < oldLayout.count(); ++i, --j) + oldLayout[i] = m_axis->axis()->orientation() == Qt::Horizontal ? rect.left() : rect.top(); + } + break; + } + + QVariantAnimation::KeyValues value; + setKeyValues(value); //workaround for wrong interpolation call + setKeyValueAt(0.0, qVariantFromValue(oldLayout)); + setKeyValueAt(1.0, qVariantFromValue(newLayout)); +} + +QVariant AxisAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress) const +{ + QVector<qreal> startVector = qvariant_cast<QVector<qreal> >(start); + QVector<qreal> endVecotr = qvariant_cast<QVector<qreal> >(end); + QVector<qreal> result; + + Q_ASSERT(startVector.count() == endVecotr.count()) ; + + for (int i = 0; i < startVector.count(); i++) { + qreal value = startVector[i] + ((endVecotr[i] - startVector[i]) * progress); + result << value; + } + return qVariantFromValue(result); +} + + +void AxisAnimation::updateCurrentValue(const QVariant &value) +{ + if (state() != QAbstractAnimation::Stopped) { //workaround + QVector<qreal> vector = qvariant_cast<QVector<qreal> >(value); + m_axis->setLayout(vector); + m_axis->updateGeometry(); + } + +} + +QT_CHARTS_END_NAMESPACE diff --git a/src/charts/animations/axisanimation_p.h b/src/charts/animations/axisanimation_p.h new file mode 100644 index 00000000..9e886b2b --- /dev/null +++ b/src/charts/animations/axisanimation_p.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Enterprise Chart API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef AXISANIMATION_H +#define AXISANIMATION_H + +#include "chartanimation_p.h" +#include <QPointF> + +QT_CHARTS_BEGIN_NAMESPACE + +class ChartAxisElement; + +class AxisAnimation: public ChartAnimation +{ +public: + enum Animation { DefaultAnimation, ZoomOutAnimation, ZoomInAnimation, MoveForwardAnimation, MoveBackwordAnimation}; + AxisAnimation(ChartAxisElement *axis); + ~AxisAnimation(); + void setAnimationType(Animation type); + void setAnimationPoint(const QPointF &point); + void setValues(QVector<qreal> &oldLayout, QVector<qreal> &newLayout); +protected: + QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const; + void updateCurrentValue(const QVariant &value); +private: + ChartAxisElement *m_axis; + Animation m_type; + QPointF m_point; +}; + +QT_CHARTS_END_NAMESPACE + + + +#endif /* AXISANIMATION_H */ diff --git a/src/charts/animations/baranimation.cpp b/src/charts/animations/baranimation.cpp new file mode 100644 index 00000000..15b69288 --- /dev/null +++ b/src/charts/animations/baranimation.cpp @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "baranimation_p.h" +#include "abstractbarchartitem_p.h" + +Q_DECLARE_METATYPE(QVector<QRectF>) + +QT_CHARTS_BEGIN_NAMESPACE + +BarAnimation::BarAnimation(AbstractBarChartItem *item) + : ChartAnimation(item), + m_item(item) +{ + setDuration(ChartAnimationDuration); + setEasingCurve(QEasingCurve::OutQuart); +} + +BarAnimation::~BarAnimation() +{ +} + +QVariant BarAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const +{ + QVector<QRectF> startVector = qvariant_cast<QVector<QRectF> >(from); + QVector<QRectF> endVector = qvariant_cast<QVector<QRectF> >(to); + QVector<QRectF> result; + + Q_ASSERT(startVector.count() == endVector.count()); + + for (int i = 0; i < startVector.count(); i++) { + QRectF start = startVector[i].normalized(); + QRectF end = endVector[i].normalized(); + qreal x1 = start.left() + progress * (end.left() - start.left()); + qreal x2 = start.right() + progress * (end.right() - start.right()); + qreal y1 = start.top() + progress * (end.top() - start.top()); + qreal y2 = start.bottom() + progress * (end.bottom() - start.bottom()); + + QRectF value(QPointF(x1, y1), QPointF(x2, y2)); + result << value.normalized(); + } + return qVariantFromValue(result); +} + +void BarAnimation::updateCurrentValue(const QVariant &value) +{ + if (state() != QAbstractAnimation::Stopped) { //workaround + + QVector<QRectF> layout = qvariant_cast<QVector<QRectF> >(value); + m_item->setLayout(layout); + } +} + +void BarAnimation::setup(const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout) +{ + QVariantAnimation::KeyValues value; + setKeyValues(value); //workaround for wrong interpolation call + setKeyValueAt(0.0, qVariantFromValue(oldLayout)); + setKeyValueAt(1.0, qVariantFromValue(newLayout)); +} + +#include "moc_baranimation_p.cpp" + +QT_CHARTS_END_NAMESPACE + diff --git a/src/charts/animations/baranimation_p.h b/src/charts/animations/baranimation_p.h new file mode 100644 index 00000000..5b49f302 --- /dev/null +++ b/src/charts/animations/baranimation_p.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Enterprise Chart API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef BARANIMATION_P_H +#define BARANIMATION_P_H + +#include "chartanimation_p.h" + +QT_CHARTS_BEGIN_NAMESPACE + +class AbstractBarChartItem; + +class BarAnimation : public ChartAnimation +{ + Q_OBJECT + +public: + BarAnimation(AbstractBarChartItem *item); + ~BarAnimation(); + +public: // from QVariantAnimation + virtual QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const; + virtual void updateCurrentValue(const QVariant &value); + + void setup(const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout); + +protected: + AbstractBarChartItem *m_item; +}; + +QT_CHARTS_END_NAMESPACE + +#endif // BARANIMATION_P_H diff --git a/src/charts/animations/boxplotanimation.cpp b/src/charts/animations/boxplotanimation.cpp new file mode 100644 index 00000000..cfd474bb --- /dev/null +++ b/src/charts/animations/boxplotanimation.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "boxplotanimation_p.h" +#include "boxplotchartitem_p.h" +#include "boxwhiskersdata_p.h" +#include "boxwhiskersanimation_p.h" + +QT_CHARTS_BEGIN_NAMESPACE + +BoxPlotAnimation::BoxPlotAnimation(BoxPlotChartItem *item) + : QObject(item), + m_item(item) +{ +} + +BoxPlotAnimation::~BoxPlotAnimation() +{ +} + +void BoxPlotAnimation::addBox(BoxWhiskers *box) +{ + BoxWhiskersAnimation *animation = m_animations.value(box); + if (!animation) { + animation = new BoxWhiskersAnimation(box, this); + m_animations.insert(box, animation); + BoxWhiskersData start; + start.m_lowerExtreme = box->m_data.m_median; + start.m_lowerQuartile = box->m_data.m_median; + start.m_median = box->m_data.m_median; + start.m_upperQuartile = box->m_data.m_median; + start.m_upperExtreme = box->m_data.m_median; + animation->setup(start, box->m_data); + } else { + animation->stop(); + animation->setEndData(box->m_data); + } +} + +ChartAnimation *BoxPlotAnimation::boxAnimation(BoxWhiskers *box) +{ + BoxWhiskersAnimation *animation = m_animations.value(box); + if (animation) + animation->m_changeAnimation = false; + + return animation; +} + +ChartAnimation *BoxPlotAnimation::boxChangeAnimation(BoxWhiskers *box) +{ + BoxWhiskersAnimation *animation = m_animations.value(box); + animation->m_changeAnimation = true; + animation->setEndData(box->m_data); + + return animation; +} + +void BoxPlotAnimation::setAnimationStart(BoxWhiskers *box) +{ + BoxWhiskersAnimation *animation = m_animations.value(box); + animation->setStartData(box->m_data); +} + +void BoxPlotAnimation::stopAll() +{ + foreach (BoxWhiskers *box, m_animations.keys()) { + BoxWhiskersAnimation *animation = m_animations.value(box); + animation->stopAndDestroyLater(); + m_animations.remove(box); + } +} + +void BoxPlotAnimation::removeBoxAnimation(BoxWhiskers *box) +{ + m_animations.remove(box); +} + +#include "moc_boxplotanimation_p.cpp" + +QT_CHARTS_END_NAMESPACE diff --git a/src/charts/animations/boxplotanimation_p.h b/src/charts/animations/boxplotanimation_p.h new file mode 100644 index 00000000..3eba311b --- /dev/null +++ b/src/charts/animations/boxplotanimation_p.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Enterprise Chart API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef BOXPLOTANIMATION_P_H +#define BOXPLOTANIMATION_P_H + +#include "chartanimation_p.h" +#include "boxwhiskers_p.h" +#include "boxwhiskersdata_p.h" +#include "boxwhiskersanimation_p.h" + +QT_CHARTS_BEGIN_NAMESPACE + +class BoxPlotChartItem; + +class BoxPlotAnimation : public QObject +{ + Q_OBJECT +public: + BoxPlotAnimation(BoxPlotChartItem *item); + ~BoxPlotAnimation(); + + void addBox(BoxWhiskers *box); + ChartAnimation *boxAnimation(BoxWhiskers *box); + ChartAnimation *boxChangeAnimation(BoxWhiskers *box); + + void setAnimationStart(BoxWhiskers *box); + void stopAll(); + void removeBoxAnimation(BoxWhiskers *box); + +protected: + BoxPlotChartItem *m_item; + QHash<BoxWhiskers *, BoxWhiskersAnimation *> m_animations; +}; + +QT_CHARTS_END_NAMESPACE + +#endif // BOXPLOTANIMATION_P_H diff --git a/src/charts/animations/boxwhiskersanimation.cpp b/src/charts/animations/boxwhiskersanimation.cpp new file mode 100644 index 00000000..6d5404fa --- /dev/null +++ b/src/charts/animations/boxwhiskersanimation.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "boxwhiskersanimation_p.h" +#include "boxplotanimation_p.h" +#include "boxplotchartitem_p.h" +#include "boxwhiskersdata_p.h" + +Q_DECLARE_METATYPE(QVector<QRectF>) +Q_DECLARE_METATYPE(QT_CHARTS_NAMESPACE::BoxWhiskersData) +Q_DECLARE_METATYPE(qreal) + +QT_CHARTS_BEGIN_NAMESPACE + +BoxWhiskersAnimation::BoxWhiskersAnimation(BoxWhiskers *box, BoxPlotAnimation *boxPlotAnimation) + : ChartAnimation(box), + m_box(box), + m_boxPlotAnimation(boxPlotAnimation) +{ + setDuration(ChartAnimationDuration); + setEasingCurve(QEasingCurve::OutQuart); +} + +BoxWhiskersAnimation::~BoxWhiskersAnimation() +{ + if (m_boxPlotAnimation) + m_boxPlotAnimation->removeBoxAnimation(m_box); +} + +QVariant BoxWhiskersAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const +{ + BoxWhiskersData startData = qvariant_cast<BoxWhiskersData>(from); + BoxWhiskersData endData = qvariant_cast<BoxWhiskersData>(to); + BoxWhiskersData result; + + if (m_changeAnimation) { + result.m_lowerExtreme = startData.m_lowerExtreme + progress * (endData.m_lowerExtreme - startData.m_lowerExtreme); + result.m_lowerQuartile = startData.m_lowerQuartile + progress * (endData.m_lowerQuartile - startData.m_lowerQuartile); + result.m_median = startData.m_median + progress * (endData.m_median - startData.m_median); + result.m_upperQuartile = startData.m_upperQuartile + progress * (endData.m_upperQuartile - startData.m_upperQuartile); + result.m_upperExtreme = startData.m_upperExtreme + progress * (endData.m_upperExtreme - startData.m_upperExtreme); + } else { + result.m_lowerExtreme = endData.m_median + progress * (endData.m_lowerExtreme - endData.m_median); + result.m_lowerQuartile = endData.m_median + progress * (endData.m_lowerQuartile - endData.m_median); + result.m_median = endData.m_median; + result.m_upperQuartile = endData.m_median + progress * (endData.m_upperQuartile - endData.m_median); + result.m_upperExtreme = endData.m_median + progress * (endData.m_upperExtreme - endData.m_median); + } + result.m_index = endData.m_index; + result.m_boxItems = endData.m_boxItems; + + result.m_maxX = endData.m_maxX; + result.m_minX = endData.m_minX; + result.m_maxY = endData.m_maxY; + result.m_minY = endData.m_minY; + result.m_seriesIndex = endData.m_seriesIndex; + result.m_seriesCount = endData.m_seriesCount; + + return qVariantFromValue(result); +} + +void BoxWhiskersAnimation::updateCurrentValue(const QVariant &value) +{ + BoxWhiskersData data = qvariant_cast<BoxWhiskersData>(value); + m_box->setLayout(data); +} + +void BoxWhiskersAnimation::setup(const BoxWhiskersData &startData, const BoxWhiskersData &endData) +{ + setKeyValueAt(0.0, qVariantFromValue(startData)); + setKeyValueAt(1.0, qVariantFromValue(endData)); +} + +void BoxWhiskersAnimation::setEndData(const BoxWhiskersData &endData) +{ + if (state() != QAbstractAnimation::Stopped) + stop(); + + setEndValue(qVariantFromValue(endData)); +} + +void BoxWhiskersAnimation::setStartData(const BoxWhiskersData &endData) +{ + if (state() != QAbstractAnimation::Stopped) + stop(); + + setStartValue(qVariantFromValue(endData)); +} + +#include "moc_boxwhiskersanimation_p.cpp" + +QT_CHARTS_END_NAMESPACE + diff --git a/src/charts/animations/boxwhiskersanimation_p.h b/src/charts/animations/boxwhiskersanimation_p.h new file mode 100644 index 00000000..ff56222b --- /dev/null +++ b/src/charts/animations/boxwhiskersanimation_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Enterprise Chart API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef BOXWHISKERSANIMATION_P_H +#define BOXWHISKERSANIMATION_P_H + +#include "chartanimation_p.h" +#include "boxwhiskers_p.h" +#include "boxwhiskersdata_p.h" + +QT_CHARTS_BEGIN_NAMESPACE + +class BoxPlotChartItem; +class BoxPlotAnimation; + +class BoxWhiskersAnimation : public ChartAnimation +{ + Q_OBJECT + +public: + BoxWhiskersAnimation(BoxWhiskers *box, BoxPlotAnimation *boxPlotAnimation); + ~BoxWhiskersAnimation(); + +public: // from QVariantAnimation + virtual QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const; + virtual void updateCurrentValue(const QVariant &value); + + void setup(const BoxWhiskersData &startData, const BoxWhiskersData &endData); + void setEndData(const BoxWhiskersData &endData); + void setStartData(const BoxWhiskersData &endData); + + void moveMedianLine(bool move); + +protected: + friend class BoxPlotAnimation; + BoxWhiskers *m_box; + bool m_changeAnimation; + BoxPlotAnimation *m_boxPlotAnimation; +}; + +QT_CHARTS_END_NAMESPACE + +#endif // BOXWHISKERSANIMATION_P_H diff --git a/src/charts/animations/chartanimation.cpp b/src/charts/animations/chartanimation.cpp new file mode 100644 index 00000000..0e512932 --- /dev/null +++ b/src/charts/animations/chartanimation.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "chartanimation_p.h" + +QT_CHARTS_BEGIN_NAMESPACE + +ChartAnimation::ChartAnimation(QObject *parent) : + QVariantAnimation(parent), + m_destructing(false) +{ +} + +void ChartAnimation::stopAndDestroyLater() +{ + m_destructing = true; + stop(); + deleteLater(); +} + +void ChartAnimation::startChartAnimation() +{ + if (!m_destructing) + start(); +} + +QT_CHARTS_END_NAMESPACE + + diff --git a/src/charts/animations/chartanimation_p.h b/src/charts/animations/chartanimation_p.h new file mode 100644 index 00000000..81ec72c4 --- /dev/null +++ b/src/charts/animations/chartanimation_p.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Enterprise Chart API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef CHARTANIMATION_H +#define CHARTANIMATION_H + +#include "qchartglobal.h" +#include <QVariantAnimation> + +QT_CHARTS_BEGIN_NAMESPACE + +const static int ChartAnimationDuration = 1000; + +class ChartAnimation: public QVariantAnimation +{ + Q_OBJECT +public: + ChartAnimation(QObject *parent = 0); + + void stopAndDestroyLater(); + +public Q_SLOTS: + void startChartAnimation(); + +protected: + bool m_destructing; +}; + +QT_CHARTS_END_NAMESPACE + +#endif /* CHARTANIMATION_H */ diff --git a/src/charts/animations/pieanimation.cpp b/src/charts/animations/pieanimation.cpp new file mode 100644 index 00000000..30d6865f --- /dev/null +++ b/src/charts/animations/pieanimation.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "pieanimation_p.h" +#include "piesliceanimation_p.h" +#include "piechartitem_p.h" + +QT_CHARTS_BEGIN_NAMESPACE + +PieAnimation::PieAnimation(PieChartItem *item) + : ChartAnimation(item), + m_item(item) +{ +} + +PieAnimation::~PieAnimation() +{ +} + +ChartAnimation *PieAnimation::updateValue(PieSliceItem *sliceItem, const PieSliceData &sliceData) +{ + PieSliceAnimation *animation = m_animations.value(sliceItem); + if (!animation) { + animation = new PieSliceAnimation(sliceItem); + m_animations.insert(sliceItem, animation); + } else { + animation->stop(); + } + + animation->updateValue(sliceData); + animation->setDuration(ChartAnimationDuration); + animation->setEasingCurve(QEasingCurve::OutQuart); + + return animation; +} + +ChartAnimation *PieAnimation::addSlice(PieSliceItem *sliceItem, const PieSliceData &sliceData, bool startupAnimation) +{ + PieSliceAnimation *animation = new PieSliceAnimation(sliceItem); + m_animations.insert(sliceItem, animation); + + PieSliceData startValue = sliceData; + startValue.m_radius = 0; + if (startupAnimation) + startValue.m_startAngle = 0; + else + startValue.m_startAngle = sliceData.m_startAngle + (sliceData.m_angleSpan / 2); + startValue.m_angleSpan = 0; + + if (sliceData.m_holeRadius > 0) + startValue.m_radius = sliceData.m_holeRadius; + + animation->setValue(startValue, sliceData); + animation->setDuration(ChartAnimationDuration); + animation->setEasingCurve(QEasingCurve::OutQuart); + + return animation; +} + +ChartAnimation *PieAnimation::removeSlice(PieSliceItem *sliceItem) +{ + PieSliceAnimation *animation = m_animations.value(sliceItem); + Q_ASSERT(animation); + animation->stop(); + + PieSliceData endValue = animation->currentSliceValue(); + if (endValue.m_holeRadius > 0) + endValue.m_radius = endValue.m_holeRadius; + else + endValue.m_radius = 0; + endValue.m_startAngle = endValue.m_startAngle + endValue.m_angleSpan; + endValue.m_angleSpan = 0; + endValue.m_isLabelVisible = false; + + animation->updateValue(endValue); + animation->setDuration(ChartAnimationDuration); + animation->setEasingCurve(QEasingCurve::OutQuart); + + // PieSliceItem is the parent of PieSliceAnimation so the animation will be deleted as well.. + connect(animation, SIGNAL(finished()), sliceItem, SLOT(deleteLater())); + m_animations.remove(sliceItem); + + return animation; +} + +void PieAnimation::updateCurrentValue(const QVariant &) +{ + // nothing to do... +} + +#include "moc_pieanimation_p.cpp" + +QT_CHARTS_END_NAMESPACE diff --git a/src/charts/animations/pieanimation_p.h b/src/charts/animations/pieanimation_p.h new file mode 100644 index 00000000..33599694 --- /dev/null +++ b/src/charts/animations/pieanimation_p.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Enterprise Chart API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef PIEANIMATION_P_H +#define PIEANIMATION_P_H + +#include "chartanimation_p.h" +#include "piechartitem_p.h" +#include "piesliceanimation_p.h" + +QT_CHARTS_BEGIN_NAMESPACE + +class PieChartItem; + +class PieAnimation : public ChartAnimation +{ + Q_OBJECT + +public: + PieAnimation(PieChartItem *item); + ~PieAnimation(); + ChartAnimation *updateValue(PieSliceItem *sliceItem, const PieSliceData &newValue); + ChartAnimation *addSlice(PieSliceItem *sliceItem, const PieSliceData &endValue, bool startupAnimation); + ChartAnimation *removeSlice(PieSliceItem *sliceItem); + +public: // from QVariantAnimation + void updateCurrentValue(const QVariant &value); + +private: + PieChartItem *m_item; + QHash<PieSliceItem *, PieSliceAnimation *> m_animations; +}; + +QT_CHARTS_END_NAMESPACE + +#endif diff --git a/src/charts/animations/piesliceanimation.cpp b/src/charts/animations/piesliceanimation.cpp new file mode 100644 index 00000000..0a4503c9 --- /dev/null +++ b/src/charts/animations/piesliceanimation.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "piesliceanimation_p.h" +#include "piechartitem_p.h" + +Q_DECLARE_METATYPE(QT_CHARTS_NAMESPACE::PieSliceData) + +QT_CHARTS_BEGIN_NAMESPACE + +qreal linearPos(qreal start, qreal end, qreal pos) +{ + return start + ((end - start) * pos); +} + +QPointF linearPos(QPointF start, QPointF end, qreal pos) +{ + qreal x = linearPos(start.x(), end.x(), pos); + qreal y = linearPos(start.y(), end.y(), pos); + return QPointF(x, y); +} + +QPen linearPos(QPen start, QPen end, qreal pos) +{ + QColor c; + c.setRedF(linearPos(start.color().redF(), end.color().redF(), pos)); + c.setGreenF(linearPos(start.color().greenF(), end.color().greenF(), pos)); + c.setBlueF(linearPos(start.color().blueF(), end.color().blueF(), pos)); + end.setColor(c); + return end; +} + +QBrush linearPos(QBrush start, QBrush end, qreal pos) +{ + QColor c; + c.setRedF(linearPos(start.color().redF(), end.color().redF(), pos)); + c.setGreenF(linearPos(start.color().greenF(), end.color().greenF(), pos)); + c.setBlueF(linearPos(start.color().blueF(), end.color().blueF(), pos)); + end.setColor(c); + return end; +} + +PieSliceAnimation::PieSliceAnimation(PieSliceItem *sliceItem) + : ChartAnimation(sliceItem), + m_sliceItem(sliceItem), + m_currentValue(m_sliceItem->m_data) +{ + +} + +PieSliceAnimation::~PieSliceAnimation() +{ +} + +void PieSliceAnimation::setValue(const PieSliceData &startValue, const PieSliceData &endValue) +{ + if (state() != QAbstractAnimation::Stopped) + stop(); + + m_currentValue = startValue; + + setKeyValueAt(0.0, qVariantFromValue(startValue)); + setKeyValueAt(1.0, qVariantFromValue(endValue)); +} + +void PieSliceAnimation::updateValue(const PieSliceData &endValue) +{ + if (state() != QAbstractAnimation::Stopped) + stop(); + + setKeyValueAt(0.0, qVariantFromValue(m_currentValue)); + setKeyValueAt(1.0, qVariantFromValue(endValue)); +} + +PieSliceData PieSliceAnimation::currentSliceValue() +{ + // NOTE: + // We must use an internal current value because QVariantAnimation::currentValue() is updated + // before the animation is actually started. So if we get 2 updateValue() calls in a row the currentValue() + // will have the end value set from the first call and the second call will interpolate that instead of + // the original current value as it was before the first call. + return m_currentValue; +} + +QVariant PieSliceAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress) const +{ + PieSliceData startValue = qvariant_cast<PieSliceData>(start); + PieSliceData endValue = qvariant_cast<PieSliceData>(end); + + PieSliceData result; + result = endValue; + result.m_center = linearPos(startValue.m_center, endValue.m_center, progress); + result.m_radius = linearPos(startValue.m_radius, endValue.m_radius, progress); + result.m_startAngle = linearPos(startValue.m_startAngle, endValue.m_startAngle, progress); + result.m_angleSpan = linearPos(startValue.m_angleSpan, endValue.m_angleSpan, progress); + result.m_slicePen = linearPos(startValue.m_slicePen, endValue.m_slicePen, progress); + result.m_sliceBrush = linearPos(startValue.m_sliceBrush, endValue.m_sliceBrush, progress); + result.m_holeRadius = linearPos(startValue.m_holeRadius, endValue.m_holeRadius, progress); + + return qVariantFromValue(result); +} + +void PieSliceAnimation::updateCurrentValue(const QVariant &value) +{ + if (state() != QAbstractAnimation::Stopped) { //workaround + m_currentValue = qvariant_cast<PieSliceData>(value); + m_sliceItem->setLayout(m_currentValue); + } +} + +QT_CHARTS_END_NAMESPACE diff --git a/src/charts/animations/piesliceanimation_p.h b/src/charts/animations/piesliceanimation_p.h new file mode 100644 index 00000000..88155054 --- /dev/null +++ b/src/charts/animations/piesliceanimation_p.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Enterprise Chart API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef PIESLICEANIMATION_P_H +#define PIESLICEANIMATION_P_H + +#include "chartanimation_p.h" +#include "piesliceitem_p.h" + +QT_CHARTS_BEGIN_NAMESPACE + +class PieChartItem; + +class PieSliceAnimation : public ChartAnimation +{ +public: + PieSliceAnimation(PieSliceItem *sliceItem); + ~PieSliceAnimation(); + void setValue(const PieSliceData &startValue, const PieSliceData &endValue); + void updateValue(const PieSliceData &endValue); + PieSliceData currentSliceValue(); + +protected: + QVariant interpolated(const QVariant &start, const QVariant &end, qreal progress) const; + void updateCurrentValue(const QVariant &value); + +private: + PieSliceItem *m_sliceItem; + PieSliceData m_currentValue; +}; + +QT_CHARTS_END_NAMESPACE + +#endif diff --git a/src/charts/animations/scatteranimation.cpp b/src/charts/animations/scatteranimation.cpp new file mode 100644 index 00000000..faf66d11 --- /dev/null +++ b/src/charts/animations/scatteranimation.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** + ** + ** Copyright (C) 2014 Digia Plc + ** All rights reserved. + ** For any questions to Digia, please use contact form at http://qt.digia.com + ** + ** This file is part of the Qt Enterprise Charts Add-on. + ** + ** $QT_BEGIN_LICENSE$ + ** Licensees holding valid Qt Enterprise licenses may use this file in + ** accordance with the Qt Enterprise License Agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and Digia. + ** + ** If you have questions regarding the use of this file, please use + ** contact form at http://qt.digia.com + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#include "scatteranimation_p.h" +#include "scatterchartitem_p.h" +#include <QDebug> + +QT_CHARTS_BEGIN_NAMESPACE + +ScatterAnimation::ScatterAnimation(ScatterChartItem *item) + : XYAnimation(item) +{ +} + +ScatterAnimation::~ScatterAnimation() +{ +} + +void ScatterAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) +{ + XYAnimation::updateState(newState, oldState); + + if (oldState == QAbstractAnimation::Running && newState == QAbstractAnimation::Stopped + && animationType() == RemovePointAnimation) { + // Removing a point from scatter chart will keep extra marker item after animation stops. + // Also, if the removed point was not the last one in series, points after the removed one + // will report wrong coordinates when clicked. To fix these issues, update geometry after + // point removal animation has finished. + chartItem()->updateGeometry(); + } +} + +QT_CHARTS_END_NAMESPACE diff --git a/src/charts/animations/scatteranimation_p.h b/src/charts/animations/scatteranimation_p.h new file mode 100644 index 00000000..7a4f8bfb --- /dev/null +++ b/src/charts/animations/scatteranimation_p.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Enterprise Chart API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef SCATTERANIMATION_P_H +#define SCATTERANIMATION_P_H +#include "xyanimation_p.h" + +QT_CHARTS_BEGIN_NAMESPACE + +class ScatterChartItem; + +class ScatterAnimation : public XYAnimation +{ +public: + ScatterAnimation(ScatterChartItem *item); + ~ScatterAnimation(); + +protected: + void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState); +}; + +QT_CHARTS_END_NAMESPACE + +#endif diff --git a/src/charts/animations/splineanimation.cpp b/src/charts/animations/splineanimation.cpp new file mode 100644 index 00000000..4056d825 --- /dev/null +++ b/src/charts/animations/splineanimation.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** + ** + ** Copyright (C) 2014 Digia Plc + ** All rights reserved. + ** For any questions to Digia, please use contact form at http://qt.digia.com + ** + ** This file is part of the Qt Enterprise Charts Add-on. + ** + ** $QT_BEGIN_LICENSE$ + ** Licensees holding valid Qt Enterprise licenses may use this file in + ** accordance with the Qt Enterprise License Agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and Digia. + ** + ** If you have questions regarding the use of this file, please use + ** contact form at http://qt.digia.com + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#include "splineanimation_p.h" +#include "splinechartitem_p.h" +#include <QDebug> + +Q_DECLARE_METATYPE(QVector<QPointF>) +Q_DECLARE_METATYPE(SplineVector) + +QT_CHARTS_BEGIN_NAMESPACE + +SplineAnimation::SplineAnimation(SplineChartItem *item) + : XYAnimation(item), + m_item(item), + m_valid(false) +{ +} + +SplineAnimation::~SplineAnimation() +{ +} + +void SplineAnimation::setup(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, QVector<QPointF> &oldControlPoints, QVector<QPointF> &newControlPoints, int index) +{ + if (newPoints.count() * 2 - 2 != newControlPoints.count() || newControlPoints.count() < 2) { + m_valid = false; + m_dirty = false; + m_item->setGeometryPoints(newPoints); + m_item->setControlGeometryPoints(newControlPoints); + m_item->setDirty(false); + m_item->updateGeometry(); + return; + } + + m_type = NewAnimation; + + if (state() != QAbstractAnimation::Stopped) { + stop(); + m_dirty = false; + } + + if (!m_dirty) { + m_dirty = true; + m_oldSpline.first = oldPoints; + m_oldSpline.second = oldControlPoints; + } + + m_newSpline.first = newPoints; + m_newSpline.second = newControlPoints; + + + int x = m_oldSpline.first.count(); + int y = m_newSpline.first.count(); + + if (x - y == 1 && index >= 0 && y > 0) { + //remove point + if (index > 0) { + m_newSpline.first.insert(index, newPoints[index - 1]); + m_newSpline.second.insert((index - 1) * 2, newPoints[index - 1]); + m_newSpline.second.insert((index - 1) * 2 + 1, newPoints[index - 1]); + } else { + m_newSpline.first.insert(0, newPoints[index]); + m_newSpline.second.insert(0, newPoints[index]); + m_newSpline.second.insert(1, newPoints[index]); + } + m_index = index; + m_type = RemovePointAnimation; + } + + if (x - y == -1 && index >= 0) { + //add point + if (index > 0) { + m_oldSpline.first.insert(index, newPoints[index - 1]); + m_oldSpline.second.insert((index - 1) * 2, newPoints[index - 1]); + m_oldSpline.second.insert((index - 1) * 2 + 1, newPoints[index - 1]); + } else { + m_oldSpline.first.insert(0, newPoints[index]); + m_oldSpline.second.insert(0, newPoints[index]); + m_oldSpline.second.insert(1, newPoints[index]); + } + m_index = index; + m_type = AddPointAnimation; + } + + x = m_oldSpline.first.count(); + y = m_newSpline.first.count(); + + if (x != y) { + m_type = NewAnimation; + } else if (m_type == NewAnimation) { + m_type = ReplacePointAnimation; + } + + + setKeyValueAt(0.0, qVariantFromValue(m_oldSpline)); + setKeyValueAt(1.0, qVariantFromValue(m_newSpline)); + + m_valid = true; + +} + +QVariant SplineAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress) const +{ + + SplineVector startPair = qvariant_cast< SplineVector >(start); + SplineVector endPair = qvariant_cast< SplineVector >(end); + SplineVector result; + + switch (animationType()) { + case RemovePointAnimation: + case AddPointAnimation: + case ReplacePointAnimation: { + if (startPair.first.count() != endPair.first.count()) + break; + Q_ASSERT(startPair.first.count() * 2 - 2 == startPair.second.count()); + Q_ASSERT(endPair.first.count() * 2 - 2 == endPair.second.count()); + for (int i = 0; i < endPair.first.count(); i++) { + qreal x = startPair.first[i].x() + ((endPair.first[i].x() - startPair.first[i].x()) * progress); + qreal y = startPair.first[i].y() + ((endPair.first[i].y() - startPair.first[i].y()) * progress); + result.first << QPointF(x, y); + if (i + 1 >= endPair.first.count()) + continue; + x = startPair.second[i * 2].x() + ((endPair.second[i * 2].x() - startPair.second[i * 2].x()) * progress); + y = startPair.second[i * 2].y() + ((endPair.second[i * 2].y() - startPair.second[i * 2].y()) * progress); + result.second << QPointF(x, y); + x = startPair.second[i * 2 + 1].x() + ((endPair.second[i * 2 + 1].x() - startPair.second[i * 2 + 1].x()) * progress); + y = startPair.second[i * 2 + 1].y() + ((endPair.second[i * 2 + 1].y() - startPair.second[i * 2 + 1].y()) * progress); + result.second << QPointF(x, y); + } + } + break; + case NewAnimation: { + Q_ASSERT(endPair.first.count() * 2 - 2 == endPair.second.count()); + int count = endPair.first.count() * qBound(qreal(0), progress, qreal(1)); + for (int i = 0; i < count; i++) { + result.first << endPair.first[i]; + if (i + 1 == count) + break; + result.second << endPair.second[2 * i]; + result.second << endPair.second[2 * i + 1]; + } + } + break; + default: + qWarning() << "Unknown type of animation"; + break; + } + + return qVariantFromValue(result); +} + +void SplineAnimation::updateCurrentValue(const QVariant &value) +{ + if (state() != QAbstractAnimation::Stopped && m_valid) { //workaround + QPair<QVector<QPointF >, QVector<QPointF > > pair = qvariant_cast< QPair< QVector<QPointF>, QVector<QPointF> > >(value); + m_item->setGeometryPoints(pair.first); + m_item->setControlGeometryPoints(pair.second); + m_item->updateGeometry(); + m_item->setDirty(true); + m_dirty = false; + } +} + +void SplineAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) +{ + XYAnimation::updateState(newState, oldState); + + if (oldState == QAbstractAnimation::Running && newState == QAbstractAnimation::Stopped) { + if (m_item->isDirty() && m_type == RemovePointAnimation) { + if (!m_newSpline.first.isEmpty()) { + if (m_index) { + m_newSpline.first.remove(m_index); + m_newSpline.second.remove((m_index - 1) * 2); + m_newSpline.second.remove((m_index - 1) * 2); + } else { + m_newSpline.first.remove(0); + m_newSpline.second.remove(0); + m_newSpline.second.remove(0); + } + } + m_item->setGeometryPoints(m_newSpline.first); + m_item->setControlGeometryPoints(m_newSpline.second); + } + } + + if (oldState == QAbstractAnimation::Stopped && newState == QAbstractAnimation::Running) { + if (!m_valid) + stop(); + } +} + +QT_CHARTS_END_NAMESPACE diff --git a/src/charts/animations/splineanimation_p.h b/src/charts/animations/splineanimation_p.h new file mode 100644 index 00000000..ad9120ed --- /dev/null +++ b/src/charts/animations/splineanimation_p.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Enterprise Chart API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef SPLINEANIMATION_P_H +#define SPLINEANIMATION_P_H +#include "xyanimation_p.h" +#include <QPointF> + +typedef QPair<QVector<QPointF >, QVector<QPointF > > SplineVector; + +QT_CHARTS_BEGIN_NAMESPACE + +class SplineChartItem; + +class SplineAnimation : public XYAnimation +{ +public: + SplineAnimation(SplineChartItem *item); + ~SplineAnimation(); + void setup(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, QVector<QPointF> &oldContorlPoints, QVector<QPointF> &newControlPoints, int index = -1); + +protected: + QVariant interpolated(const QVariant &start, const QVariant &end, qreal progress) const; + void updateCurrentValue(const QVariant &value); + void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState); + +private: + SplineVector m_oldSpline; + SplineVector m_newSpline; + SplineChartItem *m_item; + bool m_valid; +}; + +QT_CHARTS_END_NAMESPACE + +#endif diff --git a/src/charts/animations/xyanimation.cpp b/src/charts/animations/xyanimation.cpp new file mode 100644 index 00000000..3e395c1a --- /dev/null +++ b/src/charts/animations/xyanimation.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "xyanimation_p.h" +#include "xychart_p.h" +#include <QDebug> + +Q_DECLARE_METATYPE(QVector<QPointF>) + +QT_CHARTS_BEGIN_NAMESPACE + +XYAnimation::XYAnimation(XYChart *item) + : ChartAnimation(item), + m_type(NewAnimation), + m_dirty(false), + m_index(-1), + m_item(item) +{ + setDuration(ChartAnimationDuration); + setEasingCurve(QEasingCurve::OutQuart); +} + +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, qVariantFromValue(m_oldPoints)); + setKeyValueAt(1.0, qVariantFromValue(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 qVariantFromValue(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); + } + } +} + +#include "moc_chartanimation_p.cpp" +QT_CHARTS_END_NAMESPACE diff --git a/src/charts/animations/xyanimation_p.h b/src/charts/animations/xyanimation_p.h new file mode 100644 index 00000000..ef54c530 --- /dev/null +++ b/src/charts/animations/xyanimation_p.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Enterprise Chart API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef XYANIMATION_P_H +#define XYANIMATION_P_H + +#include "chartanimation_p.h" +#include <QPointF> + +QT_CHARTS_BEGIN_NAMESPACE + +class XYChart; + +class XYAnimation : public ChartAnimation +{ +protected: + enum Animation { AddPointAnimation, RemovePointAnimation, ReplacePointAnimation, NewAnimation }; +public: + XYAnimation(XYChart *item); + ~XYAnimation(); + void setup(const QVector<QPointF> &oldPoints, const QVector<QPointF> &newPoints, int index = -1); + Animation animationType() const { return m_type; }; + +protected: + QVariant interpolated(const QVariant &start, const QVariant &end, qreal progress) const; + void updateCurrentValue(const QVariant &value); + void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState); + XYChart *chartItem() { return m_item; } +protected: + Animation m_type; + bool m_dirty; + int m_index; +private: + XYChart *m_item; + QVector<QPointF> m_oldPoints; + QVector<QPointF> m_newPoints; +}; + +QT_CHARTS_END_NAMESPACE + +#endif |