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

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