1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <private/chartvalueaxisy_p.h>
5#include <QtCharts/QAbstractAxis>
6#include <private/chartpresenter_p.h>
7#include <QtCharts/QValueAxis>
8#include <private/abstractchartlayout_p.h>
9#include <private/valueaxislabel_p.h>
10#include <QtWidgets/QGraphicsLayout>
11#include <QtCore/QtMath>
12#include <QtCore/QDebug>
13
14QT_BEGIN_NAMESPACE
15
16ChartValueAxisY::ChartValueAxisY(QValueAxis *axis, QGraphicsItem *item)
17 : VerticalAxis(axis, item),
18 m_axis(axis)
19{
20 QObject::connect(sender: m_axis, SIGNAL(tickCountChanged(int)), receiver: this, SLOT(handleTickCountChanged(int)));
21 QObject::connect(sender: m_axis, SIGNAL(minorTickCountChanged(int)),
22 receiver: this, SLOT(handleMinorTickCountChanged(int)));
23 QObject::connect(sender: m_axis, SIGNAL(labelFormatChanged(QString)), receiver: this, SLOT(handleLabelFormatChanged(QString)));
24 QObject::connect(sender: m_axis, SIGNAL(tickIntervalChanged(qreal)), receiver: this, SLOT(handleTickIntervalChanged(qreal)));
25 QObject::connect(sender: m_axis, SIGNAL(tickAnchorChanged(qreal)), receiver: this, SLOT(handleTickAnchorChanged(qreal)));
26 QObject::connect(sender: m_axis, SIGNAL(tickTypeChanged(QValueAxis::TickType)), receiver: this,
27 SLOT(handleTickTypeChanged(QValueAxis::TickType)));
28}
29
30ChartValueAxisY::~ChartValueAxisY()
31{
32}
33
34QList<qreal> ChartValueAxisY::calculateLayout() const
35{
36 if (m_axis->tickType() == QValueAxis::TicksFixed) {
37 int tickCount = m_axis->tickCount();
38
39 Q_ASSERT(tickCount >= 2);
40
41 QList<qreal> points;
42 points.resize(size: tickCount);
43
44 const QRectF &gridRect = gridGeometry();
45 const qreal deltaY = gridRect.height() / (qreal(tickCount) - 1.0);
46 for (int i = 0; i < tickCount; ++i)
47 points[i] = qreal(i) * -deltaY + gridRect.bottom();
48 return points;
49 } else {
50 const qreal interval = m_axis->tickInterval();
51 const qreal anchor = m_axis->tickAnchor();
52 const qreal maxValue = max();
53 const qreal minValue = min();
54
55 // Find the first major tick right after the min of the range
56 const qreal ticksFromAnchor = (anchor - minValue) / interval;
57 const qreal firstMajorTick = anchor - std::floor(x: ticksFromAnchor) * interval;
58
59 const QRectF &gridRect = gridGeometry();
60 const qreal deltaY = gridRect.height() / (maxValue - minValue);
61
62 QList<qreal> points;
63 const qreal bottomPos = gridRect.bottom();
64 qreal value = firstMajorTick;
65 while (value <= maxValue) {
66 points << (value - minValue) * -deltaY + bottomPos;
67 value += interval;
68 }
69
70 return points;
71 }
72}
73
74void ChartValueAxisY::updateGeometry()
75{
76 const QList<qreal> &layout = ChartAxisElement::layout();
77 const QList<qreal> &dynamicMinorTicklayout = ChartAxisElement::dynamicMinorTicklayout();
78 if (layout.isEmpty() && dynamicMinorTicklayout.isEmpty())
79 return;
80 setLabels(createValueLabels(max: min(), min: max(), ticks: layout.size(), tickInterval: m_axis->tickInterval(),
81 tickAnchor: m_axis->tickAnchor(), tickType: m_axis->tickType(), format: m_axis->labelFormat()));
82 VerticalAxis::updateGeometry();
83 updateLabelsValues(axis: m_axis);
84}
85
86void ChartValueAxisY::handleTickCountChanged(int tick)
87{
88 Q_UNUSED(tick);
89 QGraphicsLayoutItem::updateGeometry();
90 if (presenter()) presenter()->layout()->invalidate();
91}
92
93void ChartValueAxisY::handleMinorTickCountChanged(int tick)
94{
95 Q_UNUSED(tick);
96 QGraphicsLayoutItem::updateGeometry();
97 if (presenter())
98 presenter()->layout()->invalidate();
99}
100
101void ChartValueAxisY::handleLabelFormatChanged(const QString &format)
102{
103 Q_UNUSED(format);
104 QGraphicsLayoutItem::updateGeometry();
105 if (presenter()) presenter()->layout()->invalidate();
106}
107
108void ChartValueAxisY::handleTickIntervalChanged(qreal interval)
109{
110 Q_UNUSED(interval);
111 QGraphicsLayoutItem::updateGeometry();
112 if (presenter()) presenter()->layout()->invalidate();
113}
114
115void ChartValueAxisY::handleTickAnchorChanged(qreal anchor)
116{
117 Q_UNUSED(anchor);
118 QGraphicsLayoutItem::updateGeometry();
119 if (presenter()) presenter()->layout()->invalidate();
120}
121
122void ChartValueAxisY::handleTickTypeChanged(QValueAxis::TickType type)
123{
124 Q_UNUSED(type);
125 QGraphicsLayoutItem::updateGeometry();
126 if (presenter()) presenter()->layout()->invalidate();
127}
128
129QSizeF ChartValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
130{
131 Q_UNUSED(constraint);
132
133 QSizeF sh;
134 QSizeF base = VerticalAxis::sizeHint(which, constraint);
135 QStringList ticksList = createValueLabels(max: min(), min: max(), ticks: m_axis->tickCount(),
136 tickInterval: m_axis->tickInterval(), tickAnchor: m_axis->tickAnchor(),
137 tickType: m_axis->tickType(), format: m_axis->labelFormat());
138 qreal width = 0;
139 // Height of vertical axis sizeHint indicates the maximum distance labels can extend past
140 // first and last ticks. Base height is irrelevant.
141 qreal height = 0;
142
143 switch (which) {
144 case Qt::MinimumSize: {
145 if (labelsVisible()) {
146 QRectF boundingRect = ChartPresenter::textBoundingRect(font: axis()->labelsFont(),
147 QStringLiteral("..."),
148 angle: axis()->labelsAngle());
149 width = boundingRect.width() + labelPadding() + base.width() + 1.0;
150 height = boundingRect.height() / 2.0;
151 } else {
152 width = base.width() + 1.0;
153 height = 0;
154 }
155 sh = QSizeF(width, height);
156 break;
157 }
158 case Qt::PreferredSize: {
159 if (labelsVisible()) {
160 qreal labelWidth = 0.0;
161 qreal firstHeight = -1.0;
162 foreach (const QString& s, ticksList) {
163 QRectF rect = ChartPresenter::textBoundingRect(font: axis()->labelsFont(), text: s, angle: axis()->labelsAngle());
164 labelWidth = qMax(a: rect.width(), b: labelWidth);
165 height = rect.height();
166 if (firstHeight < 0.0)
167 firstHeight = height;
168 }
169 width = labelWidth + labelPadding() + base.width() + 2.0; //two pixels of tolerance
170 height = qMax(a: height, b: firstHeight) / 2.0;
171 } else {
172 width = base.width() + 2.0; //two pixels of tolerance
173 height = 0;
174 }
175 sh = QSizeF(width, height);
176 break;
177 }
178 default:
179 break;
180 }
181 return sh;
182}
183
184QT_END_NAMESPACE
185
186#include "moc_chartvalueaxisy_p.cpp"
187

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