Wt examples  3.2.0
/home/koen/project/wt/public-git/wt/examples/charts/ChartsExample.C
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 Emweb bvba, Kessel-Lo, Belgium.
00003  *
00004  * See the LICENSE file for terms of use.
00005  */
00006 
00007 #include <math.h>
00008 #include <fstream>
00009 
00010 #include "ChartsExample.h"
00011 #include "ChartConfig.h"
00012 #include "CsvUtil.h"
00013 
00014 #include <Wt/WApplication>
00015 #include <Wt/WDate>
00016 #include <Wt/WEnvironment>
00017 #include <Wt/WItemDelegate>
00018 #include <Wt/WStandardItemModel>
00019 #include <Wt/WText>
00020 
00021 #include <Wt/WBorderLayout>
00022 #include <Wt/WFitLayout>
00023 
00024 #include <Wt/WStandardItem>
00025 #include <Wt/WTableView>
00026 
00027 #include <Wt/Chart/WCartesianChart>
00028 #include <Wt/Chart/WPieChart>
00029 
00030 using namespace Wt;
00031 using namespace Wt::Chart;
00032 namespace {
00033 
00034   /*
00035    * Reads a CSV file as an (editable) standard item model.
00036    */
00037   WAbstractItemModel *readCsvFile(const std::string &fname,
00038                                   WContainerWidget *parent)
00039   {
00040     WStandardItemModel *model = new WStandardItemModel(0, 0, parent);
00041     std::ifstream f(fname.c_str());
00042 
00043     if (f) {
00044       readFromCsv(f, model);
00045 
00046       for (int row = 0; row < model->rowCount(); ++row)
00047         for (int col = 0; col < model->columnCount(); ++col) {
00048           model->item(row, col)->setFlags(ItemIsSelectable | ItemIsEditable);
00049 
00050           /*
00051             Example of tool tips (disabled here because they are not updated
00052             when editing data)
00053            */
00054 
00055           /*
00056           WString toolTip = asString(model->headerData(col)) + ": "
00057             + asString(model->item(row, col)->data(DisplayRole), "%.f");
00058           model->item(row, col)->setToolTip(toolTip);
00059            */
00060         }
00061 
00062       return model;
00063     } else {
00064       WString error(WString::tr("error-missing-data"));
00065       error.arg(fname, UTF8);
00066       new WText(error, parent);
00067       return 0;
00068     }
00069   }
00070 }
00071 
00072 ChartsExample::ChartsExample(WContainerWidget *root)
00073   : WContainerWidget(root)
00074 {
00075   new WText(WString::tr("introduction"), this);
00076 
00077   new CategoryExample(this);
00078   new TimeSeriesExample(this);
00079   new ScatterPlotExample(this);
00080   new PieExample(this);
00081 }
00082 
00083 CategoryExample::CategoryExample(Wt::WContainerWidget *parent):
00084   WContainerWidget(parent)
00085 {
00086   new WText(WString::tr("category chart"), this);
00087 
00088   WAbstractItemModel *model
00089     = readCsvFile(WApplication::appRoot() + "category.csv", this);
00090 
00091   if (!model)
00092     return;
00093 
00094   // Show a view that allows editing of the model.
00095   WContainerWidget *w = new WContainerWidget(this);
00096   WTableView *table = new WTableView(w);
00097 
00098   table->setMargin(10, Top | Bottom);
00099   table->setMargin(WLength::Auto, Left | Right);
00100 
00101   table->setModel(model);
00102   table->setSortingEnabled(true);
00103   table->setColumnResizeEnabled(true);
00104   // table->setSelectionMode(ExtendedSelection);
00105   table->setAlternatingRowColors(true);
00106   table->setColumnAlignment(0, AlignCenter);
00107   table->setHeaderAlignment(0, AlignCenter);
00108   table->setRowHeight(22);
00109 
00110   // Editing does not really work without Ajax, it would require an
00111   // additional button somewhere to confirm the edited value.
00112   if (WApplication::instance()->environment().ajax()) {
00113     table->resize(600, 20 + 5*22);
00114     table->setEditTriggers(WAbstractItemView::SingleClicked);
00115   } else {
00116     table->resize(600, WLength::Auto);
00117     table->setEditTriggers(WAbstractItemView::NoEditTrigger);
00118   }
00119 
00120   // We use a single delegate for all items which rounds values to
00121   // the closest integer value.
00122   WItemDelegate *delegate = new WItemDelegate(this);
00123   delegate->setTextFormat("%.f");
00124   table->setItemDelegate(delegate);
00125 
00126   table->setColumnWidth(0, 80);
00127   for (int i = 1; i < model->columnCount(); ++i)
00128     table->setColumnWidth(i, 120);
00129 
00130   /*
00131    * Create the category chart.
00132    */
00133   WCartesianChart *chart = new WCartesianChart(this);
00134   // chart->setPreferredMethod(WPaintedWidget::PngImage);
00135   chart->setModel(model);        // set the model
00136   chart->setXSeriesColumn(0);    // set the column that holds the categories
00137   chart->setLegendEnabled(true); // enable the legend
00138 
00139   // Provide space for the X and Y axis and title. 
00140   chart->setPlotAreaPadding(80, Left);
00141   chart->setPlotAreaPadding(40, Top | Bottom);
00142 
00143   /*
00144    * Add all (but first) column as bar series
00145    */
00146   for (int i = 1; i < model->columnCount(); ++i) {
00147     WDataSeries s(i, BarSeries);
00148     s.setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
00149     chart->addSeries(s);
00150   }
00151 
00152   chart->resize(800, 400);
00153 
00154   chart->setMargin(10, Top | Bottom);
00155   chart->setMargin(WLength::Auto, Left | Right);
00156 
00157   /*
00158    * Provide a widget to manipulate chart properties
00159    */
00160   new ChartConfig(chart, this);
00161 }
00162 
00163 TimeSeriesExample::TimeSeriesExample(Wt::WContainerWidget *parent):
00164   WContainerWidget(parent)
00165 {
00166   new WText(WString::tr("scatter plot"), this);
00167 
00168   WAbstractItemModel *model = readCsvFile(
00169     WApplication::appRoot() + "timeseries.csv", this);
00170 
00171   if (!model)
00172     return;
00173 
00174   /*
00175    * Parses the first column as dates, to be able to use a date scale
00176    */
00177   for (int i = 0; i < model->rowCount(); ++i) {
00178     WString s = asString(model->data(i, 0));
00179     WDate d = WDate::fromString(s, "dd/MM/yy");
00180     model->setData(i, 0, d);
00181   }
00182 
00183   // Show a view that allows editing of the model.
00184   WContainerWidget *w = new WContainerWidget(this);
00185   WTableView *table = new WTableView(w);
00186 
00187   table->setMargin(10, Top | Bottom);
00188   table->setMargin(WLength::Auto, Left | Right);
00189 
00190   table->setModel(model);
00191   table->setSortingEnabled(false); // Does not make much sense for time series
00192   table->setColumnResizeEnabled(true);
00193   table->setSelectionMode(NoSelection);
00194   table->setAlternatingRowColors(true);
00195   table->setColumnAlignment(0, AlignCenter);
00196   table->setHeaderAlignment(0, AlignCenter);
00197   table->setRowHeight(22);
00198 
00199   // Editing does not really work without Ajax, it would require an
00200   // additional button somewhere to confirm the edited value.
00201   if (WApplication::instance()->environment().ajax()) {
00202     table->resize(800, 20 + 5*22);
00203     table->setEditTriggers(WAbstractItemView::SingleClicked);
00204   } else {
00205     table->resize(800, 20 + 5*22 + 25);
00206     table->setEditTriggers(WAbstractItemView::NoEditTrigger);
00207   }
00208 
00209   WItemDelegate *delegate = new WItemDelegate(this);
00210   delegate->setTextFormat("%.1f");
00211   table->setItemDelegate(delegate);
00212   table->setItemDelegateForColumn(0, new WItemDelegate(this));
00213 
00214   table->setColumnWidth(0, 80);
00215   for (int i = 1; i < model->columnCount(); ++i)
00216     table->setColumnWidth(i, 90);
00217 
00218   /*
00219    * Create the scatter plot.
00220    */
00221   WCartesianChart *chart = new WCartesianChart(this);
00222   //chart->setPreferredMethod(WPaintedWidget::PngImage);
00223   //chart->setBackground(gray);
00224   chart->setModel(model);        // set the model
00225   chart->setXSeriesColumn(0);    // set the column that holds the X data
00226   chart->setLegendEnabled(true); // enable the legend
00227 
00228   chart->setType(ScatterPlot);            // set type to ScatterPlot
00229   chart->axis(XAxis).setScale(DateScale); // set scale of X axis to DateScale
00230 
00231   // Provide space for the X and Y axis and title. 
00232   chart->setPlotAreaPadding(80, Left);
00233   chart->setPlotAreaPadding(40, Top | Bottom);
00234 
00235   /*
00236    * Add first two columns as line series
00237    */
00238   for (int i = 1; i < 3; ++i) {
00239     WDataSeries s(i, LineSeries);
00240     s.setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
00241     chart->addSeries(s);
00242   }
00243 
00244   chart->resize(800, 400); // WPaintedWidget must be given explicit size
00245 
00246   chart->setMargin(10, Top | Bottom);            // add margin vertically
00247   chart->setMargin(WLength::Auto, Left | Right); // center horizontally
00248 
00249   new ChartConfig(chart, this);
00250 }
00251 
00252 ScatterPlotExample::ScatterPlotExample(WContainerWidget *parent):
00253   WContainerWidget(parent)
00254 {
00255   new WText(WString::tr("scatter plot 2"), this);
00256 
00257   WStandardItemModel *model = new WStandardItemModel(40, 2, this);
00258   model->setHeaderData(0, WString("X"));
00259   model->setHeaderData(1, WString("Y = sin(X)"));
00260 
00261   for (unsigned i = 0; i < 40; ++i) {
00262     double x = (static_cast<double>(i) - 20) / 4;
00263 
00264     model->setData(i, 0, x);
00265     model->setData(i, 1, sin(x));
00266   }
00267  
00268   /*
00269    * Create the scatter plot.
00270    */
00271   WCartesianChart *chart = new WCartesianChart(this);
00272   chart->setModel(model);        // set the model
00273   chart->setXSeriesColumn(0);    // set the column that holds the X data
00274   chart->setLegendEnabled(true); // enable the legend
00275 
00276   chart->setType(ScatterPlot);   // set type to ScatterPlot
00277 
00278   // Typically, for mathematical functions, you want the axes to cross
00279   // at the 0 mark:
00280   chart->axis(XAxis).setLocation(ZeroValue);
00281   chart->axis(YAxis).setLocation(ZeroValue);
00282 
00283   // Provide space for the X and Y axis and title. 
00284   chart->setPlotAreaPadding(80, Left);
00285   chart->setPlotAreaPadding(40, Top | Bottom);
00286 
00287   // Add the curves
00288   WDataSeries s(1, CurveSeries);
00289   s.setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
00290   chart->addSeries(s);
00291 
00292   chart->resize(800, 300); // WPaintedWidget must be given explicit size
00293 
00294   chart->setMargin(10, Top | Bottom);            // add margin vertically
00295   chart->setMargin(WLength::Auto, Left | Right); // center horizontally
00296 
00297   ChartConfig *config = new ChartConfig(chart, this);
00298   config->setValueFill(ZeroValueFill);
00299 }
00300 
00301 PieExample::PieExample(WContainerWidget *parent):
00302   WContainerWidget(parent)
00303 {
00304   new WText(WString::tr("pie chart"), this);
00305 
00306   WStandardItemModel *model = new WStandardItemModel(this);
00307   
00308   //headers
00309   model->insertColumns(model->columnCount(), 2);
00310   model->setHeaderData(0, WString("Item"));
00311   model->setHeaderData(1, WString("Sales"));
00312 
00313   //data
00314   model->insertRows(model->rowCount(), 6);
00315   int row = 0;
00316   model->setData(row, 0, WString("Blueberry"));
00317   model->setData(row, 1, 120);
00318   // model->setData(row, 1, WString("Blueberry"), ToolTipRole);
00319   row++;
00320   model->setData(row, 0, WString("Cherry"));
00321   model->setData(row, 1, 30);
00322   row++;
00323   model->setData(row, 0, WString("Apple"));
00324   model->setData(row, 1, 260);
00325   row++;
00326   model->setData(row, 0, WString("Boston Cream"));
00327   model->setData(row, 1, 160);
00328   row++;
00329   model->setData(row, 0, WString("Other"));
00330   model->setData(row, 1, 40);
00331   row++;
00332   model->setData(row, 0, WString("Vanilla Cream"));
00333   model->setData(row, 1, 120);
00334   row++;
00335 
00336   //set all items to be editable and selectable
00337   for (int row = 0; row < model->rowCount(); ++row)
00338     for (int col = 0; col < model->columnCount(); ++col)
00339       model->item(row, col)->setFlags(ItemIsSelectable | ItemIsEditable);
00340 
00341   WContainerWidget *w = new WContainerWidget(this);
00342   WTableView* table = new WTableView(w);
00343 
00344   table->setMargin(10, Top | Bottom);
00345   table->setMargin(WLength::Auto, Left | Right);
00346   table->setSortingEnabled(true);
00347   table->setModel(model);
00348   table->setColumnWidth(1, 100);
00349   table->setRowHeight(22);
00350 
00351   if (WApplication::instance()->environment().ajax()) {
00352     table->resize(150 + 100 + 14, 20 + 6 * 22);
00353     table->setEditTriggers(WAbstractItemView::SingleClicked);
00354   } else {
00355     table->resize(150 + 100 + 14, WLength::Auto);
00356     table->setEditTriggers(WAbstractItemView::NoEditTrigger);    
00357   }
00358 
00359   /*
00360    * Create the pie chart.
00361    */
00362   WPieChart *chart = new WPieChart(this);
00363   chart->setModel(model);       // set the model
00364   chart->setLabelsColumn(0);    // set the column that holds the labels
00365   chart->setDataColumn(1);      // set the column that holds the data
00366 
00367   // configure location and type of labels
00368   chart->setDisplayLabels(Outside | TextLabel | TextPercentage);
00369 
00370   // enable a 3D and shadow effect
00371   chart->setPerspectiveEnabled(true, 0.2);
00372   chart->setShadowEnabled(true);
00373 
00374   // explode the first item
00375   chart->setExplode(0, 0.3);
00376 
00377   chart->resize(800, 300); // WPaintedWidget must be given an explicit size
00378 
00379   chart->setMargin(10, Top | Bottom);            // add margin vertically
00380   chart->setMargin(WLength::Auto, Left | Right); // center horizontally
00381 }
00382 

Generated on Tue Nov 29 2011 for the C++ Web Toolkit (Wt) by doxygen 1.7.5.1