Wt examples  3.3.3
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 
33 namespace {
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);
127  table->setMargin(WLength::Auto, Left | Right);
128 
129  table->setModel(model);
130  table->setSortingEnabled(true);
131  table->setColumnResizeEnabled(true);
132  // table->setSelectionMode(ExtendedSelection);
133  table->setAlternatingRowColors(true);
134  table->setColumnAlignment(0, AlignCenter);
135  table->setHeaderAlignment(0, AlignCenter);
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);
142  table->setEditTriggers(WAbstractItemView::SingleClicked);
143  } else {
144  table->resize(600, WLength::Auto);
145  table->setEditTriggers(WAbstractItemView::NoEditTrigger);
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->setPreferredMethod(WPaintedWidget::PngImage);
163  chart->setModel(model); // set the model
164  chart->setXSeriesColumn(0); // set the column that holds the categories
165  chart->setLegendEnabled(true); // enable the legend
166 
167  // Provide space for the X and Y axis and title.
168  chart->setPlotAreaPadding(80, Left);
169  chart->setPlotAreaPadding(40, Top | Bottom);
170 
171  /*
172  * Add all (but first) column as bar series
173  */
174  for (int i = 1; i < model->columnCount(); ++i) {
175  WDataSeries s(i, BarSeries);
176  s.setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
177  chart->addSeries(s);
178  }
179 
180  chart->resize(800, 400);
181 
182  chart->setMargin(10, Top | Bottom);
183  chart->setMargin(WLength::Auto, Left | Right);
184 
185  /*
186  * Provide a widget to manipulate chart properties
187  */
188  new ChartConfig(chart, this);
189 }
190 
192  WContainerWidget(parent)
193 {
194  new WText(WString::tr("scatter plot"), this);
195 
196  WAbstractItemModel *model = readCsvFile(
197  WApplication::appRoot() + "timeseries.csv", this);
198 
199  if (!model)
200  return;
201 
202  /*
203  * Parses the first column as dates, to be able to use a date scale
204  */
205  for (int i = 0; i < model->rowCount(); ++i) {
206  WString s = asString(model->data(i, 0));
207  WDate d = WDate::fromString(s, "dd/MM/yy");
208  model->setData(i, 0, d);
209  }
210 
211  // Show a view that allows editing of the model.
212  WContainerWidget *w = new WContainerWidget(this);
213  WTableView *table = new WTableView(w);
214 
215  table->setMargin(10, Top | Bottom);
216  table->setMargin(WLength::Auto, Left | Right);
217 
218  table->setModel(model);
219  table->setSortingEnabled(false); // Does not make much sense for time series
220  table->setColumnResizeEnabled(true);
222  table->setAlternatingRowColors(true);
223  table->setColumnAlignment(0, AlignCenter);
224  table->setHeaderAlignment(0, AlignCenter);
225  table->setRowHeight(22);
226 
227  // Editing does not really work without Ajax, it would require an
228  // additional button somewhere to confirm the edited value.
229  if (WApplication::instance()->environment().ajax()) {
230  table->resize(800, 20 + 5*22);
231  table->setEditTriggers(WAbstractItemView::SingleClicked);
232  } else {
233  table->resize(800, 20 + 5*22 + 25);
234  table->setEditTriggers(WAbstractItemView::NoEditTrigger);
235  }
236 
237  WItemDelegate *delegate = new WItemDelegate(this);
238  delegate->setTextFormat("%.1f");
239  table->setItemDelegate(delegate);
240  table->setItemDelegateForColumn(0, new WItemDelegate(this));
241 
242  table->setColumnWidth(0, 80);
243  for (int i = 1; i < model->columnCount(); ++i)
244  table->setColumnWidth(i, 90);
245 
246  /*
247  * Create the scatter plot.
248  */
249  WCartesianChart *chart = new WCartesianChart(this);
250  //chart->setPreferredMethod(WPaintedWidget::PngImage);
251  //chart->setBackground(gray);
252  chart->setModel(model); // set the model
253  chart->setXSeriesColumn(0); // set the column that holds the X data
254  chart->setLegendEnabled(true); // enable the legend
255 
256  chart->setType(ScatterPlot); // set type to ScatterPlot
257  chart->axis(XAxis).setScale(DateScale); // set scale of X axis to DateScale
258 
259  // Provide space for the X and Y axis and title.
260  chart->setPlotAreaPadding(80, Left);
261  chart->setPlotAreaPadding(40, Top | Bottom);
262 
263  /*
264  * Add first two columns as line series
265  */
266  for (int i = 1; i < 3; ++i) {
267  WDataSeries s(i, LineSeries);
268  s.setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
269  chart->addSeries(s);
270  }
271 
272  chart->resize(800, 400); // WPaintedWidget must be given explicit size
273 
274  chart->setMargin(10, Top | Bottom); // add margin vertically
275  chart->setMargin(WLength::Auto, Left | Right); // center horizontally
276 
277  new ChartConfig(chart, this);
278 }
279 
281  WContainerWidget(parent)
282 {
283  new WText(WString::tr("scatter plot 2"), this);
284 
285  WStandardItemModel *model = new WStandardItemModel(40, 2, this);
286  model->setItemPrototype(new NumericItem());
287  model->setHeaderData(0, WString("X"));
288  model->setHeaderData(1, WString("Y = sin(X)"));
289 
290  for (unsigned i = 0; i < 40; ++i) {
291  double x = (static_cast<double>(i) - 20) / 4;
292 
293  model->setData(i, 0, x);
294  model->setData(i, 1, sin(x));
295  }
296 
297  /*
298  * Create the scatter plot.
299  */
300  WCartesianChart *chart = new WCartesianChart(this);
301  chart->setModel(model); // set the model
302  chart->setXSeriesColumn(0); // set the column that holds the X data
303  chart->setLegendEnabled(true); // enable the legend
304 
305  chart->setType(ScatterPlot); // set type to ScatterPlot
306 
307  // Typically, for mathematical functions, you want the axes to cross
308  // at the 0 mark:
309  chart->axis(XAxis).setLocation(ZeroValue);
310  chart->axis(YAxis).setLocation(ZeroValue);
311 
312  // Provide space for the X and Y axis and title.
313  chart->setPlotAreaPadding(80, Left);
314  chart->setPlotAreaPadding(40, Top | Bottom);
315 
316  // Add the curves
317  WDataSeries s(1, CurveSeries);
318  s.setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
319  chart->addSeries(s);
320 
321  chart->resize(800, 300); // WPaintedWidget must be given explicit size
322 
323  chart->setMargin(10, Top | Bottom); // add margin vertically
324  chart->setMargin(WLength::Auto, Left | Right); // center horizontally
325 
326  ChartConfig *config = new ChartConfig(chart, this);
327  config->setValueFill(ZeroValueFill);
328 }
329 
331  WContainerWidget(parent)
332 {
333  new WText(WString::tr("pie chart"), this);
334 
335  WStandardItemModel *model = new WStandardItemModel(this);
336  model->setItemPrototype(new NumericItem());
337 
338  //headers
339  model->insertColumns(model->columnCount(), 2);
340  model->setHeaderData(0, WString("Item"));
341  model->setHeaderData(1, WString("Sales"));
342 
343  //data
344  model->insertRows(model->rowCount(), 6);
345  int row = 0;
346  model->setData(row, 0, WString("Blueberry"));
347  model->setData(row, 1, 120);
348  // model->setData(row, 1, WString("Blueberry"), ToolTipRole);
349  row++;
350  model->setData(row, 0, WString("Cherry"));
351  model->setData(row, 1, 30);
352  row++;
353  model->setData(row, 0, WString("Apple"));
354  model->setData(row, 1, 260);
355  row++;
356  model->setData(row, 0, WString("Boston Cream"));
357  model->setData(row, 1, 160);
358  row++;
359  model->setData(row, 0, WString("Other"));
360  model->setData(row, 1, 40);
361  row++;
362  model->setData(row, 0, WString("Vanilla Cream"));
363  model->setData(row, 1, 120);
364  row++;
365 
366  //set all items to be editable and selectable
367  for (int row = 0; row < model->rowCount(); ++row)
368  for (int col = 0; col < model->columnCount(); ++col)
369  model->item(row, col)->setFlags(ItemIsSelectable | ItemIsEditable);
370 
371  WContainerWidget *w = new WContainerWidget(this);
372  WTableView* table = new WTableView(w);
373 
374  table->setMargin(10, Top | Bottom);
375  table->setMargin(WLength::Auto, Left | Right);
376  table->setSortingEnabled(true);
377  table->setModel(model);
378  table->setColumnWidth(1, 100);
379  table->setRowHeight(22);
380 
381  if (WApplication::instance()->environment().ajax()) {
382  table->resize(150 + 100 + 14, 20 + 6 * 22);
383  table->setEditTriggers(WAbstractItemView::SingleClicked);
384  } else {
385  table->resize(150 + 100 + 14, WLength::Auto);
386  table->setEditTriggers(WAbstractItemView::NoEditTrigger);
387  }
388 
389  /*
390  * Create the pie chart.
391  */
392  WPieChart *chart = new WPieChart(this);
393  chart->setModel(model); // set the model
394  chart->setLabelsColumn(0); // set the column that holds the labels
395  chart->setDataColumn(1); // set the column that holds the data
396 
397  // configure location and type of labels
399 
400  // enable a 3D and shadow effect
401  chart->setPerspectiveEnabled(true, 0.2);
402  chart->setShadowEnabled(true);
403 
404  // explode the first item
405  chart->setExplode(0, 0.3);
406 
407  chart->resize(800, 300); // WPaintedWidget must be given an explicit size
408 
409  chart->setMargin(10, Top | Bottom); // add margin vertically
410  chart->setMargin(WLength::Auto, Left | Right); // center horizontally
411 }
412 
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.
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())
TextLabel
void setLabelsColumn(int column)
UserRole
XAxis
virtual void setColumnWidth(int column, const WLength &width)
A Widget that demonstrates a Pie chart.
Definition: ChartsExample.h:59
ItemIsEditable
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)
ZeroValue
CategoryExample(Wt::WContainerWidget *parent)
Creates the category chart example.
virtual int rowCount(const WModelIndex &parent=WModelIndex()) const =0
AlignCenter
void setPerspectiveEnabled(bool enabled, double height=1.0)
virtual void resize(const WLength &width, const WLength &height)
void setItemPrototype(WStandardItem *item)
std::string toUTF8() const
LineSeries
DateScale
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.
Outside
void setValueFill(Wt::Chart::FillRangeType fill)
Definition: ChartConfig.C:392
virtual int columnCount(const WModelIndex &parent=WModelIndex()) const =0
void setEditTriggers(WFlags< EditTrigger > editTriggers)
YAxis
NoSelection
void setShadowEnabled(bool enabled)
void setColumnResizeEnabled(bool enabled)
void setPlotAreaPadding(int padding, WFlags< Side > sides=All)
ZeroValueFill
virtual void setData(const boost::any &data, int role=UserRole)
virtual void setAlternatingRowColors(bool enable)
CurveSeries
ScatterPlot
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)
ItemIsSelectable
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
TextPercentage
EditRole
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:55
virtual bool setData(const WModelIndex &index, const boost::any &value, int role=EditRole)
BarSeries
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 Sun Nov 30 2014 for the C++ Web Toolkit (Wt) by doxygen 1.8.8