##// END OF EJS Templates
Fix QLogValueAxis update...
Titta Heikkala -
r2759:8e20d47d8440
parent child
Show More
@@ -1,240 +1,244
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2014 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.io
6 6 **
7 7 ** This file is part of the Qt Charts module.
8 8 **
9 9 ** Licensees holding valid commercial license for Qt may use this file in
10 10 ** accordance with the Qt License Agreement provided with the Software
11 11 ** or, alternatively, in accordance with the terms contained in a written
12 12 ** agreement between you and Digia.
13 13 **
14 14 ** If you have questions regarding the use of this file, please use
15 15 ** contact form at http://qt.io
16 16 **
17 17 ****************************************************************************/
18 18
19 19 #include <private/horizontalaxis_p.h>
20 20 #include <private/qabstractaxis_p.h>
21 21 #include <private/chartpresenter_p.h>
22 22 #include <QtCore/QtMath>
23 23 #include <QtCore/QDebug>
24 24
25 25 QT_CHARTS_BEGIN_NAMESPACE
26 26
27 27 HorizontalAxis::HorizontalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
28 28 : CartesianChartAxis(axis, item, intervalAxis)
29 29 {
30 30 }
31 31
32 32 HorizontalAxis::~HorizontalAxis()
33 33 {
34 34 }
35 35
36 36 void HorizontalAxis::updateGeometry()
37 37 {
38 38 const QVector<qreal> &layout = ChartAxisElement::layout();
39 39
40 if (layout.isEmpty())
40 if (layout.isEmpty() && axis()->type() != QAbstractAxis::AxisTypeLogValue)
41 41 return;
42 42
43 43 QStringList labelList = labels();
44 44
45 QList<QGraphicsItem *> lines = gridItems();
46 45 QList<QGraphicsItem *> labels = labelItems();
47 QList<QGraphicsItem *> shades = shadeItems();
48 46 QList<QGraphicsItem *> arrow = arrowItems();
49 47 QGraphicsTextItem *title = titleItem();
50 48
51 49 Q_ASSERT(labels.size() == labelList.size());
52 50 Q_ASSERT(layout.size() == labelList.size());
53 51
54 52 const QRectF &axisRect = axisGeometry();
55 53 const QRectF &gridRect = gridGeometry();
56 54
57 55 //arrow
58 56 QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem *>(arrow.at(0));
59 57
60 58 if (axis()->alignment() == Qt::AlignTop)
61 59 arrowItem->setLine(gridRect.left(), axisRect.bottom(), gridRect.right(), axisRect.bottom());
62 60 else if (axis()->alignment() == Qt::AlignBottom)
63 61 arrowItem->setLine(gridRect.left(), axisRect.top(), gridRect.right(), axisRect.top());
64 62
65 63 qreal width = 0;
66 64 const QLatin1String ellipsis("...");
67 65
68 66 //title
69 67 QRectF titleBoundingRect;
70 68 QString titleText = axis()->titleText();
71 69 qreal availableSpace = axisRect.height() - labelPadding();
72 70 if (!titleText.isEmpty() && titleItem()->isVisible()) {
73 71 availableSpace -= titlePadding() * 2.0;
74 72 qreal minimumLabelHeight = ChartPresenter::textBoundingRect(axis()->labelsFont(),
75 73 QStringLiteral("...")).height();
76 74 qreal titleSpace = availableSpace - minimumLabelHeight;
77 75 title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(0.0),
78 76 gridRect.width(), titleSpace,
79 77 titleBoundingRect));
80 78 title->setTextWidth(titleBoundingRect.width());
81 79
82 80 titleBoundingRect = title->boundingRect();
83 81
84 82 QPointF center = gridRect.center() - titleBoundingRect.center();
85 83 if (axis()->alignment() == Qt::AlignTop)
86 84 title->setPos(center.x(), axisRect.top() + titlePadding());
87 85 else if (axis()->alignment() == Qt::AlignBottom)
88 86 title->setPos(center.x(), axisRect.bottom() - titleBoundingRect.height() - titlePadding());
89 87
90 88 availableSpace -= titleBoundingRect.height();
91 89 }
92 90
91 if (layout.isEmpty() && axis()->type() == QAbstractAxis::AxisTypeLogValue)
92 return;
93
94 QList<QGraphicsItem *> lines = gridItems();
95 QList<QGraphicsItem *> shades = shadeItems();
96
93 97 for (int i = 0; i < layout.size(); ++i) {
94 98 //items
95 99 QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem*>(lines.at(i));
96 100 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem*>(arrow.at(i + 1));
97 101 QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labels.at(i));
98 102
99 103 //grid line
100 104 gridItem->setLine(layout[i], gridRect.top(), layout[i], gridRect.bottom());
101 105
102 106 //label text wrapping
103 107 QString text = labelList.at(i);
104 108 QRectF boundingRect;
105 109 // don't truncate empty labels
106 110 if (text.isEmpty()) {
107 111 labelItem->setHtml(text);
108 112 } else {
109 113 qreal labelWidth = axisRect.width() / layout.count() - (2 * labelPadding());
110 114 QString truncatedText = ChartPresenter::truncatedText(axis()->labelsFont(), text,
111 115 axis()->labelsAngle(),
112 116 labelWidth,
113 117 availableSpace, boundingRect);
114 118 labelItem->setTextWidth(ChartPresenter::textBoundingRect(axis()->labelsFont(),
115 119 truncatedText).width());
116 120 labelItem->setHtml(truncatedText);
117 121 }
118 122
119 123 //label transformation origin point
120 124 const QRectF& rect = labelItem->boundingRect();
121 125 QPointF center = rect.center();
122 126 labelItem->setTransformOriginPoint(center.x(), center.y());
123 127 qreal heightDiff = rect.height() - boundingRect.height();
124 128 qreal widthDiff = rect.width() - boundingRect.width();
125 129
126 130 //ticks and label position
127 131 if (axis()->alignment() == Qt::AlignTop) {
128 132 labelItem->setPos(layout[i] - center.x(), axisRect.bottom() - rect.height() + (heightDiff / 2.0) - labelPadding());
129 133 tickItem->setLine(layout[i], axisRect.bottom(), layout[i], axisRect.bottom() - labelPadding());
130 134 } else if (axis()->alignment() == Qt::AlignBottom) {
131 135 labelItem->setPos(layout[i] - center.x(), axisRect.top() - (heightDiff / 2.0) + labelPadding());
132 136 tickItem->setLine(layout[i], axisRect.top(), layout[i], axisRect.top() + labelPadding());
133 137 }
134 138
135 139 //label in between
136 140 bool forceHide = false;
137 141 if (intervalAxis() && (i + 1) != layout.size()) {
138 142 qreal leftBound = qMax(layout[i], gridRect.left());
139 143 qreal rightBound = qMin(layout[i + 1], gridRect.right());
140 144 const qreal delta = rightBound - leftBound;
141 145 // Hide label in case visible part of the category at the grid edge is too narrow
142 146 if (delta < boundingRect.width()
143 147 && (leftBound == gridRect.left() || rightBound == gridRect.right())
144 148 && !intervalAxis()) {
145 149 forceHide = true;
146 150 } else {
147 151 labelItem->setPos(leftBound + (delta / 2.0) - center.x(), labelItem->pos().y());
148 152 }
149 153 }
150 154
151 155 //label overlap detection - compensate one pixel for rounding errors
152 156 if ((labelItem->pos().x() < width && labelItem->toPlainText() == ellipsis) || forceHide ||
153 157 (labelItem->pos().x() + (widthDiff / 2.0)) < (axisRect.left() - 1.0) ||
154 158 (labelItem->pos().x() + (widthDiff / 2.0) - 1.0) > axisRect.right()) {
155 159 labelItem->setVisible(false);
156 160 } else {
157 161 labelItem->setVisible(true);
158 162 width = boundingRect.width() + labelItem->pos().x();
159 163 }
160 164
161 165 //shades
162 166 QGraphicsRectItem *shadeItem = 0;
163 167 if (i == 0)
164 168 shadeItem = static_cast<QGraphicsRectItem *>(shades.at(0));
165 169 else if (i % 2)
166 170 shadeItem = static_cast<QGraphicsRectItem *>(shades.at((i / 2) + 1));
167 171 if (shadeItem) {
168 172 qreal leftBound;
169 173 qreal rightBound;
170 174 if (i == 0) {
171 175 leftBound = gridRect.left();
172 176 rightBound = layout[0];
173 177 } else {
174 178 leftBound = layout[i];
175 179 if (i == layout.size() - 1)
176 180 rightBound = gridRect.right();
177 181 else
178 182 rightBound = qMin(layout[i + 1], gridRect.right());
179 183 }
180 184 shadeItem->setRect(leftBound, gridRect.top(), rightBound - leftBound,
181 185 gridRect.height());
182 186 if (shadeItem->rect().width() <= 0.0)
183 187 shadeItem->setVisible(false);
184 188 else
185 189 shadeItem->setVisible(true);
186 190 }
187 191
188 192 // check if the grid line and the axis tick should be shown
189 193 qreal x = gridItem->line().p1().x();
190 194 if (x < gridRect.left() || x > gridRect.right()) {
191 195 gridItem->setVisible(false);
192 196 tickItem->setVisible(false);
193 197 } else {
194 198 gridItem->setVisible(true);
195 199 tickItem->setVisible(true);
196 200 }
197 201
198 202 }
199 203
200 204 //begin/end grid line in case labels between
201 205 if (intervalAxis()) {
202 206 QGraphicsLineItem *gridLine;
203 207 gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
204 208 gridLine->setLine(gridRect.right(), gridRect.top(), gridRect.right(), gridRect.bottom());
205 209 gridLine->setVisible(true);
206 210 gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size()+1));
207 211 gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.left(), gridRect.bottom());
208 212 gridLine->setVisible(true);
209 213 }
210 214 }
211 215
212 216 QSizeF HorizontalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
213 217 {
214 218 Q_UNUSED(constraint);
215 219 QSizeF sh(0,0);
216 220
217 221 if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
218 222 return sh;
219 223
220 224 switch (which) {
221 225 case Qt::MinimumSize: {
222 226 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(),
223 227 QStringLiteral("..."));
224 228 sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2.0));
225 229 break;
226 230 }
227 231 case Qt::MaximumSize:
228 232 case Qt::PreferredSize: {
229 233 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), axis()->titleText());
230 234 sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2.0));
231 235 break;
232 236 }
233 237 default:
234 238 break;
235 239 }
236 240
237 241 return sh;
238 242 }
239 243
240 244 QT_CHARTS_END_NAMESPACE
@@ -1,137 +1,135
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2014 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.io
6 6 **
7 7 ** This file is part of the Qt Charts module.
8 8 **
9 9 ** Licensees holding valid commercial license for Qt may use this file in
10 10 ** accordance with the Qt License Agreement provided with the Software
11 11 ** or, alternatively, in accordance with the terms contained in a written
12 12 ** agreement between you and Digia.
13 13 **
14 14 ** If you have questions regarding the use of this file, please use
15 15 ** contact form at http://qt.io
16 16 **
17 17 ****************************************************************************/
18 18
19 19 #include <private/chartlogvalueaxisx_p.h>
20 20 #include <private/chartpresenter_p.h>
21 21 #include <QtCharts/QLogValueAxis>
22 22 #include <private/abstractchartlayout_p.h>
23 23 #include <QtWidgets/QGraphicsLayout>
24 24 #include <QtCore/QtMath>
25 25 #include <QtCore/QDebug>
26 26
27 27 QT_CHARTS_BEGIN_NAMESPACE
28 28
29 29 ChartLogValueAxisX::ChartLogValueAxisX(QLogValueAxis *axis, QGraphicsItem *item)
30 30 : HorizontalAxis(axis, item),
31 31 m_axis(axis)
32 32 {
33 33 QObject::connect(m_axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
34 34 QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
35 35 }
36 36
37 37 ChartLogValueAxisX::~ChartLogValueAxisX()
38 38 {
39 39 }
40 40
41 41 QVector<qreal> ChartLogValueAxisX::calculateLayout() const
42 42 {
43 43 QVector<qreal> points;
44 44
45 45 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
46 46 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
47 47 qreal leftEdge = logMin < logMax ? logMin : logMax;
48 48 qreal ceilEdge = ceil(leftEdge);
49 49 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
50 50
51 points.resize(tickCount + 1);
51 points.resize(tickCount);
52 52 const QRectF &gridRect = gridGeometry();
53 53 const qreal deltaX = gridRect.width() / qAbs(logMax - logMin);
54 for (int i = 0; i <= tickCount; ++i)
54 for (int i = 0; i < tickCount; ++i)
55 55 points[i] = (ceilEdge + qreal(i)) * deltaX - leftEdge * deltaX + gridRect.left();
56 56
57 57 return points;
58 58 }
59 59
60 60 void ChartLogValueAxisX::updateGeometry()
61 61 {
62 62 const QVector<qreal>& layout = ChartAxisElement::layout();
63 if (layout.isEmpty())
64 return;
65 63 setLabels(createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), layout.size(), m_axis->labelFormat()));
66 64 HorizontalAxis::updateGeometry();
67 65 }
68 66
69 67 void ChartLogValueAxisX::handleBaseChanged(qreal base)
70 68 {
71 69 Q_UNUSED(base);
72 70 QGraphicsLayoutItem::updateGeometry();
73 71 if(presenter()) presenter()->layout()->invalidate();
74 72 }
75 73
76 74 void ChartLogValueAxisX::handleLabelFormatChanged(const QString &format)
77 75 {
78 76 Q_UNUSED(format);
79 77 QGraphicsLayoutItem::updateGeometry();
80 78 if(presenter()) presenter()->layout()->invalidate();
81 79 }
82 80
83 81 QSizeF ChartLogValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
84 82 {
85 83 Q_UNUSED(constraint)
86 84
87 85 QSizeF sh;
88 86
89 87 QSizeF base = HorizontalAxis::sizeHint(which, constraint);
90 88 QStringList ticksList;
91 89 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
92 90 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
93 91 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
94 92 if (m_axis->max() > m_axis->min() && tickCount > 0)
95 93 ticksList = createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), tickCount, m_axis->labelFormat());
96 94 else
97 95 ticksList.append(QStringLiteral(" "));
98 96 // Width of horizontal axis sizeHint indicates the maximum distance labels can extend past
99 97 // first and last ticks. Base width is irrelevant.
100 98 qreal width = 0;
101 99 qreal height = 0;
102 100
103 101 switch (which) {
104 102 case Qt::MinimumSize:{
105 103 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
106 104 QStringLiteral("..."),
107 105 axis()->labelsAngle());
108 106 width = boundingRect.width() / 2.0;
109 107 height = boundingRect.height() + labelPadding() + base.height() + 1.0;
110 108 sh = QSizeF(width, height);
111 109 break;
112 110 }
113 111 case Qt::PreferredSize: {
114 112 qreal labelHeight = 0.0;
115 113 qreal firstWidth = -1.0;
116 114 foreach (const QString& s, ticksList) {
117 115 QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
118 116 labelHeight = qMax(rect.height(), labelHeight);
119 117 width = rect.width();
120 118 if (firstWidth < 0.0)
121 119 firstWidth = width;
122 120 }
123 121 height = labelHeight + labelPadding() + base.height() + 1.0;
124 122 width = qMax(width, firstWidth) / 2.0;
125 123 sh = QSizeF(width, height);
126 124 break;
127 125 }
128 126 default:
129 127 break;
130 128 }
131 129
132 130 return sh;
133 131 }
134 132
135 133 #include "moc_chartlogvalueaxisx_p.cpp"
136 134
137 135 QT_CHARTS_END_NAMESPACE
@@ -1,137 +1,135
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2014 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.io
6 6 **
7 7 ** This file is part of the Qt Charts module.
8 8 **
9 9 ** Licensees holding valid commercial license for Qt may use this file in
10 10 ** accordance with the Qt License Agreement provided with the Software
11 11 ** or, alternatively, in accordance with the terms contained in a written
12 12 ** agreement between you and Digia.
13 13 **
14 14 ** If you have questions regarding the use of this file, please use
15 15 ** contact form at http://qt.io
16 16 **
17 17 ****************************************************************************/
18 18
19 19 #include <private/chartlogvalueaxisy_p.h>
20 20 #include <private/chartpresenter_p.h>
21 21 #include <QtCharts/QLogValueAxis>
22 22 #include <private/abstractchartlayout_p.h>
23 23 #include <QtWidgets/QGraphicsLayout>
24 24 #include <QtCore/QtMath>
25 25 #include <QtCore/QDebug>
26 26
27 27 QT_CHARTS_BEGIN_NAMESPACE
28 28
29 29 ChartLogValueAxisY::ChartLogValueAxisY(QLogValueAxis *axis, QGraphicsItem *item)
30 30 : VerticalAxis(axis, item),
31 31 m_axis(axis)
32 32 {
33 33 QObject::connect(m_axis, SIGNAL(baseChanged(qreal)), this, SLOT(handleBaseChanged(qreal)));
34 34 QObject::connect(m_axis, SIGNAL(labelFormatChanged(QString)), this, SLOT(handleLabelFormatChanged(QString)));
35 35 }
36 36
37 37 ChartLogValueAxisY::~ChartLogValueAxisY()
38 38 {
39 39 }
40 40
41 41 QVector<qreal> ChartLogValueAxisY::calculateLayout() const
42 42 {
43 43 QVector<qreal> points;
44 44 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
45 45 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
46 46 qreal leftEdge = logMin < logMax ? logMin : logMax;
47 47 qreal ceilEdge = ceil(leftEdge);
48 48 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
49 49
50 points.resize(tickCount + 1);
50 points.resize(tickCount);
51 51 const QRectF &gridRect = gridGeometry();
52 52 const qreal deltaY = gridRect.height() / qAbs(logMax - logMin);
53 for (int i = 0; i <= tickCount; ++i)
53 for (int i = 0; i < tickCount; ++i)
54 54 points[i] = (ceilEdge + qreal(i)) * -deltaY - leftEdge * -deltaY + gridRect.bottom();
55 55
56 56 return points;
57 57 }
58 58
59 59
60 60 void ChartLogValueAxisY::updateGeometry()
61 61 {
62 62 const QVector<qreal> &layout = ChartAxisElement::layout();
63 if (layout.isEmpty())
64 return;
65 63 setLabels(createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), layout.size(), m_axis->labelFormat()));
66 64 VerticalAxis::updateGeometry();
67 65 }
68 66
69 67 void ChartLogValueAxisY::handleBaseChanged(qreal base)
70 68 {
71 69 Q_UNUSED(base);
72 70 QGraphicsLayoutItem::updateGeometry();
73 71 if(presenter()) presenter()->layout()->invalidate();
74 72 }
75 73
76 74 void ChartLogValueAxisY::handleLabelFormatChanged(const QString &format)
77 75 {
78 76 Q_UNUSED(format);
79 77 QGraphicsLayoutItem::updateGeometry();
80 78 if(presenter()) presenter()->layout()->invalidate();
81 79 }
82 80
83 81 QSizeF ChartLogValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
84 82 {
85 83 Q_UNUSED(constraint)
86 84
87 85 QSizeF sh;
88 86
89 87 QSizeF base = VerticalAxis::sizeHint(which, constraint);
90 88 QStringList ticksList;
91 89 qreal logMax = log10(m_axis->max()) / log10(m_axis->base());
92 90 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
93 91 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
94 92 if (m_axis->max() > m_axis->min() && tickCount > 0)
95 93 ticksList = createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), tickCount, m_axis->labelFormat());
96 94 else
97 95 ticksList.append(QStringLiteral(" "));
98 96 qreal width = 0;
99 97 // Height of vertical axis sizeHint indicates the maximum distance labels can extend past
100 98 // first and last ticks. Base height is irrelevant.
101 99 qreal height = 0;
102 100
103 101 switch (which) {
104 102 case Qt::MinimumSize: {
105 103 QRectF boundingRect = ChartPresenter::textBoundingRect(axis()->labelsFont(),
106 104 QStringLiteral("..."),
107 105 axis()->labelsAngle());
108 106 width = boundingRect.width() + labelPadding() + base.width() + 1.0;
109 107 height = boundingRect.height() / 2.0;
110 108 sh = QSizeF(width, height);
111 109 break;
112 110 }
113 111 case Qt::PreferredSize: {
114 112 qreal labelWidth = 0.0;
115 113 qreal firstHeight = -1.0;
116 114 foreach (const QString& s, ticksList) {
117 115 QRectF rect = ChartPresenter::textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle());
118 116 labelWidth = qMax(rect.width(), labelWidth);
119 117 height = rect.height();
120 118 if (firstHeight < 0.0)
121 119 firstHeight = height;
122 120 }
123 121 width = labelWidth + labelPadding() + base.width() + 2.0; //two pixels of tolerance
124 122 height = qMax(height, firstHeight) / 2.0;
125 123 sh = QSizeF(width, height);
126 124 break;
127 125 }
128 126 default:
129 127 break;
130 128 }
131 129
132 130 return sh;
133 131 }
134 132
135 133 #include "moc_chartlogvalueaxisy_p.cpp"
136 134
137 135 QT_CHARTS_END_NAMESPACE
@@ -1,245 +1,248
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2014 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.io
6 6 **
7 7 ** This file is part of the Qt Charts module.
8 8 **
9 9 ** Licensees holding valid commercial license for Qt may use this file in
10 10 ** accordance with the Qt License Agreement provided with the Software
11 11 ** or, alternatively, in accordance with the terms contained in a written
12 12 ** agreement between you and Digia.
13 13 **
14 14 ** If you have questions regarding the use of this file, please use
15 15 ** contact form at http://qt.io
16 16 **
17 17 ****************************************************************************/
18 18
19 19 #include <private/verticalaxis_p.h>
20 20 #include <QtCharts/QAbstractAxis>
21 21 #include <private/chartpresenter_p.h>
22 22 #include <QtCore/QDebug>
23 23
24 24 QT_CHARTS_BEGIN_NAMESPACE
25 25
26 26 VerticalAxis::VerticalAxis(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
27 27 : CartesianChartAxis(axis, item, intervalAxis)
28 28 {
29 29 }
30 30
31 31 VerticalAxis::~VerticalAxis()
32 32 {
33 33 }
34 34
35 35 void VerticalAxis::updateGeometry()
36 36 {
37 37 const QVector<qreal> &layout = ChartAxisElement::layout();
38 38
39 if (layout.isEmpty())
39 if (layout.isEmpty() && axis()->type() != QAbstractAxis::AxisTypeLogValue)
40 40 return;
41 41
42 42 QStringList labelList = labels();
43 43
44 QList<QGraphicsItem *> lines = gridItems();
45 44 QList<QGraphicsItem *> labels = labelItems();
46 QList<QGraphicsItem *> shades = shadeItems();
47 45 QList<QGraphicsItem *> arrow = arrowItems();
48 46 QGraphicsTextItem *title = titleItem();
49 47
50 48 Q_ASSERT(labels.size() == labelList.size());
51 49 Q_ASSERT(layout.size() == labelList.size());
52 50
53 51 const QRectF &axisRect = axisGeometry();
54 52 const QRectF &gridRect = gridGeometry();
55 53
56 54 qreal height = axisRect.bottom();
57 55
58
59 56 //arrow
60 57 QGraphicsLineItem *arrowItem = static_cast<QGraphicsLineItem*>(arrow.at(0));
61 58
62 59 //arrow position
63 60 if (axis()->alignment() == Qt::AlignLeft)
64 61 arrowItem->setLine(axisRect.right(), gridRect.top(), axisRect.right(), gridRect.bottom());
65 62 else if (axis()->alignment() == Qt::AlignRight)
66 63 arrowItem->setLine(axisRect.left(), gridRect.top(), axisRect.left(), gridRect.bottom());
67 64
68 65 //title
69 66 QRectF titleBoundingRect;
70 67 QString titleText = axis()->titleText();
71 68 qreal availableSpace = axisRect.width() - labelPadding();
72 69 if (!titleText.isEmpty() && titleItem()->isVisible()) {
73 70 availableSpace -= titlePadding() * 2.0;
74 71 qreal minimumLabelWidth = ChartPresenter::textBoundingRect(axis()->labelsFont(),
75 72 QStringLiteral("...")).width();
76 73 qreal titleSpace = availableSpace - minimumLabelWidth;
77 74 title->setHtml(ChartPresenter::truncatedText(axis()->titleFont(), titleText, qreal(90.0),
78 75 titleSpace, gridRect.height(),
79 76 titleBoundingRect));
80 77 title->setTextWidth(titleBoundingRect.height());
81 78
82 79 titleBoundingRect = title->boundingRect();
83 80
84 81 QPointF center = gridRect.center() - titleBoundingRect.center();
85 82 if (axis()->alignment() == Qt::AlignLeft)
86 83 title->setPos(axisRect.left() - titleBoundingRect.width() / 2.0 + titleBoundingRect.height() / 2.0 + titlePadding(), center.y());
87 84 else if (axis()->alignment() == Qt::AlignRight)
88 85 title->setPos(axisRect.right() - titleBoundingRect.width() / 2.0 - titleBoundingRect.height() / 2.0 - titlePadding(), center.y());
89 86
90 87 title->setTransformOriginPoint(titleBoundingRect.center());
91 88 title->setRotation(270);
92 89
93 90 availableSpace -= titleBoundingRect.height();
94 91 }
95 92
93 if (layout.isEmpty() && axis()->type() == QAbstractAxis::AxisTypeLogValue)
94 return;
95
96 QList<QGraphicsItem *> lines = gridItems();
97 QList<QGraphicsItem *> shades = shadeItems();
98
96 99 for (int i = 0; i < layout.size(); ++i) {
97 100 //items
98 101 QGraphicsLineItem *gridItem = static_cast<QGraphicsLineItem *>(lines.at(i));
99 102 QGraphicsLineItem *tickItem = static_cast<QGraphicsLineItem *>(arrow.at(i + 1));
100 103 QGraphicsTextItem *labelItem = static_cast<QGraphicsTextItem *>(labels.at(i));
101 104
102 105 //grid line
103 106 gridItem->setLine(gridRect.left(), layout[i], gridRect.right(), layout[i]);
104 107
105 108 //label text wrapping
106 109 QString text = labelList.at(i);
107 110 QRectF boundingRect;
108 111 // don't truncate empty labels
109 112 if (text.isEmpty()) {
110 113 labelItem->setHtml(text);
111 114 } else {
112 115 qreal labelHeight = (axisRect.height() / layout.count()) - (2 * labelPadding());
113 116 QString truncatedText = ChartPresenter::truncatedText(axis()->labelsFont(), text,
114 117 axis()->labelsAngle(),
115 118 availableSpace,
116 119 labelHeight, boundingRect);
117 120 labelItem->setTextWidth(ChartPresenter::textBoundingRect(axis()->labelsFont(),
118 121 truncatedText).width());
119 122 labelItem->setHtml(truncatedText);
120 123 }
121 124
122 125 //label transformation origin point
123 126 const QRectF &rect = labelItem->boundingRect();
124 127 QPointF center = rect.center();
125 128 labelItem->setTransformOriginPoint(center.x(), center.y());
126 129 qreal widthDiff = rect.width() - boundingRect.width();
127 130 qreal heightDiff = rect.height() - boundingRect.height();
128 131
129 132 //ticks and label position
130 133 if (axis()->alignment() == Qt::AlignLeft) {
131 134 labelItem->setPos(axisRect.right() - rect.width() + (widthDiff / 2.0) - labelPadding(), layout[i] - center.y());
132 135 tickItem->setLine(axisRect.right() - labelPadding(), layout[i], axisRect.right(), layout[i]);
133 136 } else if (axis()->alignment() == Qt::AlignRight) {
134 137 labelItem->setPos(axisRect.left() + labelPadding() - (widthDiff / 2.0), layout[i] - center.y());
135 138 tickItem->setLine(axisRect.left(), layout[i], axisRect.left() + labelPadding(), layout[i]);
136 139 }
137 140
138 141 //label in between
139 142 bool forceHide = false;
140 143 if (intervalAxis() && (i + 1) != layout.size()) {
141 144 qreal lowerBound = qMin(layout[i], gridRect.bottom());
142 145 qreal upperBound = qMax(layout[i + 1], gridRect.top());
143 146 const qreal delta = lowerBound - upperBound;
144 147 // Hide label in case visible part of the category at the grid edge is too narrow
145 148 if (delta < boundingRect.height()
146 149 && (lowerBound == gridRect.bottom() || upperBound == gridRect.top())
147 150 && !intervalAxis()) {
148 151 forceHide = true;
149 152 } else {
150 153 labelItem->setPos(labelItem->pos().x() , lowerBound - (delta / 2.0) - center.y());
151 154 }
152 155 }
153 156
154 157 //label overlap detection - compensate one pixel for rounding errors
155 158 if (labelItem->pos().y() + boundingRect.height() > height || forceHide ||
156 159 (labelItem->pos().y() + (heightDiff / 2.0) - 1.0) > axisRect.bottom() ||
157 160 labelItem->pos().y() + (heightDiff / 2.0) < (axisRect.top() - 1.0)) {
158 161 labelItem->setVisible(false);
159 162 }
160 163 else {
161 164 labelItem->setVisible(true);
162 165 height=labelItem->pos().y();
163 166 }
164 167
165 168 //shades
166 169 QGraphicsRectItem *shadeItem = 0;
167 170 if (i == 0)
168 171 shadeItem = static_cast<QGraphicsRectItem *>(shades.at(0));
169 172 else if (i % 2)
170 173 shadeItem = static_cast<QGraphicsRectItem *>(shades.at((i / 2) + 1));
171 174 if (shadeItem) {
172 175 qreal lowerBound;
173 176 qreal upperBound;
174 177 if (i == 0) {
175 178 lowerBound = gridRect.bottom();
176 179 upperBound = layout[0];
177 180 } else {
178 181 lowerBound = layout[i];
179 182 if (i == layout.size() - 1)
180 183 upperBound = gridRect.top();
181 184 else
182 185 upperBound = qMax(layout[i + 1], gridRect.top());
183 186
184 187 }
185 188 shadeItem->setRect(gridRect.left(), upperBound, gridRect.width(),
186 189 lowerBound - upperBound);
187 190 if (shadeItem->rect().height() <= 0.0)
188 191 shadeItem->setVisible(false);
189 192 else
190 193 shadeItem->setVisible(true);
191 194 }
192 195
193 196 // check if the grid line and the axis tick should be shown
194 197 qreal y = gridItem->line().p1().y();
195 198 if ((y < gridRect.top() || y > gridRect.bottom()))
196 199 {
197 200 gridItem->setVisible(false);
198 201 tickItem->setVisible(false);
199 202 }else{
200 203 gridItem->setVisible(true);
201 204 tickItem->setVisible(true);
202 205 }
203 206
204 207 }
205 208 //begin/end grid line in case labels between
206 209 if (intervalAxis()) {
207 210 QGraphicsLineItem *gridLine;
208 211 gridLine = static_cast<QGraphicsLineItem *>(lines.at(layout.size()));
209 212 gridLine->setLine(gridRect.left(), gridRect.top(), gridRect.right(), gridRect.top());
210 213 gridLine->setVisible(true);
211 214 gridLine = static_cast<QGraphicsLineItem*>(lines.at(layout.size() + 1));
212 215 gridLine->setLine(gridRect.left(), gridRect.bottom(), gridRect.right(), gridRect.bottom());
213 216 gridLine->setVisible(true);
214 217 }
215 218 }
216 219
217 220 QSizeF VerticalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
218 221 {
219 222 Q_UNUSED(constraint);
220 223 QSizeF sh(0, 0);
221 224
222 225 if (axis()->titleText().isEmpty() || !titleItem()->isVisible())
223 226 return sh;
224 227
225 228 switch (which) {
226 229 case Qt::MinimumSize: {
227 230 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(),
228 231 QStringLiteral("..."));
229 232 sh = QSizeF(titleRect.height() + (titlePadding() * 2.0), titleRect.width());
230 233 break;
231 234 }
232 235 case Qt::MaximumSize:
233 236 case Qt::PreferredSize: {
234 237 QRectF titleRect = ChartPresenter::textBoundingRect(axis()->titleFont(), axis()->titleText());
235 238 sh = QSizeF(titleRect.height() + (titlePadding() * 2.0), titleRect.width());
236 239 break;
237 240 }
238 241 default:
239 242 break;
240 243 }
241 244
242 245 return sh;
243 246 }
244 247
245 248 QT_CHARTS_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now