##// END OF EJS Templates
Kinetic scrolling is back for legend
sauimone -
r2189:4cb139890ac2
parent child
Show More
@@ -39,7 +39,8 LegendMarkerItem::LegendMarkerItem(QLegendMarkerPrivate *marker, QGraphicsObject
39 39 m_textItem(new QGraphicsSimpleTextItem(this)),
40 40 m_rectItem(new QGraphicsRectItem(this)),
41 41 m_margin(4),
42 m_space(4)
42 m_space(4),
43 m_pressPos(0, 0)
43 44 {
44 45 m_rectItem->setRect(m_markerRect);
45 46 }
@@ -163,6 +164,7 QSizeF LegendMarkerItem::sizeHint(Qt::SizeHint which, const QSizeF& constraint)
163 164 void LegendMarkerItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
164 165 {
165 166 MouseEventHandler::handleMousePressEvent(event);
167 m_pressPos = event->screenPos();
166 168 }
167 169
168 170 void LegendMarkerItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
@@ -180,18 +182,14 void LegendMarkerItem::mouseClicked()
180 182 emit m_marker->q_func()->clicked();
181 183 }
182 184
183 void LegendMarkerItem::mouseMoved(QPointF delta)
185 void LegendMarkerItem::mouseMoved(const QPointF &delta)
184 186 {
185 qreal dx = m_marker->m_legend->d_ptr->offset().x() - delta.x();
186 qreal dy = m_marker->m_legend->d_ptr->offset().y() - delta.y();
187 m_marker->m_legend->d_ptr->setOffset(dx, dy);
187 m_marker->m_legend->d_ptr->move(delta);
188 188 }
189 189
190 void LegendMarkerItem::mouseReleased(QPointF delta)
190 void LegendMarkerItem::mouseReleased(const QPointF &pos)
191 191 {
192 qreal dx = m_marker->m_legend->d_ptr->offset().x() - delta.x();
193 qreal dy = m_marker->m_legend->d_ptr->offset().y() - delta.y();
194 m_marker->m_legend->d_ptr->setOffset(dx, dy);
192 m_marker->m_legend->d_ptr->release(pos - m_pressPos);
195 193 }
196 194
197 195 #include "moc_legendmarkeritem_p.cpp"
@@ -80,8 +80,8 public:
80 80
81 81 // Filtered callbacks from MouseEventHandler
82 82 void mouseClicked();
83 void mouseMoved(QPointF delta);
84 void mouseReleased(QPointF delta);
83 void mouseMoved(const QPointF &delta);
84 void mouseReleased(const QPointF &pos);
85 85
86 86 protected:
87 87 QLegendMarkerPrivate *m_marker; // Knows
@@ -99,6 +99,8 protected:
99 99 QBrush m_brush;
100 100 bool m_visible;
101 101
102 QPointF m_pressPos;
103
102 104 friend class QLegendMarker;
103 105 friend class QLegendMarkerPrivate;
104 106 friend class LegendMarkerItem;
@@ -33,25 +33,18
33 33
34 34 #include "qlegend.h"
35 35 #include "qlegend_p.h"
36 #include "scroller_p.h"
37 36
38 37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
39 38
40 class LegendScroller: public QLegend, public Scroller
39 class LegendScroller: public QLegend
41 40 {
42 41
43 42 public:
44 43 LegendScroller(QChart *chart): QLegend(chart) { }
45 44
46 void setOffset(const QPointF &point) { d_ptr->setOffset(point.x(), point.y()); }
45 void setOffset(const QPointF &point) { d_ptr->setOffset(point); }
47 46
48 47 QPointF offset() const { return d_ptr->offset(); }
49
50 void mousePressEvent(QGraphicsSceneMouseEvent *event) { Scroller::mousePressEvent(event); }
51
52 void mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Scroller::mouseMoveEvent(event); }
53
54 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Scroller::mouseReleaseEvent(event); }
55 48 };
56 49
57 50 QTCOMMERCIALCHART_END_NAMESPACE
@@ -77,7 +77,6 void MouseEventHandler::handleMouseMoveEvent(QGraphicsSceneMouseEvent* event)
77 77
78 78 void MouseEventHandler::handleMouseReleaseEvent(QGraphicsSceneMouseEvent* event)
79 79 {
80 QPointF delta = event->screenPos() - m_lastPos;
81 80 m_lastPos = event->screenPos();
82 81
83 82 switch (m_state) {
@@ -91,7 +90,7 void MouseEventHandler::handleMouseReleaseEvent(QGraphicsSceneMouseEvent* event)
91 90 case Moved:
92 91 {
93 92 m_state = Idle;
94 mouseReleased(delta);
93 mouseReleased(m_lastPos);
95 94 event->accept();
96 95 break;
97 96 }
@@ -71,8 +71,8 public:
71 71 void setMoveTreshold(qreal treshold);
72 72
73 73 virtual void mouseClicked() = 0;
74 virtual void mouseMoved(QPointF delta) = 0;
75 virtual void mouseReleased(QPointF delta) = 0;
74 virtual void mouseMoved(const QPointF &delta) = 0;
75 virtual void mouseReleased(const QPointF &pos) = 0;
76 76
77 77 void handleMousePressEvent(QGraphicsSceneMouseEvent* event);
78 78 void handleMouseMoveEvent(QGraphicsSceneMouseEvent* event);
@@ -458,9 +458,9 QLegendPrivate::~QLegendPrivate()
458 458
459 459 }
460 460
461 void QLegendPrivate::setOffset(qreal x, qreal y)
461 void QLegendPrivate::setOffset(const QPointF &offset)
462 462 {
463 m_layout->setOffset(x, y);
463 m_layout->setOffset(offset.x(), offset.y());
464 464 }
465 465
466 466 QPointF QLegendPrivate::offset() const
@@ -31,6 +31,7
31 31 #define QLEGEND_P_H
32 32
33 33 #include "qlegend.h"
34 #include "scroller_p.h"
34 35
35 36 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36 37
@@ -41,14 +42,14 class LegendLayout;
41 42 class Domain;
42 43 class QLegendMarker;
43 44
44 class QLegendPrivate : public QObject
45 class QLegendPrivate : public QObject, public Scroller
45 46 {
46 47 Q_OBJECT
47 48 public:
48 49 QLegendPrivate(ChartPresenter *presenter, QChart *chart, QLegend *q);
49 50 ~QLegendPrivate();
50 51
51 void setOffset(qreal x, qreal y);
52 void setOffset(const QPointF &offset);
52 53 QPointF offset() const;
53 54 int roundness(qreal size);
54 55
@@ -27,9 +27,9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27
28 28 Scroller::Scroller()
29 29 : m_ticker(this),
30 m_state(Idle),
31 m_moveThreshold(10),
32 m_timeTreshold(50)
30 m_timeTresholdMin(50),
31 m_timeTresholdMax(300),
32 m_state(Idle)
33 33 {
34 34
35 35 }
@@ -38,146 +38,80 Scroller::~Scroller()
38 38 {
39 39 }
40 40
41 void Scroller::mousePressEvent(QGraphicsSceneMouseEvent *event)
41 void Scroller::move(const QPointF &delta)
42 42 {
43 if (event->button() == Qt::LeftButton) {
44 43 switch (m_state) {
45 44 case Idle:
46 m_state = Pressed;
47 m_offset = offset();
48 m_press = event->pos();
49 45 m_timeStamp = QTime::currentTime();
50 event->accept();
46 m_state = Move;
51 47 break;
52 48 case Scroll:
53 m_state = Stop;
54 m_speed = QPointF(0, 0);
55 m_offset = offset();
56 m_press = event->pos();
57 event->accept();
49 stopTicker();
50 m_timeStamp = QTime::currentTime();
51 m_state = Move;
58 52 break;
59 case Pressed:
60 case Move:
61 case Stop:
62 qWarning() << __FUNCTION__ << "Scroller unexpected state" << m_state;
63 event->ignore();
53 default:
64 54 break;
65 55 }
66 }
56 setOffset(offset() - delta);
67 57 }
68 58
69 void Scroller::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
59 void Scroller::release(const QPointF &delta)
70 60 {
71 QPointF delta = event->pos() - m_press;
61 // Starts scrolling, if at least m_timeTresholdMin msecs has gone since timestamp
62 // current time is no more than m_timeTresholdMax from timestamp
72 63
73 switch (m_state) {
74 case Pressed:
75 case Stop:
76 if (qAbs(delta.x()) > m_moveThreshold || qAbs(delta.y()) > m_moveThreshold) {
77 m_state = Move;
78 m_timeStamp = QTime::currentTime();
79 m_distance = QPointF(0, 0);
80 m_press = event->pos();
81 event->accept();
64 if ((m_timeStamp.elapsed() > m_timeTresholdMin) && (m_timeStamp.msecsTo(QTime::currentTime()) < m_timeTresholdMax)) {
65 // Release was quick enough. Start scrolling.
66 // Magic number is to make scroll bit slower (the resolution of screen may affect this)
67 m_speed = delta / 5;
68
69 qreal fraction = qMax(qAbs(m_speed.x()), qAbs(m_speed.y()));
70
71 if (!qFuzzyIsNull(fraction)) {
72 m_fraction.setX(qAbs(m_speed.x() / fraction));
73 m_fraction.setY(qAbs(m_speed.y() / fraction));
82 74 } else {
83 event->ignore();
75 m_fraction.setX(1);
76 m_fraction.setY(1);
84 77 }
85 break;
86 case Move:
87 setOffset(m_offset - delta);
88 calculateSpeed(event->pos());
89 event->accept();
90 break;
91 case Idle:
92 case Scroll:
93 qWarning() << __FUNCTION__ << "Scroller unexpected state" << m_state;
94 event->ignore();
95 break;
78 startTicker(25);
79 m_state = Scroll;
80 } else {
81 stopTicker(); // Stop ticker, if one is running.
82 m_state = Idle;
96 83 }
97 84 }
98 85
99 void Scroller::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
86 void Scroller::startTicker(int interval)
100 87 {
101 if (event->button() == Qt::LeftButton) {
102
103 switch (m_state) {
104
105 case Scroll:
106 m_state = Stop;
107 m_speed = QPointF(0, 0);
108 m_offset = offset();
109 event->accept();
110 break;
111 case Pressed:
112 m_state = Idle;
113 //if (m_timeStamp.elapsed() < m_clickedPressDelay) {
114 //emit clicked(m_offset.toPoint());
115 //}
116 event->accept();
117 break;
118 case Move:
119 calculateSpeed(event->pos());
120 m_offset = offset();
121 m_press = event->pos();
122 if (m_speed == QPointF(0, 0)) {
123 m_state = Idle;
124 } else {
125 m_speed /= 3.75;
126 88 m_state = Scroll;
127 m_ticker.start(25);
128 }
129 event->accept();
130 break;
131 case Stop:
132 case Idle:
133 qWarning() << __FUNCTION__ << "Scroller unexpected state" << m_state;
134 event->ignore();
135 break;
136 }
137 }
89 m_ticker.start(interval);
138 90 }
139 91
140 void Scroller::scroll(const QPointF &velocity)
92 void Scroller::stopTicker()
141 93 {
142 Q_UNUSED(velocity);
143 // TODO:
144 /*
145 m_offset = offset();
146 m_speed = velocity;
147 if (m_speed == QPointF(0, 0)) {
148 94 m_state = Idle;
149 }
150 else {
151 m_speed /= 3.75;
152 m_state = Scroll;
153 m_ticker.start(25);
154 }
155 */
95 m_ticker.stop();
156 96 }
157 97
158
159 98 void Scroller::scrollTick()
160 99 {
161 100 switch (m_state) {
162 101 case Scroll:
163 102 lowerSpeed(m_speed);
164 setOffset(m_offset - m_speed);
165 m_offset = offset();
103 setOffset(offset() - m_speed);
166 104 if (m_speed == QPointF(0, 0)) {
167 105 m_state = Idle;
168 106 m_ticker.stop();
169 107 }
170 108 break;
171 case Stop:
172 m_ticker.stop();
173 break;
174 109 case Idle:
175 110 case Move:
176 case Pressed:
177 111 qWarning() << __FUNCTION__ << "Scroller unexpected state" << m_state;
178 112 m_ticker.stop();
113 m_state = Idle;
179 114 break;
180
181 115 }
182 116 }
183 117
@@ -194,28 +128,6 void Scroller::lowerSpeed(QPointF &speed, qreal maxSpeed)
194 128 speed.setY(y);
195 129 }
196 130
197 void Scroller::calculateSpeed(const QPointF &position)
198 {
199 if (m_timeStamp.elapsed() > m_timeTreshold) {
200
201 QPointF distance = position - m_press;
202
203 m_timeStamp = QTime::currentTime();
204 m_speed = distance - m_distance;
205 m_distance = distance;
206
207 qreal fraction = qMax(qAbs(m_speed.x()), qAbs(m_speed.y()));
208
209 if (fraction != 0) {
210 m_fraction.setX(qAbs(m_speed.x() / fraction));
211 m_fraction.setY(qAbs(m_speed.y() / fraction));
212 } else {
213 m_fraction.setX(1);
214 m_fraction.setY(1);
215 }
216 }
217 }
218
219 131 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
220 132
221 133 ScrollTicker::ScrollTicker(Scroller *scroller, QObject *parent)
@@ -62,10 +62,8 class Scroller
62 62 public:
63 63 enum State {
64 64 Idle,
65 Pressed,
66 65 Move,
67 Scroll,
68 Stop
66 Scroll
69 67 };
70 68
71 69 Scroller();
@@ -74,15 +72,15 public:
74 72 virtual void setOffset(const QPointF &point) = 0;
75 73 virtual QPointF offset() const = 0;
76 74
77 void scroll(const QPointF& velocity);
75 void move(const QPointF &delta);
76 void release(const QPointF &delta);
78 77
79 public:
80 78 void scrollTick();
81 79
82 public:
83 void mousePressEvent(QGraphicsSceneMouseEvent *event);
84 void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
85 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
80 private:
81 void startTicker(int interval);
82 void stopTicker();
83
86 84
87 85 private:
88 86 void calculateSpeed(const QPointF &position);
@@ -90,15 +88,13 private:
90 88
91 89 private:
92 90 ScrollTicker m_ticker;
93 State m_state;
94 91 QTime m_timeStamp;
95 QPointF m_press;
96 QPointF m_offset;
97 92 QPointF m_speed;
98 QPointF m_distance;
99 93 QPointF m_fraction;
100 int m_moveThreshold;
101 int m_timeTreshold;
94 int m_timeTresholdMin;
95 int m_timeTresholdMax;
96
97 State m_state;
102 98 };
103 99
104 100 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now