1 /*
2  * This file is part of KQuickCharts
3  * SPDX-FileCopyrightText: 2019 Arjen Hiemstra <ahiemstra@heimr.nl>
4  *
5  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6  */
7 
8 #include "GridLines.h"
9 
10 #include "XYChart.h"
11 #include "scenegraph/LineGridNode.h"
12 
LinePropertiesGroup(GridLines * parent)13 LinePropertiesGroup::LinePropertiesGroup(GridLines *parent)
14     : QObject(parent)
15 {
16     m_parent = parent;
17 }
18 
visible() const19 bool LinePropertiesGroup::visible() const
20 {
21     return m_visible;
22 }
23 
setVisible(bool newVisible)24 void LinePropertiesGroup::setVisible(bool newVisible)
25 {
26     if (newVisible == m_visible) {
27         return;
28     }
29 
30     m_visible = newVisible;
31     Q_EMIT propertiesChanged();
32 }
33 
color() const34 QColor LinePropertiesGroup::color() const
35 {
36     return m_color;
37 }
38 
setColor(const QColor & newColor)39 void LinePropertiesGroup::setColor(const QColor &newColor)
40 {
41     if (newColor == m_color) {
42         return;
43     }
44 
45     m_color = newColor;
46     Q_EMIT propertiesChanged();
47 }
48 
lineWidth() const49 float LinePropertiesGroup::lineWidth() const
50 {
51     return m_lineWidth;
52 }
53 
setLineWidth(float newLineWidth)54 void LinePropertiesGroup::setLineWidth(float newLineWidth)
55 {
56     if (newLineWidth == m_lineWidth) {
57         return;
58     }
59 
60     m_lineWidth = newLineWidth;
61     Q_EMIT propertiesChanged();
62 }
63 
frequency() const64 int LinePropertiesGroup::frequency() const
65 {
66     return m_frequency;
67 }
68 
setFrequency(int newFrequency)69 void LinePropertiesGroup::setFrequency(int newFrequency)
70 {
71     if (newFrequency == m_frequency) {
72         return;
73     }
74 
75     m_frequency = newFrequency;
76     Q_EMIT propertiesChanged();
77 }
78 
count() const79 int LinePropertiesGroup::count() const
80 {
81     return m_count;
82 }
83 
setCount(int newCount)84 void LinePropertiesGroup::setCount(int newCount)
85 {
86     if (newCount == m_count) {
87         return;
88     }
89 
90     m_count = newCount;
91     Q_EMIT propertiesChanged();
92 }
93 
GridLines(QQuickItem * parent)94 GridLines::GridLines(QQuickItem *parent)
95     : QQuickItem(parent)
96 {
97     setFlag(QQuickItem::ItemHasContents);
98 
99     m_major = std::make_unique<LinePropertiesGroup>(this);
100     connect(m_major.get(), &LinePropertiesGroup::propertiesChanged, this, &GridLines::update);
101     m_minor = std::make_unique<LinePropertiesGroup>(this);
102     connect(m_minor.get(), &LinePropertiesGroup::propertiesChanged, this, &GridLines::update);
103 }
104 
direction() const105 GridLines::Direction GridLines::direction() const
106 {
107     return m_direction;
108 }
109 
setDirection(GridLines::Direction newDirection)110 void GridLines::setDirection(GridLines::Direction newDirection)
111 {
112     if (newDirection == m_direction) {
113         return;
114     }
115 
116     m_direction = newDirection;
117     update();
118     Q_EMIT directionChanged();
119 }
120 
chart() const121 XYChart *GridLines::chart() const
122 {
123     return m_chart;
124 }
125 
setChart(XYChart * newChart)126 void GridLines::setChart(XYChart *newChart)
127 {
128     if (newChart == m_chart) {
129         return;
130     }
131 
132     if (m_chart) {
133         disconnect(m_chart, &XYChart::computedRangeChanged, this, &GridLines::update);
134     }
135 
136     m_chart = newChart;
137 
138     if (m_chart) {
139         connect(m_chart, &XYChart::computedRangeChanged, this, &GridLines::update);
140     }
141 
142     update();
143     Q_EMIT chartChanged();
144 }
145 
spacing() const146 float GridLines::spacing() const
147 {
148     return m_spacing;
149 }
150 
setSpacing(float newSpacing)151 void GridLines::setSpacing(float newSpacing)
152 {
153     if (newSpacing == m_spacing || m_chart != nullptr) {
154         return;
155     }
156 
157     m_spacing = newSpacing;
158     update();
159     Q_EMIT spacingChanged();
160 }
161 
majorGroup() const162 LinePropertiesGroup *GridLines::majorGroup() const
163 {
164     return m_major.get();
165 }
166 
minorGroup() const167 LinePropertiesGroup *GridLines::minorGroup() const
168 {
169     return m_minor.get();
170 }
171 
updatePaintNode(QSGNode * node,QQuickItem::UpdatePaintNodeData *)172 QSGNode *GridLines::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *)
173 {
174     if (!node) {
175         node = new QSGNode{};
176         node->appendChildNode(new LineGridNode{});
177         node->appendChildNode(new LineGridNode{});
178     }
179 
180     if (m_chart) {
181         if (m_direction == Direction::Horizontal) {
182             m_spacing = width() / (m_chart->computedRange().distanceX - 1);
183         } else {
184             m_spacing = height() / (m_chart->computedRange().distanceY);
185         }
186     }
187 
188     updateLines(static_cast<LineGridNode *>(node->childAtIndex(0)), m_minor.get());
189     updateLines(static_cast<LineGridNode *>(node->childAtIndex(1)), m_major.get());
190 
191     return node;
192 }
193 
updateLines(LineGridNode * node,LinePropertiesGroup * properties)194 void GridLines::updateLines(LineGridNode *node, LinePropertiesGroup *properties)
195 {
196     node->setVisible(properties->visible());
197     node->setRect(boundingRect());
198     node->setVertical(m_direction == Direction::Vertical);
199     node->setColor(properties->color());
200     node->setLineWidth(properties->lineWidth());
201     if (properties->count() > 0) {
202         node->setSpacing(m_direction == Direction::Horizontal ? width() / (properties->count() + 1) : height() / (properties->count() + 1));
203     } else {
204         node->setSpacing(m_spacing * properties->frequency());
205     }
206     node->update();
207 }
208