##// END OF EJS Templates
Bug fix axis artefacts when title set
Michal Klocek -
r2142:f47f6180ca81
parent child
Show More
@@ -1,449 +1,449
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 "chartaxis_p.h"
22 22 #include "qabstractaxis.h"
23 23 #include "qabstractaxis_p.h"
24 24 #include "chartpresenter_p.h"
25 25 #include "chartlayout_p.h"
26 26 #include "domain_p.h"
27 27 #include <qmath.h>
28 28 #include <QDateTime>
29 29 #include <QValueAxis>
30 30 #include <QGraphicsLayout>
31 31 #include <QFontMetrics>
32 32
33 33 QTCOMMERCIALCHART_BEGIN_NAMESPACE
34 34
35 35 ChartAxis::ChartAxis(QAbstractAxis *axis, ChartPresenter *presenter, bool intervalAxis)
36 36 : ChartElement(presenter),
37 37 m_chartAxis(axis),
38 38 m_labelsAngle(0),
39 39 m_grid(new QGraphicsItemGroup(presenter->rootItem())),
40 40 m_shades(new QGraphicsItemGroup(presenter->rootItem())),
41 41 m_labels(new QGraphicsItemGroup(presenter->rootItem())),
42 42 m_arrow(new QGraphicsItemGroup(presenter->rootItem())),
43 43 m_title(new QGraphicsSimpleTextItem(presenter->rootItem())),
44 44 m_min(0),
45 45 m_max(0),
46 46 m_animation(0),
47 47 m_labelPadding(5),
48 48 m_intervalAxis(intervalAxis)
49 49 {
50 50 //initial initialization
51 51 m_arrow->setZValue(ChartPresenter::AxisZValue);
52 52 m_arrow->setHandlesChildEvents(false);
53 53 m_labels->setZValue(ChartPresenter::AxisZValue);
54 54 m_shades->setZValue(ChartPresenter::ShadesZValue);
55 55 m_grid->setZValue(ChartPresenter::GridZValue);
56 m_title->setZValue(ChartPresenter::GridZValue);
56 57
57 58 QObject::connect(m_chartAxis->d_ptr.data(), SIGNAL(updated()), this, SLOT(handleAxisUpdated()));
58 59
59 60 QGraphicsSimpleTextItem item;
60 61 m_font = item.font();
61 62
62 63 }
63 64
64 65 ChartAxis::~ChartAxis()
65 66 {
66 67 }
67 68
68 69 void ChartAxis::setAnimation(AxisAnimation *animation)
69 70 {
70 71 m_animation = animation;
71 72 }
72 73
73 74 void ChartAxis::setLayout(QVector<qreal> &layout)
74 75 {
75 76 m_layoutVector = layout;
76 77 }
77 78
78 79 void ChartAxis::createItems(int count)
79 80 {
80 81 if (m_arrow->children().size() == 0)
81 82 m_arrow->addToGroup(new AxisItem(this, presenter()->rootItem()));
82 83
83 84 if (m_intervalAxis && m_grid->children().size() == 0) {
84 85 for (int i = 0 ; i < 2 ; i ++)
85 86 m_grid->addToGroup(new QGraphicsLineItem(presenter()->rootItem()));
86 87 }
87 88
88 89 for (int i = 0; i < count; ++i) {
89 90 m_grid->addToGroup(new QGraphicsLineItem(presenter()->rootItem()));
90 91 m_labels->addToGroup(new QGraphicsSimpleTextItem(presenter()->rootItem()));
91 92 m_arrow->addToGroup(new QGraphicsLineItem(presenter()->rootItem()));
92 93 if ((m_grid->childItems().size()) % 2 && m_grid->childItems().size() > 2)
93 94 m_shades->addToGroup(new QGraphicsRectItem(presenter()->rootItem()));
94 95 }
95 96 }
96 97
97 98 void ChartAxis::deleteItems(int count)
98 99 {
99 100 QList<QGraphicsItem *> lines = m_grid->childItems();
100 101 QList<QGraphicsItem *> labels = m_labels->childItems();
101 102 QList<QGraphicsItem *> shades = m_shades->childItems();
102 103 QList<QGraphicsItem *> axis = m_arrow->childItems();
103 104
104 105 for (int i = 0; i < count; ++i) {
105 106 if (lines.size() % 2 && lines.size() > 1)
106 107 delete(shades.takeLast());
107 108 delete(lines.takeLast());
108 109 delete(labels.takeLast());
109 110 delete(axis.takeLast());
110 111 }
111 112 }
112 113
113 114 void ChartAxis::updateLayout(QVector<qreal> &layout)
114 115 {
115 116 int diff = m_layoutVector.size() - layout.size();
116 117
117 118 if (diff > 0)
118 119 deleteItems(diff);
119 120 else if (diff < 0)
120 121 createItems(-diff);
121 122
122 123 if (diff < 0) handleAxisUpdated();
123 124
124 125 if (m_animation) {
125 126 switch (presenter()->state()) {
126 127 case ChartPresenter::ZoomInState:
127 128 m_animation->setAnimationType(AxisAnimation::ZoomInAnimation);
128 129 m_animation->setAnimationPoint(presenter()->statePoint());
129 130 break;
130 131 case ChartPresenter::ZoomOutState:
131 132 m_animation->setAnimationType(AxisAnimation::ZoomOutAnimation);
132 133 m_animation->setAnimationPoint(presenter()->statePoint());
133 134 break;
134 135 case ChartPresenter::ScrollUpState:
135 136 case ChartPresenter::ScrollLeftState:
136 137 m_animation->setAnimationType(AxisAnimation::MoveBackwordAnimation);
137 138 break;
138 139 case ChartPresenter::ScrollDownState:
139 140 case ChartPresenter::ScrollRightState:
140 141 m_animation->setAnimationType(AxisAnimation::MoveForwardAnimation);
141 142 break;
142 143 case ChartPresenter::ShowState:
143 144 m_animation->setAnimationType(AxisAnimation::DefaultAnimation);
144 145 break;
145 146 }
146 147 m_animation->setValues(m_layoutVector, layout);
147 148 presenter()->startAnimation(m_animation);
148 149 } else {
149 150 setLayout(layout);
150 151 updateGeometry();
151 152 }
152 153 }
153 154
154 155 void ChartAxis::setArrowOpacity(qreal opacity)
155 156 {
156 157 m_arrow->setOpacity(opacity);
157 158 }
158 159
159 160 qreal ChartAxis::arrowOpacity() const
160 161 {
161 162 return m_arrow->opacity();
162 163 }
163 164
164 165 void ChartAxis::setArrowVisibility(bool visible)
165 166 {
166 167 m_arrow->setOpacity(visible);
167 168 }
168 169
169 170 void ChartAxis::setGridOpacity(qreal opacity)
170 171 {
171 172 m_grid->setOpacity(opacity);
172 173 }
173 174
174 175 qreal ChartAxis::gridOpacity() const
175 176 {
176 177 return m_grid->opacity();
177 178 }
178 179
179 180 void ChartAxis::setGridVisibility(bool visible)
180 181 {
181 182 m_grid->setOpacity(visible);
182 183 }
183 184
184 185 void ChartAxis::setLabelsOpacity(qreal opacity)
185 186 {
186 187 m_labels->setOpacity(opacity);
187 188 }
188 189
189 190 qreal ChartAxis::labelsOpacity() const
190 191 {
191 192 return m_labels->opacity();
192 193 }
193 194
194 195 void ChartAxis::setLabelsVisibility(bool visible)
195 196 {
196 197 m_labels->setOpacity(visible);
197 198 }
198 199
199 200 void ChartAxis::setShadesOpacity(qreal opacity)
200 201 {
201 202 m_shades->setOpacity(opacity);
202 203 }
203 204
204 205 qreal ChartAxis::shadesOpacity() const
205 206 {
206 207 return m_shades->opacity();
207 208 }
208 209
209 210 void ChartAxis::setShadesVisibility(bool visible)
210 211 {
211 212 m_shades->setVisible(visible);
212 213 }
213 214
214 215 void ChartAxis::setLabelsAngle(int angle)
215 216 {
216 217 foreach (QGraphicsItem *item, m_labels->childItems())
217 218 item->setRotation(angle);
218 219
219 220 m_labelsAngle = angle;
220 221 }
221 222
222 223 void ChartAxis::setLabelsPen(const QPen &pen)
223 224 {
224 225 foreach (QGraphicsItem *item , m_labels->childItems())
225 226 static_cast<QGraphicsSimpleTextItem *>(item)->setPen(pen);
226 227 }
227 228
228 229 void ChartAxis::setLabelsBrush(const QBrush &brush)
229 230 {
230 231 foreach (QGraphicsItem *item , m_labels->childItems())
231 232 static_cast<QGraphicsSimpleTextItem *>(item)->setBrush(brush);
232 233 }
233 234
234 235 void ChartAxis::setLabelsFont(const QFont &font)
235 236 {
236 237 foreach (QGraphicsItem *item , m_labels->childItems())
237 238 static_cast<QGraphicsSimpleTextItem *>(item)->setFont(font);
238 239
239 240 if (m_font != font) {
240 241 m_font = font;
241 242 foreach (QGraphicsItem *item , m_labels->childItems())
242 243 static_cast<QGraphicsSimpleTextItem *>(item)->setFont(font);
243 244 QGraphicsLayoutItem::updateGeometry();
244 245 presenter()->layout()->invalidate();
245 246 }
246 247 }
247 248
248 249 void ChartAxis::setShadesBrush(const QBrush &brush)
249 250 {
250 251 foreach (QGraphicsItem *item , m_shades->childItems())
251 252 static_cast<QGraphicsRectItem *>(item)->setBrush(brush);
252 253 }
253 254
254 255 void ChartAxis::setShadesPen(const QPen &pen)
255 256 {
256 257 foreach (QGraphicsItem *item , m_shades->childItems())
257 258 static_cast<QGraphicsRectItem *>(item)->setPen(pen);
258 259 }
259 260
260 261 void ChartAxis::setArrowPen(const QPen &pen)
261 262 {
262 263 foreach (QGraphicsItem *item , m_arrow->childItems())
263 264 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
264 265 }
265 266
266 267 void ChartAxis::setGridPen(const QPen &pen)
267 268 {
268 269 foreach (QGraphicsItem *item , m_grid->childItems())
269 270 static_cast<QGraphicsLineItem *>(item)->setPen(pen);
270 271 }
271 272
272 273 void ChartAxis::setLabelPadding(int padding)
273 274 {
274 275 m_labelPadding = padding;
275 276 }
276 277
277 278 bool ChartAxis::isEmpty()
278 279 {
279 return !m_axisRect.isValid() || m_gridRect.isEmpty() || qFuzzyIsNull(m_min - m_max);
280 return m_axisRect.isEmpty() || m_gridRect.isEmpty() || qFuzzyIsNull(m_min - m_max);
280 281 }
281 282
282 283 void ChartAxis::handleDomainUpdated()
283 284 {
284 285 Domain *domain = qobject_cast<Domain *>(sender());
285 286 qreal min(0);
286 287 qreal max(0);
287 288
288 289 if (m_chartAxis->orientation() == Qt::Horizontal) {
289 290 min = domain->minX();
290 291 max = domain->maxX();
291 292 } else if (m_chartAxis->orientation() == Qt::Vertical) {
292 293 min = domain->minY();
293 294 max = domain->maxY();
294 295 }
295 296
296 297 if (!qFuzzyIsNull(m_min - min) || !qFuzzyIsNull(m_max - max)) {
297 298 m_min = min;
298 299 m_max = max;
299 300
300 301 if (!isEmpty()) {
301 302
302 303 QVector<qreal> layout = calculateLayout();
303 304 updateLayout(layout);
304 305 QSizeF before = effectiveSizeHint(Qt::PreferredSize);
305 306 QSizeF after = sizeHint(Qt::PreferredSize);
306 307
307 308 if (before != after) {
308 309 QGraphicsLayoutItem::updateGeometry();
309 310 //we don't want to call invalidate on layout, since it will change minimum size of component,
310 311 //which we would like to avoid since it causes nasty flips when scrolling or zooming,
311 312 //instead recalculate layout and use plotArea for extra space.
312 313 presenter()->layout()->setGeometry(presenter()->layout()->geometry());
313 314 }
314 315 }
315 316 }
316 317 }
317 318
318 319 void ChartAxis::handleAxisUpdated()
319 320 {
320 321 if (isEmpty())
321 322 return;
322 323
323 324 bool visible = m_chartAxis->isVisible();
324 325
325 326 setArrowVisibility(visible && m_chartAxis->isLineVisible());
326 327 setGridVisibility(visible && m_chartAxis->isGridLineVisible());
327 328 setLabelsVisibility(visible && m_chartAxis->labelsVisible());
328 329 setShadesVisibility(visible && m_chartAxis->shadesVisible());
329 330 setLabelsAngle(m_chartAxis->labelsAngle());
330 331 setArrowPen(m_chartAxis->linePen());
331 332 setLabelsPen(m_chartAxis->labelsPen());
332 333 setLabelsBrush(m_chartAxis->labelsBrush());
333 334 setLabelsFont(m_chartAxis->labelsFont());
334 335 setGridPen(m_chartAxis->gridLinePen());
335 336 setShadesPen(m_chartAxis->shadesPen());
336 337 setShadesBrush(m_chartAxis->shadesBrush());
337 338 setTitleText(m_chartAxis->title());
338 339 }
339 340
340 341 void ChartAxis::setTitleText(const QString &title)
341 342 {
342 343 if (m_titleText != title) {
343 344 m_titleText = title;
344 m_axisRect = QRect();
345 345 QGraphicsLayoutItem::updateGeometry();
346 346 presenter()->layout()->invalidate();
347 347 }
348 348 }
349 349
350 350 void ChartAxis::hide()
351 351 {
352 352 setArrowVisibility(false);
353 353 setGridVisibility(false);
354 354 setLabelsVisibility(false);
355 355 setShadesVisibility(false);
356 356 }
357 357
358 358 void ChartAxis::setGeometry(const QRectF &axis, const QRectF &grid)
359 359 {
360 360 m_gridRect = grid;
361 361 m_axisRect = axis;
362 362
363 363 if (isEmpty())
364 364 return;
365 365
366 366 QVector<qreal> layout = calculateLayout();
367 367 updateLayout(layout);
368 368
369 369 }
370 370
371 371 void ChartAxis::axisSelected()
372 372 {
373 373 //TODO: axis clicked;
374 374 }
375 375
376 376 Qt::Orientation ChartAxis::orientation() const
377 377 {
378 378 return m_chartAxis->orientation();
379 379 }
380 380
381 381 Qt::Alignment ChartAxis::alignment() const
382 382 {
383 383 return m_chartAxis->alignment();
384 384 }
385 385
386 386 bool ChartAxis::isVisible()
387 387 {
388 388 return m_chartAxis->isVisible();
389 389 }
390 390
391 391 void ChartAxis::setLabels(const QStringList &labels)
392 392 {
393 393 m_labelsList = labels;
394 394 }
395 395
396 396 QStringList ChartAxis::createValueLabels(int ticks) const
397 397 {
398 398 Q_ASSERT(m_max > m_min);
399 399 Q_ASSERT(ticks > 1);
400 400
401 401 QStringList labels;
402 402
403 403 int n = qMax(int(-qFloor(log10((m_max - m_min) / (ticks - 1)))), 0);
404 404 n++;
405 405
406 406 QValueAxis *axis = qobject_cast<QValueAxis *>(m_chartAxis);
407 407
408 408 QString format = axis->labelFormat();
409 409
410 410 if (format.isNull()) {
411 411 for (int i = 0; i < ticks; i++) {
412 412 qreal value = m_min + (i * (m_max - m_min) / (ticks - 1));
413 413 labels << QString::number(value, 'f', n);
414 414 }
415 415 } else {
416 416 QByteArray array = format.toAscii();
417 417 for (int i = 0; i < ticks; i++) {
418 418 qreal value = m_min + (i * (m_max - m_min) / (ticks - 1));
419 419 labels << QString().sprintf(array, value);
420 420 }
421 421 }
422 422
423 423 return labels;
424 424 }
425 425
426 426 QStringList ChartAxis::createDateTimeLabels(const QString &format, int ticks) const
427 427 {
428 428 Q_ASSERT(m_max > m_min);
429 429 Q_ASSERT(ticks > 1);
430 430 QStringList labels;
431 431 int n = qMax(int(-floor(log10((m_max - m_min) / (ticks - 1)))), 0);
432 432 n++;
433 433 for (int i = 0; i < ticks; i++) {
434 434 qreal value = m_min + (i * (m_max - m_min) / (ticks - 1));
435 435 labels << QDateTime::fromMSecsSinceEpoch(value).toString(format);
436 436 }
437 437 return labels;
438 438 }
439 439
440 440 QSizeF ChartAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
441 441 {
442 442 Q_UNUSED(which);
443 443 Q_UNUSED(constraint);
444 444 return QSizeF();
445 445 }
446 446
447 447 #include "moc_chartaxis_p.cpp"
448 448
449 449 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now