From 4cb139890ac220bd171732220bbaca2593850953 2012-10-17 07:46:29 From: sauimone Date: 2012-10-17 07:46:29 Subject: [PATCH] Kinetic scrolling is back for legend --- diff --git a/src/legend/legendmarkeritem.cpp b/src/legend/legendmarkeritem.cpp index f59eeb3..85e4fa3 100644 --- a/src/legend/legendmarkeritem.cpp +++ b/src/legend/legendmarkeritem.cpp @@ -39,7 +39,8 @@ LegendMarkerItem::LegendMarkerItem(QLegendMarkerPrivate *marker, QGraphicsObject m_textItem(new QGraphicsSimpleTextItem(this)), m_rectItem(new QGraphicsRectItem(this)), m_margin(4), - m_space(4) + m_space(4), + m_pressPos(0, 0) { m_rectItem->setRect(m_markerRect); } @@ -163,6 +164,7 @@ QSizeF LegendMarkerItem::sizeHint(Qt::SizeHint which, const QSizeF& constraint) void LegendMarkerItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { MouseEventHandler::handleMousePressEvent(event); + m_pressPos = event->screenPos(); } void LegendMarkerItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) @@ -180,18 +182,14 @@ void LegendMarkerItem::mouseClicked() emit m_marker->q_func()->clicked(); } -void LegendMarkerItem::mouseMoved(QPointF delta) +void LegendMarkerItem::mouseMoved(const QPointF &delta) { - qreal dx = m_marker->m_legend->d_ptr->offset().x() - delta.x(); - qreal dy = m_marker->m_legend->d_ptr->offset().y() - delta.y(); - m_marker->m_legend->d_ptr->setOffset(dx, dy); + m_marker->m_legend->d_ptr->move(delta); } -void LegendMarkerItem::mouseReleased(QPointF delta) +void LegendMarkerItem::mouseReleased(const QPointF &pos) { - qreal dx = m_marker->m_legend->d_ptr->offset().x() - delta.x(); - qreal dy = m_marker->m_legend->d_ptr->offset().y() - delta.y(); - m_marker->m_legend->d_ptr->setOffset(dx, dy); + m_marker->m_legend->d_ptr->release(pos - m_pressPos); } #include "moc_legendmarkeritem_p.cpp" diff --git a/src/legend/legendmarkeritem_p.h b/src/legend/legendmarkeritem_p.h index 185a267..4126d5e 100644 --- a/src/legend/legendmarkeritem_p.h +++ b/src/legend/legendmarkeritem_p.h @@ -80,8 +80,8 @@ public: // Filtered callbacks from MouseEventHandler void mouseClicked(); - void mouseMoved(QPointF delta); - void mouseReleased(QPointF delta); + void mouseMoved(const QPointF &delta); + void mouseReleased(const QPointF &pos); protected: QLegendMarkerPrivate *m_marker; // Knows @@ -99,6 +99,8 @@ protected: QBrush m_brush; bool m_visible; + QPointF m_pressPos; + friend class QLegendMarker; friend class QLegendMarkerPrivate; friend class LegendMarkerItem; diff --git a/src/legend/legendscroller_p.h b/src/legend/legendscroller_p.h index b5a1797..0306899 100644 --- a/src/legend/legendscroller_p.h +++ b/src/legend/legendscroller_p.h @@ -33,25 +33,18 @@ #include "qlegend.h" #include "qlegend_p.h" -#include "scroller_p.h" QTCOMMERCIALCHART_BEGIN_NAMESPACE -class LegendScroller: public QLegend, public Scroller +class LegendScroller: public QLegend { public: LegendScroller(QChart *chart): QLegend(chart) { } - void setOffset(const QPointF &point) { d_ptr->setOffset(point.x(), point.y()); } + void setOffset(const QPointF &point) { d_ptr->setOffset(point); } QPointF offset() const { return d_ptr->offset(); } - - void mousePressEvent(QGraphicsSceneMouseEvent *event) { Scroller::mousePressEvent(event); } - - void mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Scroller::mouseMoveEvent(event); } - - void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Scroller::mouseReleaseEvent(event); } }; QTCOMMERCIALCHART_END_NAMESPACE diff --git a/src/legend/mouseeventhandler.cpp b/src/legend/mouseeventhandler.cpp index 06e6d8a..9e9508a 100644 --- a/src/legend/mouseeventhandler.cpp +++ b/src/legend/mouseeventhandler.cpp @@ -24,7 +24,7 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE MouseEventHandler::MouseEventHandler() : - m_lastPos(0,0), + m_lastPos(0, 0), m_state(Idle), m_treshold(10) { @@ -77,7 +77,6 @@ void MouseEventHandler::handleMouseMoveEvent(QGraphicsSceneMouseEvent* event) void MouseEventHandler::handleMouseReleaseEvent(QGraphicsSceneMouseEvent* event) { - QPointF delta = event->screenPos() - m_lastPos; m_lastPos = event->screenPos(); switch (m_state) { @@ -91,7 +90,7 @@ void MouseEventHandler::handleMouseReleaseEvent(QGraphicsSceneMouseEvent* event) case Moved: { m_state = Idle; - mouseReleased(delta); + mouseReleased(m_lastPos); event->accept(); break; } diff --git a/src/legend/mouseeventhandler_p.h b/src/legend/mouseeventhandler_p.h index a29d92f..ad18cd8 100644 --- a/src/legend/mouseeventhandler_p.h +++ b/src/legend/mouseeventhandler_p.h @@ -71,8 +71,8 @@ public: void setMoveTreshold(qreal treshold); virtual void mouseClicked() = 0; - virtual void mouseMoved(QPointF delta) = 0; - virtual void mouseReleased(QPointF delta) = 0; + virtual void mouseMoved(const QPointF &delta) = 0; + virtual void mouseReleased(const QPointF &pos) = 0; void handleMousePressEvent(QGraphicsSceneMouseEvent* event); void handleMouseMoveEvent(QGraphicsSceneMouseEvent* event); diff --git a/src/legend/qlegend.cpp b/src/legend/qlegend.cpp index 724eb82..2f002df 100644 --- a/src/legend/qlegend.cpp +++ b/src/legend/qlegend.cpp @@ -458,9 +458,9 @@ QLegendPrivate::~QLegendPrivate() } -void QLegendPrivate::setOffset(qreal x, qreal y) +void QLegendPrivate::setOffset(const QPointF &offset) { - m_layout->setOffset(x, y); + m_layout->setOffset(offset.x(), offset.y()); } QPointF QLegendPrivate::offset() const diff --git a/src/legend/qlegend_p.h b/src/legend/qlegend_p.h index da0eed9..c4a73d7 100644 --- a/src/legend/qlegend_p.h +++ b/src/legend/qlegend_p.h @@ -31,6 +31,7 @@ #define QLEGEND_P_H #include "qlegend.h" +#include "scroller_p.h" QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -41,14 +42,14 @@ class LegendLayout; class Domain; class QLegendMarker; -class QLegendPrivate : public QObject +class QLegendPrivate : public QObject, public Scroller { Q_OBJECT public: QLegendPrivate(ChartPresenter *presenter, QChart *chart, QLegend *q); ~QLegendPrivate(); - void setOffset(qreal x, qreal y); + void setOffset(const QPointF &offset); QPointF offset() const; int roundness(qreal size); diff --git a/src/scroller.cpp b/src/scroller.cpp index 85110f4..385688a 100644 --- a/src/scroller.cpp +++ b/src/scroller.cpp @@ -27,9 +27,9 @@ QTCOMMERCIALCHART_BEGIN_NAMESPACE Scroller::Scroller() : m_ticker(this), - m_state(Idle), - m_moveThreshold(10), - m_timeTreshold(50) + m_timeTresholdMin(50), + m_timeTresholdMax(300), + m_state(Idle) { } @@ -38,146 +38,80 @@ Scroller::~Scroller() { } -void Scroller::mousePressEvent(QGraphicsSceneMouseEvent *event) +void Scroller::move(const QPointF &delta) { - if (event->button() == Qt::LeftButton) { - switch (m_state) { - case Idle: - m_state = Pressed; - m_offset = offset(); - m_press = event->pos(); - m_timeStamp = QTime::currentTime(); - event->accept(); - break; - case Scroll: - m_state = Stop; - m_speed = QPointF(0, 0); - m_offset = offset(); - m_press = event->pos(); - event->accept(); - break; - case Pressed: - case Move: - case Stop: - qWarning() << __FUNCTION__ << "Scroller unexpected state" << m_state; - event->ignore(); - break; - } - } -} - -void Scroller::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - QPointF delta = event->pos() - m_press; - switch (m_state) { - case Pressed: - case Stop: - if (qAbs(delta.x()) > m_moveThreshold || qAbs(delta.y()) > m_moveThreshold) { - m_state = Move; - m_timeStamp = QTime::currentTime(); - m_distance = QPointF(0, 0); - m_press = event->pos(); - event->accept(); - } else { - event->ignore(); - } - break; - case Move: - setOffset(m_offset - delta); - calculateSpeed(event->pos()); - event->accept(); - break; case Idle: + m_timeStamp = QTime::currentTime(); + m_state = Move; + break; case Scroll: - qWarning() << __FUNCTION__ << "Scroller unexpected state" << m_state; - event->ignore(); + stopTicker(); + m_timeStamp = QTime::currentTime(); + m_state = Move; + break; + default: break; } + setOffset(offset() - delta); } -void Scroller::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +void Scroller::release(const QPointF &delta) { - if (event->button() == Qt::LeftButton) { + // Starts scrolling, if at least m_timeTresholdMin msecs has gone since timestamp + // current time is no more than m_timeTresholdMax from timestamp - switch (m_state) { + if ((m_timeStamp.elapsed() > m_timeTresholdMin) && (m_timeStamp.msecsTo(QTime::currentTime()) < m_timeTresholdMax)) { + // Release was quick enough. Start scrolling. + // Magic number is to make scroll bit slower (the resolution of screen may affect this) + m_speed = delta / 5; - case Scroll: - m_state = Stop; - m_speed = QPointF(0, 0); - m_offset = offset(); - event->accept(); - break; - case Pressed: - m_state = Idle; - //if (m_timeStamp.elapsed() < m_clickedPressDelay) { - //emit clicked(m_offset.toPoint()); - //} - event->accept(); - break; - case Move: - calculateSpeed(event->pos()); - m_offset = offset(); - m_press = event->pos(); - if (m_speed == QPointF(0, 0)) { - m_state = Idle; - } else { - m_speed /= 3.75; - m_state = Scroll; - m_ticker.start(25); - } - event->accept(); - break; - case Stop: - case Idle: - qWarning() << __FUNCTION__ << "Scroller unexpected state" << m_state; - event->ignore(); - break; + qreal fraction = qMax(qAbs(m_speed.x()), qAbs(m_speed.y())); + + if (!qFuzzyIsNull(fraction)) { + m_fraction.setX(qAbs(m_speed.x() / fraction)); + m_fraction.setY(qAbs(m_speed.y() / fraction)); + } else { + m_fraction.setX(1); + m_fraction.setY(1); } + startTicker(25); + m_state = Scroll; + } else { + stopTicker(); // Stop ticker, if one is running. + m_state = Idle; } } -void Scroller::scroll(const QPointF &velocity) +void Scroller::startTicker(int interval) { - Q_UNUSED(velocity); - // TODO: -/* - m_offset = offset(); - m_speed = velocity; - if (m_speed == QPointF(0, 0)) { - m_state = Idle; - } - else { - m_speed /= 3.75; - m_state = Scroll; - m_ticker.start(25); - } -*/ + m_state = Scroll; + m_ticker.start(interval); } +void Scroller::stopTicker() +{ + m_state = Idle; + m_ticker.stop(); +} void Scroller::scrollTick() { switch (m_state) { case Scroll: lowerSpeed(m_speed); - setOffset(m_offset - m_speed); - m_offset = offset(); + setOffset(offset() - m_speed); if (m_speed == QPointF(0, 0)) { m_state = Idle; m_ticker.stop(); } break; - case Stop: - m_ticker.stop(); - break; case Idle: case Move: - case Pressed: qWarning() << __FUNCTION__ << "Scroller unexpected state" << m_state; m_ticker.stop(); + m_state = Idle; break; - } } @@ -194,28 +128,6 @@ void Scroller::lowerSpeed(QPointF &speed, qreal maxSpeed) speed.setY(y); } -void Scroller::calculateSpeed(const QPointF &position) -{ - if (m_timeStamp.elapsed() > m_timeTreshold) { - - QPointF distance = position - m_press; - - m_timeStamp = QTime::currentTime(); - m_speed = distance - m_distance; - m_distance = distance; - - qreal fraction = qMax(qAbs(m_speed.x()), qAbs(m_speed.y())); - - if (fraction != 0) { - m_fraction.setX(qAbs(m_speed.x() / fraction)); - m_fraction.setY(qAbs(m_speed.y() / fraction)); - } else { - m_fraction.setX(1); - m_fraction.setY(1); - } - } -} - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ScrollTicker::ScrollTicker(Scroller *scroller, QObject *parent) diff --git a/src/scroller_p.h b/src/scroller_p.h index 7f3a949..36376bb 100644 --- a/src/scroller_p.h +++ b/src/scroller_p.h @@ -62,10 +62,8 @@ class Scroller public: enum State { Idle, - Pressed, Move, - Scroll, - Stop + Scroll }; Scroller(); @@ -74,15 +72,15 @@ public: virtual void setOffset(const QPointF &point) = 0; virtual QPointF offset() const = 0; - void scroll(const QPointF& velocity); + void move(const QPointF &delta); + void release(const QPointF &delta); -public: void scrollTick(); -public: - void mousePressEvent(QGraphicsSceneMouseEvent *event); - void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); +private: + void startTicker(int interval); + void stopTicker(); + private: void calculateSpeed(const QPointF &position); @@ -90,15 +88,13 @@ private: private: ScrollTicker m_ticker; - State m_state; QTime m_timeStamp; - QPointF m_press; - QPointF m_offset; QPointF m_speed; - QPointF m_distance; QPointF m_fraction; - int m_moveThreshold; - int m_timeTreshold; + int m_timeTresholdMin; + int m_timeTresholdMax; + + State m_state; }; QTCOMMERCIALCHART_END_NAMESPACE