Wt examples
3.3.0
|
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