Wt examples 3.3.12
ChartsExample.C
Go to the documentation of this file.
1/*
2 * Copyright (C) 2008 Emweb bvba, Kessel-Lo, Belgium.
3 *
4 * See the LICENSE file for terms of use.
5 */
6
7#include <math.h>
8#include <fstream>
9
10#include "ChartsExample.h"
11#include "ChartConfig.h"
12#include "CsvUtil.h"
13
14#include <Wt/WApplication>
15#include <Wt/WDate>
16#include <Wt/WEnvironment>
17#include <Wt/WItemDelegate>
18#include <Wt/WStandardItemModel>
19#include <Wt/WText>
20
21#include <Wt/WBorderLayout>
22#include <Wt/WFitLayout>
23
24#include <Wt/WStandardItem>
25#include <Wt/WTableView>
26
27#include <Wt/Chart/WCartesianChart>
28#include <Wt/Chart/WPieChart>
29
30using namespace Wt;
31using namespace Wt::Chart;
32
33namespace {
34
35 /*
36 * A standard item which converts text edits to numbers
37 */
38 class NumericItem : public WStandardItem {
39 public:
40 virtual NumericItem *clone() const {
41 return new NumericItem();
42 }
43
44 virtual void setData(const boost::any &data, int role = UserRole) {
45 boost::any dt;
46
47 if (role == EditRole) {
48 std::string s = Wt::asString(data).toUTF8();
49 char *endptr;
50 double d = strtod(s.c_str(), &endptr);
51 if (*endptr == 0)
52 dt = boost::any(d);
53 else
54 dt = data;
55 }
56
57 WStandardItem::setData(data, role);
58 }
59 };
60
61 /*
62 * Reads a CSV file as an (editable) standard item model.
63 */
64 WAbstractItemModel *readCsvFile(const std::string &fname,
65 WContainerWidget *parent)
66 {
67 WStandardItemModel *model = new WStandardItemModel(0, 0, parent);
68 model->setItemPrototype(new NumericItem());
69 std::ifstream f(fname.c_str());
70
71 if (f) {
72 readFromCsv(f, model);
73
74 for (int row = 0; row < model->rowCount(); ++row)
75 for (int col = 0; col < model->columnCount(); ++col) {
76 model->item(row, col)->setFlags(ItemIsSelectable | ItemIsEditable);
77
78 /*
79 Example of tool tips (disabled here because they are not updated
80 when editing data)
81 */
82
83 /*
84 WString toolTip = asString(model->headerData(col)) + ": "
85 + asString(model->item(row, col)->data(DisplayRole), "%.f");
86 model->item(row, col)->setToolTip(toolTip);
87 */
88 }
89
90 return model;
91 } else {
92 WString error(WString::tr("error-missing-data"));
93 error.arg(fname, UTF8);
94 new WText(error, parent);
95 return 0;
96 }
97 }
98}
99
101 : WContainerWidget(root)
102{
103 new WText(WString::tr("introduction"), this);
104
105 new CategoryExample(this);
106 new TimeSeriesExample(this);
107 new ScatterPlotExample(this);
108 new PieExample(this);
109}
110
112 WContainerWidget(parent)
113{
114 new WText(WString::tr("category chart"), this);
115
116 WAbstractItemModel *model
117 = readCsvFile(WApplication::appRoot() + "category.csv", this);
118
119 if (!model)
120 return;
121
122 // Show a view that allows editing of the model.
123 WContainerWidget *w = new WContainerWidget(this);
124 WTableView *table = new WTableView(w);
125
126 table->setMargin(10, Top | Bottom);
128
129 table->setModel(model);
130 table->setSortingEnabled(true);
131 table->setColumnResizeEnabled(true);
132 // table->setSelectionMode(ExtendedSelection);
133 table->setAlternatingRowColors(true);
136 table->setRowHeight(22);
137
138 // Editing does not really work without Ajax, it would require an
139 // additional button somewhere to confirm the edited value.
140 if (WApplication::instance()->environment().ajax()) {
141 table->resize(600, 20 + 5*22);
143 } else {
144 table->resize(600, WLength::Auto);
146 }
147
148 // We use a single delegate for all items which rounds values to
149 // the closest integer value.
150 WItemDelegate *delegate = new WItemDelegate(this);
151 delegate->setTextFormat("%.f");
152 table->setItemDelegate(delegate);
153
154 table->setColumnWidth(0, 80);
155 for (int i = 1; i < model->columnCount(); ++i)
156 table->setColumnWidth(i, 120);
157
158 /*
159 * Create the category chart.
160 */
161 WCartesianChart *chart = new WCartesianChart(this);
162 chart->setModel(model); // set the model
163 chart->setXSeriesColumn(0); // set the column that holds the categories
164 chart->setLegendEnabled(true); // enable the legend
165 chart->setZoomEnabled(true);
166 chart->setPanEnabled(true);
167
168 // Automatically layout chart (space for axes, legend, ...)
169 chart->setAutoLayoutEnabled(true);
170
171 chart->setBackground(WColor(200,200,200));
172
173 /*
174 * Add all (but first) column as bar series
175 */
176 for (int i = 1; i < model->columnCount(); ++i) {
177 WDataSeries *s = new WDataSeries(i, BarSeries);
178 s->setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
179 chart->addSeries(s);
180 }
181
182 chart->resize(800, 400);
183
184 chart->setMargin(10, Top | Bottom);
186
187 /*
188 * Provide a widget to manipulate chart properties
189 */
190 new ChartConfig(chart, this);
191}
192
194 WContainerWidget(parent)
195{
196 new WText(WString::tr("scatter plot"), this);
197
198 WAbstractItemModel *model = readCsvFile(
199 WApplication::appRoot() + "timeseries.csv", this);
200
201 if (!model)
202 return;
203
204 /*
205 * Parses the first column as dates, to be able to use a date scale
206 */
207 for (int i = 0; i < model->rowCount(); ++i) {
208 WString s = asString(model->data(i, 0));
209 WDate d = WDate::fromString(s, "dd/MM/yy");
210 model->setData(i, 0, d);
211 }
212
213 // Show a view that allows editing of the model.
214 WContainerWidget *w = new WContainerWidget(this);
215 WTableView *table = new WTableView(w);
216
217 table->setMargin(10, Top | Bottom);
219
220 table->setModel(model);
221 table->setSortingEnabled(false); // Does not make much sense for time series
222 table->setColumnResizeEnabled(true);
224 table->setAlternatingRowColors(true);
227 table->setRowHeight(22);
228
229 // Editing does not really work without Ajax, it would require an
230 // additional button somewhere to confirm the edited value.
231 if (WApplication::instance()->environment().ajax()) {
232 table->resize(800, 20 + 5*22);
234 } else {
235 table->resize(800, 20 + 5*22 + 25);
237 }
238
239 WItemDelegate *delegate = new WItemDelegate(this);
240 delegate->setTextFormat("%.1f");
241 table->setItemDelegate(delegate);
242 table->setItemDelegateForColumn(0, new WItemDelegate(this));
243
244 table->setColumnWidth(0, 80);
245 for (int i = 1; i < model->columnCount(); ++i)
246 table->setColumnWidth(i, 90);
247
248 /*
249 * Create the scatter plot.
250 */
251 WCartesianChart *chart = new WCartesianChart(this);
252 //chart->setPreferredMethod(WPaintedWidget::PngImage);
253 //chart->setBackground(gray);
254 chart->setModel(model); // set the model
255 chart->setXSeriesColumn(0); // set the column that holds the X data
256 chart->setLegendEnabled(true); // enable the legend
257 chart->setZoomEnabled(true);
258 chart->setPanEnabled(true);
259
260 chart->setType(ScatterPlot); // set type to ScatterPlot
261 chart->axis(XAxis).setScale(DateScale); // set scale of X axis to DateScale
262
263 // Automatically layout chart (space for axes, legend, ...)
264 chart->setAutoLayoutEnabled();
265
266 chart->setBackground(WColor(200,200,200));
267 /*
268 * Add first two columns as line series
269 */
270 for (int i = 1; i < 3; ++i) {
272 s->setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
273 chart->addSeries(s);
274 }
275
276 chart->resize(800, 400); // WPaintedWidget must be given explicit size
277
278 chart->setMargin(10, Top | Bottom); // add margin vertically
279 chart->setMargin(WLength::Auto, Left | Right); // center horizontally
280
281 new ChartConfig(chart, this);
282}
283
285 WContainerWidget(parent)
286{
287 new WText(WString::tr("scatter plot 2"), this);
288
289 WStandardItemModel *model = new WStandardItemModel(40, 2, this);
290 model->setItemPrototype(new NumericItem());
291 model->setHeaderData(0, WString("X"));
292 model->setHeaderData(1, WString("Y = sin(X)"));
293
294 for (unsigned i = 0; i < 40; ++i) {
295 double x = (static_cast<double>(i) - 20) / 4;
296
297 model->setData(i, 0, x);
298 model->setData(i, 1, sin(x));
299 }
300
301 /*
302 * Create the scatter plot.
303 */
304 WCartesianChart *chart = new WCartesianChart(this);
305 chart->setModel(model); // set the model
306 chart->setXSeriesColumn(0); // set the column that holds the X data
307 chart->setLegendEnabled(true); // enable the legend
308 chart->setZoomEnabled(true);
309 chart->setPanEnabled(true);
310 chart->setCrosshairEnabled(true);
311
312 chart->setBackground(WColor(200,200,200));
313
314 chart->setType(ScatterPlot); // set type to ScatterPlot
315
316 // Typically, for mathematical functions, you want the axes to cross
317 // at the 0 mark:
320
321 // Automatically layout chart (space for axes, legend, ...)
322 chart->setAutoLayoutEnabled();
323
324 // Add the curves
326 s->setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
327 chart->addSeries(s);
328
329 chart->resize(800, 300); // WPaintedWidget must be given explicit size
330
331 chart->setMargin(10, Top | Bottom); // add margin vertically
332 chart->setMargin(WLength::Auto, Left | Right); // center horizontally
333
334 ChartConfig *config = new ChartConfig(chart, this);
336}
337
339 WContainerWidget(parent)
340{
341 new WText(WString::tr("pie chart"), this);
342
343 WStandardItemModel *model = new WStandardItemModel(this);
344 model->setItemPrototype(new NumericItem());
345
346 //headers
347 model->insertColumns(model->columnCount(), 2);
348 model->setHeaderData(0, WString("Item"));
349 model->setHeaderData(1, WString("Sales"));
350
351 //data
352 model->insertRows(model->rowCount(), 6);
353 int row = 0;
354 model->setData(row, 0, WString("Blueberry"));
355 model->setData(row, 1, 120);
356 // model->setData(row, 1, WString("Blueberry"), ToolTipRole);
357 row++;
358 model->setData(row, 0, WString("Cherry"));
359 model->setData(row, 1, 30);
360 row++;
361 model->setData(row, 0, WString("Apple"));
362 model->setData(row, 1, 260);
363 row++;
364 model->setData(row, 0, WString("Boston Cream"));
365 model->setData(row, 1, 160);
366 row++;
367 model->setData(row, 0, WString("Other"));
368 model->setData(row, 1, 40);
369 row++;
370 model->setData(row, 0, WString("Vanilla Cream"));
371 model->setData(row, 1, 120);
372 row++;
373
374 //set all items to be editable and selectable
375 for (int row = 0; row < model->rowCount(); ++row)
376 for (int col = 0; col < model->columnCount(); ++col)
377 model->item(row, col)->setFlags(ItemIsSelectable | ItemIsEditable);
378
379 WContainerWidget *w = new WContainerWidget(this);
380 WTableView* table = new WTableView(w);
381
382 table->setMargin(10, Top | Bottom);
384 table->setSortingEnabled(true);
385 table->setModel(model);
386 table->setColumnWidth(1, 100);
387 table->setRowHeight(22);
388
389 if (WApplication::instance()->environment().ajax()) {
390 table->resize(150 + 100 + 14, 20 + 6 * 22);
392 } else {
393 table->resize(150 + 100 + 14, WLength::Auto);
395 }
396
397 /*
398 * Create the pie chart.
399 */
400 WPieChart *chart = new WPieChart(this);
401 chart->setModel(model); // set the model
402 chart->setLabelsColumn(0); // set the column that holds the labels
403 chart->setDataColumn(1); // set the column that holds the data
404
405 // configure location and type of labels
407
408 // enable a 3D and shadow effect
409 chart->setPerspectiveEnabled(true, 0.2);
410 chart->setShadowEnabled(true);
411
412 // explode the first item
413 chart->setExplode(0, 0.3);
414
415 chart->resize(800, 300); // WPaintedWidget must be given an explicit size
416
417 chart->setMargin(10, Top | Bottom); // add margin vertically
418 chart->setMargin(WLength::Auto, Left | Right); // center horizontally
419}
420
A Widget that demonstrates a category chart.
CategoryExample(Wt::WContainerWidget *parent)
Creates the category chart example.
A class that allows configuration of a cartesian chart.
Definition ChartConfig.h:41
void setValueFill(Wt::Chart::FillRangeType fill)
ChartsExample(Wt::WContainerWidget *root)
Constructor.
virtual void setData(const boost::any &data, int role=Wt::UserRole)
Definition CsvUtil.C:22
virtual NumericItem * clone() const
Definition CsvUtil.C:18
A Widget that demonstrates a Pie chart.
PieExample(Wt::WContainerWidget *parent)
Creates the pie chart example.
A Widget that demonstrates a scatter plot.
ScatterPlotExample(Wt::WContainerWidget *parent)
Creates the scatter plot example.
A widget that demonstrates a times series chart.
TimeSeriesExample(Wt::WContainerWidget *parent)
Creates the time series scatter plot example.
void setModel(WAbstractItemModel *model)
void setBackground(const WBrush &background)
void setAutoLayoutEnabled(bool enabled=true)
void setLocation(AxisValue value)
void setScale(AxisScale scale)
void setType(ChartType type)
void setLegendEnabled(bool enabled)
void setPanEnabled(bool pan=true)
void setZoomEnabled(bool zoom=true)
void setXSeriesColumn(int modelColumn)
void setCrosshairEnabled(bool crosshair=true)
WAxis & axis(Axis axis)
void addSeries(const WDataSeries &series)
void setShadow(const WShadow &shadow)
void setDataColumn(int modelColumn)
void setExplode(int modelRow, double factor)
void setShadowEnabled(bool enabled)
void setDisplayLabels(WFlags< LabelOption > options)
void setLabelsColumn(int column)
void setPerspectiveEnabled(bool enabled, double height=1.0)
virtual bool insertColumns(int column, int count, const WModelIndex &parent=WModelIndex())
virtual bool setHeaderData(int section, Orientation orientation, const boost::any &value, int role=EditRole)
virtual bool setData(const WModelIndex &index, const boost::any &value, int role=EditRole)
virtual boost::any data(const WModelIndex &index, int role=DisplayRole) const=0
virtual int rowCount(const WModelIndex &parent=WModelIndex()) const=0
virtual bool insertRows(int row, int count, const WModelIndex &parent=WModelIndex())
virtual int columnCount(const WModelIndex &parent=WModelIndex()) const=0
virtual void setHeaderAlignment(int column, WFlags< AlignmentFlag > alignment)
void setItemDelegate(WAbstractItemDelegate *delegate)
void setColumnResizeEnabled(bool enabled)
void setItemDelegateForColumn(int column, WAbstractItemDelegate *delegate)
void setEditTriggers(WFlags< EditTrigger > editTriggers)
virtual void setColumnAlignment(int column, AlignmentFlag alignment)
void setSortingEnabled(bool enabled)
void setSelectionMode(SelectionMode mode)
virtual void setMargin(const WLength &margin, WFlags< Side > sides=All)
static WDate fromString(const WString &s)
void setTextFormat(const WString &format)
static WLength Auto
virtual void resize(const WLength &width, const WLength &height)
WStandardItem * item(int row, int column=0) const
void setItemPrototype(WStandardItem *item)
virtual boost::any data(int role=UserRole) const
void setFlags(WFlags< ItemFlag > flags)
static WString tr(const char *key)
std::string toUTF8() const
virtual void setModel(WAbstractItemModel *model)
virtual void resize(const WLength &width, const WLength &height)
virtual void setRowHeight(const WLength &rowHeight)
virtual void setColumnWidth(int column, const WLength &width)
virtual void setAlternatingRowColors(bool enable)
virtual void setMargin(const WLength &margin, WFlags< Side > sides=All)
WString asString(const boost::any &v, const WString &formatString=WString())
EditRole
UserRole
ItemIsSelectable
ItemIsEditable
NoSelection
AlignCenter
void readFromCsv(std::istream &f, Wt::WAbstractItemModel *model, int numRows, bool firstLineIsHeaders)
Utility function that reads a model from a CSV file.
Definition CsvUtil.C:56

Generated on Fri May 17 2024 for the C++ Web Toolkit (Wt) by doxygen 1.9.8