Revision control
++ // Copyright (C) 2017 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ #include "qabstract3daxis_p.h"
++
++ QT_BEGIN_NAMESPACE
++
++ /*!
++ * \class QAbstract3DAxis
++ * \inmodule QtDataVisualization
++ * \brief The QAbstract3DAxis class is a base class for the axes of a graph.
++ * \since QtDataVisualization 1.0
++ *
++ * This class specifies the enumerations, properties, and functions shared by
++ * graph axes. It should not be used directly, but one of its subclasses should
++ * be used instead.
++ *
++ * \sa QCategory3DAxis, QValue3DAxis
++ */
++
++ /*!
++ * \qmltype AbstractAxis3D
++ * \inqmlmodule QtDataVisualization
++ * \since QtDataVisualization 1.0
++ * \ingroup datavisualization_qml
++ * \nativetype QAbstract3DAxis
++ * \brief A base type for the axes of a graph.
++ *
++ * This type is uncreatable, but contains properties that are exposed via subtypes.
++ *
++ * For AbstractAxis3D enums, see \l QAbstract3DAxis::AxisOrientation and
++ * \l{QAbstract3DAxis::AxisType}.
++ */
++
++ /*!
++ * \qmlproperty string AbstractAxis3D::title
++ * The title for the axis.
++ *
++ * \sa titleVisible, titleFixed
++ */
++
++ /*!
++ * \qmlproperty list AbstractAxis3D::labels
++ * The labels for the axis.
++ * \note Setting this property for ValueAxis3D does nothing, as it generates labels automatically.
++ */
++
++ /*!
++ * \qmlproperty AbstractAxis3D.AxisOrientation AbstractAxis3D::orientation
++ * The orientation of the axis.
++ */
++
++ /*!
++ * \qmlproperty AbstractAxis3D.AxisType AbstractAxis3D::type
++ * The type of the axis.
++ */
++
++ /*!
++ * \qmlproperty real AbstractAxis3D::min
++ *
++ * The minimum value on the axis.
++ * When setting this property, the maximum value is adjusted if necessary, to
++ * ensure that the range remains valid.
++ */
++
++ /*!
++ * \qmlproperty real AbstractAxis3D::max
++ *
++ * The maximum value on the axis.
++ * When setting this property, the minimum value is adjusted if necessary, to
++ * ensure that the range remains valid.
++ */
++
++ /*!
++ * \qmlproperty bool AbstractAxis3D::autoAdjustRange
++ *
++ * Defines whether the axis will automatically adjust the range so that all data fits in it.
++ */
++
++ /*!
++ * \qmlproperty real AbstractAxis3D::labelAutoRotation
++ *
++ * The maximum angle the labels can autorotate when the camera angle changes.
++ * The angle can be between 0 and 90, inclusive. The default value is 0.
++ * If the value is 0, axis labels do not automatically rotate.
++ * If the value is greater than zero, labels attempt to orient themselves toward the camera, up to
++ * the specified angle.
++ */
++
++ /*!
++ * \qmlproperty bool AbstractAxis3D::titleVisible
++ *
++ * Defines whether the axis title is visible in the primary graph view.
++ *
++ * The default value is \c{false}.
++ *
++ * \sa title, titleFixed
++ */
++
++ /*!
++ * \qmlproperty bool AbstractAxis3D::titleFixed
++ *
++ * The rotation of axis titles.
++ *
++ * If \c{true}, axis titles in the primary graph view will be rotated towards the camera similarly
++ * to the axis labels.
++ * If \c{false}, axis titles are only rotated around their axis but are not otherwise oriented
++ * towards the camera.
++ * This property does not have any effect if the labelAutoRotation property
++ * value is zero.
++ * Default value is \c{true}.
++ *
++ * \sa labelAutoRotation, title, titleVisible
++ */
++
++ /*!
++ * \enum QAbstract3DAxis::AxisOrientation
++ *
++ * The orientation of the axis object.
++ *
++ * \value AxisOrientationNone
++ * \value AxisOrientationX
++ * \value AxisOrientationY
++ * \value AxisOrientationZ
++ */
++
++ /*!
++ * \enum QAbstract3DAxis::AxisType
++ *
++ * The type of the axis object.
++ *
++ * \value AxisTypeNone
++ * \value AxisTypeCategory
++ * \value AxisTypeValue
++ */
++
++ /*!
++ * \internal
++ */
++ QAbstract3DAxis::QAbstract3DAxis(QAbstract3DAxisPrivate *d, QObject *parent) :
++ QObject(parent),
++ d_ptr(d)
++ {
++ }
++
++ /*!
++ * Destroys QAbstract3DAxis.
++ */
++ QAbstract3DAxis::~QAbstract3DAxis()
++ {
++ }
++
++ /*!
++ * \property QAbstract3DAxis::orientation
++ *
++ * \brief The orientation of the axis.
++ *
++ * The value is one of AxisOrientation values.
++ */
++ QAbstract3DAxis::AxisOrientation QAbstract3DAxis::orientation() const
++ {
++ return d_ptr->m_orientation;
++ }
++
++ /*!
++ * \property QAbstract3DAxis::type
++ *
++ * \brief The type of the axis.
++ *
++ * The value is one of AxisType values.
++ */
++ QAbstract3DAxis::AxisType QAbstract3DAxis::type() const
++ {
++ return d_ptr->m_type;
++ }
++
++ /*!
++ * \property QAbstract3DAxis::title
++ *
++ * \brief The title for the axis.
++ *
++ * \sa titleVisible, titleFixed
++ */
++ void QAbstract3DAxis::setTitle(const QString &title)
++ {
++ if (d_ptr->m_title != title) {
++ d_ptr->m_title = title;
++ emit titleChanged(title);
++ }
++ }
++
++ QString QAbstract3DAxis::title() const
++ {
++ return d_ptr->m_title;
++ }
++
++ /*!
++ * \property QAbstract3DAxis::labels
++ *
++ * \brief The labels for the axis.
++ * \note Setting this property for QValue3DAxis does nothing, as it generates labels automatically.
++ */
++ void QAbstract3DAxis::setLabels(const QStringList &labels)
++ {
++ Q_UNUSED(labels);
++ }
++
++ QStringList QAbstract3DAxis::labels() const
++ {
++ d_ptr->updateLabels();
++ return d_ptr->m_labels;
++ }
++
++ /*!
++ * Sets the value range of the axis from \a min to \a max.
++ * When setting the range, the maximum value is adjusted if necessary, to ensure
++ * that the range remains valid.
++ * \note For QCategory3DAxis, specifies the index range of rows or columns to
++ * show.
++ */
++ void QAbstract3DAxis::setRange(float min, float max)
++ {
++ d_ptr->setRange(min, max);
++ setAutoAdjustRange(false);
++ }
++
++ /*!
++ * \property QAbstract3DAxis::labelAutoRotation
++ *
++ * \brief The maximum angle the labels can autorotate when the camera angle changes.
++ *
++ * The angle can be between 0 and 90, inclusive. The default value is 0.
++ * If the value is 0, axis labels do not automatically rotate.
++ * If the value is greater than zero, labels attempt to orient themselves toward the camera, up to
++ * the specified angle.
++ */
++ void QAbstract3DAxis::setLabelAutoRotation(float angle)
++ {
++ if (angle < 0.0f)
++ angle = 0.0f;
++ if (angle > 90.0f)
++ angle = 90.0f;
++ if (d_ptr->m_labelAutoRotation != angle) {
++ d_ptr->m_labelAutoRotation = angle;
++ emit labelAutoRotationChanged(angle);
++ }
++ }
++
++ float QAbstract3DAxis::labelAutoRotation() const
++ {
++ return d_ptr->m_labelAutoRotation;
++ }
++
++ /*!
++ * \property QAbstract3DAxis::titleVisible
++ *
++ * \brief Whether the axis title is visible in the primary graph view.
++ *
++ * The default value is \c{false}.
++ *
++ * \sa title, titleFixed
++ */
++ void QAbstract3DAxis::setTitleVisible(bool visible)
++ {
++ if (d_ptr->m_titleVisible != visible) {
++ d_ptr->m_titleVisible = visible;
++ emit titleVisibilityChanged(visible);
++ }
++ }
++
++ bool QAbstract3DAxis::isTitleVisible() const
++ {
++ return d_ptr->m_titleVisible;
++ }
++
++ /*!
++ * \property QAbstract3DAxis::titleFixed
++ *
++ * \brief The rotation of the axis titles.
++ *
++ * If \c{true}, axis titles in the primary graph view will be rotated towards the camera similarly
++ * to the axis labels.
++ * If \c{false}, axis titles are only rotated around their axis but are not otherwise oriented
++ * towards the camera.
++ * This property does not have any effect if the labelAutoRotation property
++ * value is zero.
++ * Default value is \c{true}.
++ *
++ * \sa labelAutoRotation, title, titleVisible
++ */
++ void QAbstract3DAxis::setTitleFixed(bool fixed)
++ {
++ if (d_ptr->m_titleFixed != fixed) {
++ d_ptr->m_titleFixed = fixed;
++ emit titleFixedChanged(fixed);
++ }
++ }
++
++ bool QAbstract3DAxis::isTitleFixed() const
++ {
++ return d_ptr->m_titleFixed;
++ }
++
++ /*!
++ * \property QAbstract3DAxis::min
++ *
++ * \brief The minimum value on the axis.
++ *
++ * When setting this property, the maximum value is adjusted if necessary, to
++ * ensure that the range remains valid.
++ * \note For QCategory3DAxis, specifies the index of the first row or column to
++ * show.
++ */
++ void QAbstract3DAxis::setMin(float min)
++ {
++ d_ptr->setMin(min);
++ setAutoAdjustRange(false);
++ }
++
++ /*!
++ * \property QAbstract3DAxis::max
++ *
++ * \brief The maximum value on the axis.
++ *
++ * When setting this property, the minimum value is adjusted if necessary, to
++ * ensure that the range remains valid.
++ * \note For QCategory3DAxis, specifies the index of the last row or column to
++ * show.
++ */
++ void QAbstract3DAxis::setMax(float max)
++ {
++ d_ptr->setMax(max);
++ setAutoAdjustRange(false);
++ }
++
++ float QAbstract3DAxis::min() const
++ {
++ return d_ptr->m_min;
++ }
++
++ float QAbstract3DAxis::max() const
++ {
++ return d_ptr->m_max;
++ }
++
++ /*!
++ * \property QAbstract3DAxis::autoAdjustRange
++ *
++ * \brief Whether the axis will automatically adjust the range so that all data fits in it.
++ *
++ * \sa setRange(), setMin(), setMax()
++ */
++ void QAbstract3DAxis::setAutoAdjustRange(bool autoAdjust)
++ {
++ if (d_ptr->m_autoAdjust != autoAdjust) {
++ d_ptr->m_autoAdjust = autoAdjust;
++ emit autoAdjustRangeChanged(autoAdjust);
++ }
++ }
++
++ bool QAbstract3DAxis::isAutoAdjustRange() const
++ {
++ return d_ptr->m_autoAdjust;
++ }
++
++ /*!
++ * \fn QAbstract3DAxis::rangeChanged(float min, float max)
++ *
++ * Emits the minimum and maximum values of the range, \a min and \a max, when
++ * the range changes.
++ */
++
++ // QAbstract3DAxisPrivate
++ QAbstract3DAxisPrivate::QAbstract3DAxisPrivate(QAbstract3DAxis *q, QAbstract3DAxis::AxisType type)
++ : QObject(0),
++ q_ptr(q),
++ m_orientation(QAbstract3DAxis::AxisOrientationNone),
++ m_type(type),
++ m_isDefaultAxis(false),
++ m_min(0.0f),
++ m_max(10.0f),
++ m_autoAdjust(true),
++ m_labelAutoRotation(0.0f),
++ m_titleVisible(false),
++ m_titleFixed(true)
++ {
++ }
++
++ QAbstract3DAxisPrivate::~QAbstract3DAxisPrivate()
++ {
++ }
++
++ void QAbstract3DAxisPrivate::setOrientation(QAbstract3DAxis::AxisOrientation orientation)
++ {
++ if (m_orientation == QAbstract3DAxis::AxisOrientationNone) {
++ m_orientation = orientation;
++ emit q_ptr->orientationChanged(orientation);
++ } else {
++ Q_ASSERT("Attempted to reset axis orientation.");
++ }
++ }
++
++ void QAbstract3DAxisPrivate::updateLabels()
++ {
++ // Default implementation does nothing
++ }
++
++ void QAbstract3DAxisPrivate::setRange(float min, float max, bool suppressWarnings)
++ {
++ bool adjusted = false;
++ if (!allowNegatives()) {
++ if (allowZero()) {
++ if (min < 0.0f) {
++ min = 0.0f;
++ adjusted = true;
++ }
++ if (max < 0.0f) {
++ max = 0.0f;
++ adjusted = true;
++ }
++ } else {
++ if (min <= 0.0f) {
++ min = 1.0f;
++ adjusted = true;
++ }
++ if (max <= 0.0f) {
++ max = 1.0f;
++ adjusted = true;
++ }
++ }
++ }
++ // If min >= max, we adjust ranges so that
++ // m_max becomes (min + 1.0f)
++ // as axes need some kind of valid range.
++ bool minDirty = false;
++ bool maxDirty = false;
++ if (m_min != min) {
++ m_min = min;
++ minDirty = true;
++ }
++ if (m_max != max || min > max || (!allowMinMaxSame() && min == max)) {
++ if (min > max || (!allowMinMaxSame() && min == max)) {
++ m_max = min + 1.0f;
++ adjusted = true;
++ } else {
++ m_max = max;
++ }
++ maxDirty = true;
++ }
++
++ if (minDirty || maxDirty) {
++ if (adjusted && !suppressWarnings) {
++ qWarning() << "Warning: Tried to set invalid range for axis."
++ " Range automatically adjusted to a valid one:"
++ << min << "-" << max << "-->" << m_min << "-" << m_max;
++ }
++ emit q_ptr->rangeChanged(m_min, m_max);
++ }
++
++ if (minDirty)
++ emit q_ptr->minChanged(m_min);
++ if (maxDirty)
++ emit q_ptr->maxChanged(m_max);
++ }
++
++ void QAbstract3DAxisPrivate::setMin(float min)
++ {
++ if (!allowNegatives()) {
++ if (allowZero()) {
++ if (min < 0.0f) {
++ min = 0.0f;
++ qWarning() << "Warning: Tried to set negative minimum for an axis that only"
++ "supports positive values and zero:" << min;
++ }
++ } else {
++ if (min <= 0.0f) {
++ min = 1.0f;
++ qWarning() << "Warning: Tried to set negative or zero minimum for an axis that only"
++ "supports positive values:" << min;
++ }
++ }
++ }
++
++ if (m_min != min) {
++ bool maxChanged = false;
++ if (min > m_max || (!allowMinMaxSame() && min == m_max)) {
++ float oldMax = m_max;
++ m_max = min + 1.0f;
++ qWarning() << "Warning: Tried to set minimum to equal or larger than maximum for"
++ " value axis. Maximum automatically adjusted to a valid one:"
++ << oldMax << "-->" << m_max;
++ maxChanged = true;
++ }
++ m_min = min;
++
++ emit q_ptr->rangeChanged(m_min, m_max);
++ emit q_ptr->minChanged(m_min);
++ if (maxChanged)
++ emit q_ptr->maxChanged(m_max);
++ }
++ }
++
++ void QAbstract3DAxisPrivate::setMax(float max)
++ {
++ if (!allowNegatives()) {
++ if (allowZero()) {
++ if (max < 0.0f) {
++ max = 0.0f;
++ qWarning() << "Warning: Tried to set negative maximum for an axis that only"
++ "supports positive values and zero:" << max;
++ }
++ } else {
++ if (max <= 0.0f) {
++ max = 1.0f;
++ qWarning() << "Warning: Tried to set negative or zero maximum for an axis that only"
++ "supports positive values:" << max;
++ }
++ }
++ }
++
++ if (m_max != max) {
++ bool minChanged = false;
++ if (m_min > max || (!allowMinMaxSame() && m_min == max)) {
++ float oldMin = m_min;
++ m_min = max - 1.0f;
++ if (!allowNegatives() && m_min < 0.0f) {
++ if (allowZero())
++ m_min = 0.0f;
++ else
++ m_min = max / 2.0f; // Need some positive value smaller than max
++
++ if (!allowMinMaxSame() && max == 0.0f) {
++ m_min = oldMin;
++ qWarning() << "Unable to set maximum value to zero.";
++ return;
++ }
++ }
++ qWarning() << "Warning: Tried to set maximum to equal or smaller than minimum for"
++ " value axis. Minimum automatically adjusted to a valid one:"
++ << oldMin << "-->" << m_min;
++ minChanged = true;
++ }
++ m_max = max;
++ emit q_ptr->rangeChanged(m_min, m_max);
++ emit q_ptr->maxChanged(m_max);
++ if (minChanged)
++ emit q_ptr->minChanged(m_min);
++ }
++ }
++
++ QT_END_NAMESPACE