##// END OF EJS Templates
Fix the minor axis grid animation...
Miikka Heikkinen -
r2851:0e82bb0d49f5
parent child
Show More
@@ -1,380 +1,375
1 1 /******************************************************************************
2 2 **
3 3 ** Copyright (C) 2015 The Qt Company Ltd.
4 4 ** Contact: http://www.qt.io/licensing/
5 5 **
6 6 ** This file is part of the Qt Charts module.
7 7 **
8 8 ** $QT_BEGIN_LICENSE:COMM$
9 9 **
10 10 ** Commercial License Usage
11 11 ** Licensees holding valid commercial Qt licenses may use this file in
12 12 ** accordance with the commercial license agreement provided with the
13 13 ** Software or, alternatively, in accordance with the terms contained in
14 14 ** a written agreement between you and The Qt Company. For licensing terms
15 15 ** and conditions see http://www.qt.io/terms-conditions. For further
16 16 ** information use the contact form at http://www.qt.io/contact-us.
17 17 **
18 18 ** $QT_END_LICENSE$
19 19 **
20 20 ******************************************************************************/
21 21
22 22 #include <private/horizontalaxis_p.h>
23 23 #include <private/qabstractaxis_p.h>
24 24 #include <private/chartpresenter_p.h>
25 25 #include <QtCharts/QCategoryAxis>
26 26 #include <QtCore/QtMath>
27 27 #include <QtCore/QDebug>
28 28
29 29 QT_CHARTS_BEGIN_NAMESPACE
30 30
31 31 HorizontalAxis::HorizontalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
32 32 : CartesianChartAxis(axis, item, intervalAxis)
33 33 {
34 34 }
35 35
36 36 HorizontalAxis::~HorizontalAxis()
37 37 {
38 38 }
39 39
40 40 void HorizontalAxis::updateGeometry()
41 41 {
42 42 const QVector<qreal> &layout = ChartAxisElement::layout();
43 43
44 44 if (layout.isEmpty() && axis()->type() != QAbstractAxis::AxisTypeLogValue)
45 45 return;
46 46
47 47 QStringList labelList = labels();
48 48
49 49 QList<QGraphicsItem *> labels = labelItems();
50 50 QList<QGraphicsItem *> arrow = arrowItems();
51 51 QGraphicsTextItem *title = titleItem();
52 52
53 53 Q_ASSERT(labels.size() == labelList.size());
54 54 Q_ASSERT(layout.size() == labelList.size());
55 55
56 56 const QRectF &axisRect = axisGeometry();
57 57 const QRectF &gridRect = gridGeometry();
58 58
59 59 //arrow
60 60 QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem *>(arrow.at(0));
61 61
62 62 if (axis()->alignment() == Qt::AlignTop)
63 63 arrowItem->setLine(gridRect.left(), axisRect.bottom(), gridRect.right(), axisRect.bottom());
64 64 else if (axis()->alignment() == Qt::AlignBottom)
65 65 arrowItem->setLine(gridRect.left(), axisRect.top(), gridRect.right(), axisRect.top());
66 66
67 67 qreal width = 0;
68 68 const QLatin1String ellipsis("...");
69 69
70 70 //title
71 71 QRectF titleBoundingRect;
72 72 QString titleText = axis()->titleText();
73 73 qreal availableSpace = axisRect.height() - labelPadding();
74 74 if (!titleText.isEmpty() && titleItem()->isVisible()) {
75 75 availableSpace -= titlePadding() * 2.0;
76 76 qreal minimumLabelHeight = ChartPresenter::textBoundingRect(axis()->labelsFont(),
77 77 QStringLiteral("...")).height();
78 78 qreal titleSpace = availableSpace - minimumLabelHeight;
79 79 title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0),
80 80 gridRect.width(), titleSpace,
81 81 titleBoundingRect));
82 82 title->setTextWidth(titleBoundingRect.width());
83 83
84 84 titleBoundingRect = title->boundingRect();
85 85
86 86 QPointF center = gridRect.center() - titleBoundingRect.center();
87 87 if (axis()->alignment() == Qt::AlignTop)
88 88 title->setPos(center.x(), axisRect.top() + titlePadding());
89 89 else if (axis()->alignment() == Qt::AlignBottom)
90 90 title->setPos(center.x(), axisRect.bottom() - titleBoundingRect.height() - titlePadding());
91 91
92 92 availableSpace -= titleBoundingRect.height();
93 93 }
94 94
95 95 if (layout.isEmpty() && axis()->type() == QAbstractAxis::AxisTypeLogValue)
96 96 return;
97 97
98 98 QList<QGraphicsItem *> lines = gridItems();
99 99 QList<QGraphicsItem *> shades = shadeItems();
100 100 QList<QGraphicsItem *> minorLines = minorGridItems();
101 101 QList<QGraphicsItem *> minorArrows = minorArrowItems();
102 102
103 103 for (int i = 0; i < layout.size(); ++i) {
104 104 //items
105 105 QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem*>(lines.at(i));
106 106 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem*>(arrow.at(i + 1));
107 107 QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labels.at(i));
108 108
109 109 //grid line
110 110 if (axis()->isReverse()) {
111 111 gridItem->setLine(gridRect.right() - layout[i] + gridRect.left(), gridRect.top(),
112 112 gridRect.right() - layout[i] + gridRect.left(), gridRect.bottom());
113 113 } else {
114 114 gridItem->setLine(layout[i], gridRect.top(), layout[i], gridRect.bottom());
115 115 }
116 116
117 117 //label text wrapping
118 118 QString text;
119 119 if (axis()->isReverse() && axis()->type() != QAbstractAxis::AxisTypeCategory)
120 120 text = labelList.at(labelList.count() - i - 1);
121 121 else
122 122 text = labelList.at(i);
123 123
124 124 QRectF boundingRect;
125 125 // don't truncate empty labels
126 126 if (text.isEmpty()) {
127 127 labelItem->setHtml(text);
128 128 } else {
129 129 qreal labelWidth = axisRect.width() / layout.count() - (2 * labelPadding());
130 130 QString truncatedText = ChartPresenter::truncatedText(axis()->labelsFont(), text,
131 131 axis()->labelsAngle(),
132 132 labelWidth,
133 133 availableSpace, boundingRect);
134 134 labelItem->setTextWidth(ChartPresenter::textBoundingRect(axis()->labelsFont(),
135 135 truncatedText).width());
136 136 labelItem->setHtml(truncatedText);
137 137 }
138 138
139 139 //label transformation origin point
140 140 const QRectF& rect = labelItem->boundingRect();
141 141 QPointF center = rect.center();
142 142 labelItem->setTransformOriginPoint(center.x(), center.y());
143 143 qreal heightDiff = rect.height() - boundingRect.height();
144 144 qreal widthDiff = rect.width() - boundingRect.width();
145 145
146 146 //ticks and label position
147 147 QPointF labelPos;
148 148 if (axis()->alignment() == Qt::AlignTop) {
149 149 if (axis()->isReverse()) {
150 150 labelPos = QPointF(gridRect.right() - layout[layout.size() - i - 1]
151 151 + gridRect.left() - center.x(),
152 152 axisRect.bottom() - rect.height()
153 153 + (heightDiff / 2.0) - labelPadding());
154 154 tickItem->setLine(gridRect.right() + gridRect.left() - layout[i],
155 155 axisRect.bottom(),
156 156 gridRect.right() + gridRect.left() - layout[i],
157 157 axisRect.bottom() - labelPadding());
158 158 } else {
159 159 labelPos = QPointF(layout[i] - center.x(), axisRect.bottom() - rect.height()
160 160 + (heightDiff / 2.0) - labelPadding());
161 161 tickItem->setLine(layout[i], axisRect.bottom(),
162 162 layout[i], axisRect.bottom() - labelPadding());
163 163 }
164 164 } else if (axis()->alignment() == Qt::AlignBottom) {
165 165 if (axis()->isReverse()) {
166 166 labelPos = QPointF(gridRect.right() - layout[layout.size() - i - 1]
167 167 + gridRect.left() - center.x(),
168 168 axisRect.top() - (heightDiff / 2.0) + labelPadding());
169 169 tickItem->setLine(gridRect.right() + gridRect.left() - layout[i], axisRect.top(),
170 170 gridRect.right() + gridRect.left() - layout[i],
171 171 axisRect.top() + labelPadding());
172 172 } else {
173 173 labelPos = QPointF(layout[i] - center.x(), axisRect.top() - (heightDiff / 2.0)
174 174 + labelPadding());
175 175 tickItem->setLine(layout[i], axisRect.top(),
176 176 layout[i], axisRect.top() + labelPadding());
177 177 }
178 178 }
179 179
180 180 //label in between
181 181 bool forceHide = false;
182 182 if (intervalAxis() && (i + 1) != layout.size()) {
183 183 qreal leftBound;
184 184 qreal rightBound;
185 185 if (axis()->isReverse()) {
186 186 leftBound = qMax(gridRect.right() + gridRect.left() - layout[i + 1],
187 187 gridRect.left());
188 188 rightBound = qMin(gridRect.right() + gridRect.left() - layout[i], gridRect.right());
189 189 } else {
190 190 leftBound = qMax(layout[i], gridRect.left());
191 191 rightBound = qMin(layout[i + 1], gridRect.right());
192 192 }
193 193 const qreal delta = rightBound - leftBound;
194 194 if (axis()->type() != QAbstractAxis::AxisTypeCategory) {
195 195 // Hide label in case visible part of the category at the grid edge is too narrow
196 196 if (delta < boundingRect.width()
197 197 && (leftBound == gridRect.left() || rightBound == gridRect.right())) {
198 198 forceHide = true;
199 199 } else {
200 200 labelPos.setX(leftBound + (delta / 2.0) - center.x());
201 201 }
202 202 } else {
203 203 QCategoryAxis *categoryAxis = static_cast<QCategoryAxis *>(axis());
204 204 if (categoryAxis->labelsPosition() == QCategoryAxis::AxisLabelsPositionCenter) {
205 205 if (delta < boundingRect.width()
206 206 && (leftBound == gridRect.left() || rightBound == gridRect.right())) {
207 207 forceHide = true;
208 208 } else {
209 209 labelPos.setX(leftBound + (delta / 2.0) - center.x());
210 210 }
211 211 } else if (categoryAxis->labelsPosition()
212 212 == QCategoryAxis::AxisLabelsPositionOnValue) {
213 213 if (axis()->isReverse())
214 214 labelPos.setX(leftBound - center.x());
215 215 else
216 216 labelPos.setX(rightBound - center.x());
217 217 }
218 218 }
219 219 }
220 220
221 221 // Round to full pixel via QPoint to avoid one pixel clipping on the edge in some cases
222 222 labelItem->setPos(labelPos.toPoint());
223 223
224 224 //label overlap detection - compensate one pixel for rounding errors
225 225 if ((labelItem->pos().x() < width && labelItem->toPlainText() == ellipsis) || forceHide ||
226 226 (labelItem->pos().x() + (widthDiff / 2.0)) < (axisRect.left() - 1.0) ||
227 227 (labelItem->pos().x() + (widthDiff / 2.0) - 1.0) > axisRect.right()) {
228 228 labelItem->setVisible(false);
229 229 } else {
230 230 labelItem->setVisible(true);
231 231 width = boundingRect.width() + labelItem->pos().x();
232 232 }
233 233
234 234 //shades
235 235 QGraphicsRectItem *shadeItem = 0;
236 236 if (i == 0)
237 237 shadeItem = static_cast<QGraphicsRectItem *>(shades.at(0));
238 238 else if (i % 2)
239 239 shadeItem = static_cast<QGraphicsRectItem *>(shades.at((i / 2) + 1));
240 240 if (shadeItem) {
241 241 qreal leftBound;
242 242 qreal rightBound;
243 243 if (i == 0) {
244 244 if (axis()->isReverse()) {
245 245 leftBound = gridRect.right() + gridRect.left() - layout[i];
246 246 rightBound = gridRect.right();
247 247 } else {
248 248 leftBound = gridRect.left();
249 249 rightBound = layout[0];
250 250 }
251 251 } else {
252 252 if (axis()->isReverse()) {
253 253 rightBound = gridRect.right() + gridRect.left() - layout[i];
254 254 if (i == layout.size() - 1) {
255 255 leftBound = gridRect.left();
256 256 } else {
257 257 leftBound = qMax(gridRect.right() + gridRect.left() - layout[i + 1],
258 258 gridRect.left());
259 259 }
260 260 } else {
261 261 leftBound = layout[i];
262 262 if (i == layout.size() - 1)
263 263 rightBound = gridRect.right();
264 264 else
265 265 rightBound = qMin(layout[i + 1], gridRect.right());
266 266 }
267 267 }
268 268 if (leftBound < gridRect.left())
269 269 leftBound = gridRect.left();
270 270 if (rightBound > gridRect.right())
271 271 rightBound = gridRect.right();
272 272 shadeItem->setRect(leftBound, gridRect.top(), rightBound - leftBound,
273 273 gridRect.height());
274 274 if (shadeItem->rect().width() <= 0.0)
275 275 shadeItem->setVisible(false);
276 276 else
277 277 shadeItem->setVisible(true);
278 278 }
279 279
280 280 // check if the grid line and the axis tick should be shown
281 281 qreal x = gridItem->line().p1().x();
282 282 if (x < gridRect.left() || x > gridRect.right()) {
283 283 gridItem->setVisible(false);
284 284 tickItem->setVisible(false);
285 285 } else {
286 286 gridItem->setVisible(true);
287 287 tickItem->setVisible(true);
288 288 }
289 289
290 290 // add minor ticks
291 291 QValueAxis *valueAxis = qobject_cast<QValueAxis *>(axis());
292 292 if ((i + 1) != layout.size() && valueAxis) {
293 293 int minorTickCount = valueAxis->minorTickCount();
294 294 if (minorTickCount != 0) {
295 295 qreal minorTickDistance = (layout[i] - layout[i + 1]) / qreal(minorTickCount + 1);
296 if (axis()->isReverse())
297 minorTickDistance = -minorTickDistance;
296 298 for (int j = 0; j < minorTickCount; j++) {
297 299 QGraphicsLineItem *minorGridItem =
298 300 static_cast<QGraphicsLineItem *>(minorLines.at(i * minorTickCount + j));
299 301 QGraphicsLineItem *minorArrowItem =
300 302 static_cast<QGraphicsLineItem *>(minorArrows.at(i * minorTickCount + j));
301 if (i == 0) {
302 minorGridItem->setLine(gridRect.left() - minorTickDistance * qreal(j + 1),
303 gridRect.top(),
304 gridRect.left() - minorTickDistance * qreal(j + 1),
305 gridRect.bottom());
306 } else {
307 minorGridItem->setLine(gridItem->line().p1().x()
308 - minorTickDistance * qreal(j + 1),
309 gridRect.top(),
310 gridItem->line().p1().x()
311 - minorTickDistance * qreal(j + 1),
312 gridRect.bottom());
313 }
303 minorGridItem->setLine(gridItem->line().p1().x()
304 - minorTickDistance * qreal(j + 1),
305 gridRect.top(),
306 gridItem->line().p1().x()
307 - minorTickDistance * qreal(j + 1),
308 gridRect.bottom());
314 309 if (axis()->alignment() == Qt::AlignTop) {
315 310 minorArrowItem->setLine(minorGridItem->line().p1().x(),
316 311 axisRect.bottom(),
317 312 minorGridItem->line().p1().x(),
318 313 axisRect.bottom() - labelPadding() / 2);
319 314 } else if (axis()->alignment() == Qt::AlignBottom){
320 315 minorArrowItem->setLine(minorGridItem->line().p1().x(),
321 316 axisRect.top(),
322 317 minorGridItem->line().p1().x(),
323 318 axisRect.top() + labelPadding() / 2);
324 319 }
325 320
326 321 // check if the minor grid line and the axis tick should be shown
327 322 qreal minorXPos = minorGridItem->line().p1().x();
328 323 if (minorXPos < gridRect.left() || minorXPos > gridRect.right()) {
329 324 minorGridItem->setVisible(false);
330 325 minorArrowItem->setVisible(false);
331 326 } else {
332 327 minorGridItem->setVisible(true);
333 328 minorArrowItem->setVisible(true);
334 329 }
335 330 }
336 331 }
337 332 }
338 333 }
339 334
340 335 //begin/end grid line in case labels between
341 336 if (intervalAxis()) {
342 337 QGraphicsLineItem *gridLine;
343 338 gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
344 339 gridLine->setLine(gridRect.right(), gridRect.top(), gridRect.right(), gridRect.bottom());
345 340 gridLine->setVisible(true);
346 341 gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size()+1));
347 342 gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.left(), gridRect.bottom());
348 343 gridLine->setVisible(true);
349 344 }
350 345 }
351 346
352 347 QSizeF HorizontalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
353 348 {
354 349 Q_UNUSED(constraint);
355 350 QSizeF sh(0,0);
356 351
357 352 if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
358 353 return sh;
359 354
360 355 switch (which) {
361 356 case Qt::MinimumSize: {
362 357 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(),
363 358 QStringLiteral("..."));
364 359 sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2.0));
365 360 break;
366 361 }
367 362 case Qt::MaximumSize:
368 363 case Qt::PreferredSize: {
369 364 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), axis()->titleText());
370 365 sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2.0));
371 366 break;
372 367 }
373 368 default:
374 369 break;
375 370 }
376 371
377 372 return sh;
378 373 }
379 374
380 375 QT_CHARTS_END_NAMESPACE
@@ -1,395 +1,390
1 1 /******************************************************************************
2 2 **
3 3 ** Copyright (C) 2015 The Qt Company Ltd.
4 4 ** Contact: http://www.qt.io/licensing/
5 5 **
6 6 ** This file is part of the Qt Charts module.
7 7 **
8 8 ** $QT_BEGIN_LICENSE:COMM$
9 9 **
10 10 ** Commercial License Usage
11 11 ** Licensees holding valid commercial Qt licenses may use this file in
12 12 ** accordance with the commercial license agreement provided with the
13 13 ** Software or, alternatively, in accordance with the terms contained in
14 14 ** a written agreement between you and The Qt Company. For licensing terms
15 15 ** and conditions see http://www.qt.io/terms-conditions. For further
16 16 ** information use the contact form at http://www.qt.io/contact-us.
17 17 **
18 18 ** $QT_END_LICENSE$
19 19 **
20 20 ******************************************************************************/
21 21
22 22 #include <private/verticalaxis_p.h>
23 23 #include <QtCharts/QAbstractAxis>
24 24 #include <private/chartpresenter_p.h>
25 25 #include <QtCharts/QCategoryAxis>
26 26 #include <QtCore/QDebug>
27 27
28 28 QT_CHARTS_BEGIN_NAMESPACE
29 29
30 30 VerticalAxis::VerticalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
31 31 : CartesianChartAxis(axis, item, intervalAxis)
32 32 {
33 33 }
34 34
35 35 VerticalAxis::~VerticalAxis()
36 36 {
37 37 }
38 38
39 39 void VerticalAxis::updateGeometry()
40 40 {
41 41 const QVector<qreal> &layout = ChartAxisElement::layout();
42 42
43 43 if (layout.isEmpty() && axis()->type() != QAbstractAxis::AxisTypeLogValue)
44 44 return;
45 45
46 46 QStringList labelList = labels();
47 47
48 48 QList<QGraphicsItem *> labels = labelItems();
49 49 QList<QGraphicsItem *> arrow = arrowItems();
50 50 QGraphicsTextItem *title = titleItem();
51 51
52 52 Q_ASSERT(labels.size() == labelList.size());
53 53 Q_ASSERT(layout.size() == labelList.size());
54 54
55 55 const QRectF &axisRect = axisGeometry();
56 56 const QRectF &gridRect = gridGeometry();
57 57
58 58 qreal height = axisRect.bottom();
59 59
60 60 //arrow
61 61 QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem*>(arrow.at(0));
62 62
63 63 //arrow position
64 64 if (axis()->alignment() == Qt::AlignLeft)
65 65 arrowItem->setLine(axisRect.right(), gridRect.top(), axisRect.right(), gridRect.bottom());
66 66 else if (axis()->alignment() == Qt::AlignRight)
67 67 arrowItem->setLine(axisRect.left(), gridRect.top(), axisRect.left(), gridRect.bottom());
68 68
69 69 //title
70 70 QRectF titleBoundingRect;
71 71 QString titleText = axis()->titleText();
72 72 qreal availableSpace = axisRect.width() - labelPadding();
73 73 if (!titleText.isEmpty() && titleItem()->isVisible()) {
74 74 availableSpace -= titlePadding() * 2.0;
75 75 qreal minimumLabelWidth = ChartPresenter::textBoundingRect(axis()->labelsFont(),
76 76 QStringLiteral("...")).width();
77 77 qreal titleSpace = availableSpace - minimumLabelWidth;
78 78 title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(90.0),
79 79 titleSpace, gridRect.height(),
80 80 titleBoundingRect));
81 81 title->setTextWidth(titleBoundingRect.height());
82 82
83 83 titleBoundingRect = title->boundingRect();
84 84
85 85 QPointF center = gridRect.center() - titleBoundingRect.center();
86 86 if (axis()->alignment() == Qt::AlignLeft)
87 87 title->setPos(axisRect.left() - titleBoundingRect.width() / 2.0 + titleBoundingRect.height() / 2.0 + titlePadding(), center.y());
88 88 else if (axis()->alignment() == Qt::AlignRight)
89 89 title->setPos(axisRect.right() - titleBoundingRect.width() / 2.0 - titleBoundingRect.height() / 2.0 - titlePadding(), center.y());
90 90
91 91 title->setTransformOriginPoint(titleBoundingRect.center());
92 92 title->setRotation(270);
93 93
94 94 availableSpace -= titleBoundingRect.height();
95 95 }
96 96
97 97 if (layout.isEmpty() && axis()->type() == QAbstractAxis::AxisTypeLogValue)
98 98 return;
99 99
100 100 QList<QGraphicsItem *> lines = gridItems();
101 101 QList<QGraphicsItem *> shades = shadeItems();
102 102 QList<QGraphicsItem *> minorLines = minorGridItems();
103 103 QList<QGraphicsItem *> minorArrows = minorArrowItems();
104 104
105 105 for (int i = 0; i < layout.size(); ++i) {
106 106 //items
107 107 QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem *>(lines.at(i));
108 108 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrow.at(i + 1));
109 109 QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labels.at(i));
110 110
111 111 //grid line
112 112 if (axis()->isReverse()) {
113 113 gridItem->setLine(gridRect.left(), gridRect.top() + gridRect.bottom() - layout[i],
114 114 gridRect.right(), gridRect.top() + gridRect.bottom() - layout[i]);
115 115 } else {
116 116 gridItem->setLine(gridRect.left(), layout[i], gridRect.right(), layout[i]);
117 117 }
118 118
119 119 //label text wrapping
120 120 QString text;
121 121 if (axis()->isReverse() && axis()->type() != QAbstractAxis::AxisTypeCategory)
122 122 text = labelList.at(labelList.count() - i - 1);
123 123 else
124 124 text = labelList.at(i);
125 125
126 126 QRectF boundingRect;
127 127 // don't truncate empty labels
128 128 if (text.isEmpty()) {
129 129 labelItem->setHtml(text);
130 130 } else {
131 131 qreal labelHeight = (axisRect.height() / layout.count()) - (2 * labelPadding());
132 132 QString truncatedText = ChartPresenter::truncatedText(axis()->labelsFont(), text,
133 133 axis()->labelsAngle(),
134 134 availableSpace,
135 135 labelHeight, boundingRect);
136 136 labelItem->setTextWidth(ChartPresenter::textBoundingRect(axis()->labelsFont(),
137 137 truncatedText).width());
138 138 labelItem->setHtml(truncatedText);
139 139 }
140 140
141 141 //label transformation origin point
142 142 const QRectF &rect = labelItem->boundingRect();
143 143 QPointF center = rect.center();
144 144 labelItem->setTransformOriginPoint(center.x(), center.y());
145 145 qreal widthDiff = rect.width() - boundingRect.width();
146 146 qreal heightDiff = rect.height() - boundingRect.height();
147 147
148 148 //ticks and label position
149 149 QPointF labelPos;
150 150 if (axis()->alignment() == Qt::AlignLeft) {
151 151 if (axis()->isReverse()) {
152 152 labelPos = QPointF(axisRect.right() - rect.width() + (widthDiff / 2.0)
153 153 - labelPadding(),
154 154 gridRect.top() + gridRect.bottom()
155 155 - layout[layout.size() - i - 1] - center.y());
156 156 tickItem->setLine(axisRect.right() - labelPadding(),
157 157 gridRect.top() + gridRect.bottom() - layout[i],
158 158 axisRect.right(),
159 159 gridRect.top() + gridRect.bottom() - layout[i]);
160 160 } else {
161 161 labelPos = QPointF(axisRect.right() - rect.width() + (widthDiff / 2.0)
162 162 - labelPadding(),
163 163 layout[i] - center.y());
164 164 tickItem->setLine(axisRect.right() - labelPadding(), layout[i],
165 165 axisRect.right(), layout[i]);
166 166 }
167 167 } else if (axis()->alignment() == Qt::AlignRight) {
168 168 if (axis()->isReverse()) {
169 169 tickItem->setLine(axisRect.left(),
170 170 gridRect.top() + gridRect.bottom() - layout[i],
171 171 axisRect.left() + labelPadding(),
172 172 gridRect.top() + gridRect.bottom() - layout[i]);
173 173 labelPos = QPointF(axisRect.left() + labelPadding() - (widthDiff / 2.0),
174 174 gridRect.top() + gridRect.bottom()
175 175 - layout[layout.size() - i - 1] - center.y());
176 176 } else {
177 177 labelPos = QPointF(axisRect.left() + labelPadding() - (widthDiff / 2.0),
178 178 layout[i] - center.y());
179 179 tickItem->setLine(axisRect.left(), layout[i],
180 180 axisRect.left() + labelPadding(), layout[i]);
181 181 }
182 182 }
183 183
184 184 //label in between
185 185 bool forceHide = false;
186 186 bool labelOnValue = false;
187 187 if (intervalAxis() && (i + 1) != layout.size()) {
188 188 qreal lowerBound;
189 189 qreal upperBound;
190 190 if (axis()->isReverse()) {
191 191 lowerBound = qMax(gridRect.top() + gridRect.bottom() - layout[i + 1],
192 192 gridRect.top());
193 193 upperBound = qMin(gridRect.top() + gridRect.bottom() - layout[i],
194 194 gridRect.bottom());
195 195 } else {
196 196 lowerBound = qMin(layout[i], gridRect.bottom());
197 197 upperBound = qMax(layout[i + 1], gridRect.top());
198 198 }
199 199 const qreal delta = lowerBound - upperBound;
200 200 if (axis()->type() != QAbstractAxis::AxisTypeCategory) {
201 201 // Hide label in case visible part of the category at the grid edge is too narrow
202 202 if (delta < boundingRect.height()
203 203 && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())) {
204 204 forceHide = true;
205 205 } else {
206 206 labelPos.setY(lowerBound - (delta / 2.0) - center.y());
207 207 }
208 208 } else {
209 209 QCategoryAxis *categoryAxis = static_cast<QCategoryAxis *>(axis());
210 210 if (categoryAxis->labelsPosition() == QCategoryAxis::AxisLabelsPositionCenter) {
211 211 if (delta < boundingRect.height()
212 212 && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())) {
213 213 forceHide = true;
214 214 } else {
215 215 labelPos.setY(lowerBound - (delta / 2.0) - center.y());
216 216 }
217 217 } else if (categoryAxis->labelsPosition()
218 218 == QCategoryAxis::AxisLabelsPositionOnValue) {
219 219 labelOnValue = true;
220 220 if (axis()->isReverse()) {
221 221 labelPos.setY(gridRect.top() + gridRect.bottom()
222 222 - layout[i + 1] - center.y());
223 223 } else {
224 224 labelPos.setY(upperBound - center.y());
225 225 }
226 226 }
227 227 }
228 228 }
229 229
230 230 // Round to full pixel via QPoint to avoid one pixel clipping on the edge in some cases
231 231 labelItem->setPos(labelPos.toPoint());
232 232
233 233 //label overlap detection - compensate one pixel for rounding errors
234 234 if (axis()->isReverse()) {
235 235 if (forceHide)
236 236 labelItem->setVisible(false);
237 237 } else if (labelItem->pos().y() + boundingRect.height() > height || forceHide ||
238 238 ((labelItem->pos().y() + (heightDiff / 2.0) - 1.0) > axisRect.bottom()
239 239 && !labelOnValue) ||
240 240 (labelItem->pos().y() + (heightDiff / 2.0) < (axisRect.top() - 1.0) && !labelOnValue)) {
241 241 labelItem->setVisible(false);
242 242 }
243 243 else {
244 244 labelItem->setVisible(true);
245 245 height=labelItem->pos().y();
246 246 }
247 247
248 248 //shades
249 249 QGraphicsRectItem *shadeItem = 0;
250 250 if (i == 0)
251 251 shadeItem = static_cast<QGraphicsRectItem *>(shades.at(0));
252 252 else if (i % 2)
253 253 shadeItem = static_cast<QGraphicsRectItem *>(shades.at((i / 2) + 1));
254 254 if (shadeItem) {
255 255 qreal lowerBound;
256 256 qreal upperBound;
257 257 if (i == 0) {
258 258 if (axis()->isReverse()) {
259 259 upperBound = gridRect.top();
260 260 lowerBound = gridRect.top() + gridRect.bottom() - layout[i];
261 261 } else {
262 262 lowerBound = gridRect.bottom();
263 263 upperBound = layout[0];
264 264 }
265 265 } else {
266 266 if (axis()->isReverse()) {
267 267 upperBound = gridRect.top() + gridRect.bottom() - layout[i];
268 268 if (i == layout.size() - 1) {
269 269 lowerBound = gridRect.bottom();
270 270 } else {
271 271 lowerBound = qMax(gridRect.top() + gridRect.bottom() - layout[i + 1],
272 272 gridRect.top());
273 273 }
274 274 } else {
275 275 lowerBound = layout[i];
276 276 if (i == layout.size() - 1)
277 277 upperBound = gridRect.top();
278 278 else
279 279 upperBound = qMax(layout[i + 1], gridRect.top());
280 280 }
281 281
282 282 }
283 283 if (lowerBound > gridRect.bottom())
284 284 lowerBound = gridRect.bottom();
285 285 if (upperBound < gridRect.top())
286 286 upperBound = gridRect.top();
287 287 shadeItem->setRect(gridRect.left(), upperBound, gridRect.width(),
288 288 lowerBound - upperBound);
289 289 if (shadeItem->rect().height() <= 0.0)
290 290 shadeItem->setVisible(false);
291 291 else
292 292 shadeItem->setVisible(true);
293 293 }
294 294
295 295 // check if the grid line and the axis tick should be shown
296 296 qreal y = gridItem->line().p1().y();
297 297 if ((y < gridRect.top() || y > gridRect.bottom()))
298 298 {
299 299 gridItem->setVisible(false);
300 300 tickItem->setVisible(false);
301 301 }else{
302 302 gridItem->setVisible(true);
303 303 tickItem->setVisible(true);
304 304 }
305 305
306 306 // add minor ticks
307 307 QValueAxis *valueAxis = qobject_cast<QValueAxis *>(axis());
308 308 if ((i + 1) != layout.size() && valueAxis) {
309 309 int minorTickCount = valueAxis->minorTickCount();
310 310 if (minorTickCount != 0) {
311 311 qreal minorTickDistance = (layout[i] - layout[i + 1]) / qreal(minorTickCount + 1);
312 if (axis()->isReverse())
313 minorTickDistance = -minorTickDistance;
312 314 for (int j = 0; j < minorTickCount; j++) {
313 315 QGraphicsLineItem *minorGridItem =
314 316 static_cast<QGraphicsLineItem *>(minorLines.at(i * minorTickCount + j));
315 317 QGraphicsLineItem *minorArrowItem =
316 318 static_cast<QGraphicsLineItem *>(minorArrows.at(i * minorTickCount + j));
317 if (i == 0) {
318 minorGridItem->setLine(gridRect.left(),
319 gridRect.bottom() - minorTickDistance * qreal(j + 1),
320 gridRect.right(),
321 gridRect.bottom() - minorTickDistance * qreal(j + 1));
322 } else {
323 minorGridItem->setLine(gridRect.left(),
324 gridItem->line().p1().y()
325 - minorTickDistance * qreal(j + 1),
326 gridRect.right(),
327 gridItem->line().p1().y()
328 - minorTickDistance * qreal(j + 1));
329 }
319 minorGridItem->setLine(gridRect.left(),
320 gridItem->line().p1().y()
321 - minorTickDistance * qreal(j + 1),
322 gridRect.right(),
323 gridItem->line().p1().y()
324 - minorTickDistance * qreal(j + 1));
330 325 if (axis()->alignment() == Qt::AlignLeft) {
331 326 minorArrowItem->setLine(gridRect.left() - labelPadding() / 2,
332 327 minorGridItem->line().p1().y(),
333 328 gridRect.left(),
334 329 minorGridItem->line().p1().y());
335 330 } else if (axis()->alignment() == Qt::AlignRight){
336 331 minorArrowItem->setLine(gridRect.right(),
337 332 minorGridItem->line().p1().y(),
338 333 gridRect.right() + labelPadding() / 2,
339 334 minorGridItem->line().p1().y());
340 335 }
341 336
342 337 // check if the minor grid line and the axis tick should be shown
343 338 qreal minorYPos = minorGridItem->line().p1().y();
344 339 if (minorYPos < gridRect.top() || minorYPos > gridRect.bottom()) {
345 340 minorGridItem->setVisible(false);
346 341 minorArrowItem->setVisible(false);
347 342 } else {
348 343 minorGridItem->setVisible(true);
349 344 minorArrowItem->setVisible(true);
350 345 }
351 346 }
352 347 }
353 348 }
354 349 }
355 350 //begin/end grid line in case labels between
356 351 if (intervalAxis()) {
357 352 QGraphicsLineItem *gridLine;
358 353 gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
359 354 gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.right(), gridRect.top());
360 355 gridLine->setVisible(true);
361 356 gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size() + 1));
362 357 gridLine->setLine(gridRect.left(), gridRect.bottom(), gridRect.right(), gridRect.bottom());
363 358 gridLine->setVisible(true);
364 359 }
365 360 }
366 361
367 362 QSizeF VerticalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
368 363 {
369 364 Q_UNUSED(constraint);
370 365 QSizeF sh(0, 0);
371 366
372 367 if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
373 368 return sh;
374 369
375 370 switch (which) {
376 371 case Qt::MinimumSize: {
377 372 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(),
378 373 QStringLiteral("..."));
379 374 sh = QSizeF(titleRect.height() + (titlePadding() * 2.0), titleRect.width());
380 375 break;
381 376 }
382 377 case Qt::MaximumSize:
383 378 case Qt::PreferredSize: {
384 379 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), axis()->titleText());
385 380 sh = QSizeF(titleRect.height() + (titlePadding() * 2.0), titleRect.width());
386 381 break;
387 382 }
388 383 default:
389 384 break;
390 385 }
391 386
392 387 return sh;
393 388 }
394 389
395 390 QT_CHARTS_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now