##// END OF EJS Templates
Fix legend truncation...
Titta Heikkala -
r2617:57e2d8f758e8
parent child
Show More
@@ -1,408 +1,492
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Enterprise Charts Add-on.
7 ** This file is part of the Qt Enterprise Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
11 ** accordance with the Qt Enterprise License Agreement provided with the
11 ** accordance with the Qt Enterprise License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "legendlayout_p.h"
21 #include "legendlayout_p.h"
22 #include "chartpresenter_p.h"
22 #include "chartpresenter_p.h"
23 #include "qlegend_p.h"
23 #include "qlegend_p.h"
24 #include "abstractchartlayout_p.h"
24 #include "abstractchartlayout_p.h"
25
25
26 #include "qlegendmarker_p.h"
26 #include "qlegendmarker_p.h"
27 #include "legendmarkeritem_p.h"
27 #include "legendmarkeritem_p.h"
28 #include "qlegendmarker.h"
28 #include "qlegendmarker.h"
29
29
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
31
32 LegendLayout::LegendLayout(QLegend *legend)
32 LegendLayout::LegendLayout(QLegend *legend)
33 : m_legend(legend),
33 : m_legend(legend),
34 m_offsetX(0),
34 m_offsetX(0),
35 m_offsetY(0)
35 m_offsetY(0)
36 {
36 {
37
37
38 }
38 }
39
39
40 LegendLayout::~LegendLayout()
40 LegendLayout::~LegendLayout()
41 {
41 {
42
42
43 }
43 }
44
44
45 void LegendLayout::setOffset(qreal x, qreal y)
45 void LegendLayout::setOffset(qreal x, qreal y)
46 {
46 {
47 bool scrollHorizontal = true;
47 bool scrollHorizontal = true;
48 switch (m_legend->alignment()) {
48 switch (m_legend->alignment()) {
49 case Qt::AlignTop:
49 case Qt::AlignTop:
50 case Qt::AlignBottom:
50 case Qt::AlignBottom:
51 scrollHorizontal = true;
51 scrollHorizontal = true;
52 break;
52 break;
53 case Qt::AlignLeft:
53 case Qt::AlignLeft:
54 case Qt::AlignRight:
54 case Qt::AlignRight:
55 scrollHorizontal = false;
55 scrollHorizontal = false;
56 break;
56 break;
57 }
57 }
58
58
59 // If detached, the scrolling direction is vertical instead of horizontal and vice versa.
59 // If detached, the scrolling direction is vertical instead of horizontal and vice versa.
60 if (!m_legend->isAttachedToChart())
60 if (!m_legend->isAttachedToChart())
61 scrollHorizontal = !scrollHorizontal;
61 scrollHorizontal = !scrollHorizontal;
62
62
63 QRectF boundingRect = geometry();
63 QRectF boundingRect = geometry();
64 qreal left, top, right, bottom;
64 qreal left, top, right, bottom;
65 getContentsMargins(&left, &top, &right, &bottom);
65 getContentsMargins(&left, &top, &right, &bottom);
66 boundingRect.adjust(left, top, -right, -bottom);
66 boundingRect.adjust(left, top, -right, -bottom);
67
67
68 // Limit offset between m_minOffset and m_maxOffset
68 // Limit offset between m_minOffset and m_maxOffset
69 if (scrollHorizontal) {
69 if (scrollHorizontal) {
70 if (m_width <= boundingRect.width())
70 if (m_width <= boundingRect.width())
71 return;
71 return;
72
72
73 if (x != m_offsetX) {
73 if (x != m_offsetX) {
74 m_offsetX = qBound(m_minOffsetX, x, m_maxOffsetX);
74 m_offsetX = qBound(m_minOffsetX, x, m_maxOffsetX);
75 m_legend->d_ptr->items()->setPos(-m_offsetX, boundingRect.top());
75 m_legend->d_ptr->items()->setPos(-m_offsetX, boundingRect.top());
76 }
76 }
77 } else {
77 } else {
78 if (m_height <= boundingRect.height())
78 if (m_height <= boundingRect.height())
79 return;
79 return;
80
80
81 if (y != m_offsetY) {
81 if (y != m_offsetY) {
82 m_offsetY = qBound(m_minOffsetY, y, m_maxOffsetY);
82 m_offsetY = qBound(m_minOffsetY, y, m_maxOffsetY);
83 m_legend->d_ptr->items()->setPos(boundingRect.left(), -m_offsetY);
83 m_legend->d_ptr->items()->setPos(boundingRect.left(), -m_offsetY);
84 }
84 }
85 }
85 }
86 }
86 }
87
87
88 QPointF LegendLayout::offset() const
88 QPointF LegendLayout::offset() const
89 {
89 {
90 return QPointF(m_offsetX, m_offsetY);
90 return QPointF(m_offsetX, m_offsetY);
91 }
91 }
92
92
93 void LegendLayout::invalidate()
93 void LegendLayout::invalidate()
94 {
94 {
95 QGraphicsLayout::invalidate();
95 QGraphicsLayout::invalidate();
96 if (m_legend->isAttachedToChart())
96 if (m_legend->isAttachedToChart())
97 m_legend->d_ptr->m_presenter->layout()->invalidate();
97 m_legend->d_ptr->m_presenter->layout()->invalidate();
98 }
98 }
99
99
100 void LegendLayout::setGeometry(const QRectF &rect)
100 void LegendLayout::setGeometry(const QRectF &rect)
101 {
101 {
102 m_legend->d_ptr->items()->setVisible(m_legend->isVisible());
102 m_legend->d_ptr->items()->setVisible(m_legend->isVisible());
103
103
104 QGraphicsLayout::setGeometry(rect);
104 QGraphicsLayout::setGeometry(rect);
105
105
106 if (m_legend->isAttachedToChart())
106 if (m_legend->isAttachedToChart())
107 setAttachedGeometry(rect);
107 setAttachedGeometry(rect);
108 else
108 else
109 setDettachedGeometry(rect);
109 setDettachedGeometry(rect);
110 }
110 }
111
111
112 void LegendLayout::setAttachedGeometry(const QRectF &rect)
112 void LegendLayout::setAttachedGeometry(const QRectF &rect)
113 {
113 {
114 if (!rect.isValid())
114 if (!rect.isValid())
115 return;
115 return;
116
116
117 qreal oldOffsetX = m_offsetX;
117 qreal oldOffsetX = m_offsetX;
118 qreal oldOffsetY = m_offsetY;
118 qreal oldOffsetY = m_offsetY;
119 m_offsetX = 0;
119 m_offsetX = 0;
120 m_offsetY = 0;
120 m_offsetY = 0;
121
121
122 QSizeF size(0, 0);
122 QSizeF size(0, 0);
123
123
124 if (m_legend->d_ptr->markers().isEmpty()) {
124 if (m_legend->d_ptr->markers().isEmpty()) {
125 return;
125 return;
126 }
126 }
127
127
128 m_width = 0;
128 m_width = 0;
129 m_height = 0;
129 m_height = 0;
130
130
131 qreal left, top, right, bottom;
131 qreal left, top, right, bottom;
132 getContentsMargins(&left, &top, &right, &bottom);
132 getContentsMargins(&left, &top, &right, &bottom);
133
133
134 QRectF geometry = rect.adjusted(left, top, -right, -bottom);
134 QRectF geometry = rect.adjusted(left, top, -right, -bottom);
135
135
136 switch(m_legend->alignment()) {
136 switch(m_legend->alignment()) {
137 case Qt::AlignTop:
137 case Qt::AlignTop:
138 case Qt::AlignBottom: {
138 case Qt::AlignBottom: {
139 // Calculate the space required for items and add them to a sorted list.
140 qreal markerItemsWidth = 0;
141 qreal itemMargins = 0;
142 QList<LegendWidthStruct *> legendWidthList;
143 foreach (QLegendMarker *marker, m_legend->d_ptr->markers()) {
144 LegendMarkerItem *item = marker->d_ptr->item();
145 if (item->isVisible()) {
146 QSizeF dummySize;
147 qreal itemWidth = item->sizeHint(Qt::PreferredSize, dummySize).width();
148 LegendWidthStruct *structItem = new LegendWidthStruct;
149 structItem->item = item;
150 structItem->width = itemWidth;
151 legendWidthList.append(structItem);
152 markerItemsWidth += itemWidth;
153 itemMargins += marker->d_ptr->item()->m_margin;
154 }
155 }
156 qSort(legendWidthList.begin(), legendWidthList.end(), widthLongerThan);
157
158 // If the items would occupy more space than is available, start truncating them
159 // from the longest one.
160 qreal availableGeometry = geometry.width() - right - left * 2 - itemMargins;
161 if (markerItemsWidth >= availableGeometry && legendWidthList.count() > 1) {
162 bool truncated(false);
163 int count = legendWidthList.count();
164 for (int i = 1; i < count; i++) {
165 int truncateIndex = i - 1;
166
167 while (legendWidthList.at(truncateIndex)->width >= legendWidthList.at(i)->width
168 && !truncated) {
169 legendWidthList.at(truncateIndex)->width--;
170 markerItemsWidth--;
171 if (i > 1) {
172 // Truncate the items that are before the truncated one in the list.
173 for (int j = truncateIndex - 1; j >= 0; j--) {
174 if (legendWidthList.at(truncateIndex)->width
175 < legendWidthList.at(j)->width) {
176 legendWidthList.at(j)->width--;
177 markerItemsWidth--;
178 }
179 }
180 }
181 if (markerItemsWidth < availableGeometry)
182 truncated = true;
183 }
184 // Truncate the last item if needed.
185 if (i == count - 1) {
186 if (legendWidthList.at(count - 1)->width
187 > legendWidthList.at(truncateIndex)->width) {
188 legendWidthList.at(count - 1)->width--;
189 markerItemsWidth--;
190 }
191 }
192
193 if (truncated)
194 break;
195 }
196 // Items are of same width and all of them need to be truncated.
197 while (markerItemsWidth >= availableGeometry) {
198 for (int i = 0; i < count; i++) {
199 legendWidthList.at(i)->width--;
200 markerItemsWidth--;
201 }
202 }
203 }
204
139 QPointF point(0,0);
205 QPointF point(0,0);
140 foreach (QLegendMarker *marker, m_legend->d_ptr->markers()) {
206 foreach (QLegendMarker *marker, m_legend->d_ptr->markers()) {
141 LegendMarkerItem *item = marker->d_ptr->item();
207 LegendMarkerItem *item = marker->d_ptr->item();
142 if (item->isVisible()) {
208 if (item->isVisible()) {
143 item->setGeometry(geometry);
209 QRectF itemRect = geometry;
210 qreal availableWidth = 0;
211 for (int i = 0; i < legendWidthList.size(); ++i) {
212 if (legendWidthList.at(i)->item == item) {
213 availableWidth = legendWidthList.at(i)->width;
214 break;
215 }
216 }
217 itemRect.setWidth(availableWidth);
218 item->setGeometry(itemRect);
144 item->setPos(point.x(),geometry.height()/2 - item->boundingRect().height()/2);
219 item->setPos(point.x(),geometry.height()/2 - item->boundingRect().height()/2);
145 const QRectF &rect = item->boundingRect();
220 const QRectF &rect = item->boundingRect();
146 size = size.expandedTo(rect.size());
221 size = size.expandedTo(rect.size());
147 qreal w = rect.width();
222 qreal w = rect.width();
148 m_width+=w;
223 m_width = m_width + w - item->m_margin;
149 point.setX(point.x() + w);
224 point.setX(point.x() + w);
150 }
225 }
151 }
226 }
227 // Delete structs from the container
228 qDeleteAll(legendWidthList);
229
152 if (m_width < geometry.width())
230 if (m_width < geometry.width())
153 m_legend->d_ptr->items()->setPos(geometry.width() / 2 - m_width / 2, geometry.top());
231 m_legend->d_ptr->items()->setPos(geometry.width() / 2 - m_width / 2, geometry.top());
154 else
232 else
155 m_legend->d_ptr->items()->setPos(geometry.topLeft());
233 m_legend->d_ptr->items()->setPos(geometry.topLeft());
156 m_height = size.height();
234 m_height = size.height();
157 }
235 }
158 break;
236 break;
159 case Qt::AlignLeft:
237 case Qt::AlignLeft:
160 case Qt::AlignRight: {
238 case Qt::AlignRight: {
161 QPointF point(0,0);
239 QPointF point(0,0);
162 foreach (QLegendMarker *marker, m_legend->d_ptr->markers()) {
240 foreach (QLegendMarker *marker, m_legend->d_ptr->markers()) {
163 LegendMarkerItem *item = marker->d_ptr->item();
241 LegendMarkerItem *item = marker->d_ptr->item();
164 if (item->isVisible()) {
242 if (item->isVisible()) {
165 item->setGeometry(geometry);
243 item->setGeometry(geometry);
166 item->setPos(point);
244 item->setPos(point);
167 const QRectF &rect = item->boundingRect();
245 const QRectF &rect = item->boundingRect();
168 qreal h = rect.height();
246 qreal h = rect.height();
169 size = size.expandedTo(rect.size());
247 size = size.expandedTo(rect.size());
170 m_height+=h;
248 m_height+=h;
171 point.setY(point.y() + h);
249 point.setY(point.y() + h);
172 }
250 }
173 }
251 }
174
252
175 if (m_height < geometry.height())
253 if (m_height < geometry.height())
176 m_legend->d_ptr->items()->setPos(geometry.left(), geometry.height() / 2 - m_height / 2);
254 m_legend->d_ptr->items()->setPos(geometry.left(), geometry.height() / 2 - m_height / 2);
177 else
255 else
178 m_legend->d_ptr->items()->setPos(geometry.topLeft());
256 m_legend->d_ptr->items()->setPos(geometry.topLeft());
179 m_width = size.width();
257 m_width = size.width();
180 break;
258 break;
181 }
259 }
182 }
260 }
183
261
184 m_minOffsetX = -left;
262 m_minOffsetX = -left;
185 m_minOffsetY = - top;
263 m_minOffsetY = - top;
186 m_maxOffsetX = m_width - geometry.width() - right;
264 m_maxOffsetX = m_width - geometry.width() - right;
187 m_maxOffsetY = m_height - geometry.height() - bottom;
265 m_maxOffsetY = m_height - geometry.height() - bottom;
188
266
189 setOffset(oldOffsetX, oldOffsetY);
267 setOffset(oldOffsetX, oldOffsetY);
190 }
268 }
191
269
192 void LegendLayout::setDettachedGeometry(const QRectF &rect)
270 void LegendLayout::setDettachedGeometry(const QRectF &rect)
193 {
271 {
194 if (!rect.isValid())
272 if (!rect.isValid())
195 return;
273 return;
196
274
197 // Detached layout is different.
275 // Detached layout is different.
198 // In detached mode legend may have multiple rows and columns, so layout calculations
276 // In detached mode legend may have multiple rows and columns, so layout calculations
199 // differ a log from attached mode.
277 // differ a log from attached mode.
200 // Also the scrolling logic is bit different.
278 // Also the scrolling logic is bit different.
201
279
202 qreal oldOffsetX = m_offsetX;
280 qreal oldOffsetX = m_offsetX;
203 qreal oldOffsetY = m_offsetY;
281 qreal oldOffsetY = m_offsetY;
204 m_offsetX = 0;
282 m_offsetX = 0;
205 m_offsetY = 0;
283 m_offsetY = 0;
206
284
207 qreal left, top, right, bottom;
285 qreal left, top, right, bottom;
208 getContentsMargins(&left, &top, &right, &bottom);
286 getContentsMargins(&left, &top, &right, &bottom);
209 QRectF geometry = rect.adjusted(left, top, -right, -bottom);
287 QRectF geometry = rect.adjusted(left, top, -right, -bottom);
210
288
211 QSizeF size(0, 0);
289 QSizeF size(0, 0);
212
290
213 QList<QLegendMarker *> markers = m_legend->d_ptr->markers();
291 QList<QLegendMarker *> markers = m_legend->d_ptr->markers();
214
292
215 if (markers.isEmpty())
293 if (markers.isEmpty())
216 return;
294 return;
217
295
218 switch (m_legend->alignment()) {
296 switch (m_legend->alignment()) {
219 case Qt::AlignTop: {
297 case Qt::AlignTop: {
220 QPointF point(0, 0);
298 QPointF point(0, 0);
221 m_width = 0;
299 m_width = 0;
222 m_height = 0;
300 m_height = 0;
223 for (int i = 0; i < markers.count(); i++) {
301 for (int i = 0; i < markers.count(); i++) {
224 LegendMarkerItem *item = markers.at(i)->d_ptr->item();
302 LegendMarkerItem *item = markers.at(i)->d_ptr->item();
225 if (item->isVisible()) {
303 if (item->isVisible()) {
226 item->setGeometry(geometry);
304 item->setGeometry(geometry);
227 item->setPos(point.x(),point.y());
305 item->setPos(point.x(),point.y());
228 const QRectF &boundingRect = item->boundingRect();
306 const QRectF &boundingRect = item->boundingRect();
229 qreal w = boundingRect.width();
307 qreal w = boundingRect.width();
230 qreal h = boundingRect.height();
308 qreal h = boundingRect.height();
231 m_width = qMax(m_width,w);
309 m_width = qMax(m_width,w);
232 m_height = qMax(m_height,h);
310 m_height = qMax(m_height,h);
233 point.setX(point.x() + w);
311 point.setX(point.x() + w);
234 if (point.x() + w > geometry.left() + geometry.width() - right) {
312 if (point.x() + w > geometry.left() + geometry.width() - right) {
235 // Next item would go off rect.
313 // Next item would go off rect.
236 point.setX(0);
314 point.setX(0);
237 point.setY(point.y() + h);
315 point.setY(point.y() + h);
238 if (i+1 < markers.count()) {
316 if (i+1 < markers.count()) {
239 m_height += h;
317 m_height += h;
240 }
318 }
241 }
319 }
242 }
320 }
243 }
321 }
244 m_legend->d_ptr->items()->setPos(geometry.topLeft());
322 m_legend->d_ptr->items()->setPos(geometry.topLeft());
245
323
246 m_minOffsetX = -left;
324 m_minOffsetX = -left;
247 m_minOffsetY = -top;
325 m_minOffsetY = -top;
248 m_maxOffsetX = m_width - geometry.width() - right;
326 m_maxOffsetX = m_width - geometry.width() - right;
249 m_maxOffsetY = m_height - geometry.height() - bottom;
327 m_maxOffsetY = m_height - geometry.height() - bottom;
250 }
328 }
251 break;
329 break;
252 case Qt::AlignBottom: {
330 case Qt::AlignBottom: {
253 QPointF point(0, geometry.height());
331 QPointF point(0, geometry.height());
254 m_width = 0;
332 m_width = 0;
255 m_height = 0;
333 m_height = 0;
256 for (int i = 0; i < markers.count(); i++) {
334 for (int i = 0; i < markers.count(); i++) {
257 LegendMarkerItem *item = markers.at(i)->d_ptr->item();
335 LegendMarkerItem *item = markers.at(i)->d_ptr->item();
258 if (item->isVisible()) {
336 if (item->isVisible()) {
259 item->setGeometry(geometry);
337 item->setGeometry(geometry);
260 const QRectF &boundingRect = item->boundingRect();
338 const QRectF &boundingRect = item->boundingRect();
261 qreal w = boundingRect.width();
339 qreal w = boundingRect.width();
262 qreal h = boundingRect.height();
340 qreal h = boundingRect.height();
263 m_width = qMax(m_width,w);
341 m_width = qMax(m_width,w);
264 m_height = qMax(m_height,h);
342 m_height = qMax(m_height,h);
265 item->setPos(point.x(),point.y() - h);
343 item->setPos(point.x(),point.y() - h);
266 point.setX(point.x() + w);
344 point.setX(point.x() + w);
267 if (point.x() + w > geometry.left() + geometry.width() - right) {
345 if (point.x() + w > geometry.left() + geometry.width() - right) {
268 // Next item would go off rect.
346 // Next item would go off rect.
269 point.setX(0);
347 point.setX(0);
270 point.setY(point.y() - h);
348 point.setY(point.y() - h);
271 if (i+1 < markers.count()) {
349 if (i+1 < markers.count()) {
272 m_height += h;
350 m_height += h;
273 }
351 }
274 }
352 }
275 }
353 }
276 }
354 }
277 m_legend->d_ptr->items()->setPos(geometry.topLeft());
355 m_legend->d_ptr->items()->setPos(geometry.topLeft());
278
356
279 m_minOffsetX = -left;
357 m_minOffsetX = -left;
280 m_minOffsetY = -m_height + geometry.height() - top;
358 m_minOffsetY = -m_height + geometry.height() - top;
281 m_maxOffsetX = m_width - geometry.width() - right;
359 m_maxOffsetX = m_width - geometry.width() - right;
282 m_maxOffsetY = -bottom;
360 m_maxOffsetY = -bottom;
283 }
361 }
284 break;
362 break;
285 case Qt::AlignLeft: {
363 case Qt::AlignLeft: {
286 QPointF point(0, 0);
364 QPointF point(0, 0);
287 m_width = 0;
365 m_width = 0;
288 m_height = 0;
366 m_height = 0;
289 qreal maxWidth = 0;
367 qreal maxWidth = 0;
290 for (int i = 0; i < markers.count(); i++) {
368 for (int i = 0; i < markers.count(); i++) {
291 LegendMarkerItem *item = markers.at(i)->d_ptr->item();
369 LegendMarkerItem *item = markers.at(i)->d_ptr->item();
292 if (item->isVisible()) {
370 if (item->isVisible()) {
293 item->setGeometry(geometry);
371 item->setGeometry(geometry);
294 const QRectF &boundingRect = item->boundingRect();
372 const QRectF &boundingRect = item->boundingRect();
295 qreal w = boundingRect.width();
373 qreal w = boundingRect.width();
296 qreal h = boundingRect.height();
374 qreal h = boundingRect.height();
297 m_height = qMax(m_height,h);
375 m_height = qMax(m_height,h);
298 maxWidth = qMax(maxWidth,w);
376 maxWidth = qMax(maxWidth,w);
299 item->setPos(point.x(),point.y());
377 item->setPos(point.x(),point.y());
300 point.setY(point.y() + h);
378 point.setY(point.y() + h);
301 if (point.y() + h > geometry.bottom() - bottom) {
379 if (point.y() + h > geometry.bottom() - bottom) {
302 // Next item would go off rect.
380 // Next item would go off rect.
303 point.setX(point.x() + maxWidth);
381 point.setX(point.x() + maxWidth);
304 point.setY(0);
382 point.setY(0);
305 if (i+1 < markers.count()) {
383 if (i+1 < markers.count()) {
306 m_width += maxWidth;
384 m_width += maxWidth;
307 maxWidth = 0;
385 maxWidth = 0;
308 }
386 }
309 }
387 }
310 }
388 }
311 }
389 }
312 m_width += maxWidth;
390 m_width += maxWidth;
313 m_legend->d_ptr->items()->setPos(geometry.topLeft());
391 m_legend->d_ptr->items()->setPos(geometry.topLeft());
314
392
315 m_minOffsetX = -left;
393 m_minOffsetX = -left;
316 m_minOffsetY = -top;
394 m_minOffsetY = -top;
317 m_maxOffsetX = m_width - geometry.width() - right;
395 m_maxOffsetX = m_width - geometry.width() - right;
318 m_maxOffsetY = m_height - geometry.height() - bottom;
396 m_maxOffsetY = m_height - geometry.height() - bottom;
319 }
397 }
320 break;
398 break;
321 case Qt::AlignRight: {
399 case Qt::AlignRight: {
322 QPointF point(geometry.width(), 0);
400 QPointF point(geometry.width(), 0);
323 m_width = 0;
401 m_width = 0;
324 m_height = 0;
402 m_height = 0;
325 qreal maxWidth = 0;
403 qreal maxWidth = 0;
326 for (int i = 0; i < markers.count(); i++) {
404 for (int i = 0; i < markers.count(); i++) {
327 LegendMarkerItem *item = markers.at(i)->d_ptr->item();
405 LegendMarkerItem *item = markers.at(i)->d_ptr->item();
328 if (item->isVisible()) {
406 if (item->isVisible()) {
329 item->setGeometry(geometry);
407 item->setGeometry(geometry);
330 const QRectF &boundingRect = item->boundingRect();
408 const QRectF &boundingRect = item->boundingRect();
331 qreal w = boundingRect.width();
409 qreal w = boundingRect.width();
332 qreal h = boundingRect.height();
410 qreal h = boundingRect.height();
333 m_height = qMax(m_height,h);
411 m_height = qMax(m_height,h);
334 maxWidth = qMax(maxWidth,w);
412 maxWidth = qMax(maxWidth,w);
335 item->setPos(point.x() - w,point.y());
413 item->setPos(point.x() - w,point.y());
336 point.setY(point.y() + h);
414 point.setY(point.y() + h);
337 if (point.y() + h > geometry.bottom()-bottom) {
415 if (point.y() + h > geometry.bottom()-bottom) {
338 // Next item would go off rect.
416 // Next item would go off rect.
339 point.setX(point.x() - maxWidth);
417 point.setX(point.x() - maxWidth);
340 point.setY(0);
418 point.setY(0);
341 if (i+1 < markers.count()) {
419 if (i+1 < markers.count()) {
342 m_width += maxWidth;
420 m_width += maxWidth;
343 maxWidth = 0;
421 maxWidth = 0;
344 }
422 }
345 }
423 }
346 }
424 }
347 }
425 }
348 m_width += maxWidth;
426 m_width += maxWidth;
349 m_legend->d_ptr->items()->setPos(geometry.topLeft());
427 m_legend->d_ptr->items()->setPos(geometry.topLeft());
350
428
351 m_minOffsetX = - m_width + geometry.width() - left;
429 m_minOffsetX = - m_width + geometry.width() - left;
352 m_minOffsetY = -top;
430 m_minOffsetY = -top;
353 m_maxOffsetX = - right;
431 m_maxOffsetX = - right;
354 m_maxOffsetY = m_height - geometry.height() - bottom;
432 m_maxOffsetY = m_height - geometry.height() - bottom;
355 }
433 }
356 break;
434 break;
357 default:
435 default:
358 break;
436 break;
359 }
437 }
360
438
361 setOffset(oldOffsetX, oldOffsetY);
439 setOffset(oldOffsetX, oldOffsetY);
362 }
440 }
363
441
364 QSizeF LegendLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
442 QSizeF LegendLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
365 {
443 {
366 QSizeF size(0, 0);
444 QSizeF size(0, 0);
367 qreal left, top, right, bottom;
445 qreal left, top, right, bottom;
368 getContentsMargins(&left, &top, &right, &bottom);
446 getContentsMargins(&left, &top, &right, &bottom);
369
447
370 if(constraint.isValid()) {
448 if(constraint.isValid()) {
371 foreach(QLegendMarker *marker, m_legend->d_ptr->markers()) {
449 foreach(QLegendMarker *marker, m_legend->d_ptr->markers()) {
372 LegendMarkerItem *item = marker->d_ptr->item();
450 LegendMarkerItem *item = marker->d_ptr->item();
373 size = size.expandedTo(item->effectiveSizeHint(which));
451 size = size.expandedTo(item->effectiveSizeHint(which));
374 }
452 }
375 size = size.boundedTo(constraint);
453 size = size.boundedTo(constraint);
376 }
454 }
377 else if (constraint.width() >= 0) {
455 else if (constraint.width() >= 0) {
378 qreal width = 0;
456 qreal width = 0;
379 qreal height = 0;
457 qreal height = 0;
380 foreach(QLegendMarker *marker, m_legend->d_ptr->markers()) {
458 foreach(QLegendMarker *marker, m_legend->d_ptr->markers()) {
381 LegendMarkerItem *item = marker->d_ptr->item();
459 LegendMarkerItem *item = marker->d_ptr->item();
382 width+=item->effectiveSizeHint(which).width();
460 width+=item->effectiveSizeHint(which).width();
383 height=qMax(height,item->effectiveSizeHint(which).height());
461 height=qMax(height,item->effectiveSizeHint(which).height());
384 }
462 }
385
463
386 size = QSizeF(qMin(constraint.width(),width), height);
464 size = QSizeF(qMin(constraint.width(),width), height);
387 }
465 }
388 else if (constraint.height() >= 0) {
466 else if (constraint.height() >= 0) {
389 qreal width = 0;
467 qreal width = 0;
390 qreal height = 0;
468 qreal height = 0;
391 foreach(QLegendMarker *marker, m_legend->d_ptr->markers()) {
469 foreach(QLegendMarker *marker, m_legend->d_ptr->markers()) {
392 LegendMarkerItem *item = marker->d_ptr->item();
470 LegendMarkerItem *item = marker->d_ptr->item();
393 width=qMax(width,item->effectiveSizeHint(which).width());
471 width=qMax(width,item->effectiveSizeHint(which).width());
394 height+=height,item->effectiveSizeHint(which).height();
472 height+=height,item->effectiveSizeHint(which).height();
395 }
473 }
396 size = QSizeF(width,qMin(constraint.height(),height));
474 size = QSizeF(width,qMin(constraint.height(),height));
397 }
475 }
398 else {
476 else {
399 foreach(QLegendMarker *marker, m_legend->d_ptr->markers()) {
477 foreach(QLegendMarker *marker, m_legend->d_ptr->markers()) {
400 LegendMarkerItem *item = marker->d_ptr->item();
478 LegendMarkerItem *item = marker->d_ptr->item();
401 size = size.expandedTo(item->effectiveSizeHint(which));
479 size = size.expandedTo(item->effectiveSizeHint(which));
402 }
480 }
403 }
481 }
404 size += QSize(left + right, top + bottom);
482 size += QSize(left + right, top + bottom);
405 return size;
483 return size;
406 }
484 }
407
485
486 bool LegendLayout::widthLongerThan(const LegendWidthStruct *item1,
487 const LegendWidthStruct *item2)
488 {
489 return item1->width > item2->width;
490 }
491
408 QTCOMMERCIALCHART_END_NAMESPACE
492 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,76 +1,84
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2013 Digia Plc
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Enterprise Charts Add-on.
7 ** This file is part of the Qt Enterprise Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
10 ** Licensees holding valid Qt Enterprise licenses may use this file in
11 ** accordance with the Qt Enterprise License Agreement provided with the
11 ** accordance with the Qt Enterprise License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 // W A R N I N G
21 // W A R N I N G
22 // -------------
22 // -------------
23 //
23 //
24 // This file is not part of the Qt Enterprise Chart API. It exists purely as an
24 // This file is not part of the Qt Enterprise Chart API. It exists purely as an
25 // implementation detail. This header file may change from version to
25 // implementation detail. This header file may change from version to
26 // version without notice, or even be removed.
26 // version without notice, or even be removed.
27 //
27 //
28 // We mean it.
28 // We mean it.
29
29
30 #ifndef LEGENDLAYOUT_H
30 #ifndef LEGENDLAYOUT_H
31 #define LEGENDLAYOUT_H
31 #define LEGENDLAYOUT_H
32 #include <QGraphicsLayout>
32 #include <QGraphicsLayout>
33 #include "qchartglobal.h"
33 #include "qchartglobal.h"
34
34
35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36
36
37 class QLegend;
37 class QLegend;
38 class LegendMarkerItem;
38
39
39 class LegendLayout : public QGraphicsLayout
40 class LegendLayout : public QGraphicsLayout
40 {
41 {
41 public:
42 public:
42
43
43 LegendLayout(QLegend *legend);
44 LegendLayout(QLegend *legend);
44 virtual ~LegendLayout();
45 virtual ~LegendLayout();
45
46
46 void setGeometry(const QRectF &rect);
47 void setGeometry(const QRectF &rect);
47
48
48 void setOffset(qreal x, qreal y);
49 void setOffset(qreal x, qreal y);
49 QPointF offset() const;
50 QPointF offset() const;
50
51
51 void invalidate();
52 void invalidate();
52 protected:
53 protected:
53 QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
54 QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
54 int count() const { return 0; }
55 int count() const { return 0; }
55 QGraphicsLayoutItem *itemAt(int) const { return 0; };
56 QGraphicsLayoutItem *itemAt(int) const { return 0; };
56 void removeAt(int) {};
57 void removeAt(int) {};
57
58
58 private:
59 private:
59 void setAttachedGeometry(const QRectF &rect);
60 void setAttachedGeometry(const QRectF &rect);
60 void setDettachedGeometry(const QRectF &rect);
61 void setDettachedGeometry(const QRectF &rect);
61
62
63 struct LegendWidthStruct {
64 LegendMarkerItem *item;
65 qreal width;
66 };
67 static bool widthLongerThan(const LegendWidthStruct *item1,
68 const LegendWidthStruct *item2);
69
62 private:
70 private:
63 QLegend *m_legend;
71 QLegend *m_legend;
64 qreal m_offsetX;
72 qreal m_offsetX;
65 qreal m_offsetY;
73 qreal m_offsetY;
66 qreal m_minOffsetX;
74 qreal m_minOffsetX;
67 qreal m_minOffsetY;
75 qreal m_minOffsetY;
68 qreal m_maxOffsetX;
76 qreal m_maxOffsetX;
69 qreal m_maxOffsetY;
77 qreal m_maxOffsetY;
70 qreal m_width;
78 qreal m_width;
71 qreal m_height;
79 qreal m_height;
72 };
80 };
73
81
74 QTCOMMERCIALCHART_END_NAMESPACE
82 QTCOMMERCIALCHART_END_NAMESPACE
75
83
76 #endif
84 #endif
General Comments 0
You need to be logged in to leave comments. Login now