@@ -0,0 +1,26 | |||
|
1 | #include "legendscrollbutton_p.h" | |
|
2 | #include <QGraphicsSceneEvent> | |
|
3 | ||
|
4 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |
|
5 | ||
|
6 | LegendScrollButton::LegendScrollButton(ScrollButtonId id, QGraphicsItem *parent) | |
|
7 | : QGraphicsPolygonItem(parent) | |
|
8 | ,mId(id) | |
|
9 | { | |
|
10 | setAcceptedMouseButtons(Qt::LeftButton); | |
|
11 | } | |
|
12 | ||
|
13 | LegendScrollButton::ScrollButtonId LegendScrollButton::id() | |
|
14 | { | |
|
15 | return mId; | |
|
16 | } | |
|
17 | ||
|
18 | void LegendScrollButton::mousePressEvent(QGraphicsSceneMouseEvent *event) | |
|
19 | { | |
|
20 | emit clicked(event); | |
|
21 | } | |
|
22 | ||
|
23 | #include "moc_legendscrollbutton_p.cpp" | |
|
24 | ||
|
25 | QTCOMMERCIALCHART_END_NAMESPACE | |
|
26 |
@@ -0,0 +1,38 | |||
|
1 | #ifndef LEGENDSCROLLBUTTON_P_H | |
|
2 | #define LEGENDSCROLLBUTTON_P_H | |
|
3 | ||
|
4 | #include <QObject> | |
|
5 | #include <qchartglobal.h> | |
|
6 | #include <QGraphicsPolygonItem> | |
|
7 | ||
|
8 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |
|
9 | ||
|
10 | class LegendScrollButton : public QObject, public QGraphicsPolygonItem | |
|
11 | { | |
|
12 | Q_OBJECT | |
|
13 | public: | |
|
14 | enum ScrollButtonId { | |
|
15 | ScrollButtonIdLeft, | |
|
16 | ScrollButtonIdRight, | |
|
17 | ScrollButtonIdUp, | |
|
18 | ScrollButtonIdDown | |
|
19 | }; | |
|
20 | ||
|
21 | explicit LegendScrollButton(ScrollButtonId id, QGraphicsItem *parent = 0); | |
|
22 | ScrollButtonId id(); | |
|
23 | ||
|
24 | virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); | |
|
25 | ||
|
26 | signals: | |
|
27 | void clicked(QGraphicsSceneMouseEvent* event); | |
|
28 | ||
|
29 | public slots: | |
|
30 | ||
|
31 | private: | |
|
32 | ||
|
33 | ScrollButtonId mId; | |
|
34 | }; | |
|
35 | ||
|
36 | QTCOMMERCIALCHART_END_NAMESPACE | |
|
37 | ||
|
38 | #endif // LEGENDSCROLLBUTTON_P_H |
@@ -337,12 +337,44 void QChart::updateLayout() | |||
|
337 | 337 | // recalculate legend position |
|
338 | 338 | if (m_legend) { |
|
339 | 339 | if (m_legend->parentObject() == this) { |
|
340 | m_legend->setMaximumSize(rect.size()); | |
|
341 | m_legend->setPos(rect.topLeft()); | |
|
340 | updateLegendLayout(); | |
|
342 | 341 | } |
|
343 | 342 | } |
|
344 | 343 | } |
|
345 | 344 | |
|
345 | void QChart::updateLegendLayout() | |
|
346 | { | |
|
347 | QRectF plotRect = m_rect.adjusted(m_padding,m_padding, -m_padding, -m_padding); | |
|
348 | QRectF legendRect; | |
|
349 | ||
|
350 | switch (m_legend->preferredLayout()) | |
|
351 | { | |
|
352 | case QLegend::PreferredLayoutTop:{ | |
|
353 | legendRect = m_rect.adjusted(m_padding,0,-m_padding,-m_padding - plotRect.height()); | |
|
354 | break; | |
|
355 | } | |
|
356 | case QLegend::PreferredLayoutBottom: { | |
|
357 | legendRect = m_rect.adjusted(m_padding,m_padding + plotRect.height(),-m_padding,0); | |
|
358 | break; | |
|
359 | } | |
|
360 | case QLegend::PreferredLayoutLeft: { | |
|
361 | legendRect = m_rect.adjusted(0,m_padding,-m_padding - plotRect.width(),-m_padding); | |
|
362 | break; | |
|
363 | } | |
|
364 | case QLegend::PreferredLayoutRight: { | |
|
365 | legendRect = m_rect.adjusted(m_padding + plotRect.width(),m_padding,0,-m_padding); | |
|
366 | break; | |
|
367 | } | |
|
368 | default: { | |
|
369 | legendRect = plotRect; | |
|
370 | break; | |
|
371 | } | |
|
372 | } | |
|
373 | ||
|
374 | m_legend->setMaximumSize(legendRect.size()); | |
|
375 | m_legend->setPos(legendRect.topLeft()); | |
|
376 | } | |
|
377 | ||
|
346 | 378 | |
|
347 | 379 | int QChart::padding() const |
|
348 | 380 | { |
@@ -101,6 +101,7 private: | |||
|
101 | 101 | void setBackgroundPadding(int padding); |
|
102 | 102 | void setBackgroundDiameter(int diameter); |
|
103 | 103 | void updateLayout(); |
|
104 | void updateLegendLayout(); | |
|
104 | 105 | |
|
105 | 106 | private: |
|
106 | 107 | Q_DISABLE_COPY(QChart) |
@@ -2,6 +2,7 | |||
|
2 | 2 | #include "qlegend.h" |
|
3 | 3 | #include "qseries.h" |
|
4 | 4 | #include "legendmarker_p.h" |
|
5 | #include "legendscrollbutton_p.h" | |
|
5 | 6 | #include "qxyseries.h" |
|
6 | 7 | #include "qlineseries.h" |
|
7 | 8 | #include "qareaseries.h" |
@@ -27,10 +28,23 QLegend::QLegend(QGraphicsItem *parent) | |||
|
27 | 28 | ,mSize(0,0) |
|
28 | 29 | ,mMinimumSize(50,20) // TODO: magic numbers |
|
29 | 30 | ,mMaximumSize(150,100) |
|
30 | ,m_brush(Qt::darkGray) // TODO: from theme? | |
|
31 |
,mPreferredLayout(QLegend::PreferredLayout |
|
|
31 | ,m_brush(Qt::darkGray) // TODO: from theme? | |
|
32 | ,mPreferredLayout(QLegend::PreferredLayoutTop) | |
|
33 | ,mFirstMarker(0) | |
|
34 | ,mMargin(5) | |
|
32 | 35 | { |
|
33 | setVisible(false); | |
|
36 | // setVisible(false); | |
|
37 | ||
|
38 | mScrollButtonLeft = new LegendScrollButton(LegendScrollButton::ScrollButtonIdLeft, this); | |
|
39 | mScrollButtonRight = new LegendScrollButton(LegendScrollButton::ScrollButtonIdRight, this); | |
|
40 | mScrollButtonUp = new LegendScrollButton(LegendScrollButton::ScrollButtonIdUp, this); | |
|
41 | mScrollButtonDown = new LegendScrollButton(LegendScrollButton::ScrollButtonIdDown, this); | |
|
42 | ||
|
43 | connect(mScrollButtonLeft,SIGNAL(clicked(QGraphicsSceneMouseEvent*)),this,SLOT(handleScrollButtonClicked(QGraphicsSceneMouseEvent*))); | |
|
44 | connect(mScrollButtonRight,SIGNAL(clicked(QGraphicsSceneMouseEvent*)),this,SLOT(handleScrollButtonClicked(QGraphicsSceneMouseEvent*))); | |
|
45 | connect(mScrollButtonUp,SIGNAL(clicked(QGraphicsSceneMouseEvent*)),this,SLOT(handleScrollButtonClicked(QGraphicsSceneMouseEvent*))); | |
|
46 | connect(mScrollButtonDown,SIGNAL(clicked(QGraphicsSceneMouseEvent*)),this,SLOT(handleScrollButtonClicked(QGraphicsSceneMouseEvent*))); | |
|
47 | ||
|
34 | 48 | setZValue(ChartPresenter::LegendZValue); |
|
35 | 49 | } |
|
36 | 50 | |
@@ -39,7 +53,7 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q | |||
|
39 | 53 | Q_UNUSED(option) |
|
40 | 54 | Q_UNUSED(widget) |
|
41 | 55 | |
|
42 |
painter->setOpacity(0. |
|
|
56 | painter->setOpacity(0.8); | |
|
43 | 57 | painter->setPen(m_pen); |
|
44 | 58 | painter->setBrush(m_brush); |
|
45 | 59 | painter->drawRect(boundingRect()); |
@@ -79,7 +93,12 QPen QLegend::pen() const | |||
|
79 | 93 | void QLegend::setPreferredLayout(QLegend::PreferredLayout preferred) |
|
80 | 94 | { |
|
81 | 95 | mPreferredLayout = preferred; |
|
82 |
|
|
|
96 | updateLayout(); | |
|
97 | } | |
|
98 | ||
|
99 | QLegend::PreferredLayout QLegend::preferredLayout() const | |
|
100 | { | |
|
101 | return mPreferredLayout; | |
|
83 | 102 | } |
|
84 | 103 | |
|
85 | 104 | QSizeF QLegend::maximumSize() const |
@@ -90,7 +109,7 QSizeF QLegend::maximumSize() const | |||
|
90 | 109 | void QLegend::setMaximumSize(const QSizeF size) |
|
91 | 110 | { |
|
92 | 111 | mMaximumSize = size; |
|
93 |
|
|
|
112 | updateLayout(); | |
|
94 | 113 | } |
|
95 | 114 | |
|
96 | 115 | void QLegend::setSize(const QSizeF size) |
@@ -107,7 +126,7 void QLegend::setSize(const QSizeF size) | |||
|
107 | 126 | void QLegend::setPos(const QPointF &pos) |
|
108 | 127 | { |
|
109 | 128 | mPos = pos; |
|
110 |
|
|
|
129 | updateLayout(); | |
|
111 | 130 | } |
|
112 | 131 | |
|
113 | 132 | void QLegend::handleSeriesAdded(QSeries* series, Domain* domain) |
@@ -116,7 +135,7 void QLegend::handleSeriesAdded(QSeries* series, Domain* domain) | |||
|
116 | 135 | |
|
117 | 136 | createMarkers(series); |
|
118 | 137 | connectSeries(series); |
|
119 |
|
|
|
138 | updateLayout(); | |
|
120 | 139 | } |
|
121 | 140 | |
|
122 | 141 | void QLegend::handleSeriesRemoved(QSeries* series) |
@@ -133,7 +152,7 void QLegend::handleSeriesRemoved(QSeries* series) | |||
|
133 | 152 | deleteMarkers(series); |
|
134 | 153 | } |
|
135 | 154 | |
|
136 |
|
|
|
155 | updateLayout(); | |
|
137 | 156 | } |
|
138 | 157 | |
|
139 | 158 | void QLegend::handleAdded(QList<QPieSlice*> slices) |
@@ -150,7 +169,7 void QLegend::handleAdded(QList<QPieSlice*> slices) | |||
|
150 | 169 | mMarkers.append(marker); |
|
151 | 170 | childItems().append(marker); |
|
152 | 171 | } |
|
153 |
|
|
|
172 | updateLayout(); | |
|
154 | 173 | } |
|
155 | 174 | |
|
156 | 175 | void QLegend::handleRemoved(QList<QPieSlice *> slices) |
@@ -166,7 +185,36 void QLegend::handleMarkerDestroyed() | |||
|
166 | 185 | // TODO: what if more than one markers are destroyed and we update layout after first one? |
|
167 | 186 | LegendMarker* m = static_cast<LegendMarker*> (sender()); |
|
168 | 187 | mMarkers.removeOne(m); |
|
169 |
|
|
|
188 | updateLayout(); | |
|
189 | } | |
|
190 | ||
|
191 | void QLegend::handleScrollButtonClicked(QGraphicsSceneMouseEvent *event) | |
|
192 | { | |
|
193 | Q_UNUSED(event); // Maybe later somethin happens with right click... | |
|
194 | ||
|
195 | // TODO: detect sender object. scroll to appropiate direction. | |
|
196 | LegendScrollButton* scrollButton = static_cast<LegendScrollButton*> (sender()); | |
|
197 | Q_ASSERT(scrollButton); | |
|
198 | ||
|
199 | switch (scrollButton->id()) { | |
|
200 | case LegendScrollButton::ScrollButtonIdLeft: | |
|
201 | case LegendScrollButton::ScrollButtonIdUp: { | |
|
202 | // Lower limit is same in these cases | |
|
203 | mFirstMarker--; | |
|
204 | checkMarkerBounds(); | |
|
205 | break; | |
|
206 | } | |
|
207 | case LegendScrollButton::ScrollButtonIdRight: | |
|
208 | case LegendScrollButton::ScrollButtonIdDown: { | |
|
209 | mFirstMarker++; | |
|
210 | checkMarkerBounds(); | |
|
211 | break; | |
|
212 | } | |
|
213 | default: { | |
|
214 | break; | |
|
215 | } | |
|
216 | } | |
|
217 | updateLayout(); | |
|
170 | 218 | } |
|
171 | 219 | |
|
172 | 220 | void QLegend::connectSeries(QSeries *series) |
@@ -371,111 +419,158 void QLegend::deleteMarkers(QSeries *series) | |||
|
371 | 419 | } |
|
372 | 420 | } |
|
373 | 421 | |
|
374 |
void QLegend:: |
|
|
422 | void QLegend::updateLayout() | |
|
375 | 423 | { |
|
376 | 424 | // Calculate layout for markers and text |
|
377 | 425 | if (mMarkers.count() <= 0) { |
|
378 | 426 | // Nothing to do |
|
379 | 427 | return; |
|
380 | 428 | } |
|
429 | checkMarkerBounds(); | |
|
381 | 430 | |
|
382 | 431 | // Find out widest item. |
|
383 | qreal itemMaxWidth = 0; | |
|
384 | qreal itemMaxHeight = 0; | |
|
385 | foreach (LegendMarker* m, mMarkers) { | |
|
386 | if (m->boundingRect().width() > itemMaxWidth) { | |
|
387 | itemMaxWidth = m->boundingRect().width(); | |
|
388 | } | |
|
389 | if (m->boundingRect().height() > itemMaxHeight) { | |
|
390 | itemMaxHeight = m->boundingRect().height(); | |
|
391 | } | |
|
392 | } | |
|
432 | QSizeF markerMaxSize = maximumMarkerSize(); | |
|
393 | 433 | |
|
394 | int maxHorizontalItems = boundingRect().width() / itemMaxWidth; | |
|
395 | int maxVerticalItems = boundingRect().height() / itemMaxHeight; | |
|
434 | // Use max height as scroll button size | |
|
435 | rescaleScrollButtons(QSize(markerMaxSize.height() ,markerMaxSize.height())); | |
|
396 | 436 | |
|
397 | if (mMarkers.count() > maxHorizontalItems * maxVerticalItems) { | |
|
398 | // TODO: overlapping layout | |
|
399 | //qDebug() << "Warning. Not enough space to layout all legend items properly."; | |
|
400 | } | |
|
401 | ||
|
402 | qreal margin = 5; | |
|
403 | 437 | qreal totalWidth = 0; |
|
404 | 438 | qreal totalHeight = 0; |
|
405 | 439 | switch (mPreferredLayout) |
|
406 | 440 | { |
|
407 | case QLegend::PreferredLayoutHorizontal: { | |
|
408 | /* | |
|
409 | qreal xStep = mMaximumSize.width() / (mMarkers.count()+1); | |
|
410 | if (xStep > itemMaxWidth) { | |
|
411 |
|
|
|
412 | } | |
|
413 | qreal yStep = mMaximumSize.height() / (mMarkers.count()+1); | |
|
414 | if (yStep > itemMaxHeight) { | |
|
415 | yStep = itemMaxHeight; | |
|
416 | }*/ | |
|
417 | qreal xStep = itemMaxWidth; | |
|
418 | qreal yStep = itemMaxHeight; | |
|
419 | qreal x = mPos.x() + margin; | |
|
420 | qreal y = mPos.y() + margin; | |
|
421 | int row = 1; | |
|
441 | // Both cases organise items horizontally | |
|
442 | case QLegend::PreferredLayoutBottom: | |
|
443 | case QLegend::PreferredLayoutTop: { | |
|
444 | ||
|
445 | qreal xStep = markerMaxSize.width(); | |
|
446 | qreal x = mPos.x() + mMargin; | |
|
447 | qreal y = mPos.y() + mMargin; | |
|
422 | 448 | int column = 0; |
|
423 | int maxRows = 1; | |
|
424 | 449 | int maxColumns = 1; |
|
425 | foreach (LegendMarker* m, mMarkers) { | |
|
426 | maxRows = row; | |
|
427 | m->setPos(x,y); | |
|
428 | x += xStep; | |
|
429 | column++; | |
|
430 | if (column > maxColumns) { | |
|
431 | maxColumns = column; | |
|
432 | } | |
|
433 | if ((x + itemMaxWidth + margin*2) > (mPos.x() + mMaximumSize.width())) { | |
|
434 | x = mPos.x() + margin; | |
|
435 | y += yStep; | |
|
436 | row++; | |
|
437 | column = 0; | |
|
450 | qreal scrollButtonPadding = 0; | |
|
451 | ||
|
452 | // Set correct visibility for scroll scrollbuttons | |
|
453 | if (scrollButtonsVisible()) { | |
|
454 | mScrollButtonLeft->setVisible(true); | |
|
455 | mScrollButtonRight->setVisible(true); | |
|
456 | totalWidth += (mScrollButtonLeft->boundingRect().width() + mMargin) * 2; // scrollbuttons visible, so add their width to total width | |
|
457 | x += mScrollButtonLeft->boundingRect().width() + mMargin; // start position changes by scrollbutton width | |
|
458 | scrollButtonPadding = mScrollButtonLeft->boundingRect().width(); | |
|
459 | } else { | |
|
460 | mScrollButtonLeft->setVisible(false); | |
|
461 | mScrollButtonRight->setVisible(false); | |
|
462 | } | |
|
463 | mScrollButtonUp->setVisible(false); | |
|
464 | mScrollButtonDown->setVisible(false); | |
|
465 | ||
|
466 | for (int i=0; i<mMarkers.count(); i++) { | |
|
467 | LegendMarker* m = mMarkers.at(i); | |
|
468 | if (i<mFirstMarker) { | |
|
469 | // Markers before first are not visible. | |
|
470 | m->setVisible(false); | |
|
471 | } else { | |
|
472 | if ((x + xStep + scrollButtonPadding) > (mPos.x() + mMaximumSize.width())) { | |
|
473 | // This marker would go outside legend rect. | |
|
474 | m->setVisible(false); | |
|
475 | } else { | |
|
476 | // This marker is ok | |
|
477 | m->setVisible(true); | |
|
478 | m->setPos(x,y); | |
|
479 | x += xStep; | |
|
480 | column++; | |
|
481 | } | |
|
438 | 482 | } |
|
483 | maxColumns = column; | |
|
439 | 484 | } |
|
440 | totalWidth = maxColumns * itemMaxWidth + margin * 2; | |
|
441 | totalHeight = maxRows * itemMaxHeight + margin * 2; | |
|
485 | ||
|
486 | mScrollButtonLeft->setPos(mPos.x() + mMargin, y); | |
|
487 | mScrollButtonRight->setPos(x+mMargin,y); | |
|
488 | ||
|
489 | totalWidth += maxColumns * markerMaxSize.width() + mMargin * 2; | |
|
490 | totalHeight = markerMaxSize.height() + mMargin * 2; | |
|
491 | ||
|
442 | 492 | break; |
|
443 | 493 | } |
|
444 | case QLegend::PreferredLayoutVertical: { | |
|
445 | /* | |
|
446 | qreal xStep = mMaximumSize.width() / (mMarkers.count()+1); | |
|
447 | if (xStep > itemMaxWidth) { | |
|
448 | xStep = itemMaxWidth; | |
|
494 | // Both cases organize items vertically | |
|
495 | case QLegend::PreferredLayoutLeft: | |
|
496 | case QLegend::PreferredLayoutRight: { | |
|
497 | qreal yStep = markerMaxSize.height(); | |
|
498 | qreal x = mPos.x() + mMargin; | |
|
499 | qreal y = mPos.y() + mMargin; | |
|
500 | int row = 1; | |
|
501 | int maxRows = 1; | |
|
502 | qreal scrollButtonPadding = 0; | |
|
503 | ||
|
504 | // Set correct visibility for scroll scrollbuttons | |
|
505 | if (scrollButtonsVisible()) { | |
|
506 | mScrollButtonUp->setVisible(true); | |
|
507 | mScrollButtonDown->setVisible(true); | |
|
508 | totalHeight += (mScrollButtonUp->boundingRect().height() + mMargin) * 2; // scrollbuttons visible, so add their height to total height | |
|
509 | y += mScrollButtonUp->boundingRect().height() + mMargin; // start position changes by scrollbutton height | |
|
510 | scrollButtonPadding = mScrollButtonUp->boundingRect().height(); | |
|
511 | } else { | |
|
512 | mScrollButtonUp->setVisible(false); | |
|
513 | mScrollButtonDown->setVisible(false); | |
|
449 | 514 | } |
|
450 | qreal yStep = mMaximumSize.height() / (mMarkers.count()+1); | |
|
451 | if (yStep > itemMaxHeight) { | |
|
452 | yStep = itemMaxHeight; | |
|
453 | }*/ | |
|
454 | qreal xStep = itemMaxWidth; | |
|
455 | qreal yStep = itemMaxHeight; | |
|
456 | qreal x = mPos.x() + margin; | |
|
457 | qreal y = mPos.y() + margin; | |
|
515 | mScrollButtonLeft->setVisible(false); | |
|
516 | mScrollButtonRight->setVisible(false); | |
|
517 | ||
|
518 | for (int i=0; i<mMarkers.count(); i++) { | |
|
519 | LegendMarker* m = mMarkers.at(i); | |
|
520 | if (i<mFirstMarker) { | |
|
521 | // Markers before first are not visible. | |
|
522 | m->setVisible(false); | |
|
523 | } else { | |
|
524 | if ((y + yStep + scrollButtonPadding) > (mPos.y() + mMaximumSize.height())) { | |
|
525 | // This marker would go outside legend rect. | |
|
526 | m->setVisible(false); | |
|
527 | } else { | |
|
528 | // This marker is ok | |
|
529 | m->setVisible(true); | |
|
530 | m->setPos(x,y); | |
|
531 | y += yStep; | |
|
532 | row++; | |
|
533 | } | |
|
534 | } | |
|
535 | maxRows = row; | |
|
536 | } | |
|
537 | ||
|
538 | mScrollButtonUp->setPos(mPos.x() + mMargin, mPos.y() + mMargin); | |
|
539 | mScrollButtonDown->setPos(mPos.x() + mMargin, y + mMargin); | |
|
540 | ||
|
541 | totalWidth += markerMaxSize.width() + mMargin * 2; | |
|
542 | totalHeight = maxRows * markerMaxSize.height() + mMargin * 4 + scrollButtonPadding; // TODO: check this | |
|
543 | ||
|
544 | /* | |
|
545 | qreal yStep = markerMaxSize.height(); | |
|
546 | qreal x = mPos.x() + mMargin; | |
|
547 | qreal y = mPos.y() + mMargin; | |
|
458 | 548 | int row = 0; |
|
459 | int column = 1; | |
|
460 | 549 | int maxRows = 1; |
|
461 | 550 | int maxColumns = 1; |
|
462 | foreach (LegendMarker* m, mMarkers) { | |
|
463 | maxColumns = column; | |
|
464 | m->setPos(x,y); | |
|
465 | y += yStep; | |
|
466 | row++; | |
|
467 |
|
|
|
468 | maxRows = row; | |
|
469 | } | |
|
470 | if ((y + itemMaxHeight + margin*2) > (mPos.y() + mMaximumSize.height())) { | |
|
471 | y = mPos.y() + margin; | |
|
472 | x += xStep; | |
|
473 | column++; | |
|
474 |
|
|
|
551 | for (int i=0; i<mMarkers.count(); i++) { | |
|
552 | LegendMarker* m = mMarkers.at(i); | |
|
553 | if (i<mFirstMarker) { | |
|
554 | // Markers before first are not visible. | |
|
555 | m->setVisible(false); | |
|
556 | } else { | |
|
557 | if ((y + markerMaxSize.height() + mMargin*2) > (mPos.y() + mMaximumSize.height())) { | |
|
558 | // This marker would go outside legend rect. | |
|
559 | m->setVisible(false); | |
|
560 | } else { | |
|
561 | // This marker is ok | |
|
562 | m->setVisible(true); | |
|
563 | maxRows = row; | |
|
564 | m->setPos(x,y); | |
|
565 | y += yStep; | |
|
566 | row++; | |
|
567 | } | |
|
475 | 568 | } |
|
569 | maxRows = row; | |
|
476 | 570 | } |
|
477 |
totalWidth = maxColumns * |
|
|
478 |
totalHeight = maxRows * |
|
|
571 | totalWidth = maxColumns * markerMaxSize.width() + mMargin * 2; | |
|
572 | totalHeight = maxRows * markerMaxSize.height() + mMargin * 2; | |
|
573 | */ | |
|
479 | 574 | break; |
|
480 | 575 | } |
|
481 | 576 | default: { |
@@ -485,6 +580,81 void QLegend::layoutChanged() | |||
|
485 | 580 | |
|
486 | 581 | mSize.setWidth(totalWidth); |
|
487 | 582 | mSize.setHeight(totalHeight); |
|
583 | ||
|
584 | update(); | |
|
585 | } | |
|
586 | ||
|
587 | void QLegend::rescaleScrollButtons(const QSize &size) | |
|
588 | { | |
|
589 | QPolygonF left; | |
|
590 | left << QPointF(size.width(),0) << QPointF(0,size.height()/2) << QPointF(size.width(),size.height()); | |
|
591 | QPolygonF right; | |
|
592 | right << QPointF(0,0) << QPointF(size.width(),size.height()/2) << QPointF(0,size.height()); | |
|
593 | QPolygonF up; | |
|
594 | up << QPointF(0,size.height()) << QPointF(size.width()/2,0) << QPointF(size.width(),size.height()); | |
|
595 | QPolygonF down; | |
|
596 | down << QPointF(0,0) << QPointF(size.width()/2,size.height()) << QPointF(size.width(),0); | |
|
597 | ||
|
598 | mScrollButtonLeft->setPolygon(left); | |
|
599 | mScrollButtonRight->setPolygon(right); | |
|
600 | mScrollButtonUp->setPolygon(up); | |
|
601 | mScrollButtonDown->setPolygon(down); | |
|
602 | } | |
|
603 | ||
|
604 | QSizeF QLegend::maximumMarkerSize() | |
|
605 | { | |
|
606 | QSizeF max(0,0); | |
|
607 | foreach (LegendMarker* m, mMarkers) { | |
|
608 | if (m->boundingRect().width() > max.width()) { | |
|
609 | max.setWidth(m->boundingRect().width()); | |
|
610 | } | |
|
611 | if (m->boundingRect().height() > max.height()) { | |
|
612 | max.setHeight(m->boundingRect().height()); | |
|
613 | } | |
|
614 | } | |
|
615 | return max; | |
|
616 | } | |
|
617 | ||
|
618 | void QLegend::checkMarkerBounds() | |
|
619 | { | |
|
620 | if ((mPreferredLayout == QLegend::PreferredLayoutLeft) || (mPreferredLayout == QLegend::PreferredLayoutRight)) { | |
|
621 | // Bounds limited by height | |
|
622 | int max; | |
|
623 | if (scrollButtonsVisible()) { | |
|
624 | max = (mMaximumSize.height() - mScrollButtonLeft->boundingRect().height() * 2 - mMargin*2) / maximumMarkerSize().height(); | |
|
625 | } else { | |
|
626 | max = mMaximumSize.height() / maximumMarkerSize().height(); | |
|
627 | } | |
|
628 | ||
|
629 | if (mFirstMarker > mMarkers.count() - max) { | |
|
630 | mFirstMarker = mMarkers.count() - max; | |
|
631 | } | |
|
632 | } else { | |
|
633 | // Bounds limited by width | |
|
634 | int max; | |
|
635 | if (scrollButtonsVisible()) { | |
|
636 | max = (mMaximumSize.width() - mScrollButtonLeft->boundingRect().width() * 2 - mMargin*2) / maximumMarkerSize().width(); | |
|
637 | } else { | |
|
638 | max = mMaximumSize.width() / maximumMarkerSize().width(); | |
|
639 | } | |
|
640 | ||
|
641 | if (mFirstMarker > mMarkers.count() - max) { | |
|
642 | mFirstMarker = mMarkers.count() - max; | |
|
643 | } | |
|
644 | } | |
|
645 | ||
|
646 | if (mFirstMarker < 0) { | |
|
647 | mFirstMarker = 0; | |
|
648 | } | |
|
649 | } | |
|
650 | ||
|
651 | bool QLegend::scrollButtonsVisible() | |
|
652 | { | |
|
653 | // Just a helper to clarify, what the magic below means :) | |
|
654 | if ((mPreferredLayout == QLegend::PreferredLayoutTop) || (mPreferredLayout == QLegend::PreferredLayoutBottom)) { | |
|
655 | return (maximumMarkerSize().width() * mMarkers.count() + mMargin * 3 > mMaximumSize.width()); | |
|
656 | } | |
|
657 | return (maximumMarkerSize().height() * mMarkers.count() + mMargin * 3 > mMaximumSize.height()); | |
|
488 | 658 | } |
|
489 | 659 | |
|
490 | 660 | #include "moc_qlegend.cpp" |
@@ -14,6 +14,7 class QXYSeries; | |||
|
14 | 14 | class QBarSet; |
|
15 | 15 | class QBarSeries; |
|
16 | 16 | class QPieSeries; |
|
17 | class LegendScrollButton; | |
|
17 | 18 | |
|
18 | 19 | class QTCOMMERCIALCHART_EXPORT QLegend : public QGraphicsObject |
|
19 | 20 | { |
@@ -21,8 +22,10 class QTCOMMERCIALCHART_EXPORT QLegend : public QGraphicsObject | |||
|
21 | 22 | public: |
|
22 | 23 | |
|
23 | 24 | enum PreferredLayout { |
|
24 |
PreferredLayout |
|
|
25 |
PreferredLayout |
|
|
25 | PreferredLayoutTop, | |
|
26 | PreferredLayoutBottom, | |
|
27 | PreferredLayoutLeft, | |
|
28 | PreferredLayoutRight, | |
|
26 | 29 | }; |
|
27 | 30 | |
|
28 | 31 | explicit QLegend(QGraphicsItem *parent = 0); |
@@ -37,6 +40,7 public: | |||
|
37 | 40 | QPen pen() const; |
|
38 | 41 | |
|
39 | 42 | void setPreferredLayout(QLegend::PreferredLayout preferred); |
|
43 | QLegend::PreferredLayout preferredLayout() const; | |
|
40 | 44 | |
|
41 | 45 | QSizeF maximumSize() const; |
|
42 | 46 | void setMaximumSize(const QSizeF size); |
@@ -56,6 +60,7 public slots: | |||
|
56 | 60 | void handleAdded(QList<QPieSlice*> slices); |
|
57 | 61 | void handleRemoved(QList<QPieSlice*> slices); |
|
58 | 62 | void handleMarkerDestroyed(); |
|
63 | void handleScrollButtonClicked(QGraphicsSceneMouseEvent* event); | |
|
59 | 64 | |
|
60 | 65 | private: |
|
61 | 66 | // PIMPL ---> |
@@ -66,8 +71,13 private: | |||
|
66 | 71 | void appendMarkers(QBarSeries* series); |
|
67 | 72 | void appendMarkers(QPieSeries* series); |
|
68 | 73 | void deleteMarkers(QSeries* series); |
|
69 | void layoutChanged(); | |
|
70 | // <--- PIMPL | |
|
74 | // void layoutChanged(); // This tries to fit all items to legend | |
|
75 | void updateLayout(); // New version of layout. Fits items only to row or column and adds scrollbars. | |
|
76 | void rescaleScrollButtons(const QSize& size); | |
|
77 | QSizeF maximumMarkerSize(); | |
|
78 | void checkMarkerBounds(); | |
|
79 | bool scrollButtonsVisible(); | |
|
80 | // void updateScrollButtonsLayout(); | |
|
71 | 81 | |
|
72 | 82 | QPointF mPos; |
|
73 | 83 | QSizeF mSize; |
@@ -79,6 +89,16 private: | |||
|
79 | 89 | QBrush m_brush; |
|
80 | 90 | QPen m_pen; |
|
81 | 91 | QLegend::PreferredLayout mPreferredLayout; |
|
92 | ||
|
93 | int mFirstMarker; | |
|
94 | ||
|
95 | LegendScrollButton* mScrollButtonLeft; | |
|
96 | LegendScrollButton* mScrollButtonRight; | |
|
97 | LegendScrollButton* mScrollButtonUp; | |
|
98 | LegendScrollButton* mScrollButtonDown; | |
|
99 | ||
|
100 | qreal mMargin; | |
|
101 | // <--- PIMPL | |
|
82 | 102 | }; |
|
83 | 103 | |
|
84 | 104 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -17,6 +17,7 SOURCES += \ | |||
|
17 | 17 | $$PWD/qseries.cpp \ |
|
18 | 18 | $$PWD/qlegend.cpp \ |
|
19 | 19 | $$PWD/legendmarker.cpp \ |
|
20 | $$PWD/legendscrollbutton.cpp \ | |
|
20 | 21 | $$PWD/chartbackground.cpp \ |
|
21 | 22 | $$PWD/chart.cpp |
|
22 | 23 | PRIVATE_HEADERS += \ |
@@ -26,6 +27,7 PRIVATE_HEADERS += \ | |||
|
26 | 27 | $$PWD/charttheme_p.h \ |
|
27 | 28 | $$PWD/domain_p.h \ |
|
28 | 29 | $$PWD/legendmarker_p.h \ |
|
30 | $$PWD/legendscrollbutton_p.h \ | |
|
29 | 31 | $$PWD/chartbackground_p.h \ |
|
30 | 32 | $$PWD/chart_p.h |
|
31 | 33 | PUBLIC_HEADERS += \ |
General Comments 0
You need to be logged in to leave comments.
Login now