##// END OF EJS Templates
Fix label truncate issues with multiple axes...
Miikka Heikkinen -
r2411:6fca0e6f42a3
parent child
Show More
@@ -1,347 +1,394
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "chartlayout_p.h"
22 22 #include "chartpresenter_p.h"
23 23 #include "qlegend_p.h"
24 24 #include "chartaxis_p.h"
25 25 #include "charttitle_p.h"
26 26 #include "chartbackground_p.h"
27 27 #include <QDebug>
28 28
29 29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 30
31 static const qreal golden_ratio = 0.4;
31 static const qreal maxAxisPortion = 0.4;
32 32
33 33 ChartLayout::ChartLayout(ChartPresenter *presenter)
34 34 : m_presenter(presenter),
35 35 m_margins(20, 20, 20, 20),
36 36 m_minChartRect(0, 0, 200, 200)
37 37 {
38 38
39 39 }
40 40
41 41 ChartLayout::~ChartLayout()
42 42 {
43 43
44 44 }
45 45
46 46 void ChartLayout::setGeometry(const QRectF &rect)
47 47 {
48 48 if (!rect.isValid())
49 49 return;
50 50
51 51 QList<ChartAxis *> axes = m_presenter->axisItems();
52 52 ChartTitle *title = m_presenter->titleElement();
53 53 QLegend *legend = m_presenter->legend();
54 54 ChartBackground *background = m_presenter->backgroundElement();
55 55
56 56 QRectF contentGeometry = calculateBackgroundGeometry(rect, background);
57 57
58 58 contentGeometry = calculateContentGeometry(contentGeometry);
59 59
60 60 if (title && title->isVisible())
61 61 contentGeometry = calculateTitleGeometry(contentGeometry, title);
62 62
63 63 if (legend->isAttachedToChart() && legend->isVisible())
64 64 contentGeometry = calculateLegendGeometry(contentGeometry, legend);
65 65
66 66 contentGeometry = calculateAxisGeometry(contentGeometry, axes);
67 67
68 68 m_presenter->setGeometry(contentGeometry);
69 69
70 70 QGraphicsLayout::setGeometry(rect);
71 71 }
72 72
73 73 QRectF ChartLayout::calculateContentGeometry(const QRectF &geometry) const
74 74 {
75 75 return geometry.adjusted(m_margins.left(), m_margins.top(), -m_margins.right(), -m_margins.bottom());
76 76 }
77 77
78 78 QRectF ChartLayout::calculateContentMinimum(const QRectF &minimum) const
79 79 {
80 80 return minimum.adjusted(0, 0, m_margins.left() + m_margins.right(), m_margins.top() + m_margins.bottom());
81 81 }
82 82
83 83
84 84 QRectF ChartLayout::calculateBackgroundGeometry(const QRectF &geometry, ChartBackground *background) const
85 85 {
86 86 qreal left, top, right, bottom;
87 87 getContentsMargins(&left, &top, &right, &bottom);
88 88 QRectF backgroundGeometry = geometry.adjusted(left, top, -right, -bottom);
89 89 if (background)
90 90 background->setRect(backgroundGeometry);
91 91 return backgroundGeometry;
92 92 }
93 93
94 94 QRectF ChartLayout::calculateBackgroundMinimum(const QRectF &minimum) const
95 95 {
96 96 qreal left, top, right, bottom;
97 97 getContentsMargins(&left, &top, &right, &bottom);
98 98 return minimum.adjusted(0, 0, left + right, top + bottom);
99 99 }
100 100
101 101
102 102 QRectF ChartLayout::calculateAxisGeometry(const QRectF &geometry, const QList<ChartAxis *>& axes) const
103 103 {
104 104 QSizeF left(0,0);
105 105 QSizeF minLeft(0,0);
106 106 QSizeF right(0,0);
107 107 QSizeF minRight(0,0);
108 108 QSizeF bottom(0,0);
109 109 QSizeF minBottom(0,0);
110 110 QSizeF top(0,0);
111 111 QSizeF minTop(0,0);
112 112 int leftCount = 0;
113 113 int rightCount = 0;
114 114 int topCount = 0;
115 115 int bottomCount = 0;
116 116
117 117 foreach (ChartAxis *axis , axes) {
118 118
119 119 if (!axis->isVisible())
120 120 continue;
121 121
122 122
123 123 QSizeF size = axis->effectiveSizeHint(Qt::PreferredSize);
124 124 //this is used to get single thick font size
125 125 QSizeF minSize = axis->effectiveSizeHint(Qt::MinimumSize);
126 126
127 127 switch (axis->alignment()) {
128 128 case Qt::AlignLeft:
129 129 left.setWidth(left.width()+size.width());
130 130 left.setHeight(qMax(left.height(),size.height()));
131 131 minLeft.setWidth(minLeft.width()+minSize.width());
132 132 minLeft.setHeight(qMax(minLeft.height(),minSize.height()));
133 133 leftCount++;
134 134 break;
135 135 case Qt::AlignRight:
136 136 right.setWidth(right.width()+size.width());
137 137 right.setHeight(qMax(right.height(),size.height()));
138 138 minRight.setWidth(minRight.width()+minSize.width());
139 139 minRight.setHeight(qMax(minRight.height(),minSize.height()));
140 140 rightCount++;
141 141 break;
142 142 case Qt::AlignTop:
143 143 top.setWidth(qMax(top.width(),size.width()));
144 144 top.setHeight(top.height()+size.height());
145 145 minTop.setWidth(qMax(minTop.width(),minSize.width()));
146 146 minTop.setHeight(minTop.height()+minSize.height());
147 147 topCount++;
148 148 break;
149 149 case Qt::AlignBottom:
150 150 bottom.setWidth(qMax(bottom.width(), size.width()));
151 151 bottom.setHeight(bottom.height() + size.height());
152 152 minBottom.setWidth(qMax(minBottom.width(),minSize.width()));
153 153 minBottom.setHeight(minBottom.height() + minSize.height());
154 154 bottomCount++;
155 155 break;
156 156 default:
157 157 qWarning()<<"Axis is without alignment !";
158 158 break;
159 159 }
160 160 }
161 161
162 int horizontal = leftCount + rightCount;
163 qreal hratio = 0 ;
164 if(horizontal>0)
165 hratio = (golden_ratio*geometry.width())/horizontal;
162 int totalVerticalAxes = leftCount + rightCount;
163 qreal leftSqueezeRatio = 1.0;
164 qreal rightSqueezeRatio = 1.0;
165 qreal vratio = 0;
166 166
167 if(leftCount>0)
168 left.setWidth(qMin(left.width(),hratio*leftCount));
169 if(rightCount>0)
170 right.setWidth(qMin(right.width(),hratio*rightCount));
167 if (totalVerticalAxes > 0)
168 vratio = (maxAxisPortion * geometry.width()) / totalVerticalAxes;
169
170 if (leftCount > 0) {
171 int maxWidth = vratio * leftCount;
172 if (left.width() > maxWidth) {
173 leftSqueezeRatio = maxWidth / left.width();
174 left.setWidth(maxWidth);
175 }
176 }
177 if (rightCount > 0) {
178 int maxWidth = vratio * rightCount;
179 if (right.width() > maxWidth) {
180 rightSqueezeRatio = maxWidth / right.width();
181 right.setWidth(maxWidth);
182 }
183 }
184
185 int totalHorizontalAxes = topCount + bottomCount;
186 qreal topSqueezeRatio = 1.0;
187 qreal bottomSqueezeRatio = 1.0;
188 qreal hratio = 0;
189
190 if (totalHorizontalAxes > 0)
191 hratio = (maxAxisPortion * geometry.height()) / totalHorizontalAxes;
192
193 if (topCount > 0) {
194 int maxHeight = hratio * topCount;
195 if (top.height() > maxHeight) {
196 topSqueezeRatio = maxHeight / top.height();
197 top.setHeight(maxHeight);
198 }
199 }
200 if (bottomCount > 0) {
201 int maxHeight = hratio * bottomCount;
202 if (bottom.height() > maxHeight) {
203 bottomSqueezeRatio = maxHeight / bottom.height();
204 bottom.setHeight(maxHeight);
205 }
206 }
171 207
172 208 qreal minHeight = qMax(minLeft.height(),minRight.height()) + 1;
173 209 qreal minWidth = qMax(minTop.width(),minBottom.width()) + 1;
174 210
175 211 QRectF chartRect = geometry.adjusted(qMax(left.width(),minWidth/2), qMax(top.height(), minHeight/2),-qMax(right.width(),minWidth/2),-qMax(bottom.height(),minHeight/2));
176 212
177 213 qreal leftOffset = 0;
178 214 qreal rightOffset = 0;
179 215 qreal topOffset = 0;
180 216 qreal bottomOffset = 0;
181 217
182 218 foreach(ChartElement *axisElement , axes) {
183 219
184 220 //TODO fixme
185 221 ChartAxis* axis = qobject_cast<ChartAxis*>(axisElement);
186 222
187 223 if (!axis->isVisible())
188 224 continue;
189 225
190 226 QSizeF size = axis->effectiveSizeHint(Qt::PreferredSize);
191 227
192 228 switch(axis->alignment()){
193 229 case Qt::AlignLeft:{
194 qreal width = qMin(size.width(),(left.width()/leftCount));
230 qreal width = size.width();
231 if (leftSqueezeRatio < 1.0)
232 width *= leftSqueezeRatio;
195 233 leftOffset+=width;
196 234 axis->setGeometry(QRect(chartRect.left()-leftOffset, geometry.top(),width, geometry.bottom()),chartRect);
197 235 break;
198 236 }
199 237 case Qt::AlignRight:{
200 qreal width = qMin(size.width(),(right.width()/rightCount));
238 qreal width = size.width();
239 if (rightSqueezeRatio < 1.0)
240 width *= rightSqueezeRatio;
201 241 axis->setGeometry(QRect(chartRect.right()+rightOffset,geometry.top(),width,geometry.bottom()),chartRect);
202 242 rightOffset+=width;
203 243 break;
204 244 }
205 case Qt::AlignTop:
206 axis->setGeometry(QRect(geometry.left(), chartRect.top() - topOffset - size.height(), geometry.width(), size.height()), chartRect);
207 topOffset += size.height();
245 case Qt::AlignTop: {
246 qreal height = size.height();
247 if (topSqueezeRatio < 1.0)
248 height *= topSqueezeRatio;
249 axis->setGeometry(QRect(geometry.left(), chartRect.top() - topOffset - height, geometry.width(), height), chartRect);
250 topOffset += height;
208 251 break;
252 }
209 253 case Qt::AlignBottom:
210 axis->setGeometry(QRect(geometry.left(), chartRect.bottom() + bottomOffset, geometry.width(), size.height()), chartRect);
211 bottomOffset += size.height();
254 qreal height = size.height();
255 if (bottomSqueezeRatio < 1.0)
256 height *= bottomSqueezeRatio;
257 axis->setGeometry(QRect(geometry.left(), chartRect.bottom() + bottomOffset, geometry.width(), height), chartRect);
258 bottomOffset += height;
212 259 break;
213 260 }
214 261 }
215 262
216 263 return chartRect;
217 264 }
218 265
219 266 QRectF ChartLayout::calculateAxisMinimum(const QRectF &minimum, const QList<ChartAxis *>& axes) const
220 267 {
221 268 QSizeF left;
222 269 QSizeF right;
223 270 QSizeF bottom;
224 271 QSizeF top;
225 272
226 273 foreach (ChartAxis *axis, axes) {
227 274
228 275 QSizeF size = axis->effectiveSizeHint(Qt::MinimumSize);
229 276
230 277 if (!axis->isVisible())
231 278 continue;
232 279
233 280 switch (axis->alignment()) {
234 281 case Qt::AlignLeft:
235 282 left.setWidth(left.width() + size.width());
236 283 left.setHeight(qMax(left.height() * 2, size.height()));
237 284 break;
238 285 case Qt::AlignRight:
239 286 right.setWidth(right.width() + size.width());
240 287 right.setHeight(qMax(right.height() * 2, size.height()));
241 288 break;
242 289 case Qt::AlignTop:
243 290 top.setWidth(qMax(top.width(), size.width()));
244 291 top.setHeight(top.height() + size.height());
245 292 break;
246 293 case Qt::AlignBottom:
247 294 bottom.setWidth(qMax(bottom.width(), size.width()));
248 295 bottom.setHeight(bottom.height() + size.height());
249 296 break;
250 297 }
251 298 }
252 299 return minimum.adjusted(0, 0, left.width() + right.width() + qMax(top.width(), bottom.width()), top.height() + bottom.height() + qMax(left.height(), right.height()));
253 300 }
254 301
255 302 QRectF ChartLayout::calculateLegendGeometry(const QRectF &geometry, QLegend *legend) const
256 303 {
257 304 QSizeF size = legend->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1));
258 305 QRectF legendRect;
259 306 QRectF result;
260 307
261 308 switch (legend->alignment()) {
262 309 case Qt::AlignTop: {
263 310 legendRect = QRectF(geometry.topLeft(), QSizeF(geometry.width(), size.height()));
264 311 result = geometry.adjusted(0, legendRect.height(), 0, 0);
265 312 break;
266 313 }
267 314 case Qt::AlignBottom: {
268 315 legendRect = QRectF(QPointF(geometry.left(), geometry.bottom() - size.height()), QSizeF(geometry.width(), size.height()));
269 316 result = geometry.adjusted(0, 0, 0, -legendRect.height());
270 317 break;
271 318 }
272 319 case Qt::AlignLeft: {
273 qreal width = qMin(size.width(), geometry.width() * golden_ratio);
320 qreal width = qMin(size.width(), geometry.width() * maxAxisPortion);
274 321 legendRect = QRectF(geometry.topLeft(), QSizeF(width, geometry.height()));
275 322 result = geometry.adjusted(width, 0, 0, 0);
276 323 break;
277 324 }
278 325 case Qt::AlignRight: {
279 qreal width = qMin(size.width(), geometry.width() * golden_ratio);
326 qreal width = qMin(size.width(), geometry.width() * maxAxisPortion);
280 327 legendRect = QRectF(QPointF(geometry.right() - width, geometry.top()), QSizeF(width, geometry.height()));
281 328 result = geometry.adjusted(0, 0, -width, 0);
282 329 break;
283 330 }
284 331 default: {
285 332 legendRect = QRectF(0, 0, 0, 0);
286 333 result = geometry;
287 334 break;
288 335 }
289 336 }
290 337
291 338 legend->setGeometry(legendRect);
292 339
293 340 return result;
294 341 }
295 342
296 343 QRectF ChartLayout::calculateLegendMinimum(const QRectF &geometry, QLegend *legend) const
297 344 {
298 345 QSizeF minSize = legend->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, -1));
299 346 return geometry.adjusted(0, 0, minSize.width(), minSize.height());
300 347 }
301 348
302 349 QRectF ChartLayout::calculateTitleGeometry(const QRectF &geometry, ChartTitle *title) const
303 350 {
304 351 title->setGeometry(geometry);
305 352 QPointF center = geometry.center() - title->boundingRect().center();
306 353 title->setPos(center.x(),title->pos().y());
307 354 return geometry.adjusted(0,title->boundingRect().height()+1,0,0);
308 355 }
309 356
310 357 QRectF ChartLayout::calculateTitleMinimum(const QRectF &minimum, ChartTitle *title) const
311 358 {
312 359 QSizeF min = title->sizeHint(Qt::MinimumSize);
313 360 return minimum.adjusted(0, 0, min.width(), min.height());
314 361 }
315 362
316 363 QSizeF ChartLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
317 364 {
318 365 Q_UNUSED(constraint);
319 366 if (which == Qt::MinimumSize) {
320 367 QList<ChartAxis *> axes = m_presenter->axisItems();
321 368 ChartTitle *title = m_presenter->titleElement();
322 369 QLegend *legend = m_presenter->legend();
323 370 QRectF minimumRect(0, 0, 0, 0);
324 371 minimumRect = calculateBackgroundMinimum(minimumRect);
325 372 minimumRect = calculateContentMinimum(minimumRect);
326 373 minimumRect = calculateTitleMinimum(minimumRect, title);
327 374 minimumRect = calculateLegendMinimum(minimumRect, legend);
328 375 minimumRect = calculateAxisMinimum(minimumRect, axes);
329 376 return minimumRect.united(m_minChartRect).size().toSize();
330 377 }
331 378 return QSize(-1, -1);
332 379 }
333 380
334 381 void ChartLayout::setMargins(const QMargins &margins)
335 382 {
336 383 if (m_margins != margins) {
337 384 m_margins = margins;
338 385 updateGeometry();
339 386 }
340 387 }
341 388
342 389 QMargins ChartLayout::margins() const
343 390 {
344 391 return m_margins;
345 392 }
346 393
347 394 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now