summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOwais Akhtar <owais.akhtar@qt.io>2024-04-16 15:07:38 +0300
committerOwais Akhtar <owais.akhtar@qt.io>2024-05-03 15:14:11 +0300
commit688da7b80ecc7ad2a72833bee6f505c519dc70e7 (patch)
tree6b3c16ee0fae79c9f3c52e4a714f81c58a7bc114
parent27beaeaa8acb6cc007f08fc069409f006094ad62 (diff)
Implementation for DateTimeAxis
Task-number: QTBUG-121633 Change-Id: Ief34227fa2c94c4d9ffae2a21e35c9a994c4a360 Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
-rw-r--r--examples/graphs/2d/testbed/CMakeLists.txt1
-rw-r--r--examples/graphs/2d/testbed/qml/testbed/DateTimeAxis.qml156
-rw-r--r--examples/graphs/2d/testbed/qml/testbed/StartupView.qml4
-rw-r--r--src/graphs2d/CMakeLists.txt1
-rw-r--r--src/graphs2d/axis/datetimeaxis/qdatetimeaxis.cpp291
-rw-r--r--src/graphs2d/axis/datetimeaxis/qdatetimeaxis.h65
-rw-r--r--src/graphs2d/axis/datetimeaxis/qdatetimeaxis_p.h51
-rw-r--r--src/graphs2d/axis/qabstractaxis.cpp1
-rw-r--r--src/graphs2d/axis/qabstractaxis.h6
-rw-r--r--src/graphs2d/qsgrenderer/axisrenderer.cpp170
-rw-r--r--src/graphs2d/qsgrenderer/axisrenderer_p.h3
-rw-r--r--src/graphs2d/qsgrenderer/pointrenderer.cpp58
-rw-r--r--tests/auto/cpp2dtest/CMakeLists.txt1
-rw-r--r--tests/auto/cpp2dtest/qgaxis-datetime/CMakeLists.txt13
-rw-r--r--tests/auto/cpp2dtest/qgaxis-datetime/tst_datetimeaxis.cpp93
-rw-r--r--tests/auto/qml2dtest/axes/tst_datetimeaxis.qml137
16 files changed, 1028 insertions, 23 deletions
diff --git a/examples/graphs/2d/testbed/CMakeLists.txt b/examples/graphs/2d/testbed/CMakeLists.txt
index 2dd4d5c..a8d87d4 100644
--- a/examples/graphs/2d/testbed/CMakeLists.txt
+++ b/examples/graphs/2d/testbed/CMakeLists.txt
@@ -68,6 +68,7 @@ qt6_add_qml_module(testbed
qml/testbed/AreaSeries.qml
qml/testbed/DynamicSeries.qml
qml/testbed/Donut.qml
+ qml/testbed/DateTimeAxis.qml
RESOURCES
qml/testbed/images/arrow_icon.png
qml/testbed/images/icon_settings.png
diff --git a/examples/graphs/2d/testbed/qml/testbed/DateTimeAxis.qml b/examples/graphs/2d/testbed/qml/testbed/DateTimeAxis.qml
new file mode 100644
index 0000000..c99b0ed
--- /dev/null
+++ b/examples/graphs/2d/testbed/qml/testbed/DateTimeAxis.qml
@@ -0,0 +1,156 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtGraphs
+import QtQuick.Dialogs
+import QtQuick.Controls.Basic
+import QtQuick.Layouts
+
+Rectangle {
+ id: mainView
+ width: 800
+ height: 600
+ color: "#202020"
+
+ RowLayout {
+ id:bar
+ height: 100
+
+ Text {
+ Layout.leftMargin: 20
+ font.pixelSize: 24
+ color: "#ffffff"
+ text: "X:"
+ }
+
+ Slider {
+ id: sliderX
+
+ value: (new Date(1950,1,1)).getTime()
+ from: (new Date(1900,1,1)).getTime()
+ to: (new Date(2000,1,1)).getTime()
+ }
+
+ Text {
+ font.pixelSize: 24
+ color: "#ffffff"
+ text: "Y:"
+ }
+
+ Slider {
+ id: sliderY
+
+ value: (new Date(1950,1,1)).getTime()
+ from: (new Date(1900,1,1)).getTime()
+ to: (new Date(2000,1,1)).getTime()
+ }
+
+ Text {
+ Layout.leftMargin: 20
+ font.pixelSize: 24
+ color: "#ffffff"
+ text: "X Ticks:"
+ }
+
+ SpinBox {
+ onValueChanged: xAxis.tickInterval = value
+ }
+
+ Text {
+ Layout.leftMargin: 20
+ font.pixelSize: 24
+ color: "#ffffff"
+ text: "X Format:"
+ }
+ TextField {
+ placeholderText: "MMMM-yyyy"
+ onAccepted: xAxis.labelFormat = text
+ }
+ }
+
+ GraphsView {
+ id: chartView
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.top: bar.bottom
+ anchors.margins: 10
+ backgroundColor: "#010101"
+ theme: gtheme
+
+ GraphsTheme {
+ id: gtheme
+ axisYLabelFont.pixelSize: 8
+ colorScheme: Qt.Dark
+ theme: GraphsTheme.Theme.QtGreen
+ }
+
+ axisX: DateTimeAxis {
+ id: xAxis
+ minorTickCount: 2
+ labelsAngle: 45
+ labelFormat: "MMMM-yyyy"
+ tickInterval: 0
+ min: new Date(1930,12,31)
+ max: new Date(sliderX.value)
+ }
+
+ axisY: DateTimeAxis {
+ id: yAxis
+ minorTickCount: 2
+ labelsAngle: 45
+ labelFormat: "MMMM-yyyy"
+ tickInterval: 10
+ min: new Date(1930,12,31)
+ max: new Date(sliderY.value)
+ }
+
+ ToolTip {
+ id: tooltip
+ }
+
+ onHoverEnter: {
+ tooltip.visible = true;
+ }
+
+ onHoverExit: {
+ tooltip.visible = false;
+ }
+
+ onHover: (seriesName, position, value) => {
+ tooltip.x = position.x + 1;
+ tooltip.y = position.y + 1;
+ tooltip.text = new Date(value.x).toString();
+ }
+
+ LineSeries {
+ id: line
+ theme: gtheme
+ width: 8
+ hoverable: true
+
+ XYPoint { x: new Date(1910, 2, 15);y: new Date(1900, 12, 31) }
+ XYPoint { x: new Date(1915, 2, 15);y: new Date(1910, 12, 31) }
+ XYPoint { x: new Date(1920, 1, 1); y: new Date(1920, 12, 31) }
+ XYPoint { x: new Date(1930, 12, 31); y: new Date(1960, 12, 31) }
+ XYPoint { x: new Date(1940, 7, 1); y: new Date(1940, 12, 31) }
+ XYPoint { x: new Date(1950, 8, 2); y: new Date(1950, 12, 31) }
+ XYPoint { x: new Date(1960, 8, 2); y: new Date(1960, 12, 31) }
+ }
+
+ SplineSeries {
+ id: spline
+ theme: gtheme
+ width: 4
+
+ XYPoint { x: new Date(1910, 7, 1); y: new Date(1940, 12, 31) }
+ XYPoint { x: new Date(1920, 8, 2); y: new Date(1950, 12, 31) }
+ XYPoint { x: new Date(1930, 8, 2); y: new Date(1960, 12, 31) }
+ XYPoint { x: new Date(1940, 2, 15);y: new Date(1900, 12, 31) }
+ XYPoint { x: new Date(1955, 2, 15);y: new Date(1910, 12, 31) }
+ XYPoint { x: new Date(1960, 1, 1); y: new Date(1920, 12, 31) }
+ XYPoint { x: new Date(1970, 12, 31); y: new Date(1960, 12, 31) }
+ }
+ }
+}
diff --git a/examples/graphs/2d/testbed/qml/testbed/StartupView.qml b/examples/graphs/2d/testbed/qml/testbed/StartupView.qml
index 60798eb..605b29b 100644
--- a/examples/graphs/2d/testbed/qml/testbed/StartupView.qml
+++ b/examples/graphs/2d/testbed/qml/testbed/StartupView.qml
@@ -81,6 +81,10 @@ Item {
name: "BarChangingSetCount"
file: "BarChangingSetCount.qml"
}
+ ListElement {
+ name: "DateTime Axis"
+ file: "DateTimeAxis.qml"
+ }
}
Component {
diff --git a/src/graphs2d/CMakeLists.txt b/src/graphs2d/CMakeLists.txt
index 5377213..397eba9 100644
--- a/src/graphs2d/CMakeLists.txt
+++ b/src/graphs2d/CMakeLists.txt
@@ -33,6 +33,7 @@ qt_internal_extend_target(Graphs
animation/qgraphpointanimation.cpp animation/qgraphpointanimation_p.h
animation/qgraphtransition_p.h animation/qgraphtransition.cpp
animation/qxyseriesanimation_p.h animation/qxyseriesanimation.cpp
+ axis/datetimeaxis/qdatetimeaxis.h axis/datetimeaxis/qdatetimeaxis.cpp axis/datetimeaxis/qdatetimeaxis_p.h
)
add_subdirectory(qml/designer)
diff --git a/src/graphs2d/axis/datetimeaxis/qdatetimeaxis.cpp b/src/graphs2d/axis/datetimeaxis/qdatetimeaxis.cpp
new file mode 100644
index 0000000..2fdca2d
--- /dev/null
+++ b/src/graphs2d/axis/datetimeaxis/qdatetimeaxis.cpp
@@ -0,0 +1,291 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtCore/QObject>
+#include <QtGraphs/QDateTimeAxis>
+#include "private/qdatetimeaxis_p.h"
+
+QT_BEGIN_NAMESPACE
+/*!
+ \class QDateTimeAxis
+ \inmodule QtGraphs
+ \ingroup graphs_2D
+ \brief The QDateTimeAxis adds support for DateTime values to be added to a graph's axis.
+
+ A DateTime Axis can be used to display DateTime representations with tick marks and grid lines.
+ The DateTime items on the axis are displayed at the position of the ticks.
+*/
+
+/*!
+ \qmltype DateTimeAxis
+ \instantiates QDateTimeAxis
+ \inqmlmodule QtGraphs
+ \ingroup graphs_qml_2D
+ \inherits AbstractAxis
+ \brief Adds DateTime items to a graph's axis.
+
+ A DateTime Axis can be used to display DateTime representations with tick marks and grid lines.
+ The DateTime items on the axis are displayed at the position of the ticks.
+
+ The following example code illustrates how to use the DateTimeAxis type:
+ \code
+ GraphsView {
+ LineSeries {
+ axisX: DateTimeAxis {
+ min: new Date(2000,1,1)
+ max: new Date(1970,1,1)
+ }
+
+ // Add a few XYPoint data...
+ }
+ }
+ \endcode
+*/
+
+/*!
+ \property QDateTimeAxis::min
+ \brief The minimum value on the axis
+
+ This value can be lower or higher than the maximum.
+ The default value is new Date(1970,1,1)
+*/
+/*!
+ \qmlproperty real DateTimeAxis::min
+ The minimum value on the axis.
+
+ This value can be lower or higher than the maximum.
+ The default value is new Date(1970,1,1)
+*/
+
+/*!
+ \property QDateTimeAxis::max
+ \brief The maximum value on the axis
+
+ This value can be lower or higher than the minimum.
+ The default value is new Date(1980,1,1)
+*/
+/*!
+ \qmlproperty real DateTimeAxis::max
+ The maximum value on the axis.
+
+ This value can be lower or higher than the minimum.
+ The default value is new Date(1980,1,1)
+*/
+/*!
+ \property QDateTimeAxis::minorTickCount
+ \brief The number of minor tick marks on the axis. This indicates how many grid lines are drawn
+ between major ticks on the graph. Labels are not drawn for minor ticks. The default value is 0.
+*/
+/*!
+ \qmlproperty int DateTimeAxis::minorTickCount
+ The number of minor tick marks on the axis. This indicates how many grid lines are drawn
+ between major ticks on the graph. Labels are not drawn for minor ticks. The default value is 0.
+*/
+/*!
+ \property QDateTimeAxis::tickInterval
+ \brief The interval between dynamically placed tick marks and labels.
+ The default value is 0, which means that intervals are automatically calculated
+ based on the min and max range.
+*/
+/*!
+ \qmlproperty real DateTimeAxis::tickInterval
+ The interval between dynamically placed tick marks and labels.
+ The default value is 0, which means that intervals are automatically calculated
+ based on the min and max range.
+*/
+
+/*!
+ \property QDateTimeAxis::labelFormat
+ \brief The format of the DateTime labels on the axis.
+ The format property allows to signify the visual representation of the DateTime object, in days,
+ months, and years. The default value is dd-MMMM-yy.
+*/
+
+/*!
+ \qmlproperty string DateTimeAxis::labelFormat
+ The format of the DateTime labels on the axis
+ The format property allows to signify the visual representation of the DateTime object, in days,
+ months, and years. The default value is dd-MMMM-yy.
+ */
+/*!
+ \qmlsignal DateTimeAxis::minChanged(DateTime min)
+ This signal is emitted when the minimum value of the axis, specified by \a min, changes.
+*/
+/*!
+ \qmlsignal DateTimeAxis::maxChanged(DateTime max)
+ This signal is emitted when the maximum value of the axis, specified by \a max, changes.
+*/
+/*!
+ \qmlsignal DateTimeAxis::minorTickCountChanged(int minorTickCount)
+ This signal is emitted when the number of minor tick marks on the axis, specified by
+ \a minorTickCount, changes.
+*/
+/*!
+ \qmlsignal DateTimeAxis::rangeChanged(real min, real max)
+ This signal is emitted when the minimum or maximum value of the axis, specified by \a min
+ and \a max, changes.
+*/
+/*!
+ \qmlsignal DateTimeAxis::labelFormatChanged(string format)
+ This signal is emitted when the \a format of axis labels changes.
+*/
+/*!
+ \qmlsignal DateTimeAxis::tickIntervalChanged(real tickInterval)
+ This signal is emitted when the tick interval value, specified by
+ \a tickInterval, changes.
+*/
+
+QDateTimeAxis::QDateTimeAxis(QObject *parent)
+ : QAbstractAxis(*(new QDateTimeAxisPrivate), parent)
+{}
+
+QDateTimeAxis::~QDateTimeAxis()
+{
+ Q_D(QDateTimeAxis);
+ if (d->m_graph)
+ d->m_graph->removeAxis(this);
+}
+
+QAbstractAxis::AxisType QDateTimeAxis::type() const
+{
+ return QAbstractAxis::AxisType::DateTime;
+}
+
+void QDateTimeAxis::setMin(QDateTime min)
+{
+ Q_D(QDateTimeAxis);
+ if (min.isValid()) {
+ d->setRange(min.toMSecsSinceEpoch(), d->m_max);
+ emit minChanged(QDateTime::fromMSecsSinceEpoch(d->m_min));
+ emit update();
+ }
+}
+
+QDateTime QDateTimeAxis::min() const
+{
+ Q_D(const QDateTimeAxis);
+ return QDateTime::fromMSecsSinceEpoch(d->m_min);
+}
+
+void QDateTimeAxis::setMax(QDateTime max)
+{
+ Q_D(QDateTimeAxis);
+ if (max.isValid()) {
+ d->setRange(d->m_min, max.toMSecsSinceEpoch());
+ emit maxChanged(QDateTime::fromMSecsSinceEpoch(d->m_max));
+ emit update();
+ }
+}
+
+QDateTime QDateTimeAxis::max() const
+{
+ Q_D(const QDateTimeAxis);
+ return QDateTime::fromMSecsSinceEpoch(d->m_max);
+}
+
+void QDateTimeAxis::setLabelFormat(QString format)
+{
+ Q_D(QDateTimeAxis);
+ if (d->m_format != format) {
+ d->m_format = format;
+ emit labelFormatChanged(format);
+ emit update();
+ }
+}
+
+QString QDateTimeAxis::labelFormat() const
+{
+ Q_D(const QDateTimeAxis);
+ return d->m_format;
+}
+
+qreal QDateTimeAxis::tickInterval() const
+{
+ Q_D(const QDateTimeAxis);
+ return d->m_tickInterval;
+}
+
+void QDateTimeAxis::setTickInterval(qreal newTickInterval)
+{
+ Q_D(QDateTimeAxis);
+
+ if (newTickInterval < 0.0)
+ newTickInterval = 0.0;
+
+ if (qFuzzyCompare(d->m_tickInterval, newTickInterval))
+ return;
+ d->m_tickInterval = newTickInterval;
+ emit tickIntervalChanged();
+ emit update();
+}
+
+int QDateTimeAxis::minorTickCount() const
+{
+ Q_D(const QDateTimeAxis);
+ return d->m_minorTickCount;
+}
+
+void QDateTimeAxis::setMinorTickCount(int newMinorTickCount)
+{
+ Q_D(QDateTimeAxis);
+
+ if (newMinorTickCount < 0.0)
+ newMinorTickCount = 0.0;
+
+ if (d->m_minorTickCount == newMinorTickCount)
+ return;
+ d->m_minorTickCount = newMinorTickCount;
+ emit minorTickCountChanged();
+ emit update();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QDateTimeAxisPrivate::QDateTimeAxisPrivate() {}
+
+QDateTimeAxisPrivate::~QDateTimeAxisPrivate() {}
+
+void QDateTimeAxisPrivate::setMin(const QVariant &min)
+{
+ Q_Q(QDateTimeAxis);
+ if (min.canConvert<QDateTime>())
+ q->setMin(min.toDateTime());
+}
+
+void QDateTimeAxisPrivate::setMax(const QVariant &max)
+{
+ Q_Q(QDateTimeAxis);
+ if (max.canConvert<QDateTime>())
+ q->setMax(max.toDateTime());
+}
+
+void QDateTimeAxisPrivate::setRange(const QVariant &min, const QVariant &max)
+{
+ Q_Q(QDateTimeAxis);
+ if (min.canConvert<QDateTime>() && max.canConvert<QDateTime>())
+ q->setRange(min.toDateTime(), max.toDateTime());
+}
+
+void QDateTimeAxisPrivate::setRange(qreal min, qreal max)
+{
+ Q_Q(QDateTimeAxis);
+
+ bool changed = false;
+
+ if (m_min != min) {
+ m_min = min;
+ changed = true;
+ emit q->minChanged(QDateTime::fromMSecsSinceEpoch(min));
+ }
+
+ if (m_max != max) {
+ m_max = max;
+ changed = true;
+ emit q->maxChanged(QDateTime::fromMSecsSinceEpoch(max));
+ }
+
+ if (changed)
+ emit q->rangeChanged(min, max);
+}
+
+QT_END_NAMESPACE
diff --git a/src/graphs2d/axis/datetimeaxis/qdatetimeaxis.h b/src/graphs2d/axis/datetimeaxis/qdatetimeaxis.h
new file mode 100644
index 0000000..d1a1abb
--- /dev/null
+++ b/src/graphs2d/axis/datetimeaxis/qdatetimeaxis.h
@@ -0,0 +1,65 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QDATETIMEAXIS_H
+#define QDATETIMEAXIS_H
+
+#include <QtGraphs/QAbstractAxis>
+
+QT_BEGIN_NAMESPACE
+
+class QDateTimeAxisPrivate;
+
+class Q_GRAPHS_EXPORT QDateTimeAxis : public QAbstractAxis
+{
+ Q_OBJECT
+ Q_PROPERTY(QDateTime min READ min WRITE setMin NOTIFY minChanged FINAL)
+ Q_PROPERTY(QDateTime max READ max WRITE setMax NOTIFY maxChanged FINAL)
+ Q_PROPERTY(
+ QString labelFormat READ labelFormat WRITE setLabelFormat NOTIFY labelFormatChanged FINAL)
+ Q_PROPERTY(
+ int minorTickCount READ minorTickCount WRITE setMinorTickCount NOTIFY minorTickCountChanged)
+ Q_PROPERTY(
+ qreal tickInterval READ tickInterval WRITE setTickInterval NOTIFY tickIntervalChanged FINAL)
+ QML_NAMED_ELEMENT(DateTimeAxis)
+
+public:
+ explicit QDateTimeAxis(QObject *parent = nullptr);
+ ~QDateTimeAxis() override;
+
+protected:
+ QDateTimeAxis(QDateTimeAxisPrivate &d, QObject *parent = nullptr);
+
+public:
+ AxisType type() const override;
+
+ //range handling
+ void setMin(QDateTime min);
+ QDateTime min() const;
+ void setMax(QDateTime max);
+ QDateTime max() const;
+
+ void setLabelFormat(QString format);
+ QString labelFormat() const;
+
+ qreal tickInterval() const;
+ void setTickInterval(qreal newTickInterval);
+
+ int minorTickCount() const;
+ void setMinorTickCount(int newMinorTickCount);
+
+Q_SIGNALS:
+ void minChanged(QDateTime min);
+ void maxChanged(QDateTime max);
+ void labelFormatChanged(QString format);
+ void tickIntervalChanged();
+ void minorTickCountChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QDateTimeAxis)
+ Q_DISABLE_COPY(QDateTimeAxis)
+};
+
+QT_END_NAMESPACE
+
+#endif // QDATETIMEAXIS_H
diff --git a/src/graphs2d/axis/datetimeaxis/qdatetimeaxis_p.h b/src/graphs2d/axis/datetimeaxis/qdatetimeaxis_p.h
new file mode 100644
index 0000000..0f87e69
--- /dev/null
+++ b/src/graphs2d/axis/datetimeaxis/qdatetimeaxis_p.h
@@ -0,0 +1,51 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtGraphs API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QDATETIMEAXIS_P_H
+#define QDATETIMEAXIS_P_H
+
+#include <QtGraphs/QDateTimeAxis>
+#include <private/qabstractaxis_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDateTimeAxisPrivate : public QAbstractAxisPrivate
+{
+public:
+ QDateTimeAxisPrivate();
+ ~QDateTimeAxisPrivate();
+
+protected:
+ qreal m_min = QDateTime(QDate(1970, 1, 1), QTime::fromMSecsSinceStartOfDay(0))
+ .toMSecsSinceEpoch();
+ qreal m_max = QDateTime(QDate(1970, 1, 1), QTime::fromMSecsSinceStartOfDay(0))
+ .addYears(10)
+ .toMSecsSinceEpoch();
+ qreal m_tickInterval = 0.0;
+ int m_minorTickCount = 0;
+ QString m_format = QStringLiteral("dd-MMMM-yy");
+
+public:
+ void setMin(const QVariant &min) override;
+ void setMax(const QVariant &max) override;
+ void setRange(const QVariant &min, const QVariant &max) override;
+ void setRange(qreal min, qreal max) override;
+ qreal min() override { return m_min; }
+ qreal max() override { return m_max; }
+
+private:
+ Q_DECLARE_PUBLIC(QDateTimeAxis)
+};
+
+QT_END_NAMESPACE
+
+#endif // QDATETIMEAXIS_P_H
diff --git a/src/graphs2d/axis/qabstractaxis.cpp b/src/graphs2d/axis/qabstractaxis.cpp
index a27cdbe..835b71a 100644
--- a/src/graphs2d/axis/qabstractaxis.cpp
+++ b/src/graphs2d/axis/qabstractaxis.cpp
@@ -39,6 +39,7 @@ QT_BEGIN_NAMESPACE
\value Value
\value BarCategory
+ \value DateTime
*/
/*!
diff --git a/src/graphs2d/axis/qabstractaxis.h b/src/graphs2d/axis/qabstractaxis.h
index c9da4be..319eb65 100644
--- a/src/graphs2d/axis/qabstractaxis.h
+++ b/src/graphs2d/axis/qabstractaxis.h
@@ -43,11 +43,7 @@ class Q_GRAPHS_EXPORT QAbstractAxis : public QObject
Q_DECLARE_PRIVATE(QAbstractAxis)
public:
-
- enum class AxisType {
- Value,
- BarCategory
- };
+ enum class AxisType { Value, BarCategory, DateTime };
Q_ENUM(AxisType)
protected:
diff --git a/src/graphs2d/qsgrenderer/axisrenderer.cpp b/src/graphs2d/qsgrenderer/axisrenderer.cpp
index 1326418..8a93c5c 100644
--- a/src/graphs2d/qsgrenderer/axisrenderer.cpp
+++ b/src/graphs2d/qsgrenderer/axisrenderer.cpp
@@ -1,11 +1,13 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+#include <QtGraphs/QBarCategoryAxis>
+#include <QtGraphs/QGraphsTheme>
#include <private/axisrenderer_p.h>
#include <private/qabstractaxis_p.h>
#include <private/qbarseries_p.h>
+#include <private/qdatetimeaxis_p.h>
#include <private/qgraphsview_p.h>
-#include <QtGraphs/QBarCategoryAxis>
#include <private/qvalueaxis_p.h>
QT_BEGIN_NAMESPACE
@@ -194,7 +196,6 @@ void AxisRenderer::updateAxis()
m_axisVerticalValueStep = step;
int axisVerticalMinorTickCount = vaxis->minorTickCount();
m_axisVerticalMinorTickScale = axisVerticalMinorTickCount > 0 ? 1.0 / (axisVerticalMinorTickCount + 1) : 1.0;
-
m_axisVerticalStepPx = (height() - m_graph->m_marginTop - m_graph->m_marginBottom - m_axisHeight) / (m_axisVerticalValueRange / m_axisVerticalValueStep);
double axisVerticalValueDiff = m_axisVerticalMinLabel - m_axisVerticalMinValue;
m_axisYMovement = -(axisVerticalValueDiff / m_axisVerticalValueStep) * m_axisVerticalStepPx;
@@ -257,6 +258,80 @@ void AxisRenderer::updateAxis()
updateBarYAxisLabels(vaxis, yAxisRect);
}
+ if (auto vaxis = qobject_cast<QDateTimeAxis *>(m_axisVertical)) {
+ // Todo: make constant for all axis, or clamp in class? (QTBUG-124736)
+ const double MAX_DIVS = 100.0;
+
+ double interval = std::clamp(vaxis->tickInterval(), 0.0, MAX_DIVS);
+ m_axisVerticalMaxValue = vaxis->max().toMSecsSinceEpoch();
+ m_axisVerticalMinValue = vaxis->min().toMSecsSinceEpoch();
+ m_axisVerticalValueRange = std::abs(m_axisVerticalMaxValue - m_axisVerticalMinValue);
+
+ // in ms
+ double segment;
+ if (interval <= 0) {
+ segment = getValueStepsFromRange(m_axisVerticalValueRange);
+ interval = m_axisVerticalValueRange / segment;
+ } else {
+ segment = m_axisVerticalValueRange / interval;
+ }
+
+ m_axisVerticalMinLabel = std::clamp(interval, 1.0, MAX_DIVS);
+
+ m_axisVerticalValueStep = segment;
+ int axisVerticalMinorTickCount = vaxis->minorTickCount();
+ m_axisVerticalMinorTickScale = axisVerticalMinorTickCount > 0
+ ? 1.0 / (axisVerticalMinorTickCount + 1)
+ : 1.0;
+ m_axisVerticalStepPx = (height() - m_graph->m_marginTop - m_graph->m_marginBottom
+ - m_axisHeight)
+ / (qFuzzyCompare(segment, 0)
+ ? interval
+ : (m_axisVerticalValueRange / m_axisVerticalValueStep));
+
+ float rightMargin = 20;
+ yAxisRect = {m_graph->m_marginLeft, m_graph->m_marginTop, m_axisWidth - rightMargin, h};
+ updateDateTimeYAxisLabels(vaxis, yAxisRect);
+ }
+
+ if (auto haxis = qobject_cast<QDateTimeAxis *>(m_axisHorizontal)) {
+ const double MAX_DIVS = 100.0;
+
+ double interval = std::clamp(haxis->tickInterval(), 0.0, MAX_DIVS);
+ m_axisHorizontalMaxValue = haxis->max().toMSecsSinceEpoch();
+ m_axisHorizontalMinValue = haxis->min().toMSecsSinceEpoch();
+ m_axisHorizontalValueRange = std::abs(m_axisHorizontalMaxValue - m_axisHorizontalMinValue);
+
+ // in ms
+ double segment;
+ if (interval <= 0) {
+ segment = getValueStepsFromRange(m_axisHorizontalValueRange);
+ interval = m_axisHorizontalValueRange / segment;
+ } else {
+ segment = m_axisHorizontalValueRange / interval;
+ }
+
+ m_axisHorizontalMinLabel = std::clamp(interval, 1.0, MAX_DIVS);
+
+ m_axisHorizontalValueStep = segment;
+ int axisHorizontalMinorTickCount = haxis->minorTickCount();
+ m_axisHorizontalMinorTickScale = axisHorizontalMinorTickCount > 0
+ ? 1.0 / (axisHorizontalMinorTickCount + 1)
+ : 1.0;
+ m_axisHorizontalStepPx = (width() - m_graph->m_marginLeft - m_graph->m_marginRight
+ - m_axisWidth)
+ / (qFuzzyCompare(segment, 0)
+ ? interval
+ : (m_axisHorizontalValueRange / m_axisHorizontalValueStep));
+
+ float topMargin = 20;
+ xAxisRect = {m_graph->m_marginLeft + m_axisWidth,
+ m_graph->m_marginTop + h - m_graph->m_marginBottom + topMargin,
+ w,
+ m_axisHeight};
+ updateDateTimeXAxisLabels(haxis, xAxisRect);
+ }
+
updateAxisTickers();
updateAxisTickersShadow();
updateAxisGrid();
@@ -706,6 +781,97 @@ void AxisRenderer::updateValueXAxisLabels(QValueAxis *axis, const QRectF &rect)
}
}
+void AxisRenderer::updateDateTimeYAxisLabels(QDateTimeAxis *axis, const QRectF &rect)
+{
+ auto maxDate = axis->max();
+ auto minDate = axis->min();
+ int dateTimeSize = m_axisVerticalMinLabel + 1;
+ auto segment = (maxDate.toMSecsSinceEpoch() - minDate.toMSecsSinceEpoch())
+ / m_axisVerticalMinLabel;
+
+ // See if we need more text items
+ updateAxisLabelItems(m_yAxisTextItems, dateTimeSize);
+
+ for (auto i = 0; i < dateTimeSize; ++i) {
+ auto &textItem = m_yAxisTextItems[i];
+ if (axis->isVisible() && axis->labelsVisible()) {
+ // TODO: Not general, fix vertical align to work in all cases
+ float fontSize = theme()->axisYLabelFont().pixelSize() < 0
+ ? theme()->axisYLabelFont().pointSize()
+ : theme()->axisYLabelFont().pixelSize();
+ float posX = rect.x();
+ textItem->setX(posX);
+ float posY = rect.y() + rect.height() - (((float) i) * m_axisVerticalStepPx);
+ const double titleMargin = 0.01;
+ if ((posY - titleMargin) > (rect.height() + rect.y())
+ || (posY + titleMargin) < rect.y()) {
+ // Hide text item which are outside the axis area
+ textItem->setVisible(false);
+ continue;
+ }
+ // Take font size into account only after hiding
+ posY -= fontSize;
+ textItem->setY(posY);
+ textItem->setHAlign(QQuickText::HAlignment::AlignHCenter);
+ textItem->setVAlign(QQuickText::VAlignment::AlignVCenter);
+ textItem->setHAlign(QQuickText::HAlignment::AlignRight);
+ textItem->setVAlign(QQuickText::VAlignment::AlignBottom);
+ textItem->setWidth(rect.width());
+ textItem->setHeight(textItem->contentHeight());
+ textItem->setFont(theme()->axisYLabelFont());
+ textItem->setColor(theme()->axisYLabelColor());
+ textItem->setRotation(axis->labelsAngle());
+ textItem->setText(minDate.addMSecs(segment * i).toString(axis->labelFormat()));
+ textItem->setVisible(true);
+ } else {
+ textItem->setVisible(false);
+ }
+ }
+}
+
+void AxisRenderer::updateDateTimeXAxisLabels(QDateTimeAxis *axis, const QRectF &rect)
+{
+ auto maxDate = axis->max();
+ auto minDate = axis->min();
+ int dateTimeSize = m_axisHorizontalMinLabel + 1;
+ auto segment = (maxDate.toMSecsSinceEpoch() - minDate.toMSecsSinceEpoch())
+ / m_axisHorizontalMinLabel;
+
+ // See if we need more text items
+ updateAxisLabelItems(m_xAxisTextItems, dateTimeSize);
+
+ for (auto i = 0; i < dateTimeSize; ++i) {
+ auto &textItem = m_xAxisTextItems[i];
+ if (axis->isVisible() && axis->labelsVisible()) {
+ float posY = rect.y();
+ textItem->setY(posY);
+ float textItemWidth = 20;
+ float posX = rect.x() + (((float) i) * m_axisHorizontalStepPx);
+ const double titleMargin = 0.01;
+ if ((posX - titleMargin) > (rect.width() + rect.x())
+ || (posX + titleMargin) < rect.x()) {
+ // Hide text item which are outside the axis area
+ textItem->setVisible(false);
+ continue;
+ }
+ // Take text size into account only after hiding
+ posX -= 0.5 * textItemWidth;
+ textItem->setX(posX);
+ textItem->setHAlign(QQuickText::HAlignment::AlignHCenter);
+ textItem->setVAlign(QQuickText::VAlignment::AlignBottom);
+ textItem->setWidth(textItemWidth);
+ textItem->setHeight(rect.height());
+ textItem->setFont(theme()->axisYLabelFont());
+ textItem->setColor(theme()->axisYLabelColor());
+ textItem->setRotation(axis->labelsAngle());
+ textItem->setText(minDate.addMSecs(segment * i).toString(axis->labelFormat()));
+ textItem->setVisible(true);
+ } else {
+ textItem->setVisible(false);
+ }
+ }
+}
+
// Calculate suitable major step based on range
double AxisRenderer::getValueStepsFromRange(double range)
{
diff --git a/src/graphs2d/qsgrenderer/axisrenderer_p.h b/src/graphs2d/qsgrenderer/axisrenderer_p.h
index eb29848..e7b5e96 100644
--- a/src/graphs2d/qsgrenderer/axisrenderer_p.h
+++ b/src/graphs2d/qsgrenderer/axisrenderer_p.h
@@ -30,6 +30,7 @@ class QGraphsView;
class QBarCategoryAxis;
class QValueAxis;
class QGraphsTheme;
+class QDateTimeAxis;
class AxisRenderer : public QQuickItem
{
@@ -49,6 +50,8 @@ public:
void updateBarYAxisLabels(QBarCategoryAxis *axis, const QRectF &rect);
void updateValueYAxisLabels(QValueAxis *axis, const QRectF &rect);
void updateValueXAxisLabels(QValueAxis *axis, const QRectF &rect);
+ void updateDateTimeYAxisLabels(QDateTimeAxis *axis, const QRectF &rect);
+ void updateDateTimeXAxisLabels(QDateTimeAxis *axis, const QRectF &rect);
void initialize();
Q_SIGNALS:
diff --git a/src/graphs2d/qsgrenderer/pointrenderer.cpp b/src/graphs2d/qsgrenderer/pointrenderer.cpp
index 9dd0147..42f5eb3 100644
--- a/src/graphs2d/qsgrenderer/pointrenderer.cpp
+++ b/src/graphs2d/qsgrenderer/pointrenderer.cpp
@@ -53,9 +53,15 @@ qreal PointRenderer::defaultSize(QXYSeries *series)
void PointRenderer::calculateRenderCoordinates(
AxisRenderer *axisRenderer, qreal origX, qreal origY, qreal *renderX, qreal *renderY)
{
+ auto flipX = axisRenderer->m_axisHorizontalMaxValue < axisRenderer->m_axisHorizontalMinValue
+ ? -1
+ : 1;
+ auto flipY = axisRenderer->m_axisVerticalMaxValue < axisRenderer->m_axisVerticalMinValue ? -1
+ : 1;
+
*renderX = m_graph->m_marginLeft + axisRenderer->m_axisWidth
- + m_areaWidth * origX * m_maxHorizontal - m_horizontalOffset;
- *renderY = m_graph->m_marginTop + m_areaHeight - m_areaHeight * origY * m_maxVertical
+ + m_areaWidth * flipX * origX * m_maxHorizontal - m_horizontalOffset;
+ *renderY = m_graph->m_marginTop + m_areaHeight - m_areaHeight * flipY * origY * m_maxVertical
+ m_verticalOffset;
}
@@ -291,12 +297,20 @@ void PointRenderer::handlePolish(QXYSeries *series)
m_maxHorizontal = m_graph->m_axisRenderer->m_axisHorizontalValueRange > 0
? 1.0 / m_graph->m_axisRenderer->m_axisHorizontalValueRange
: 100.0;
- m_verticalOffset = (m_graph->m_axisRenderer->m_axisVerticalMinValue
- / m_graph->m_axisRenderer->m_axisVerticalValueRange)
- * m_areaHeight;
- m_horizontalOffset = (m_graph->m_axisRenderer->m_axisHorizontalMinValue
- / m_graph->m_axisRenderer->m_axisHorizontalValueRange)
- * m_areaWidth;
+
+ auto vmin = m_graph->m_axisRenderer->m_axisVerticalMinValue
+ > m_graph->m_axisRenderer->m_axisVerticalMaxValue
+ ? std::abs(m_graph->m_axisRenderer->m_axisVerticalMinValue)
+ : m_graph->m_axisRenderer->m_axisVerticalMinValue;
+
+ m_verticalOffset = (vmin / m_graph->m_axisRenderer->m_axisVerticalValueRange) * m_areaHeight;
+
+ auto hmin = m_graph->m_axisRenderer->m_axisHorizontalMinValue
+ > m_graph->m_axisRenderer->m_axisHorizontalMaxValue
+ ? std::abs(m_graph->m_axisRenderer->m_axisHorizontalMinValue)
+ : m_graph->m_axisRenderer->m_axisHorizontalMinValue;
+
+ m_horizontalOffset = (hmin / m_graph->m_axisRenderer->m_axisHorizontalValueRange) * m_areaWidth;
if (!m_groups.contains(series)) {
PointGroup *group = new PointGroup();
@@ -447,6 +461,12 @@ bool PointRenderer::handleHoverMove(QHoverEvent *event)
if (!group->series->hoverable())
continue;
+ auto axisRenderer = group->series->graph()->m_axisRenderer;
+ bool isHNegative = axisRenderer->m_axisHorizontalMaxValue
+ < axisRenderer->m_axisHorizontalMinValue;
+ bool isVNegative = axisRenderer->m_axisVerticalMaxValue
+ < axisRenderer->m_axisVerticalMinValue;
+
if (group->series->type() == QAbstractSeries::SeriesType::Scatter) {
const QString &name = group->series->name();
@@ -479,23 +499,26 @@ bool PointRenderer::handleHoverMove(QHoverEvent *event)
if (points.size() >= 2) {
bool hovering = false;
-
for (int i = 0; i < points.size() - 1; i++) {
qreal x1, y1, x2, y2;
if (i == 0) {
- x1 = group->shapePath->startX();
+ auto curve = qobject_cast<QQuickCurve *>(group->paths[0]);
+
+ x1 = isHNegative ? curve->x() : group->shapePath->startX();
y1 = group->shapePath->startY();
- auto curve = qobject_cast<QQuickCurve *>(group->paths[0]);
- x2 = curve->x();
+ x2 = isHNegative ? group->shapePath->startX() : curve->x();
y2 = curve->y();
} else {
- auto curve1 = qobject_cast<QQuickCurve *>(group->paths[i - 1]);
+ bool n = isVNegative | isHNegative;
+
+ auto curve1 = qobject_cast<QQuickCurve *>(group->paths[n ? i : i - 1]);
+ auto curve2 = qobject_cast<QQuickCurve *>(group->paths[n ? i - 1 : i]);
+
x1 = curve1->x();
y1 = curve1->y();
- auto curve2 = qobject_cast<QQuickCurve *>(group->paths[i]);
x2 = curve2->x();
y2 = curve2->y();
}
@@ -504,6 +527,7 @@ bool PointRenderer::handleHoverMove(QHoverEvent *event)
if (denominator > 0) {
qreal hoverDistance = qAbs((x2 - x1) * (y1 - y0) - (x1 - x0) * (y2 - y1))
/ qSqrt(denominator);
+
if (hoverDistance < hoverSize) {
qreal alpha = 0;
qreal extrapolation = 0;
@@ -520,8 +544,10 @@ bool PointRenderer::handleHoverMove(QHoverEvent *event)
}
if (alpha >= -extrapolation && alpha <= 1.0 + extrapolation) {
- const QPointF &point1 = points[i];
- const QPointF &point2 = points[i + 1];
+ bool n = isVNegative | isHNegative;
+
+ const QPointF &point1 = points[n ? i + 1 : i];
+ const QPointF &point2 = points[n ? i : i + 1];
QPointF point = (point2 * (1.0 - alpha)) + (point1 * alpha);
diff --git a/tests/auto/cpp2dtest/CMakeLists.txt b/tests/auto/cpp2dtest/CMakeLists.txt
index 5372b0f..1fa0bea 100644
--- a/tests/auto/cpp2dtest/CMakeLists.txt
+++ b/tests/auto/cpp2dtest/CMakeLists.txt
@@ -4,6 +4,7 @@
add_subdirectory(qgaxis-abstract)
add_subdirectory(qgaxis-barcategory)
add_subdirectory(qgaxis-value)
+add_subdirectory(qgaxis-datetime)
add_subdirectory(qgbars)
add_subdirectory(qgbars-set)
add_subdirectory(qglines)
diff --git a/tests/auto/cpp2dtest/qgaxis-datetime/CMakeLists.txt b/tests/auto/cpp2dtest/qgaxis-datetime/CMakeLists.txt
new file mode 100644
index 0000000..cc40c94
--- /dev/null
+++ b/tests/auto/cpp2dtest/qgaxis-datetime/CMakeLists.txt
@@ -0,0 +1,13 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_internal_add_test(tst_qgdatetimeaxis2d
+ SOURCES
+ tst_datetimeaxis.cpp
+ INCLUDE_DIRECTORIES
+ ../common
+ LIBRARIES
+ Qt::Gui
+ Qt::GuiPrivate
+ Qt::Graphs
+)
diff --git a/tests/auto/cpp2dtest/qgaxis-datetime/tst_datetimeaxis.cpp b/tests/auto/cpp2dtest/qgaxis-datetime/tst_datetimeaxis.cpp
new file mode 100644
index 0000000..75dac68
--- /dev/null
+++ b/tests/auto/cpp2dtest/qgaxis-datetime/tst_datetimeaxis.cpp
@@ -0,0 +1,93 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtGraphs/QDateTimeAxis>
+#include <QtTest/QtTest>
+#include "qtestcase.h"
+
+class tst_datetimeaxis : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+ void construct();
+
+ void initialProperties();
+ void initializeProperties();
+ void invalidProperties();
+
+private:
+ QDateTimeAxis *m_axis;
+};
+
+void tst_datetimeaxis::initTestCase() {}
+
+void tst_datetimeaxis::cleanupTestCase() {}
+
+void tst_datetimeaxis::init()
+{
+ m_axis = new QDateTimeAxis();
+}
+
+void tst_datetimeaxis::cleanup()
+{
+ delete m_axis;
+}
+
+void tst_datetimeaxis::construct()
+{
+ QDateTimeAxis *axis = new QDateTimeAxis();
+ QVERIFY(axis);
+ delete axis;
+}
+
+void tst_datetimeaxis::initialProperties()
+{
+ QVERIFY(m_axis);
+
+ QCOMPARE(m_axis->min(), QDateTime(QDate(1970, 1, 1), QTime::fromMSecsSinceStartOfDay(0)));
+ QCOMPARE(m_axis->max(),
+ QDateTime(QDate(1970, 1, 1), QTime::fromMSecsSinceStartOfDay(0)).addYears(10));
+ QCOMPARE(m_axis->labelFormat(), "dd-MMMM-yy");
+ QCOMPARE(m_axis->minorTickCount(), 0);
+ QCOMPARE(m_axis->tickInterval(), 0.0);
+}
+
+void tst_datetimeaxis::initializeProperties()
+{
+ QVERIFY(m_axis);
+
+ m_axis->setMin(QDateTime(QDate::currentDate(), QTime::fromMSecsSinceStartOfDay(0)));
+ m_axis->setMax(QDateTime(QDate::currentDate(), QTime::fromMSecsSinceStartOfDay(0)).addYears(20));
+ m_axis->setLabelFormat("yyyy");
+ m_axis->setMinorTickCount(2);
+ m_axis->setTickInterval(0.5);
+
+ QCOMPARE(m_axis->min(), QDateTime(QDate::currentDate(), QTime::fromMSecsSinceStartOfDay(0)));
+ QCOMPARE(m_axis->max(),
+ QDateTime(QDate::currentDate(), QTime::fromMSecsSinceStartOfDay(0)).addYears(20));
+ QCOMPARE(m_axis->labelFormat(), "yyyy");
+ QCOMPARE(m_axis->minorTickCount(), 2);
+ QCOMPARE(m_axis->tickInterval(), 0.5);
+}
+
+void tst_datetimeaxis::invalidProperties()
+{
+ QVERIFY(m_axis);
+
+ m_axis->setMin(QDateTime(QDate::currentDate(), QTime::fromMSecsSinceStartOfDay(0)).addDays(10));
+ m_axis->setMax(QDateTime(QDate::currentDate(), QTime::fromMSecsSinceStartOfDay(0)));
+ m_axis->setMinorTickCount(-1);
+
+ QCOMPARE(m_axis->min(), QDateTime(QDate::currentDate(), QTime::fromMSecsSinceStartOfDay(0)));
+ QCOMPARE(m_axis->max(), QDateTime(QDate::currentDate(), QTime::fromMSecsSinceStartOfDay(0)));
+ QCOMPARE(m_axis->minorTickCount(), 0);
+}
+
+QTEST_MAIN(tst_datetimeaxis)
+#include "tst_datetimeaxis.moc"
diff --git a/tests/auto/qml2dtest/axes/tst_datetimeaxis.qml b/tests/auto/qml2dtest/axes/tst_datetimeaxis.qml
new file mode 100644
index 0000000..1bff858
--- /dev/null
+++ b/tests/auto/qml2dtest/axes/tst_datetimeaxis.qml
@@ -0,0 +1,137 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtGraphs
+import QtTest
+
+Item {
+ id: top
+ height: 150
+ width: 150
+
+ DateTimeAxis {
+ id: initial
+ }
+
+ DateTimeAxis {
+ id: initialized
+
+ labelFormat: "yyyy"
+ min: new Date(1960,1,1)
+ max: new Date(2000,1,1)
+ minorTickCount: 2
+ tickInterval: 2
+
+ gridVisible: false
+ labelsAngle: 90
+ labelsVisible: false
+ lineVisible: false
+ minorGridVisible: false
+ visible: false
+ }
+
+ TestCase {
+ name: "DateTimeAxis Initial"
+
+ function test_1_initial() {
+ compare(initial.labelFormat, "dd-MMMM-yy")
+ compare(initial.min, new Date(1970,0,1))
+ compare(initial.max, new Date(1980,0,1))
+ compare(initial.minorTickCount, 0)
+ compare(initial.tickInterval, 0)
+ }
+
+ function test_2_initial_common() {
+ compare(initial.gridVisible, true)
+ compare(initial.labelsAngle, 0)
+ compare(initial.labelsVisible, true)
+ compare(initial.lineVisible, true)
+ compare(initial.minorGridVisible, true)
+ compare(initial.visible, true)
+ }
+
+ function test_3_initial_change() {
+ initial.labelFormat = "yyyy"
+ initial.min = new Date(1960, 1, 1)
+ initial.max = new Date(2000, 1, 1)
+ initial.minorTickCount = 2
+ initial.tickInterval = 2
+
+ initial.gridVisible = false
+ initial.labelsAngle = 90
+ initial.labelsVisible = false
+ initial.lineVisible = false
+ initial.minorGridVisible = false
+ initial.visible = false
+
+ compare(initial.labelFormat, "yyyy")
+ compare(initial.min, new Date(1960, 1, 1))
+ compare(initial.max, new Date(2000, 1, 1))
+ compare(initial.minorTickCount, 2)
+ compare(initial.tickInterval, 2)
+
+ compare(initial.gridVisible, false)
+ compare(initial.labelsAngle, 90)
+ compare(initial.labelsVisible, false)
+ compare(initial.lineVisible, false)
+ compare(initial.minorGridVisible, false)
+ compare(initial.visible, false)
+ }
+ }
+
+ TestCase {
+ name: "DateTimeAxis Initialized"
+
+ function test_1_initialized() {
+ compare(initialized.labelFormat, "yyyy")
+ compare(initialized.min, new Date(1960, 1, 1))
+ compare(initialized.max, new Date(2000, 1, 1))
+ compare(initialized.minorTickCount, 2)
+ compare(initialized.tickInterval, 2)
+
+ compare(initialized.gridVisible, false)
+ compare(initialized.labelsAngle, 90)
+ compare(initialized.labelsVisible, false)
+ compare(initialized.lineVisible, false)
+ compare(initialized.minorGridVisible, false)
+ compare(initialized.visible, false)
+ }
+
+ function test_2_initialized_changed() {
+ initialized.labelFormat = "dddd"
+ initialized.min = new Date(2000, 1, 1)
+ initialized.max = new Date(2025, 1, 1)
+ initialized.minorTickCount = 8
+ initialized.tickInterval = 8
+
+ initialized.gridVisible = true
+ initialized.labelsAngle = 50
+ initialized.labelsVisible = true
+ initialized.lineVisible = true
+ initialized.minorGridVisible = true
+ initialized.visible = true
+
+ compare(initialized.labelFormat, "dddd")
+ compare(initialized.min, new Date(2000, 1, 1))
+ compare(initialized.max, new Date(2025, 1, 1))
+ compare(initialized.minorTickCount, 8)
+ compare(initialized.tickInterval, 8)
+
+ compare(initialized.gridVisible, true)
+ compare(initialized.labelsAngle, 50)
+ compare(initialized.labelsVisible, true)
+ compare(initialized.lineVisible, true)
+ compare(initialized.minorGridVisible, true)
+ compare(initialized.visible, true)
+ }
+
+ function test_3_invalid() {
+ initialized.minorTickCount = -1;
+ initialized.tickInterval = -1;
+
+ compare(initialized.tickInterval, 0)
+ compare(initialized.minorTickCount, 0)
+ }
+ }
+}