1 /*
2 * Copyright (C) 2008 Emweb bv, Herent, Belgium.
3 *
4 * See the LICENSE file for terms of use.
5 */
6
7 #include <Wt/WPointF.h>
8 #include <Wt/Chart/WChartPalette.h>
9 #include <Wt/Chart/WDataSeries.h>
10 #include <Wt/Chart/WCartesianChart.h>
11
12 namespace Wt {
13 namespace Chart {
14
WDataSeries(int modelColumn,SeriesType type,Axis axis)15 WDataSeries::WDataSeries(int modelColumn, SeriesType type, Axis axis)
16 : chart_(nullptr),
17 model_(nullptr),
18 modelColumn_(modelColumn),
19 XSeriesColumn_(-1),
20 stacked_(false),
21 type_(type),
22 xAxis_(0),
23 yAxis_(axis == Axis::Y1 ? 0 : 1),
24 customFlags_(None),
25 fillRange_(FillRangeType::None),
26 marker_(type == SeriesType::Point ?
27 MarkerType::Circle : MarkerType::None),
28 markerSize_(6),
29 legend_(true),
30 xLabel_(false),
31 yLabel_(false),
32 barWidth_(0.8),
33 hidden_(false),
34 offset_(0.0),
35 scale_(1.0),
36 offsetDirty_(true),
37 scaleDirty_(true)
38 { }
39
WDataSeries(int modelColumn,SeriesType type,int axis)40 WDataSeries::WDataSeries(int modelColumn, SeriesType type, int axis)
41 : chart_(nullptr),
42 model_(nullptr),
43 modelColumn_(modelColumn),
44 XSeriesColumn_(-1),
45 stacked_(false),
46 type_(type),
47 xAxis_(0),
48 yAxis_(axis),
49 customFlags_(None),
50 fillRange_(FillRangeType::None),
51 marker_(type == SeriesType::Point ?
52 MarkerType::Circle : MarkerType::None),
53 markerSize_(6),
54 legend_(true),
55 xLabel_(false),
56 yLabel_(false),
57 barWidth_(0.8),
58 hidden_(false),
59 offset_(0.0),
60 scale_(1.0),
61 offsetDirty_(true),
62 scaleDirty_(true)
63 { }
64
~WDataSeries()65 WDataSeries::~WDataSeries()
66 {
67 if (model_) {
68 for (unsigned i = 0; i < modelConnections_.size(); ++i)
69 modelConnections_[i].disconnect();
70 }
71 }
72
setBarWidth(const double width)73 void WDataSeries::setBarWidth(const double width)
74 {
75 barWidth_ = width;
76 }
77
barWidth()78 double WDataSeries::barWidth() const
79 {
80 return barWidth_;
81 }
82
setType(SeriesType type)83 void WDataSeries::setType(SeriesType type)
84 {
85 set(type_, type);
86 }
87
setStacked(bool stacked)88 void WDataSeries::setStacked(bool stacked)
89 {
90 set(stacked_, stacked);
91 }
92
setModelColumn(int modelColumn)93 void WDataSeries::setModelColumn(int modelColumn)
94 {
95 set(modelColumn_, modelColumn);
96 }
97
bindToAxis(Axis axis)98 void WDataSeries::bindToAxis(Axis axis)
99 {
100 set(yAxis_, axis == Axis::Y1 ? 0 : 1);
101 }
102
bindToXAxis(int xAxis)103 void WDataSeries::bindToXAxis(int xAxis)
104 {
105 set(xAxis_, xAxis);
106 }
107
bindToYAxis(int yAxis)108 void WDataSeries::bindToYAxis(int yAxis)
109 {
110 set(yAxis_, yAxis);
111 }
112
setCustomFlags(WFlags<CustomFlag> flags)113 void WDataSeries::setCustomFlags(WFlags<CustomFlag> flags)
114 {
115 set(customFlags_, flags);
116 }
117
setPen(const WPen & pen)118 void WDataSeries::setPen(const WPen& pen)
119 {
120 set(pen_, pen);
121
122 customFlags_ |= CustomFlag::Pen;
123 }
124
setShadow(const WShadow & shadow)125 void WDataSeries::setShadow(const WShadow& shadow)
126 {
127 set(shadow_, shadow);
128 }
129
shadow()130 const WShadow& WDataSeries::shadow() const
131 {
132 return shadow_;
133 }
134
pen()135 WPen WDataSeries::pen() const
136 {
137 if (customFlags_.test(CustomFlag::Pen))
138 return pen_;
139 else
140 if (chart_)
141 if (type_ == SeriesType::Bar)
142 return chart_->palette()
143 ->borderPen(chart_->seriesIndexOf(*this));
144 else
145 return chart_->palette()
146 ->strokePen(chart_->seriesIndexOf(*this));
147 else {
148 WPen defaultPen;
149 defaultPen.setCapStyle(PenCapStyle::Round);
150 defaultPen.setJoinStyle(PenJoinStyle::Round);
151 return defaultPen;
152 }
153 }
154
setBrush(const WBrush & brush)155 void WDataSeries::setBrush(const WBrush& brush)
156 {
157 set(brush_, brush);
158
159 customFlags_ |= CustomFlag::Brush;
160 }
161
brush()162 WBrush WDataSeries::brush() const
163 {
164 if (customFlags_.test(CustomFlag::Brush))
165 return brush_;
166 else
167 if (chart_)
168 return chart_->palette()->brush(chart_->seriesIndexOf(*this));
169 else
170 return WBrush();
171 }
172
labelColor()173 WColor WDataSeries::labelColor() const
174 {
175 if (customFlags_.test(CustomFlag::LabelColor))
176 return labelColor_;
177 else
178 if (chart_)
179 return chart_->palette()->fontColor(chart_->seriesIndexOf(*this));
180 else
181 return WColor(StandardColor::Black);
182 }
183
setLabelColor(const WColor & color)184 void WDataSeries::setLabelColor(const WColor& color)
185 {
186 set(labelColor_, color);
187
188 customFlags_ |= CustomFlag::LabelColor;
189 }
190
setFillRange(FillRangeType fillRange)191 void WDataSeries::setFillRange(FillRangeType fillRange)
192 {
193 set(fillRange_, fillRange);
194 }
195
fillRange()196 FillRangeType WDataSeries::fillRange() const
197 {
198 if (type_ == SeriesType::Bar && fillRange_ == FillRangeType::None)
199 return FillRangeType::ZeroValue;
200 else
201 return fillRange_;
202 }
203
setMarker(MarkerType marker)204 void WDataSeries::setMarker(MarkerType marker)
205 {
206 set(marker_, marker);
207 }
208
setCustomMarker(const WPainterPath & path)209 void WDataSeries::setCustomMarker(const WPainterPath& path)
210 {
211 set(marker_, MarkerType::Custom);
212
213 customMarker_ = path;
214 }
215
setMarkerSize(double size)216 void WDataSeries::setMarkerSize(double size)
217 {
218 set(markerSize_, size);
219 }
220
setMarkerPen(const WPen & pen)221 void WDataSeries::setMarkerPen(const WPen& pen)
222 {
223 set(markerPen_, pen);
224
225 customFlags_ |= CustomFlag::MarkerPen;
226 }
227
markerPen()228 WPen WDataSeries::markerPen() const
229 {
230 if (customFlags_.test(CustomFlag::MarkerPen))
231 return markerPen_;
232 else
233 return pen();
234 }
235
setMarkerBrush(const WBrush & brush)236 void WDataSeries::setMarkerBrush(const WBrush& brush)
237 {
238 set(markerBrush_, brush);
239
240 customFlags_ |= CustomFlag::MarkerBrush;
241 }
242
markerBrush()243 WBrush WDataSeries::markerBrush() const
244 {
245 if (customFlags_.test(CustomFlag::MarkerBrush))
246 return markerBrush_;
247 else
248 return brush();
249 }
250
setLegendEnabled(bool enabled)251 void WDataSeries::setLegendEnabled(bool enabled)
252 {
253 set(legend_, enabled);
254 }
255
isLegendEnabled()256 bool WDataSeries::isLegendEnabled() const
257 {
258 if (!isHidden())
259 return legend_;
260 else
261 return false;
262 }
263
setLabelsEnabled(Axis axis,bool enabled)264 void WDataSeries::setLabelsEnabled(Axis axis, bool enabled)
265 {
266 if (axis == Axis::X)
267 xLabel_ = enabled;
268 else
269 yLabel_ = enabled;
270
271 update();
272 }
273
isLabelsEnabled(Axis axis)274 bool WDataSeries::isLabelsEnabled(Axis axis) const
275 {
276 return axis == Axis::X ? xLabel_ : yLabel_;
277 }
278
setHidden(bool hidden)279 void WDataSeries::setHidden(bool hidden)
280 {
281 hidden_ = hidden;
282 }
283
isHidden()284 bool WDataSeries::isHidden() const
285 {
286 return hidden_;
287 }
288
setChart(WCartesianChart * chart)289 void WDataSeries::setChart(WCartesianChart *chart)
290 {
291 chart_ = chart;
292 }
293
update()294 void WDataSeries::update()
295 {
296 if (chart_)
297 chart_->update();
298 }
299
mapFromDevice(const WPointF & deviceCoordinates)300 WPointF WDataSeries::mapFromDevice(const WPointF& deviceCoordinates) const
301 {
302 if (chart_)
303 return chart_->mapFromDevice(deviceCoordinates,
304 chart_->xAxis(xAxis_),
305 chart_->yAxis(yAxis_));
306 else
307 return WPointF();
308 }
309
mapToDevice(const cpp17::any & xValue,const cpp17::any & yValue,int segment)310 WPointF WDataSeries::mapToDevice(const cpp17::any& xValue, const cpp17::any& yValue,
311 int segment) const
312 {
313 if (chart_)
314 return chart_->mapToDevice(xValue, yValue,
315 chart_->xAxis(xAxis_),
316 chart_->yAxis(yAxis_),
317 segment);
318 else
319 return WPointF();
320 }
321
setXSeriesColumn(int modelColumn)322 void WDataSeries::setXSeriesColumn(int modelColumn)
323 {
324 XSeriesColumn_ = modelColumn;
325 }
326
setOffset(double offset)327 void WDataSeries::setOffset(double offset)
328 {
329 if (offset_ != offset) {
330 offset_ = offset;
331 update();
332 }
333 offsetDirty_ = true;
334 }
335
setScale(double scale)336 void WDataSeries::setScale(double scale)
337 {
338 if (scale_ != scale) {
339 scale_ = scale;
340 update();
341 }
342 scaleDirty_ = true;
343 }
344
setModel(const std::shared_ptr<WAbstractChartModel> & model)345 void WDataSeries::setModel(const std::shared_ptr<WAbstractChartModel>& model)
346 {
347 if (model_) {
348 /* disconnect slots from previous model */
349 for (unsigned i = 0; i < modelConnections_.size(); ++i)
350 modelConnections_[i].disconnect();
351
352 modelConnections_.clear();
353 }
354
355 model_ = model;
356
357 if (model_) {
358 #ifdef WT_TARGET_JAVA
359 modelConnections_.push_back(model_->changed().connect(this, std::bind(&WDataSeries::modelReset, this)));
360 #else // !WT_TARGET_JAVA
361 modelConnections_.push_back(model_->changed().connect(std::bind(&WDataSeries::modelReset, this)));
362 #endif // WT_TARGET_JAVA
363 }
364
365 if (chart_)
366 chart_->update();
367 }
368
modelReset()369 void WDataSeries::modelReset()
370 {
371 if (chart_)
372 chart_->modelReset();
373 }
374
model()375 std::shared_ptr<WAbstractChartModel> WDataSeries::model() const
376 {
377 if (model_)
378 return model_;
379
380 if (chart_)
381 return chart_->model();
382
383 return nullptr;
384 }
385
386 }
387 }
388