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

Generated on Wed Jun 11 2014 for the C++ Web Toolkit (Wt) by doxygen 1.8.7