1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Charts module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include <private/chartvalueaxisy_p.h>
31#include <QtCharts/QAbstractAxis>
32#include <private/chartpresenter_p.h>
33#include <QtCharts/QValueAxis>
34#include <private/abstractchartlayout_p.h>
35#include <private/valueaxislabel_p.h>
36#include <QtWidgets/QGraphicsLayout>
37#include <QtCore/QtMath>
38#include <QtCore/QDebug>
39
40QT_CHARTS_BEGIN_NAMESPACE
41
42ChartValueAxisY::ChartValueAxisY(QValueAxis *axis, QGraphicsItem *item)
43 : VerticalAxis(axis, item),
44 m_axis(axis)
45{
46 QObject::connect(sender: m_axis, SIGNAL(tickCountChanged(int)), receiver: this, SLOT(handleTickCountChanged(int)));
47 QObject::connect(sender: m_axis, SIGNAL(minorTickCountChanged(int)),
48 receiver: this, SLOT(handleMinorTickCountChanged(int)));
49 QObject::connect(sender: m_axis, SIGNAL(labelFormatChanged(QString)), receiver: this, SLOT(handleLabelFormatChanged(QString)));
50 QObject::connect(sender: m_axis, SIGNAL(tickIntervalChanged(qreal)), receiver: this, SLOT(handleTickIntervalChanged(qreal)));
51 QObject::connect(sender: m_axis, SIGNAL(tickAnchorChanged(qreal)), receiver: this, SLOT(handleTickAnchorChanged(qreal)));
52 QObject::connect(sender: m_axis, SIGNAL(tickTypeChanged(QValueAxis::TickType)), receiver: this,
53 SLOT(handleTickTypeChanged(QValueAxis::TickType)));
54}
55
56ChartValueAxisY::~ChartValueAxisY()
57{
58}
59
60QVector<qreal> ChartValueAxisY::calculateLayout() const
61{
62 if (m_axis->tickType() == QValueAxis::TicksFixed) {
63 int tickCount = m_axis->tickCount();
64
65 Q_ASSERT(tickCount >= 2);
66
67 QVector<qreal> points;
68 points.resize(size: tickCount);
69
70 const QRectF &gridRect = gridGeometry();
71
72 const qreal deltaY = gridRect.height() / (qreal(tickCount) - 1.0);
73 for (int i = 0; i < tickCount; ++i)
74 points[i] = qreal(i) * -deltaY + gridRect.bottom();
75
76 return points;
77 } else {
78 const qreal interval = m_axis->tickInterval();
79 qreal value = m_axis->tickAnchor();
80 const qreal maxValue = max();
81 const qreal minValue = min();
82
83 // Find the first major tick right after the min of range
84 if (value > minValue)
85 value = value - int((value - minValue) / interval) * interval;
86 else
87 value = value + qCeil(v: (minValue - value) / interval) * interval;
88
89 const QRectF &gridRect = gridGeometry();
90 const qreal deltaY = gridRect.height() / (maxValue - minValue);
91
92 QVector<qreal> points;
93 const qreal bottomPos = gridRect.bottom();
94 while (value <= maxValue || qFuzzyCompare(p1: value, p2: maxValue)) {
95 points << (value - minValue) * -deltaY + bottomPos;
96 value += interval;
97 }
98
99 return points;
100 }
101}
102
103void ChartValueAxisY::updateGeometry()
104{
105 const QVector<qreal> &layout = ChartAxisElement::layout();
106 const QVector<qreal>& dynamicMinorTicklayout = ChartAxisElement::dynamicMinorTicklayout();
107 if (layout.isEmpty() && dynamicMinorTicklayout.isEmpty())
108 return;
109 setLabels(createValueLabels(max: min(), min: max(), ticks: layout.size(), tickInterval: m_axis->tickInterval(),
110 tickAnchor: m_axis->tickAnchor(), tickType: m_axis->tickType(), format: m_axis->labelFormat()));
111 VerticalAxis::updateGeometry();
112 updateLabelsValues(axis: m_axis);
113}
114
115void ChartValueAxisY::handleTickCountChanged(int tick)
116{
117 Q_UNUSED(tick);
118 QGraphicsLayoutItem::updateGeometry();
119 if (presenter()) presenter()->layout()->invalidate();
120}
121
122void ChartValueAxisY::handleMinorTickCountChanged(int tick)
123{
124 Q_UNUSED(tick);
125 QGraphicsLayoutItem::updateGeometry();
126 if (presenter())
127 presenter()->layout()->invalidate();
128}
129
130void ChartValueAxisY::handleLabelFormatChanged(const QString &format)
131{
132 Q_UNUSED(format);
133 QGraphicsLayoutItem::updateGeometry();
134 if (presenter()) presenter()->layout()->invalidate();
135}
136
137void ChartValueAxisY::handleTickIntervalChanged(qreal interval)
138{
139 Q_UNUSED(interval)
140 QGraphicsLayoutItem::updateGeometry();
141 if (presenter()) presenter()->layout()->invalidate();
142}
143
144void ChartValueAxisY::handleTickAnchorChanged(qreal anchor)
145{
146 Q_UNUSED(anchor)
147 QGraphicsLayoutItem::updateGeometry();
148 if (presenter()) presenter()->layout()->invalidate();
149}
150
151void ChartValueAxisY::handleTickTypeChanged(QValueAxis::TickType type)
152{
153 Q_UNUSED(type)
154 QGraphicsLayoutItem::updateGeometry();
155 if (presenter()) presenter()->layout()->invalidate();
156}
157
158QSizeF ChartValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
159{
160 Q_UNUSED(constraint)
161
162 QSizeF sh;
163 QSizeF base = VerticalAxis::sizeHint(which, constraint);
164 QStringList ticksList = createValueLabels(max: min(), min: max(), ticks: m_axis->tickCount(),
165 tickInterval: m_axis->tickInterval(), tickAnchor: m_axis->tickAnchor(),
166 tickType: m_axis->tickType(), format: m_axis->labelFormat());
167 qreal width = 0;
168 // Height of vertical axis sizeHint indicates the maximum distance labels can extend past
169 // first and last ticks. Base height is irrelevant.
170 qreal height = 0;
171
172 switch (which) {
173 case Qt::MinimumSize: {
174 QRectF boundingRect = ChartPresenter::textBoundingRect(font: axis()->labelsFont(),
175 QStringLiteral("..."),
176 angle: axis()->labelsAngle());
177 width = boundingRect.width() + labelPadding() + base.width() + 1.0;
178 height = boundingRect.height() / 2.0;
179 sh = QSizeF(width, height);
180 break;
181 }
182 case Qt::PreferredSize: {
183 qreal labelWidth = 0.0;
184 qreal firstHeight = -1.0;
185 foreach (const QString& s, ticksList) {
186 QRectF rect = ChartPresenter::textBoundingRect(font: axis()->labelsFont(), text: s, angle: axis()->labelsAngle());
187 labelWidth = qMax(a: rect.width(), b: labelWidth);
188 height = rect.height();
189 if (firstHeight < 0.0)
190 firstHeight = height;
191 }
192 width = labelWidth + labelPadding() + base.width() + 2.0; //two pixels of tolerance
193 height = qMax(a: height, b: firstHeight) / 2.0;
194 sh = QSizeF(width, height);
195 break;
196 }
197 default:
198 break;
199 }
200 return sh;
201}
202
203QT_CHARTS_END_NAMESPACE
204
205#include "moc_chartvalueaxisy_p.cpp"
206

source code of qtcharts/src/charts/axis/valueaxis/chartvalueaxisy.cpp