1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qabstract3daxis_p.h"
5
6QT_BEGIN_NAMESPACE
7
8/*!
9 * \class QAbstract3DAxis
10 * \inmodule QtDataVisualization
11 * \brief The QAbstract3DAxis class is a base class for the axes of a graph.
12 * \since QtDataVisualization 1.0
13 *
14 * This class specifies the enumerations, properties, and functions shared by
15 * graph axes. It should not be used directly, but one of its subclasses should
16 * be used instead.
17 *
18 * \sa QCategory3DAxis, QValue3DAxis
19 */
20
21/*!
22 * \qmltype AbstractAxis3D
23 * \inqmlmodule QtDataVisualization
24 * \since QtDataVisualization 1.0
25 * \ingroup datavisualization_qml
26 * \instantiates QAbstract3DAxis
27 * \brief A base type for the axes of a graph.
28 *
29 * This type is uncreatable, but contains properties that are exposed via subtypes.
30 *
31 * For AbstractAxis3D enums, see \l QAbstract3DAxis::AxisOrientation and
32 * \l{QAbstract3DAxis::AxisType}.
33 */
34
35/*!
36 * \qmlproperty string AbstractAxis3D::title
37 * The title for the axis.
38 *
39 * \sa titleVisible, titleFixed
40 */
41
42/*!
43 * \qmlproperty list AbstractAxis3D::labels
44 * The labels for the axis.
45 * \note Setting this property for ValueAxis3D does nothing, as it generates labels automatically.
46 */
47
48/*!
49 * \qmlproperty AbstractAxis3D.AxisOrientation AbstractAxis3D::orientation
50 * The orientation of the axis.
51 */
52
53/*!
54 * \qmlproperty AbstractAxis3D.AxisType AbstractAxis3D::type
55 * The type of the axis.
56 */
57
58/*!
59 * \qmlproperty real AbstractAxis3D::min
60 *
61 * The minimum value on the axis.
62 * When setting this property, the maximum value is adjusted if necessary, to
63 * ensure that the range remains valid.
64 */
65
66/*!
67 * \qmlproperty real AbstractAxis3D::max
68 *
69 * The maximum value on the axis.
70 * When setting this property, the minimum value is adjusted if necessary, to
71 * ensure that the range remains valid.
72 */
73
74/*!
75 * \qmlproperty bool AbstractAxis3D::autoAdjustRange
76 *
77 * Defines whether the axis will automatically adjust the range so that all data fits in it.
78 */
79
80/*!
81 * \qmlproperty real AbstractAxis3D::labelAutoRotation
82 *
83 * The maximum angle the labels can autorotate when the camera angle changes.
84 * The angle can be between 0 and 90, inclusive. The default value is 0.
85 * If the value is 0, axis labels do not automatically rotate.
86 * If the value is greater than zero, labels attempt to orient themselves toward the camera, up to
87 * the specified angle.
88 */
89
90/*!
91 * \qmlproperty bool AbstractAxis3D::titleVisible
92 *
93 * Defines whether the axis title is visible in the primary graph view.
94 *
95 * The default value is \c{false}.
96 *
97 * \sa title, titleFixed
98 */
99
100/*!
101 * \qmlproperty bool AbstractAxis3D::titleFixed
102 *
103 * The rotation of axis titles.
104 *
105 * If \c{true}, axis titles in the primary graph view will be rotated towards the camera similarly
106 * to the axis labels.
107 * If \c{false}, axis titles are only rotated around their axis but are not otherwise oriented
108 * towards the camera.
109 * This property does not have any effect if the labelAutoRotation property
110 * value is zero.
111 * Default value is \c{true}.
112 *
113 * \sa labelAutoRotation, title, titleVisible
114 */
115
116/*!
117 * \enum QAbstract3DAxis::AxisOrientation
118 *
119 * The orientation of the axis object.
120 *
121 * \value AxisOrientationNone
122 * \value AxisOrientationX
123 * \value AxisOrientationY
124 * \value AxisOrientationZ
125 */
126
127/*!
128 * \enum QAbstract3DAxis::AxisType
129 *
130 * The type of the axis object.
131 *
132 * \value AxisTypeNone
133 * \value AxisTypeCategory
134 * \value AxisTypeValue
135 */
136
137/*!
138 * \internal
139 */
140QAbstract3DAxis::QAbstract3DAxis(QAbstract3DAxisPrivate *d, QObject *parent) :
141 QObject(parent),
142 d_ptr(d)
143{
144}
145
146/*!
147 * Destroys QAbstract3DAxis.
148 */
149QAbstract3DAxis::~QAbstract3DAxis()
150{
151}
152
153/*!
154 * \property QAbstract3DAxis::orientation
155 *
156 * \brief The orientation of the axis.
157 *
158 * The value is one of AxisOrientation values.
159 */
160QAbstract3DAxis::AxisOrientation QAbstract3DAxis::orientation() const
161{
162 return d_ptr->m_orientation;
163}
164
165/*!
166 * \property QAbstract3DAxis::type
167 *
168 * \brief The type of the axis.
169 *
170 * The value is one of AxisType values.
171 */
172QAbstract3DAxis::AxisType QAbstract3DAxis::type() const
173{
174 return d_ptr->m_type;
175}
176
177/*!
178 * \property QAbstract3DAxis::title
179 *
180 * \brief The title for the axis.
181 *
182 * \sa titleVisible, titleFixed
183 */
184void QAbstract3DAxis::setTitle(const QString &title)
185{
186 if (d_ptr->m_title != title) {
187 d_ptr->m_title = title;
188 emit titleChanged(newTitle: title);
189 }
190}
191
192QString QAbstract3DAxis::title() const
193{
194 return d_ptr->m_title;
195}
196
197/*!
198 * \property QAbstract3DAxis::labels
199 *
200 * \brief The labels for the axis.
201 * \note Setting this property for QValue3DAxis does nothing, as it generates labels automatically.
202 */
203void QAbstract3DAxis::setLabels(const QStringList &labels)
204{
205 Q_UNUSED(labels);
206}
207
208QStringList QAbstract3DAxis::labels() const
209{
210 d_ptr->updateLabels();
211 return d_ptr->m_labels;
212}
213
214/*!
215 * Sets the value range of the axis from \a min to \a max.
216 * When setting the range, the maximum value is adjusted if necessary, to ensure
217 * that the range remains valid.
218 * \note For QCategory3DAxis, specifies the index range of rows or columns to
219 * show.
220 */
221void QAbstract3DAxis::setRange(float min, float max)
222{
223 d_ptr->setRange(min, max);
224 setAutoAdjustRange(false);
225}
226
227/*!
228 * \property QAbstract3DAxis::labelAutoRotation
229 *
230 * \brief The maximum angle the labels can autorotate when the camera angle changes.
231 *
232 * The angle can be between 0 and 90, inclusive. The default value is 0.
233 * If the value is 0, axis labels do not automatically rotate.
234 * If the value is greater than zero, labels attempt to orient themselves toward the camera, up to
235 * the specified angle.
236 */
237void QAbstract3DAxis::setLabelAutoRotation(float angle)
238{
239 if (angle < 0.0f)
240 angle = 0.0f;
241 if (angle > 90.0f)
242 angle = 90.0f;
243 if (d_ptr->m_labelAutoRotation != angle) {
244 d_ptr->m_labelAutoRotation = angle;
245 emit labelAutoRotationChanged(angle);
246 }
247}
248
249float QAbstract3DAxis::labelAutoRotation() const
250{
251 return d_ptr->m_labelAutoRotation;
252}
253
254/*!
255 * \property QAbstract3DAxis::titleVisible
256 *
257 * \brief Whether the axis title is visible in the primary graph view.
258 *
259 * The default value is \c{false}.
260 *
261 * \sa title, titleFixed
262 */
263void QAbstract3DAxis::setTitleVisible(bool visible)
264{
265 if (d_ptr->m_titleVisible != visible) {
266 d_ptr->m_titleVisible = visible;
267 emit titleVisibilityChanged(visible);
268 }
269}
270
271bool QAbstract3DAxis::isTitleVisible() const
272{
273 return d_ptr->m_titleVisible;
274}
275
276/*!
277 * \property QAbstract3DAxis::titleFixed
278 *
279 * \brief The rotation of the axis titles.
280 *
281 * If \c{true}, axis titles in the primary graph view will be rotated towards the camera similarly
282 * to the axis labels.
283 * If \c{false}, axis titles are only rotated around their axis but are not otherwise oriented
284 * towards the camera.
285 * This property does not have any effect if the labelAutoRotation property
286 * value is zero.
287 * Default value is \c{true}.
288 *
289 * \sa labelAutoRotation, title, titleVisible
290 */
291void QAbstract3DAxis::setTitleFixed(bool fixed)
292{
293 if (d_ptr->m_titleFixed != fixed) {
294 d_ptr->m_titleFixed = fixed;
295 emit titleFixedChanged(fixed);
296 }
297}
298
299bool QAbstract3DAxis::isTitleFixed() const
300{
301 return d_ptr->m_titleFixed;
302}
303
304/*!
305 * \property QAbstract3DAxis::min
306 *
307 * \brief The minimum value on the axis.
308 *
309 * When setting this property, the maximum value is adjusted if necessary, to
310 * ensure that the range remains valid.
311 * \note For QCategory3DAxis, specifies the index of the first row or column to
312 * show.
313 */
314void QAbstract3DAxis::setMin(float min)
315{
316 d_ptr->setMin(min);
317 setAutoAdjustRange(false);
318}
319
320/*!
321 * \property QAbstract3DAxis::max
322 *
323 * \brief The maximum value on the axis.
324 *
325 * When setting this property, the minimum value is adjusted if necessary, to
326 * ensure that the range remains valid.
327 * \note For QCategory3DAxis, specifies the index of the last row or column to
328 * show.
329 */
330void QAbstract3DAxis::setMax(float max)
331{
332 d_ptr->setMax(max);
333 setAutoAdjustRange(false);
334}
335
336float QAbstract3DAxis::min() const
337{
338 return d_ptr->m_min;
339}
340
341float QAbstract3DAxis::max() const
342{
343 return d_ptr->m_max;
344}
345
346/*!
347 * \property QAbstract3DAxis::autoAdjustRange
348 *
349 * \brief Whether the axis will automatically adjust the range so that all data fits in it.
350 *
351 * \sa setRange(), setMin(), setMax()
352 */
353void QAbstract3DAxis::setAutoAdjustRange(bool autoAdjust)
354{
355 if (d_ptr->m_autoAdjust != autoAdjust) {
356 d_ptr->m_autoAdjust = autoAdjust;
357 emit autoAdjustRangeChanged(autoAdjust);
358 }
359}
360
361bool QAbstract3DAxis::isAutoAdjustRange() const
362{
363 return d_ptr->m_autoAdjust;
364}
365
366/*!
367 * \fn QAbstract3DAxis::rangeChanged(float min, float max)
368 *
369 * Emits the minimum and maximum values of the range, \a min and \a max, when
370 * the range changes.
371 */
372
373// QAbstract3DAxisPrivate
374QAbstract3DAxisPrivate::QAbstract3DAxisPrivate(QAbstract3DAxis *q, QAbstract3DAxis::AxisType type)
375 : QObject(0),
376 q_ptr(q),
377 m_orientation(QAbstract3DAxis::AxisOrientationNone),
378 m_type(type),
379 m_isDefaultAxis(false),
380 m_min(0.0f),
381 m_max(10.0f),
382 m_autoAdjust(true),
383 m_labelAutoRotation(0.0f),
384 m_titleVisible(false),
385 m_titleFixed(true)
386{
387}
388
389QAbstract3DAxisPrivate::~QAbstract3DAxisPrivate()
390{
391}
392
393void QAbstract3DAxisPrivate::setOrientation(QAbstract3DAxis::AxisOrientation orientation)
394{
395 if (m_orientation == QAbstract3DAxis::AxisOrientationNone) {
396 m_orientation = orientation;
397 emit q_ptr->orientationChanged(orientation);
398 } else {
399 Q_ASSERT("Attempted to reset axis orientation.");
400 }
401}
402
403void QAbstract3DAxisPrivate::updateLabels()
404{
405 // Default implementation does nothing
406}
407
408void QAbstract3DAxisPrivate::setRange(float min, float max, bool suppressWarnings)
409{
410 bool adjusted = false;
411 if (!allowNegatives()) {
412 if (allowZero()) {
413 if (min < 0.0f) {
414 min = 0.0f;
415 adjusted = true;
416 }
417 if (max < 0.0f) {
418 max = 0.0f;
419 adjusted = true;
420 }
421 } else {
422 if (min <= 0.0f) {
423 min = 1.0f;
424 adjusted = true;
425 }
426 if (max <= 0.0f) {
427 max = 1.0f;
428 adjusted = true;
429 }
430 }
431 }
432 // If min >= max, we adjust ranges so that
433 // m_max becomes (min + 1.0f)
434 // as axes need some kind of valid range.
435 bool minDirty = false;
436 bool maxDirty = false;
437 if (m_min != min) {
438 m_min = min;
439 minDirty = true;
440 }
441 if (m_max != max || min > max || (!allowMinMaxSame() && min == max)) {
442 if (min > max || (!allowMinMaxSame() && min == max)) {
443 m_max = min + 1.0f;
444 adjusted = true;
445 } else {
446 m_max = max;
447 }
448 maxDirty = true;
449 }
450
451 if (minDirty || maxDirty) {
452 if (adjusted && !suppressWarnings) {
453 qWarning() << "Warning: Tried to set invalid range for axis."
454 " Range automatically adjusted to a valid one:"
455 << min << "-" << max << "-->" << m_min << "-" << m_max;
456 }
457 emit q_ptr->rangeChanged(min: m_min, max: m_max);
458 }
459
460 if (minDirty)
461 emit q_ptr->minChanged(value: m_min);
462 if (maxDirty)
463 emit q_ptr->maxChanged(value: m_max);
464}
465
466void QAbstract3DAxisPrivate::setMin(float min)
467{
468 if (!allowNegatives()) {
469 if (allowZero()) {
470 if (min < 0.0f) {
471 min = 0.0f;
472 qWarning() << "Warning: Tried to set negative minimum for an axis that only"
473 "supports positive values and zero:" << min;
474 }
475 } else {
476 if (min <= 0.0f) {
477 min = 1.0f;
478 qWarning() << "Warning: Tried to set negative or zero minimum for an axis that only"
479 "supports positive values:" << min;
480 }
481 }
482 }
483
484 if (m_min != min) {
485 bool maxChanged = false;
486 if (min > m_max || (!allowMinMaxSame() && min == m_max)) {
487 float oldMax = m_max;
488 m_max = min + 1.0f;
489 qWarning() << "Warning: Tried to set minimum to equal or larger than maximum for"
490 " value axis. Maximum automatically adjusted to a valid one:"
491 << oldMax << "-->" << m_max;
492 maxChanged = true;
493 }
494 m_min = min;
495
496 emit q_ptr->rangeChanged(min: m_min, max: m_max);
497 emit q_ptr->minChanged(value: m_min);
498 if (maxChanged)
499 emit q_ptr->maxChanged(value: m_max);
500 }
501}
502
503void QAbstract3DAxisPrivate::setMax(float max)
504{
505 if (!allowNegatives()) {
506 if (allowZero()) {
507 if (max < 0.0f) {
508 max = 0.0f;
509 qWarning() << "Warning: Tried to set negative maximum for an axis that only"
510 "supports positive values and zero:" << max;
511 }
512 } else {
513 if (max <= 0.0f) {
514 max = 1.0f;
515 qWarning() << "Warning: Tried to set negative or zero maximum for an axis that only"
516 "supports positive values:" << max;
517 }
518 }
519 }
520
521 if (m_max != max) {
522 bool minChanged = false;
523 if (m_min > max || (!allowMinMaxSame() && m_min == max)) {
524 float oldMin = m_min;
525 m_min = max - 1.0f;
526 if (!allowNegatives() && m_min < 0.0f) {
527 if (allowZero())
528 m_min = 0.0f;
529 else
530 m_min = max / 2.0f; // Need some positive value smaller than max
531
532 if (!allowMinMaxSame() && max == 0.0f) {
533 m_min = oldMin;
534 qWarning() << "Unable to set maximum value to zero.";
535 return;
536 }
537 }
538 qWarning() << "Warning: Tried to set maximum to equal or smaller than minimum for"
539 " value axis. Minimum automatically adjusted to a valid one:"
540 << oldMin << "-->" << m_min;
541 minChanged = true;
542 }
543 m_max = max;
544 emit q_ptr->rangeChanged(min: m_min, max: m_max);
545 emit q_ptr->maxChanged(value: m_max);
546 if (minChanged)
547 emit q_ptr->minChanged(value: m_min);
548 }
549}
550
551QT_END_NAMESPACE
552

source code of qtdatavis3d/src/datavisualization/axis/qabstract3daxis.cpp