diff options
author | Michal Klocek <michal.klocek@digia.com> | 2012-05-25 13:47:19 +0300 |
---|---|---|
committer | Michal Klocek <michal.klocek@digia.com> | 2012-05-25 13:49:11 +0300 |
commit | 51695bb27b0ea6cae78968b5b21021ea88320527 (patch) | |
tree | 37651f9b1f6b42f000a3dd1aa8b7dd7c38fd823b | |
parent | 897a83c64309456c739ecd282b297a28a123d567 (diff) |
Refactors axis animation, line animations
-rw-r--r-- | src/animations/axisanimation.cpp | 75 | ||||
-rw-r--r-- | src/animations/axisanimation_p.h | 11 | ||||
-rw-r--r-- | src/animations/chartanimation_p.h | 1 | ||||
-rw-r--r-- | src/animations/chartanimator.cpp | 102 | ||||
-rw-r--r-- | src/animations/chartanimator_p.h | 12 | ||||
-rw-r--r-- | src/animations/splineanimation.cpp | 7 | ||||
-rw-r--r-- | src/animations/xyanimation.cpp | 80 | ||||
-rw-r--r-- | src/animations/xyanimation_p.h | 8 | ||||
-rw-r--r-- | src/areachart/areachartitem.cpp | 5 | ||||
-rw-r--r-- | src/areachart/areachartitem_p.h | 4 | ||||
-rw-r--r-- | src/axis/axis.pri | 4 | ||||
-rw-r--r-- | src/axis/chartaxis.cpp | 215 | ||||
-rw-r--r-- | src/axis/chartaxis_p.h | 35 | ||||
-rw-r--r-- | src/axis/chartaxisx.cpp | 112 | ||||
-rw-r--r-- | src/axis/chartaxisx_p.h | 46 | ||||
-rw-r--r-- | src/axis/chartaxisy.cpp | 116 | ||||
-rw-r--r-- | src/axis/chartaxisy_p.h | 46 | ||||
-rw-r--r-- | src/chartpresenter.cpp | 70 | ||||
-rw-r--r-- | src/chartpresenter_p.h | 22 | ||||
-rw-r--r-- | src/splinechart/splinechartitem.cpp | 2 | ||||
-rw-r--r-- | src/xychart/xychart.cpp | 99 | ||||
-rw-r--r-- | src/xychart/xychart_p.h | 6 |
22 files changed, 690 insertions, 388 deletions
diff --git a/src/animations/axisanimation.cpp b/src/animations/axisanimation.cpp index 9f694ed4..e27cf1cc 100644 --- a/src/animations/axisanimation.cpp +++ b/src/animations/axisanimation.cpp @@ -19,7 +19,9 @@ ****************************************************************************/ #include "axisanimation_p.h" +#include "chartaxis_p.h" #include <QTimer> +#include <QDebug> Q_DECLARE_METATYPE(QVector<qreal>) @@ -27,14 +29,84 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE AxisAnimation::AxisAnimation(ChartAxis *axis): ChartAnimation(axis), - m_axis(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(); + + if (newLayout.count() == 0) + return; + + switch (m_type) { + case ZoomOutAnimation: { + QRectF rect = m_axis->geometry(); + oldLayout.resize(newLayout.count()); + + for(int i = 0, j = oldLayout.count() - 1; i < (oldLayout.count() + 1) / 2; ++i, --j) { + oldLayout[i] = m_axis->axisType() == ChartAxis::X_AXIS ? rect.left() : rect.bottom(); + oldLayout[j] = m_axis->axisType() == ChartAxis::X_AXIS ? rect.right() : rect.top(); + } + } + break; + case ZoomInAnimation: { + int index = qMin(oldLayout.count() * (m_axis->axisType() == ChartAxis::X_AXIS ? m_point.x() : (1 - m_point.y())), newLayout.count() - 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->geometry(); + for(int i = 0, j = oldLayout.count() - 1; i < oldLayout.count(); ++i, --j) + oldLayout[i] = m_axis->axisType() == ChartAxis::X_AXIS ? 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 = qVariantValue<QVector<qreal> >(start); @@ -58,6 +130,7 @@ void AxisAnimation::updateCurrentValue (const QVariant &value ) QVector<qreal> vector = qVariantValue<QVector<qreal> >(value); Q_ASSERT(vector.count() != 0); m_axis->setLayout(vector); + m_axis->updateGeometry(); } } diff --git a/src/animations/axisanimation_p.h b/src/animations/axisanimation_p.h index ff2317cf..97ec839e 100644 --- a/src/animations/axisanimation_p.h +++ b/src/animations/axisanimation_p.h @@ -21,22 +21,29 @@ #ifndef AXISANIMATION_H #define AXISANIMATION_H -#include "chartaxis_p.h" #include "chartanimation_p.h" - +#include <QPointF> QTCOMMERCIALCHART_BEGIN_NAMESPACE +class ChartAxis; + class AxisAnimation: public ChartAnimation { public: + enum Animation { DefaultAnimation, ZoomOutAnimation, ZoomInAnimation, MoveForwardAnimation, MoveBackwordAnimation}; AxisAnimation(ChartAxis *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: ChartAxis *m_axis; + Animation m_type; + QPointF m_point; }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/animations/chartanimation_p.h b/src/animations/chartanimation_p.h index 0e855e8f..cba058cc 100644 --- a/src/animations/chartanimation_p.h +++ b/src/animations/chartanimation_p.h @@ -30,6 +30,7 @@ const static int ChartAnimationDuration = 1000; class ChartAnimation: public QVariantAnimation { + Q_OBJECT public: ChartAnimation(QObject *parent = 0):QVariantAnimation(parent){}; }; diff --git a/src/animations/chartanimator.cpp b/src/animations/chartanimator.cpp index abc03667..be5a1b90 100644 --- a/src/animations/chartanimator.cpp +++ b/src/animations/chartanimator.cpp @@ -29,6 +29,7 @@ #include "areachartitem_p.h" #include "splinechartitem_p.h" #include "scatterchartitem_p.h" +#include "chartaxis_p.h" #include <QTimer> Q_DECLARE_METATYPE(QVector<QPointF>) @@ -37,27 +38,13 @@ Q_DECLARE_METATYPE(QVector<QRectF>) QTCOMMERCIALCHART_BEGIN_NAMESPACE -ChartAnimator::ChartAnimator(QObject *parent):QObject(parent), - m_state(ShowState) +ChartAnimator::ChartAnimator(QObject *parent):QObject(parent) { } ChartAnimator::~ChartAnimator() { } - -void ChartAnimator::addAnimation(ChartAxis *item) -{ - ChartAnimation *animation = m_animations.value(item); - - if (!animation) { - animation = new AxisAnimation(item); - m_animations.insert(item, animation); - } - - item->setAnimator(this); -} - void ChartAnimator::addAnimation(PieChartItem *item) { ChartAnimation *animation = m_animations.value(item); @@ -89,75 +76,6 @@ void ChartAnimator::removeAnimation(Chart *item) m_animations.remove(item); } -void ChartAnimator::updateLayout(ChartAxis *item , QVector<qreal> &newLayout) -{ - AxisAnimation *animation = static_cast<AxisAnimation*>(m_animations.value(item)); - - Q_ASSERT(animation); - - QVector<qreal> oldLayout = item->layout(); - - if (newLayout.count() == 0) - return; - - switch (m_state) { - case ZoomOutState: { - QRectF rect = item->geometry(); - oldLayout.resize(newLayout.count()); - - for(int i = 0, j = oldLayout.count() - 1; i < (oldLayout.count() + 1) / 2; ++i, --j) { - oldLayout[i] = item->axisType() == ChartAxis::X_AXIS ? rect.left() : rect.bottom(); - oldLayout[j] = item->axisType() == ChartAxis::X_AXIS ? rect.right() : rect.top(); - } - } - break; - case ZoomInState: { - int index = qMin(oldLayout.count() * (item->axisType() == ChartAxis::X_AXIS ? m_point.x() : (1 - m_point.y())), newLayout.count() - 1.0); - oldLayout.resize(newLayout.count()); - - for(int i = 0; i < oldLayout.count(); i++) - oldLayout[i]= oldLayout[index]; - } - break; - case ScrollDownState: - case ScrollRightState: { - oldLayout.resize(newLayout.count()); - - for(int i = 0, j = i + 1; i < oldLayout.count() - 1; ++i, ++j) - oldLayout[i]= oldLayout[j]; - } - break; - case ScrollUpState: - case ScrollLeftState: { - 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 = item->geometry(); - for(int i = 0, j = oldLayout.count() - 1; i < oldLayout.count(); ++i, --j) - oldLayout[i] = item->axisType() == ChartAxis::X_AXIS ? rect.left() : rect.top(); - } - break; - } - - - if (animation->state() != QAbstractAnimation::Stopped) - animation->stop(); - - animation->setDuration(ChartAnimationDuration); - animation->setEasingCurve(QEasingCurve::OutQuart); - QVariantAnimation::KeyValues value; - animation->setKeyValues(value); //workaround for wrong interpolation call - animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout)); - animation->setKeyValueAt(1.0, qVariantFromValue(newLayout)); - - QTimer::singleShot(0, animation, SLOT(start())); -} - void ChartAnimator::addAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData, bool startupAnimation) { PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item)); @@ -189,22 +107,6 @@ void ChartAnimator::updateLayout(BarChartItem *item, const QVector<QRectF> &oldL QTimer::singleShot(0, animation, SLOT(start())); } - -void ChartAnimator::setState(State state, const QPointF &point) -{ - m_state = state; - m_point = point; -} - -void ChartAnimator::startAnimation(XYAnimation* animation) -{ - Q_ASSERT(animation); - if (animation->state() != QAbstractAnimation::Stopped) animation->stop(); - animation->setDuration(ChartAnimationDuration); - animation->setEasingCurve(QEasingCurve::OutQuart); - QTimer::singleShot(0, animation, SLOT(start())); -} - #include "moc_chartanimator_p.cpp" QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/animations/chartanimator_p.h b/src/animations/chartanimator_p.h index d22d89fe..a9b747ad 100644 --- a/src/animations/chartanimator_p.h +++ b/src/animations/chartanimator_p.h @@ -42,33 +42,21 @@ class ChartAnimator : public QObject { Q_OBJECT public: - enum State{ShowState, ScrollUpState, ScrollDownState, ScrollLeftState, ScrollRightState, ZoomInState, ZoomOutState}; - ChartAnimator(QObject *parent = 0); virtual ~ChartAnimator(); - void addAnimation(ChartAxis *item); void addAnimation(PieChartItem *item); void addAnimation(BarChartItem *item); void removeAnimation(Chart *item); - void animationStarted(); - void updateLayout(ChartAxis *item, QVector<qreal> &layout); - void addAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData, bool isEmpty); void removeAnimation(PieChartItem *item, PieSliceItem *sliceItem); void updateAnimation(PieChartItem *item, PieSliceItem *sliceItem, const PieSliceData &sliceData); void updateLayout(BarChartItem *item, const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout); - void setState(State state,const QPointF &point = QPointF()); - - void startAnimation(XYAnimation* animation); - private: QMap<Chart *, ChartAnimation *> m_animations; - State m_state; - QPointF m_point; }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/animations/splineanimation.cpp b/src/animations/splineanimation.cpp index 700778a6..51fce1ac 100644 --- a/src/animations/splineanimation.cpp +++ b/src/animations/splineanimation.cpp @@ -94,7 +94,10 @@ QVariant SplineAnimation::interpolated(const QVariant &start, const QVariant &en switch (animationType()) { - case MoveDownAnimation: { + case RemovePointAnimation: + case AddPointAnimation: + case ReplacePointAnimation: + { if (startPair.first.count() != endPair.first.count()) break; Q_ASSERT(startPair.first.count() * 2 - 2 == startPair.second.count()); @@ -115,7 +118,7 @@ QVariant SplineAnimation::interpolated(const QVariant &start, const QVariant &en } break; - case LineDrawAnimation:{ + 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++) { diff --git a/src/animations/xyanimation.cpp b/src/animations/xyanimation.cpp index 104f84a6..2b9ada51 100644 --- a/src/animations/xyanimation.cpp +++ b/src/animations/xyanimation.cpp @@ -29,8 +29,10 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE XYAnimation::XYAnimation(XYChart *item):ChartAnimation(item), m_item(item), m_dirty(false), - m_type(MoveDownAnimation) + m_type(NewAnimation) { + setDuration(ChartAnimationDuration); + setEasingCurve(QEasingCurve::OutQuart); } XYAnimation::~XYAnimation() @@ -39,38 +41,48 @@ XYAnimation::~XYAnimation() void XYAnimation::setAnimationType(Animation type) { - if (state() != QAbstractAnimation::Stopped) stop(); + if (state() != QAbstractAnimation::Stopped) stop(); m_type=type; } -void XYAnimation::setValues(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index) +void XYAnimation::setValues(const QVector<QPointF> &oldPoints, const QVector<QPointF> &newPoints, int index) { - if (state() != QAbstractAnimation::Stopped) stop(); + if (state() != QAbstractAnimation::Stopped) stop(); - int x = oldPoints.count(); - int y = newPoints.count(); - - if (x != y && abs(x - y) != 1) { - m_oldPoints = newPoints; - oldPoints.resize(newPoints.size()); - setKeyValueAt(0.0, qVariantFromValue(oldPoints)); - setKeyValueAt(1.0, qVariantFromValue(newPoints)); - m_dirty = false; + if (m_item->isDirty()) { + m_oldPoints = oldPoints; + m_newPoints = newPoints; + m_dirty=false; } else { - if (m_dirty) { + if(m_dirty) { + m_newPoints = newPoints; m_oldPoints = oldPoints; - m_dirty = false; + m_dirty=false; + } + } + + int x = m_oldPoints.count(); + int y = m_newPoints.count(); + + if (abs(x - y) == 1) { + if (y < x){ + if(!newPoints.isEmpty()) m_newPoints.insert(index,newPoints[index]); + m_index=index;if(newPoints.isEmpty()) + m_dirty=true; + } + if (y > x){ + m_oldPoints.insert(index, x > 0 ? m_oldPoints[index-1] : newPoints[index]);//add } - oldPoints = newPoints; - if (y < x) - m_oldPoints.remove(index); //remove - if (y > x) - m_oldPoints.insert(index, x > 0 ? m_oldPoints[index-1] : newPoints[index]); //add - setKeyValueAt(0.0, qVariantFromValue(m_oldPoints)); - setKeyValueAt(1.0, qVariantFromValue(newPoints)); - Q_ASSERT(m_oldPoints.count() == newPoints.count()); + }else{ + m_newPoints=newPoints; + m_dirty=false; + m_oldPoints.resize(m_newPoints.size()); } + + setKeyValueAt(0.0, qVariantFromValue(m_oldPoints)); + setKeyValueAt(1.0, qVariantFromValue(m_newPoints)); + } QVariant XYAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress ) const @@ -81,8 +93,10 @@ QVariant XYAnimation::interpolated(const QVariant &start, const QVariant &end, q switch (m_type) { - case MoveDownAnimation: { - + case ReplacePointAnimation: + case AddPointAnimation: + case RemovePointAnimation: + { if (startVector.count() != endVector.count()) break; @@ -94,7 +108,7 @@ QVariant XYAnimation::interpolated(const QVariant &start, const QVariant &end, q } break; - case LineDrawAnimation: { + case NewAnimation: { for(int i = 0; i < endVector.count() * qBound(qreal(0), progress, qreal(1)); i++) result << endVector[i]; } @@ -110,11 +124,23 @@ QVariant XYAnimation::interpolated(const QVariant &start, const QVariant &end, q void XYAnimation::updateCurrentValue (const QVariant &value) { if(state()!=QAbstractAnimation::Stopped){ //workaround - m_dirty = true; QVector<QPointF> vector = qVariantValue<QVector<QPointF> >(value); m_item->setGeometryPoints(vector); m_item->updateGeometry(); + m_item->setDirty(true); } } +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" QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/animations/xyanimation_p.h b/src/animations/xyanimation_p.h index 92d644f4..50b3478a 100644 --- a/src/animations/xyanimation_p.h +++ b/src/animations/xyanimation_p.h @@ -31,20 +31,22 @@ class XYChart; class XYAnimation : public ChartAnimation { public: - enum Animation { LineDrawAnimation, MoveDownAnimation, MoveUpAnimation }; + enum Animation { AddPointAnimation, RemovePointAnimation, ReplacePointAnimation, NewAnimation }; XYAnimation(XYChart *item); ~XYAnimation(); - void setValues(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints,int index); + void setValues(const QVector<QPointF> &oldPoints, const QVector<QPointF> &newPoints,int index); void setAnimationType(Animation type); 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 ); private: XYChart *m_item; QVector<QPointF> m_oldPoints; + QVector<QPointF> m_newPoints; + int m_index; bool m_dirty; Animation m_type; }; diff --git a/src/areachart/areachartitem.cpp b/src/areachart/areachartitem.cpp index 636f98ad..6735f67c 100644 --- a/src/areachart/areachartitem.cpp +++ b/src/areachart/areachartitem.cpp @@ -25,6 +25,7 @@ #include "chartpresenter_p.h" #include <QPainter> #include <QGraphicsSceneMouseEvent> +#include <QDebug> QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -39,9 +40,9 @@ AreaChartItem::AreaChartItem(QAreaSeries *areaSeries, ChartPresenter *presenter) m_pointsVisible(false) { setZValue(ChartPresenter::LineChartZValue); - m_upper = new AreaBoundItem(this,m_series->upperSeries()); + m_upper = new AreaBoundItem(this,m_series->upperSeries(),presenter); if (m_series->lowerSeries()) - m_lower = new AreaBoundItem(this,m_series->lowerSeries()); + m_lower = new AreaBoundItem(this,m_series->lowerSeries(),presenter); QObject::connect(m_series->d_func(),SIGNAL(updated()),this,SLOT(handleUpdated())); QObject::connect(this,SIGNAL(clicked(QPointF)),areaSeries,SIGNAL(clicked(QPointF))); diff --git a/src/areachart/areachartitem_p.h b/src/areachart/areachartitem_p.h index dbc7af3a..1e932717 100644 --- a/src/areachart/areachartitem_p.h +++ b/src/areachart/areachartitem_p.h @@ -75,7 +75,9 @@ private: class AreaBoundItem : public LineChartItem { public: - AreaBoundItem(AreaChartItem *item,QLineSeries *lineSeries) : LineChartItem(lineSeries, 0), m_item(item) {} + AreaBoundItem(AreaChartItem *item,QLineSeries *lineSeries,ChartPresenter* presenter) : LineChartItem(lineSeries, 0), m_item(item) { + setPresenter(presenter); + } ~AreaBoundItem() {} void updateGeometry() { diff --git a/src/axis/axis.pri b/src/axis/axis.pri index 1579635e..96b8afe7 100644 --- a/src/axis/axis.pri +++ b/src/axis/axis.pri @@ -3,11 +3,15 @@ DEPENDPATH += $$PWD SOURCES += \ $$PWD/chartaxis.cpp \ + $$PWD/chartaxisx.cpp \ + $$PWD/chartaxisy.cpp \ $$PWD/qaxis.cpp \ $$PWD/qaxiscategories.cpp PRIVATE_HEADERS += \ $$PWD/chartaxis_p.h \ + $$PWD/chartaxisx_p.h \ + $$PWD/chartaxisy_p.h \ $$PWD/qaxis_p.h \ $$PWD/qaxiscategories_p.h diff --git a/src/axis/chartaxis.cpp b/src/axis/chartaxis.cpp index 24cd0211..612444d5 100644 --- a/src/axis/chartaxis.cpp +++ b/src/axis/chartaxis.cpp @@ -28,13 +28,10 @@ #include <QDebug> #include <cmath> -static int label_padding = 5; - QTCOMMERCIALCHART_BEGIN_NAMESPACE -ChartAxis::ChartAxis(QAxis *axis,ChartPresenter *presenter,AxisType type) : Chart(presenter), +ChartAxis::ChartAxis(QAxis *axis,ChartPresenter *presenter) : Chart(presenter), m_chartAxis(axis), - m_type(type), m_labelsAngle(0), m_grid(new QGraphicsItemGroup(presenter->rootItem())), m_shades(new QGraphicsItemGroup(presenter->rootItem())), @@ -42,7 +39,8 @@ ChartAxis::ChartAxis(QAxis *axis,ChartPresenter *presenter,AxisType type) : Char m_axis(new QGraphicsItemGroup(presenter->rootItem())), m_min(0), m_max(0), - m_ticksCount(0) + m_ticksCount(0), + m_animation(0) { //initial initialization m_axis->setZValue(ChartPresenter::AxisZValue); @@ -61,17 +59,26 @@ ChartAxis::~ChartAxis() { } -void ChartAxis::createItems(int count) +void ChartAxis::setAnimation(AxisAnimation* animation) { + m_animation=animation; +} +void ChartAxis::setLayout(QVector<qreal> &layout) +{ + m_layoutVector=layout; +} + +void ChartAxis::createItems(int count) +{ if (m_axis->children().size() == 0) - m_axis->addToGroup(new AxisItem(this)); + m_axis->addToGroup(new AxisItem(this)); for (int i = 0; i < count; ++i) { m_grid->addToGroup(new QGraphicsLineItem()); m_labels->addToGroup(new QGraphicsSimpleTextItem()); m_axis->addToGroup(new QGraphicsLineItem()); if ((m_grid->childItems().size())%2 && m_grid->childItems().size()>2) m_shades->addToGroup(new QGraphicsRectItem()); - } + } } void ChartAxis::deleteItems(int count) @@ -91,16 +98,51 @@ void ChartAxis::deleteItems(int count) void ChartAxis::updateLayout(QVector<qreal> &layout) { - if (animator()) { - animator()->updateLayout(this,layout); - } else { + int diff = m_layoutVector.size() - layout.size(); + + if (diff>0) { + deleteItems(diff); + } + else if (diff<0) { + createItems(-diff); + } + + if( diff!=0) handleAxisUpdated(); + + if (m_animation) { + switch(presenter()->state()){ + case ChartPresenter::ZoomInState: + m_animation->setAnimationType(AxisAnimation::ZoomInAnimation); + m_animation->setAnimationPoint(presenter()->statePoint()); + break; + case ChartPresenter::ZoomOutState: + m_animation->setAnimationType(AxisAnimation::ZoomOutAnimation); + m_animation->setAnimationPoint(presenter()->statePoint()); + break; + case ChartPresenter::ScrollUpState: + case ChartPresenter::ScrollLeftState: + m_animation->setAnimationType(AxisAnimation::MoveBackwordAnimation); + break; + case ChartPresenter::ScrollDownState: + case ChartPresenter::ScrollRightState: + m_animation->setAnimationType(AxisAnimation::MoveForwardAnimation); + break; + case ChartPresenter::ShowState: + m_animation->setAnimationType(AxisAnimation::DefaultAnimation); + break; + } + m_animation->setValues(m_layoutVector,layout); + presenter()->startAnimation(m_animation); + } + else { setLayout(layout); + updateGeometry(); } } bool ChartAxis::createLabels(QStringList &labels,qreal min, qreal max,int ticks) const { - Q_ASSERT(max>=min); + Q_ASSERT(max>min); Q_ASSERT(ticks>1); QAxisCategories* categories = m_chartAxis->categories(); @@ -112,6 +154,7 @@ bool ChartAxis::createLabels(QStringList &labels,qreal min, qreal max,int ticks) n++; for (int i=0; i< ticks; i++) { qreal value = min + (i * (max - min)/ (ticks-1)); + Q_UNUSED(value); labels << QString::number(value,'f',n); } } else { @@ -230,153 +273,6 @@ void ChartAxis::setGridPen(const QPen &pen) } } -QVector<qreal> ChartAxis::calculateLayout() const -{ - Q_ASSERT(m_ticksCount>=2); - - QVector<qreal> points; - points.resize(m_ticksCount); - - switch (m_type) - { - case X_AXIS: - { - const qreal deltaX = m_rect.width()/(m_ticksCount-1); - for (int i = 0; i < m_ticksCount; ++i) { - int x = i * deltaX + m_rect.left(); - points[i] = x; - } - } - break; - case Y_AXIS: - { - const qreal deltaY = m_rect.height()/(m_ticksCount-1); - for (int i = 0; i < m_ticksCount; ++i) { - int y = i * -deltaY + m_rect.bottom(); - points[i] = y; - } - } - break; - } - return points; -} - -void ChartAxis::setLayout(QVector<qreal> &layout) -{ - int diff = m_layoutVector.size() - layout.size(); - - if (diff>0) { - deleteItems(diff); - } else if (diff<0) { - createItems(-diff); - } - - if( diff!=0) handleAxisUpdated(); - - QStringList ticksList; - - bool categories = createLabels(ticksList,m_min,m_max,layout.size()); - - QList<QGraphicsItem *> lines = m_grid->childItems(); - QList<QGraphicsItem *> labels = m_labels->childItems(); - QList<QGraphicsItem *> shades = m_shades->childItems(); - QList<QGraphicsItem *> axis = m_axis->childItems(); - - Q_ASSERT(labels.size() == ticksList.size()); - Q_ASSERT(layout.size() == ticksList.size()); - - qreal minWidth = 0; - qreal minHeight = 0; - - switch (m_type) - { - case X_AXIS: - { - QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(axis.at(0)); - lineItem->setLine(m_rect.left(), m_rect.bottom(), m_rect.right(), m_rect.bottom()); - - for (int i = 0; i < layout.size(); ++i) { - QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(lines.at(i)); - lineItem->setLine(layout[i], m_rect.top(), layout[i], m_rect.bottom()); - QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem*>(labels.at(i)); - if (!categories || i<1) { - labelItem->setText(ticksList.at(i)); - const QRectF& rect = labelItem->boundingRect(); - minWidth+=rect.width(); - minHeight=qMax(rect.height(),minHeight); - QPointF center = rect.center(); - labelItem->setTransformOriginPoint(center.x(), center.y()); - labelItem->setPos(layout[i] - center.x(), m_rect.bottom() + label_padding); - } else { - labelItem->setText(ticksList.at(i)); - const QRectF& rect = labelItem->boundingRect(); - minWidth+=rect.width(); - minHeight=qMax(rect.height()+label_padding,minHeight); - QPointF center = rect.center(); - labelItem->setTransformOriginPoint(center.x(), center.y()); - labelItem->setPos(layout[i] - (layout[i] - layout[i-1])/2 - center.x(), m_rect.bottom() + label_padding); - } - - if ((i+1)%2 && i>1) { - QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem*>(shades.at(i/2-1)); - rectItem->setRect(layout[i-1],m_rect.top(),layout[i]-layout[i-1],m_rect.height()); - } - lineItem = static_cast<QGraphicsLineItem*>(axis.at(i+1)); - lineItem->setLine(layout[i],m_rect.bottom(),layout[i],m_rect.bottom()+5); - } - - } - break; - - case Y_AXIS: - { - QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(axis.at(0)); - lineItem->setLine(m_rect.left() , m_rect.top(), m_rect.left(), m_rect.bottom()); - - for (int i = 0; i < layout.size(); ++i) { - QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(lines.at(i)); - lineItem->setLine(m_rect.left() , layout[i], m_rect.right(), layout[i]); - QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem*>(labels.at(i)); - - if (!categories || i<1) { - labelItem->setText(ticksList.at(i)); - const QRectF& rect = labelItem->boundingRect(); - minWidth=qMax(rect.width()+label_padding,minWidth); - minHeight+=rect.height(); - QPointF center = rect.center(); - labelItem->setTransformOriginPoint(center.x(), center.y()); - labelItem->setPos(m_rect.left() - rect.width() - label_padding , layout[i]-center.y()); - } else { - labelItem->setText(ticksList.at(i)); - const QRectF& rect = labelItem->boundingRect(); - minWidth=qMax(rect.width(),minWidth); - minHeight+=rect.height(); - QPointF center = rect.center(); - labelItem->setTransformOriginPoint(center.x(), center.y()); - labelItem->setPos(m_rect.left() - rect.width() - label_padding , layout[i] - (layout[i] - layout[i-1])/2 -center.y()); - } - - if ((i+1)%2 && i>1) { - QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem*>(shades.at(i/2-1)); - rectItem->setRect(m_rect.left(),layout[i],m_rect.width(),layout[i-1]-layout[i]); - } - lineItem = static_cast<QGraphicsLineItem*>(axis.at(i+1)); - lineItem->setLine(m_rect.left()-5,layout[i],m_rect.left(),layout[i]); - } - } - break; - default: - qWarning()<<"Unknown axis type"; - break; - } - - m_layoutVector=layout; - - presenter()->setMinimumMarginWidth(this,minWidth); - presenter()->setMinimumMarginHeight(this,minHeight); - -} - bool ChartAxis::isEmpty() { return m_rect.isEmpty() || qFuzzyIsNull(m_min - m_max) || m_ticksCount==0; @@ -442,7 +338,6 @@ void ChartAxis::handleRangeChanged(qreal min, qreal max,int tickCount) if (isEmpty()) return; QVector<qreal> layout = calculateLayout(); updateLayout(layout); - } void ChartAxis::handleGeometryChanged(const QRectF &rect) diff --git a/src/axis/chartaxis_p.h b/src/axis/chartaxis_p.h index bb6c6615..b55b9312 100644 --- a/src/axis/chartaxis_p.h +++ b/src/axis/chartaxis_p.h @@ -18,11 +18,12 @@ ** ****************************************************************************/ -#ifndef AXIS_H -#define AXIS_H +#ifndef CHARTAXIS_H +#define CHARTAXIS_H #include "qchartglobal.h" #include "chart_p.h" +#include "axisanimation_p.h" #include <QGraphicsItem> QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -34,12 +35,12 @@ class ChartAxis : public Chart { Q_OBJECT public: - enum AxisType{X_AXIS,Y_AXIS}; + enum AxisType{ X_AXIS,Y_AXIS }; - ChartAxis(QAxis *axis, ChartPresenter *presenter, AxisType type = X_AXIS); + ChartAxis(QAxis *axis, ChartPresenter *presenter); ~ChartAxis(); - AxisType axisType() const { return m_type; } + virtual AxisType axisType() const = 0; void setAxisOpacity(qreal opacity); qreal axisOpacity() const; @@ -66,8 +67,18 @@ public: void setLabelsBrush(const QBrush &brush); void setLabelsFont(const QFont &font); - inline QRectF geometry() const { return m_rect; } - inline QVector<qreal> layout() { return m_layoutVector; } + void setLayout(QVector<qreal> &layout); + QVector<qreal> layout() const { return m_layoutVector; } + + void setAnimation(AxisAnimation* animation); + ChartAnimation* animation() const { return m_animation; }; + + QRectF geometry() const { return m_rect; } + +protected: + virtual void updateGeometry() = 0; + virtual QVector<qreal> calculateLayout() const = 0; + bool createLabels(QStringList &labels,qreal min, qreal max,int ticks) const; public Q_SLOTS: void handleAxisUpdated(); @@ -75,22 +86,15 @@ public Q_SLOTS: void handleRangeChanged(qreal min , qreal max,int tickCount); void handleGeometryChanged(const QRectF &size); - private: inline bool isEmpty(); void createItems(int count); void deleteItems(int count); - - QVector<qreal> calculateLayout() const; void updateLayout(QVector<qreal> &layout); - void setLayout(QVector<qreal> &layout); - - bool createLabels(QStringList &labels,qreal min, qreal max,int ticks) const; void axisSelected(); -private: +protected: QAxis* m_chartAxis; - AxisType m_type; QRectF m_rect; int m_labelsAngle; QScopedPointer<QGraphicsItemGroup> m_grid; @@ -101,6 +105,7 @@ private: qreal m_min; qreal m_max; int m_ticksCount; + AxisAnimation *m_animation; friend class AxisAnimation; friend class AxisItem; diff --git a/src/axis/chartaxisx.cpp b/src/axis/chartaxisx.cpp new file mode 100644 index 00000000..5414ed07 --- /dev/null +++ b/src/axis/chartaxisx.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 Commercial Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial 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 "chartaxisx_p.h" +#include "qaxis.h" +#include "qaxis_p.h" +#include "qaxiscategories_p.h" +#include "chartpresenter_p.h" +#include "chartanimator_p.h" + +static int label_padding = 5; + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +ChartAxisX::ChartAxisX(QAxis *axis,ChartPresenter *presenter) : ChartAxis(axis,presenter) +{ +} + +ChartAxisX::~ChartAxisX() +{ +} + +QVector<qreal> ChartAxisX::calculateLayout() const +{ + Q_ASSERT(m_ticksCount>=2); + + QVector<qreal> points; + points.resize(m_ticksCount); + + const qreal deltaX = m_rect.width()/(m_ticksCount-1); + for (int i = 0; i < m_ticksCount; ++i) { + int x = i * deltaX + m_rect.left(); + points[i] = x; + } + return points; +} + +void ChartAxisX::updateGeometry() +{ + const QVector<qreal>& layout = ChartAxis::layout(); + + QStringList ticksList; + + bool categories = createLabels(ticksList,m_min,m_max,layout.size()); + + QList<QGraphicsItem *> lines = m_grid->childItems(); + QList<QGraphicsItem *> labels = m_labels->childItems(); + QList<QGraphicsItem *> shades = m_shades->childItems(); + QList<QGraphicsItem *> axis = m_axis->childItems(); + + Q_ASSERT(labels.size() == ticksList.size()); + Q_ASSERT(layout.size() == ticksList.size()); + + qreal minWidth = 0; + qreal minHeight = 0; + + QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(axis.at(0)); + lineItem->setLine(m_rect.left(), m_rect.bottom(), m_rect.right(), m_rect.bottom()); + + for (int i = 0; i < layout.size(); ++i) { + QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(lines.at(i)); + lineItem->setLine(layout[i], m_rect.top(), layout[i], m_rect.bottom()); + QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem*>(labels.at(i)); + if (!categories || i<1) { + labelItem->setText(ticksList.at(i)); + const QRectF& rect = labelItem->boundingRect(); + minWidth+=rect.width(); + minHeight=qMax(rect.height(),minHeight); + QPointF center = rect.center(); + labelItem->setTransformOriginPoint(center.x(), center.y()); + labelItem->setPos(layout[i] - center.x(), m_rect.bottom() + label_padding); + } + else { + labelItem->setText(ticksList.at(i)); + const QRectF& rect = labelItem->boundingRect(); + minWidth+=rect.width(); + minHeight=qMax(rect.height()+label_padding,minHeight); + QPointF center = rect.center(); + labelItem->setTransformOriginPoint(center.x(), center.y()); + labelItem->setPos(layout[i] - (layout[i] - layout[i-1])/2 - center.x(), m_rect.bottom() + label_padding); + } + + if ((i+1)%2 && i>1) { + QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem*>(shades.at(i/2-1)); + rectItem->setRect(layout[i-1],m_rect.top(),layout[i]-layout[i-1],m_rect.height()); + } + lineItem = static_cast<QGraphicsLineItem*>(axis.at(i+1)); + lineItem->setLine(layout[i],m_rect.bottom(),layout[i],m_rect.bottom()+5); + } + + presenter()->setMinimumMarginWidth(this,minWidth); + presenter()->setMinimumMarginHeight(this,minHeight); +} + +QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/axis/chartaxisx_p.h b/src/axis/chartaxisx_p.h new file mode 100644 index 00000000..fa8e7ff1 --- /dev/null +++ b/src/axis/chartaxisx_p.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 Commercial Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial 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$ +** +****************************************************************************/ + +#ifndef CHARTAXISX_H +#define CHARTAXISX_H + +#include "chartaxis_p.h" + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +class QAxis; +class ChartPresenter; + +class ChartAxisX : public ChartAxis +{ +public: + ChartAxisX(QAxis *axis, ChartPresenter *presenter); + ~ChartAxisX(); + + AxisType axisType() const { return X_AXIS;} + +protected: + QVector<qreal> calculateLayout() const; + void updateGeometry(); +}; + +QTCOMMERCIALCHART_END_NAMESPACE + +#endif /* AXISITEM_H_ */ diff --git a/src/axis/chartaxisy.cpp b/src/axis/chartaxisy.cpp new file mode 100644 index 00000000..b357aa7f --- /dev/null +++ b/src/axis/chartaxisy.cpp @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 Commercial Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial 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 "chartaxisy_p.h" +#include "qaxis.h" +#include "qaxis_p.h" +#include "qaxiscategories_p.h" +#include "chartpresenter_p.h" +#include "chartanimator_p.h" + + +static int label_padding = 5; + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +ChartAxisY::ChartAxisY(QAxis *axis,ChartPresenter *presenter) : ChartAxis(axis,presenter) +{ +} + +ChartAxisY::~ChartAxisY() +{ +} + +QVector<qreal> ChartAxisY::calculateLayout() const +{ + Q_ASSERT(m_ticksCount>=2); + + QVector<qreal> points; + points.resize(m_ticksCount); + + const qreal deltaY = m_rect.height()/(m_ticksCount-1); + for (int i = 0; i < m_ticksCount; ++i) { + int y = i * -deltaY + m_rect.bottom(); + points[i] = y; + } + + return points; +} + +void ChartAxisY::updateGeometry() +{ + const QVector<qreal> &layout = ChartAxis::layout(); + + QStringList ticksList; + + bool categories = createLabels(ticksList,m_min,m_max,layout.size()); + + QList<QGraphicsItem *> lines = m_grid->childItems(); + QList<QGraphicsItem *> labels = m_labels->childItems(); + QList<QGraphicsItem *> shades = m_shades->childItems(); + QList<QGraphicsItem *> axis = m_axis->childItems(); + + Q_ASSERT(labels.size() == ticksList.size()); + Q_ASSERT(layout.size() == ticksList.size()); + + qreal minWidth = 0; + qreal minHeight = 0; + + QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(axis.at(0)); + lineItem->setLine(m_rect.left() , m_rect.top(), m_rect.left(), m_rect.bottom()); + + for (int i = 0; i < layout.size(); ++i) { + QGraphicsLineItem *lineItem = static_cast<QGraphicsLineItem*>(lines.at(i)); + lineItem->setLine(m_rect.left() , layout[i], m_rect.right(), layout[i]); + QGraphicsSimpleTextItem *labelItem = static_cast<QGraphicsSimpleTextItem*>(labels.at(i)); + + if (!categories || i<1) { + labelItem->setText(ticksList.at(i)); + const QRectF& rect = labelItem->boundingRect(); + minWidth=qMax(rect.width()+label_padding,minWidth); + minHeight+=rect.height(); + QPointF center = rect.center(); + labelItem->setTransformOriginPoint(center.x(), center.y()); + labelItem->setPos(m_rect.left() - rect.width() - label_padding , layout[i]-center.y()); + } + else { + labelItem->setText(ticksList.at(i)); + const QRectF& rect = labelItem->boundingRect(); + minWidth=qMax(rect.width(),minWidth); + minHeight+=rect.height(); + QPointF center = rect.center(); + labelItem->setTransformOriginPoint(center.x(), center.y()); + labelItem->setPos(m_rect.left() - rect.width() - label_padding , layout[i] - (layout[i] - layout[i-1])/2 -center.y()); + } + + if ((i+1)%2 && i>1) { + QGraphicsRectItem *rectItem = static_cast<QGraphicsRectItem*>(shades.at(i/2-1)); + rectItem->setRect(m_rect.left(),layout[i],m_rect.width(),layout[i-1]-layout[i]); + } + lineItem = static_cast<QGraphicsLineItem*>(axis.at(i+1)); + lineItem->setLine(m_rect.left()-5,layout[i],m_rect.left(),layout[i]); + } + + presenter()->setMinimumMarginWidth(this,minWidth); + presenter()->setMinimumMarginHeight(this,minHeight); + +} + +QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/axis/chartaxisy_p.h b/src/axis/chartaxisy_p.h new file mode 100644 index 00000000..a16801aa --- /dev/null +++ b/src/axis/chartaxisy_p.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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 Commercial Charts Add-on. +** +** $QT_BEGIN_LICENSE$ +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial 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$ +** +****************************************************************************/ + +#ifndef CHARTAXISY_H +#define CHARTAXISY_H + +#include "chartaxis_p.h" + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +class QAxis; +class ChartPresenter; + +class ChartAxisY : public ChartAxis +{ +public: + ChartAxisY(QAxis *axis, ChartPresenter *presenter); + ~ChartAxisY(); + + AxisType axisType() const { return Y_AXIS;} + +protected: + QVector<qreal> calculateLayout() const; + void updateGeometry(); +}; + +QTCOMMERCIALCHART_END_NAMESPACE + +#endif /* AXISITEM_H_ */ diff --git a/src/chartpresenter.cpp b/src/chartpresenter.cpp index 8a5d0bd1..1a767011 100644 --- a/src/chartpresenter.cpp +++ b/src/chartpresenter.cpp @@ -24,11 +24,15 @@ #include "chartdataset_p.h" #include "charttheme_p.h" #include "chartanimator_p.h" +#include "chartanimation_p.h" #include "qabstractseries_p.h" #include "qareaseries.h" #include "chartaxis_p.h" +#include "chartaxisx_p.h" +#include "chartaxisy_p.h" #include "areachartitem_p.h" #include "chartbackground_p.h" +#include <QTimer> QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -41,6 +45,7 @@ m_chartRect(QRectF(QPoint(0,0),m_chart->size())), m_options(QChart::NoAnimation), m_minLeftMargin(0), m_minBottomMargin(0), +m_state(ShowState), m_backgroundItem(0), m_titleItem(0), m_marginBig(60), @@ -48,6 +53,7 @@ m_marginSmall(20), m_marginTiny(10), m_chartMargins(QRect(m_marginBig,m_marginBig,0,0)) { + } ChartPresenter::~ChartPresenter() @@ -112,10 +118,17 @@ void ChartPresenter::setMinimumMarginHeight(ChartAxis* axis, qreal height) void ChartPresenter::handleAxisAdded(QAxis* axis,Domain* domain) { - ChartAxis* item = new ChartAxis(axis,this,axis==m_dataset->axisX()?ChartAxis::X_AXIS : ChartAxis::Y_AXIS); + ChartAxis* item; + + if(axis == m_dataset->axisX()){ + item = new ChartAxisX(axis,this); + }else{ + item = new ChartAxisY(axis,this); + } if(m_options.testFlag(QChart::GridAxisAnimations)){ - m_animator->addAnimation(item); + item->setAnimator(m_animator); + item->setAnimation(new AxisAnimation(item)); } if(axis==m_dataset->axisX()){ @@ -244,21 +257,15 @@ void ChartPresenter::zoomIn(const QRectF& rect) if (!r.isValid()) return; - if (m_animator) { - QPointF point(r.center().x()/chartGeometry().width(),r.center().y()/chartGeometry().height()); - m_animator->setState(ChartAnimator::ZoomInState,point); - } - + m_state = ZoomInState; + m_statePoint = QPointF(r.center().x()/chartGeometry().width(),r.center().y()/chartGeometry().height()); m_dataset->zoomInDomain(r,chartGeometry().size()); - - if (m_animator) - m_animator->setState(ChartAnimator::ShowState); + m_state = ShowState; } void ChartPresenter::zoomOut(qreal factor) { - if (m_animator) - m_animator->setState(ChartAnimator::ZoomOutState); + m_state = ZoomOutState; QRectF chartRect; chartRect.setSize(chartGeometry().size()); @@ -268,27 +275,21 @@ void ChartPresenter::zoomOut(qreal factor) rect.moveCenter(chartRect.center()); if (!rect.isValid()) return; - + m_statePoint = QPointF(rect.center().x()/chartGeometry().width(),rect.center().y()/chartGeometry().height()); m_dataset->zoomOutDomain(rect, chartRect.size()); - - if (m_animator) - m_animator->setState(ChartAnimator::ShowState); + m_state = ShowState; } void ChartPresenter::scroll(int dx,int dy) { - if(m_animator){ - if(dx<0) m_animator->setState(ChartAnimator::ScrollLeftState,QPointF()); - if(dx>0) m_animator->setState(ChartAnimator::ScrollRightState,QPointF()); - if(dy<0) m_animator->setState(ChartAnimator::ScrollUpState,QPointF()); - if(dy>0) m_animator->setState(ChartAnimator::ScrollDownState,QPointF()); - } - m_dataset->scrollDomain(dx,dy,chartGeometry().size()); + if(dx<0) m_state=ScrollLeftState; + if(dx>0) m_state=ScrollRightState; + if(dy<0) m_state=ScrollUpState; + if(dy>0) m_state=ScrollDownState; - if(m_animator){ - m_animator->setState(ChartAnimator::ShowState); - } + m_dataset->scrollDomain(dx,dy,chartGeometry().size()); + m_state = ShowState; } QChart::AnimationOptions ChartPresenter::animationOptions() const @@ -389,7 +390,6 @@ void ChartPresenter::updateLayout() emit geometryChanged(m_chartRect); } - } void ChartPresenter::createChartBackgroundItem() @@ -409,6 +409,22 @@ void ChartPresenter::createChartTitleItem() } } +void ChartPresenter::handleAnimationFinished() +{ + m_animations.removeAll(qobject_cast<ChartAnimation*>(sender())); + if(m_animations.empty()) emit animationsFinished(); +} + +void ChartPresenter::startAnimation(ChartAnimation* animation) +{ + if (animation->state() != QAbstractAnimation::Stopped) animation->stop(); + QObject::connect(animation, SIGNAL(finished()),this,SLOT(handleAnimationFinished()),Qt::UniqueConnection); + if(!m_animations.isEmpty()){ + m_animations.append(animation); + } + QTimer::singleShot(0, animation, SLOT(start())); +} + #include "moc_chartpresenter_p.cpp" QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/chartpresenter_p.h b/src/chartpresenter_p.h index 41bf3c4b..4abf4bee 100644 --- a/src/chartpresenter_p.h +++ b/src/chartpresenter_p.h @@ -35,6 +35,7 @@ class ChartAxis; class ChartTheme; class ChartAnimator; class ChartBackground; +class ChartAnimation; class ChartPresenter: public QObject { @@ -51,6 +52,14 @@ public: AxisZValue, LegendZValue }; + enum State {ShowState, + ScrollUpState, + ScrollDownState, + ScrollLeftState, + ScrollRightState, + ZoomInState, + ZoomOutState + }; ChartPresenter(QChart* chart,ChartDataSet *dataset); virtual ~ChartPresenter(); @@ -79,6 +88,9 @@ public: qreal minimumLeftMargin() const { return m_minLeftMargin; } qreal minimumBottomMargin() const { return m_minBottomMargin; } + void startAnimation(ChartAnimation* animation); + State state() const { return m_state; } + QPointF statePoint() const { return m_statePoint; } public: //TODO: fix me void resetAllElements(); void createChartBackgroundItem(); @@ -92,9 +104,12 @@ public Q_SLOTS: void handleAxisRemoved(QAxis* axis); void updateLayout(); +private Q_SLOTS: + void handleAnimationFinished(); + Q_SIGNALS: void geometryChanged(const QRectF& rect); - + void animationsFinished(); private: QChart* m_chart; @@ -108,6 +123,10 @@ private: QChart::AnimationOptions m_options; qreal m_minLeftMargin; qreal m_minBottomMargin; + State m_state; + QPointF m_statePoint; + QList<ChartAnimation*> m_animations; + public: //TODO: fixme ChartBackground* m_backgroundItem; QGraphicsSimpleTextItem* m_titleItem; @@ -116,7 +135,6 @@ public: //TODO: fixme int m_marginTiny; QRectF m_chartMargins; QRectF m_legendMargins; - }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/splinechart/splinechartitem.cpp b/src/splinechart/splinechartitem.cpp index 20997a77..019fe466 100644 --- a/src/splinechart/splinechartitem.cpp +++ b/src/splinechart/splinechartitem.cpp @@ -87,7 +87,7 @@ void SplineChartItem::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> if (m_animation) { m_animation->setValues(oldPoints,newPoints,m_controlPoints,controlPoints,index); - animator()->startAnimation(m_animation); + presenter()->startAnimation(m_animation); } else { setGeometryPoints(newPoints); diff --git a/src/xychart/xychart.cpp b/src/xychart/xychart.cpp index eefd3c3b..d77fe93c 100644 --- a/src/xychart/xychart.cpp +++ b/src/xychart/xychart.cpp @@ -26,6 +26,7 @@ #include <QPainter> #include <QAbstractItemModel> #include "qxymodelmapper.h" +#include <QDebug> QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -37,7 +38,8 @@ m_maxX(0), m_minY(0), m_maxY(0), m_series(series), -m_animation(0) +m_animation(0), +m_dirty(true) { QObject::connect(series->d_func(),SIGNAL(pointReplaced(int)),this,SLOT(handlePointReplaced(int))); QObject::connect(series->d_func(),SIGNAL(pointAdded(int)),this,SLOT(handlePointAdded(int))); @@ -46,7 +48,7 @@ m_animation(0) QObject::connect(this,SIGNAL(clicked(QPointF)),series,SIGNAL(clicked(QPointF))); } -void XYChart::setGeometryPoints(QVector<QPointF>& points) +void XYChart::setGeometryPoints(const QVector<QPointF>& points) { m_points = points; } @@ -61,6 +63,11 @@ void XYChart::setAnimation(XYAnimation* animation) m_animation=animation; } +void XYChart::setDirty(bool dirty) +{ + m_dirty=dirty; +} + QPointF XYChart::calculateGeometryPoint(const QPointF &point) const { const qreal deltaX = m_size.width()/(m_maxX-m_minX); @@ -110,7 +117,9 @@ void XYChart::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoin { if (m_animation) { m_animation->setValues(oldPoints, newPoints, index); - animator()->startAnimation(m_animation); + setGeometryPoints(newPoints); + setDirty(false); + presenter()->startAnimation(m_animation); } else { setGeometryPoints(newPoints); @@ -124,45 +133,65 @@ void XYChart::handlePointAdded(int index) { Q_ASSERT(index<m_series->count()); Q_ASSERT(index>=0); - QVector<QPointF> points = m_points; - QPointF point; - point = calculateGeometryPoint(index); - points.insert(index, point); - if(m_animation) { - m_animation->setAnimationType(XYAnimation::LineDrawAnimation); - } + QVector<QPointF> points; + + if(m_animation) { + m_animation->setAnimationType(XYAnimation::AddPointAnimation); + } - updateChart(m_points,points,index); + if(m_dirty) { + points = calculateGeometryPoints(); + } else { + points = m_points; + QPointF point = calculateGeometryPoint(index); + points.insert(index, point); + } + + updateChart(m_points,points,index); } void XYChart::handlePointRemoved(int index) { - Q_ASSERT(index<m_series->count() + 1); - Q_ASSERT(index>=0); - QVector<QPointF> points = m_points; - points.remove(index); + Q_ASSERT(index<=m_series->count()); + Q_ASSERT(index>=0); - if(m_animation) { - m_animation->setAnimationType(XYAnimation::LineDrawAnimation); - } + QVector<QPointF> points; - updateChart(m_points,points,index); + if(m_animation) { + m_animation->setAnimationType(XYAnimation::RemovePointAnimation); + } + + if(m_dirty) { + points = calculateGeometryPoints(); + } else { + points = m_points; + points.remove(index); + } + + updateChart(m_points,points,index); } void XYChart::handlePointReplaced(int index) { - Q_ASSERT(index<m_series->count()); - Q_ASSERT(index>=0); - QPointF point = calculateGeometryPoint(index); - QVector<QPointF> points = m_points; - points.replace(index,point); + Q_ASSERT(index<m_series->count()); + Q_ASSERT(index>=0); - if(m_animation) { - m_animation->setAnimationType(XYAnimation::MoveDownAnimation); - } + QVector<QPointF> points; - updateChart(m_points,points,index); + if(m_animation) { + m_animation->setAnimationType(XYAnimation::ReplacePointAnimation); + } + + if(m_dirty) { + points = calculateGeometryPoints(); + } else { + QPointF point = calculateGeometryPoint(index); + points = m_points; + points.replace(index,point); + } + + updateChart(m_points,points,index); } void XYChart::handleReinitialized() @@ -170,7 +199,7 @@ void XYChart::handleReinitialized() QVector<QPointF> points = calculateGeometryPoints(); if(m_animation) { - m_animation->setAnimationType(XYAnimation::LineDrawAnimation); + m_animation->setAnimationType(XYAnimation::NewAnimation); } updateChart(m_points,points); @@ -178,16 +207,19 @@ void XYChart::handleReinitialized() void XYChart::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY) { + qDebug()<<__FUNCTION__; m_minX=minX; m_maxX=maxX; m_minY=minY; m_maxY=maxY; if (isEmpty()) return; + QVector<QPointF> points = calculateGeometryPoints(); if(m_animation) { - m_animation->setAnimationType(XYAnimation::MoveDownAnimation); + m_animation->setAnimationType(XYAnimation::ReplacePointAnimation); } + updateChart(m_points,points); } @@ -199,10 +231,13 @@ void XYChart::handleGeometryChanged(const QRectF &rect) m_origin=rect.topLeft(); if (isEmpty()) return; + QVector<QPointF> points = calculateGeometryPoints(); + if(m_animation) { - m_animation->setAnimationType(XYAnimation::LineDrawAnimation); - } + m_animation->setAnimationType(XYAnimation::NewAnimation); + } + updateChart(m_points,points); } diff --git a/src/xychart/xychart_p.h b/src/xychart/xychart_p.h index 9c4f1628..dc6a014d 100644 --- a/src/xychart/xychart_p.h +++ b/src/xychart/xychart_p.h @@ -38,7 +38,7 @@ public: explicit XYChart(QXYSeries *series, ChartPresenter *presenter); ~XYChart(){}; - void setGeometryPoints(QVector<QPointF>& points); + void setGeometryPoints(const QVector<QPointF>& points); QVector<QPointF> geometryPoints() const { return m_points; } void setClipRect(const QRectF &rect); @@ -51,6 +51,9 @@ public: ChartAnimation* animation() const { return m_animation; } virtual void updateGeometry() = 0; + bool isDirty() const { return m_dirty; } + void setDirty(bool dirty); + public Q_SLOTS: void handlePointAdded(int index); void handlePointRemoved(int index); @@ -83,6 +86,7 @@ private: QRectF m_clipRect; QVector<QPointF> m_points; XYAnimation* m_animation; + bool m_dirty; friend class AreaChartItem; |