summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTitta Heikkala <titta.heikkala@digia.com>2013-09-26 12:28:22 +0300
committerTitta Heikkala <titta.heikkala@digia.com>2013-09-27 08:49:53 +0300
commit57e2d8f758e8315cec06c3ff9194b77456503f0f (patch)
tree8ea5ccf6d1f98de8bf04707b40bbc7b14dd3a3d4 /src
parent2b1fa3a15eecbd6f05763966bd679dfe275b3175 (diff)
Fix legend truncation
Legend marker items that are on a legend which is positioned on the top or on the bottom of a chart are truncated to fit the space available. The truncation starts at the longest legend marker item. Task-number: QTRD-2092 Change-Id: I22581b4447591fda11adab3873553cd5ee3dc001 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/legend/legendlayout.cpp88
-rw-r--r--src/legend/legendlayout_p.h8
2 files changed, 94 insertions, 2 deletions
diff --git a/src/legend/legendlayout.cpp b/src/legend/legendlayout.cpp
index fb43b325..c76cda52 100644
--- a/src/legend/legendlayout.cpp
+++ b/src/legend/legendlayout.cpp
@@ -136,19 +136,97 @@ void LegendLayout::setAttachedGeometry(const QRectF &rect)
switch(m_legend->alignment()) {
case Qt::AlignTop:
case Qt::AlignBottom: {
+ // Calculate the space required for items and add them to a sorted list.
+ qreal markerItemsWidth = 0;
+ qreal itemMargins = 0;
+ QList<LegendWidthStruct *> legendWidthList;
+ foreach (QLegendMarker *marker, m_legend->d_ptr->markers()) {
+ LegendMarkerItem *item = marker->d_ptr->item();
+ if (item->isVisible()) {
+ QSizeF dummySize;
+ qreal itemWidth = item->sizeHint(Qt::PreferredSize, dummySize).width();
+ LegendWidthStruct *structItem = new LegendWidthStruct;
+ structItem->item = item;
+ structItem->width = itemWidth;
+ legendWidthList.append(structItem);
+ markerItemsWidth += itemWidth;
+ itemMargins += marker->d_ptr->item()->m_margin;
+ }
+ }
+ qSort(legendWidthList.begin(), legendWidthList.end(), widthLongerThan);
+
+ // If the items would occupy more space than is available, start truncating them
+ // from the longest one.
+ qreal availableGeometry = geometry.width() - right - left * 2 - itemMargins;
+ if (markerItemsWidth >= availableGeometry && legendWidthList.count() > 1) {
+ bool truncated(false);
+ int count = legendWidthList.count();
+ for (int i = 1; i < count; i++) {
+ int truncateIndex = i - 1;
+
+ while (legendWidthList.at(truncateIndex)->width >= legendWidthList.at(i)->width
+ && !truncated) {
+ legendWidthList.at(truncateIndex)->width--;
+ markerItemsWidth--;
+ if (i > 1) {
+ // Truncate the items that are before the truncated one in the list.
+ for (int j = truncateIndex - 1; j >= 0; j--) {
+ if (legendWidthList.at(truncateIndex)->width
+ < legendWidthList.at(j)->width) {
+ legendWidthList.at(j)->width--;
+ markerItemsWidth--;
+ }
+ }
+ }
+ if (markerItemsWidth < availableGeometry)
+ truncated = true;
+ }
+ // Truncate the last item if needed.
+ if (i == count - 1) {
+ if (legendWidthList.at(count - 1)->width
+ > legendWidthList.at(truncateIndex)->width) {
+ legendWidthList.at(count - 1)->width--;
+ markerItemsWidth--;
+ }
+ }
+
+ if (truncated)
+ break;
+ }
+ // Items are of same width and all of them need to be truncated.
+ while (markerItemsWidth >= availableGeometry) {
+ for (int i = 0; i < count; i++) {
+ legendWidthList.at(i)->width--;
+ markerItemsWidth--;
+ }
+ }
+ }
+
QPointF point(0,0);
foreach (QLegendMarker *marker, m_legend->d_ptr->markers()) {
LegendMarkerItem *item = marker->d_ptr->item();
if (item->isVisible()) {
- item->setGeometry(geometry);
+ QRectF itemRect = geometry;
+ qreal availableWidth = 0;
+ for (int i = 0; i < legendWidthList.size(); ++i) {
+ if (legendWidthList.at(i)->item == item) {
+ availableWidth = legendWidthList.at(i)->width;
+ break;
+ }
+ }
+ itemRect.setWidth(availableWidth);
+ item->setGeometry(itemRect);
item->setPos(point.x(),geometry.height()/2 - item->boundingRect().height()/2);
const QRectF &rect = item->boundingRect();
size = size.expandedTo(rect.size());
qreal w = rect.width();
- m_width+=w;
+ m_width = m_width + w - item->m_margin;
point.setX(point.x() + w);
}
}
+ // Delete structs from the container
+ qDeleteAll(legendWidthList);
+
if (m_width < geometry.width())
m_legend->d_ptr->items()->setPos(geometry.width() / 2 - m_width / 2, geometry.top());
else
@@ -405,4 +483,10 @@ QSizeF LegendLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) cons
return size;
}
+bool LegendLayout::widthLongerThan(const LegendWidthStruct *item1,
+ const LegendWidthStruct *item2)
+{
+ return item1->width > item2->width;
+}
+
QTCOMMERCIALCHART_END_NAMESPACE
diff --git a/src/legend/legendlayout_p.h b/src/legend/legendlayout_p.h
index 8b971ae0..14cb2582 100644
--- a/src/legend/legendlayout_p.h
+++ b/src/legend/legendlayout_p.h
@@ -35,6 +35,7 @@
QTCOMMERCIALCHART_BEGIN_NAMESPACE
class QLegend;
+class LegendMarkerItem;
class LegendLayout : public QGraphicsLayout
{
@@ -59,6 +60,13 @@ private:
void setAttachedGeometry(const QRectF &rect);
void setDettachedGeometry(const QRectF &rect);
+ struct LegendWidthStruct {
+ LegendMarkerItem *item;
+ qreal width;
+ };
+ static bool widthLongerThan(const LegendWidthStruct *item1,
+ const LegendWidthStruct *item2);
+
private:
QLegend *m_legend;
qreal m_offsetX;