diff --git a/src/axisanimationitem.cpp b/src/axisanimationitem.cpp new file mode 100644 index 0000000..bb2f5f8 --- /dev/null +++ b/src/axisanimationitem.cpp @@ -0,0 +1,70 @@ +#include "axisanimationitem_p.h" +#include + +Q_DECLARE_METATYPE(QVector) + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +const static int duration = 500; + +AxisAnimationItem::AxisAnimationItem(AxisType type,QGraphicsItem* parent) : +AxisItem(type,parent) +{ +} + +AxisAnimationItem::~AxisAnimationItem() +{ +} + +void AxisAnimationItem::updateItems(QVector& vector1) +{ + QVector vector0 = vector1; + calculateLayout(vector1); + if(vector1.count()==0) return; + vector0.resize(vector1.size()); + + AxisAnimator *animation = new AxisAnimator(this); + animation->setDuration(duration); + animation->setEasingCurve(QEasingCurve::InOutBack); + animation->setKeyValueAt(0.0, qVariantFromValue(vector0)); + animation->setKeyValueAt(1.0, qVariantFromValue(vector1)); + animation->start(QAbstractAnimation::DeleteWhenStopped); +} + +void AxisAnimationItem::setLabelsAngle(int angle) +{ + AxisItem::setLabelsAngle(angle); +} + +AxisAnimator::AxisAnimator(AxisItem *axis): m_axis(axis) +{ +} + +AxisAnimator::~AxisAnimator() +{ +} + +QVariant AxisAnimator::interpolated(const QVariant &start, const QVariant & end, qreal progress ) const +{ + QVector startVector = qVariantValue >(start); + QVector endVecotr = qVariantValue >(end); + QVector result; + Q_ASSERT(startVector.count() == endVecotr.count()); + + for(int i =0 ;i< startVector.count();i++){ + qreal value = startVector[i] + ((endVecotr[i]- startVector[i]) * progress);//qBound(0.0, progress, 1.0)); + result << value; + } + return qVariantFromValue(result); +} + + +void AxisAnimator::updateCurrentValue (const QVariant & value ) +{ + QVector vector = qVariantValue >(value); + m_axis->applyLayout(vector); +} + +#include "moc_axisanimationitem_p.cpp" + +QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/axisanimationitem_p.h b/src/axisanimationitem_p.h new file mode 100644 index 0000000..7434941 --- /dev/null +++ b/src/axisanimationitem_p.h @@ -0,0 +1,44 @@ +#ifndef AXISANIMATIONITEM_H_ +#define AXISANIMATIONITEM_H_ + +#include "domain_p.h" +#include "axisitem_p.h" +#include +#include + +QTCOMMERCIALCHART_BEGIN_NAMESPACE + +class QChartAxis; + +class AxisAnimationItem : public AxisItem +{ + Q_OBJECT + +public: + AxisAnimationItem(AxisType type = X_AXIS,QGraphicsItem* parent = 0); + ~AxisAnimationItem(); + + void setLabelsAngle(int angle); + +protected: + void updateItems(QVector& vector); + +}; + +class AxisAnimator: public QVariantAnimation +{ +public: + AxisAnimator(AxisItem *axis); + virtual ~AxisAnimator(); +protected: + virtual QVariant interpolated (const QVariant & from, const QVariant & to, qreal progress ) const; + virtual void updateCurrentValue (const QVariant & value ); +private: + AxisItem* m_axis; +}; + +QTCOMMERCIALCHART_END_NAMESPACE + + + +#endif /* AXISITEM_H_ */ diff --git a/src/axisitem.cpp b/src/axisitem.cpp index 705a7a1..d363553 100644 --- a/src/axisitem.cpp +++ b/src/axisitem.cpp @@ -30,36 +30,33 @@ AxisItem::~AxisItem() QRectF AxisItem::boundingRect() const { - return m_rect; + return QRectF(); } void AxisItem::createItems(int count) { - m_axis.addToGroup(new QGraphicsLineItem(this)); + if(m_axis.children().size()==0) + m_axis.addToGroup(new QGraphicsLineItem()); for (int i = 0; i < count; ++i) { - m_grid.addToGroup(new QGraphicsLineItem(this)); - m_labels.addToGroup(new QGraphicsSimpleTextItem(this)); - if(i%2) m_shades.addToGroup(new QGraphicsRectItem(this)); - m_axis.addToGroup(new QGraphicsLineItem(this)); + m_grid.addToGroup(new QGraphicsLineItem()); + m_labels.addToGroup(new QGraphicsSimpleTextItem()); + if(m_grid.childItems().size()%2) m_shades.addToGroup(new QGraphicsRectItem()); + m_axis.addToGroup(new QGraphicsLineItem()); } } -void AxisItem::clear() +void AxisItem::clear(int count) { - foreach(QGraphicsItem* item , m_shades.childItems()) { - delete item; - } - - foreach(QGraphicsItem* item , m_grid.childItems()) { - delete item; - } - - foreach(QGraphicsItem* item , m_labels.childItems()) { - delete item; - } + QList lines = m_grid.childItems(); + QList labels = m_labels.childItems(); + QList shades = m_shades.childItems(); + QList axis = m_axis.childItems(); - foreach(QGraphicsItem* item , m_axis.childItems()) { - delete item; + for (int i = 0; i < count; ++i) { + delete(lines.takeLast()); + delete(labels.takeLast()); + if(lines.size()%2) delete(shades.takeLast()); + delete(axis.takeLast()); } m_thicksList.clear(); @@ -68,75 +65,16 @@ void AxisItem::clear() void AxisItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - + Q_UNUSED(painter); + Q_UNUSED(option); + Q_UNUSED(widget); } -void AxisItem::updateItem(int count) +void AxisItem::updateItems(QVector& vector) { - if(count ==0) return; - - QList lines = m_grid.childItems(); - QList labels = m_labels.childItems(); - QList shades = m_shades.childItems(); - QList axis = m_axis.childItems(); - - switch (m_type) - { - case X_AXIS: - { - const qreal deltaX = m_rect.width() / (count-1); - - QGraphicsLineItem *lineItem = static_cast(axis.at(0)); - lineItem->setLine(m_rect.left(), m_rect.bottom(), m_rect.right(), m_rect.bottom()); - - for (int i = 0; i < count; ++i) { - int x = i * deltaX + m_rect.left(); - QGraphicsLineItem *lineItem = static_cast(lines.at(i)); - lineItem->setLine(x, m_rect.top(), x, m_rect.bottom()); - QGraphicsSimpleTextItem *labelItem = static_cast(labels.at(i)); - labelItem->setText(m_thicksList.at(i)); - QPointF center = labelItem->boundingRect().center(); - labelItem->setTransformOriginPoint(center.x(), center.y()); - labelItem->setPos(x - center.x(), m_rect.bottom() + label_padding); - if(i%2){ - QGraphicsRectItem *rectItem = static_cast(shades.at(i/2)); - rectItem->setRect(x,m_rect.top(),deltaX,m_rect.height()); - } - lineItem = static_cast(axis.at(i+1)); - lineItem->setLine(x,m_rect.bottom(),x,m_rect.bottom()+5); - } - } - break; - - case Y_AXIS: - { - const qreal deltaY = m_rect.height()/ (count-1); - - QGraphicsLineItem *lineItem = static_cast(axis.at(0)); - lineItem->setLine(m_rect.left() , m_rect.top(), m_rect.left(), m_rect.bottom()); - - for (int i = 0; i < count; ++i) { - int y = i * -deltaY + m_rect.bottom(); - QGraphicsLineItem *lineItem = static_cast(lines.at(i)); - lineItem->setLine(m_rect.left() , y, m_rect.right(), y); - QGraphicsSimpleTextItem *labelItem = static_cast(labels.at(i)); - labelItem->setText(m_thicksList.at(i)); - QPointF center = labelItem->boundingRect().center(); - labelItem->setTransformOriginPoint(center.x(), center.y()); - labelItem->setPos(m_rect.left() - labelItem->boundingRect().width() - label_padding , y-center.y()); - if(i%2){ - QGraphicsRectItem *rectItem = static_cast(shades.at(i/2)); - rectItem->setRect(m_rect.left(),y,m_rect.width(),deltaY); - } - lineItem = static_cast(axis.at(i+1)); - lineItem->setLine(m_rect.left()-5,y,m_rect.left(),y); - } - } - break; - default: - qDebug()<<"Unknown axis type"; - break; - } + calculateLayout(vector); + if(vector.count()==0) return; + applyLayout(vector); } void AxisItem::handleAxisUpdate(QChartAxis* axis) @@ -182,32 +120,23 @@ void AxisItem::handleAxisUpdate(QChartAxis* axis) void AxisItem::handleLabelsChanged(QChartAxis* axis,const QStringList& labels) { - m_thicksList=labels; - QList items = m_labels.childItems(); - //if(items.size()!=m_thicksList.size()){ - clear(); - m_thicksList=labels; - createItems(m_thicksList.size()); - updateItem(m_thicksList.size()); - items = m_labels.childItems(); - handleAxisUpdate(axis); - // } - - Q_ASSERT(items.size()==m_thicksList.size()); - - int i=0; - foreach(QGraphicsItem* item, items){ - static_cast(item)->setText(m_thicksList.at(i)); - i++; + int diff = m_thicksList.size() - labels.size(); + + if(diff>0){ + clear(diff); + }else if(diff<0){ + createItems(-diff); } - update(); + m_thicksList=labels; + m_layoutVector.resize(m_thicksList.size()); + updateItems(m_layoutVector); + handleAxisUpdate(axis); } void AxisItem::handleGeometryChanged(const QRectF& rect) { m_rect = rect; - updateItem(m_thicksList.size()); - update(); + updateItems(m_layoutVector); } void AxisItem::setAxisOpacity(qreal opacity) @@ -309,6 +238,94 @@ void AxisItem::setGridPen(const QPen& pen) } } +void AxisItem::calculateLayout(QVector& points) +{ + switch (m_type) + { + case X_AXIS: + { + const qreal deltaX = m_rect.width()/(m_thicksList.size()-1); + for (int i = 0; i < m_thicksList.size(); ++i) { + int x = i * deltaX + m_rect.left(); + points[i]=x; + } + } + break; + case Y_AXIS: + { + const qreal deltaY = m_rect.height()/(m_thicksList.size()-1); + for (int i = 0; i < m_thicksList.size(); ++i) { + int y = i * -deltaY + m_rect.bottom(); + points[i]=y; + } + } + break; + } +} + +void AxisItem::applyLayout(const QVector& points) +{ + Q_ASSERT(points.size() == m_thicksList.size()); + + QList lines = m_grid.childItems(); + QList labels = m_labels.childItems(); + QList shades = m_shades.childItems(); + QList axis = m_axis.childItems(); + + Q_ASSERT(labels.size() == m_thicksList.size()); + + switch (m_type) + { + case X_AXIS: + { + QGraphicsLineItem *lineItem = static_cast(axis.at(0)); + lineItem->setLine(m_rect.left(), m_rect.bottom(), m_rect.right(), m_rect.bottom()); + + for (int i = 0; i < points.size(); ++i) { + QGraphicsLineItem *lineItem = static_cast(lines.at(i)); + lineItem->setLine(points[i], m_rect.top(), points[i], m_rect.bottom()); + QGraphicsSimpleTextItem *labelItem = static_cast(labels.at(i)); + labelItem->setText(m_thicksList.at(i)); + QPointF center = labelItem->boundingRect().center(); + labelItem->setTransformOriginPoint(center.x(), center.y()); + labelItem->setPos(points[i] - center.x(), m_rect.bottom() + label_padding); + if(i%2){ + QGraphicsRectItem *rectItem = static_cast(shades.at(i/2)); + rectItem->setRect(points[i],m_rect.top(),points[i+1]-points[i],m_rect.height()); + } + lineItem = static_cast(axis.at(i+1)); + lineItem->setLine(points[i],m_rect.bottom(),points[i],m_rect.bottom()+5); + } + } + break; + + case Y_AXIS: + { + QGraphicsLineItem *lineItem = static_cast(axis.at(0)); + lineItem->setLine(m_rect.left() , m_rect.top(), m_rect.left(), m_rect.bottom()); + + for (int i = 0; i < points.size(); ++i) { + QGraphicsLineItem *lineItem = static_cast(lines.at(i)); + lineItem->setLine(m_rect.left() , points[i], m_rect.right(), points[i]); + QGraphicsSimpleTextItem *labelItem = static_cast(labels.at(i)); + labelItem->setText(m_thicksList.at(i)); + QPointF center = labelItem->boundingRect().center(); + labelItem->setTransformOriginPoint(center.x(), center.y()); + labelItem->setPos(m_rect.left() - labelItem->boundingRect().width() - label_padding , points[i]-center.y()); + if(i%2){ + QGraphicsRectItem *rectItem = static_cast(shades.at(i/2)); + rectItem->setRect(m_rect.left(),points[i],m_rect.width(),points[i]-points[i+1]); + } + lineItem = static_cast(axis.at(i+1)); + lineItem->setLine(m_rect.left()-5,points[i],m_rect.left(),points[i]); + } + } + break; + default: + qDebug()<<"Unknown axis type"; + break; + } +} //TODO "nice numbers algorithm" #include "moc_axisitem_p.cpp" diff --git a/src/axisitem_p.h b/src/axisitem_p.h index 9d6b1c4..ab9a2db 100644 --- a/src/axisitem_p.h +++ b/src/axisitem_p.h @@ -53,10 +53,12 @@ public slots: void handleAxisUpdate(QChartAxis* axis); //look and feel void handleLabelsChanged(QChartAxis* axis,const QStringList& labels); //labels from dataset void handleGeometryChanged(const QRectF& size); // geometry from presenter -protected: - void updateItem(int count); +public: + virtual void updateItems(QVector& points); + virtual void calculateLayout(QVector& points); + virtual void applyLayout(const QVector& points); private: - void clear(); + void clear(int count); void createItems(int count); private: AxisType m_type; @@ -67,6 +69,7 @@ private: QGraphicsItemGroup m_labels; QGraphicsItemGroup m_axis; QStringList m_thicksList; + QVector m_layoutVector; }; diff --git a/src/src.pro b/src/src.pro index e5ab3a2..9a29bd6 100644 --- a/src/src.pro +++ b/src/src.pro @@ -8,6 +8,7 @@ CONFIG += debug_and_release CONFIG(debug, debug|release):TARGET = QtCommercialChartd SOURCES += \ axisitem.cpp \ + axisanimationitem.cpp \ chartdataset.cpp \ chartpresenter.cpp \ charttheme.cpp \ @@ -18,6 +19,7 @@ SOURCES += \ qchartview.cpp PRIVATE_HEADERS += \ axisitem_p.h \ + axisanimationitem_p.h \ chartdataset_p.h \ chartitem_p.h \ chartpresenter_p.h \