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