#include <ChartConfig.h>
Public Member Functions | |
ChartConfig (Wt::Chart::WCartesianChart *chart, Wt::WContainerWidget *parent) | |
Constructor. | |
void | setValueFill (Wt::Chart::FillRangeType fill) |
Private Member Functions | |
void | connectSignals (Wt::WFormWidget *w) |
void | update () |
Static Private Member Functions | |
static bool | validate (Wt::WFormWidget *w) |
Private Attributes | |
Wt::Chart::WCartesianChart * | chart_ |
Wt::Chart::FillRangeType | fill_ |
std::vector< SeriesControl > | seriesControls_ |
Controls for series. | |
std::vector< AxisControl > | axisControls_ |
Controls for axes. | |
Wt::WLineEdit * | titleEdit_ |
Wt::WLineEdit * | chartWidthEdit_ |
Wt::WLineEdit * | chartHeightEdit_ |
Wt::WComboBox * | chartOrientationEdit_ |
Classes | |
struct | AxisControl |
Struct that holds the controls for one axis. More... | |
struct | SeriesControl |
Struct that holds the controls for one series. More... |
This widget provides forms for configuring chart, series, and axis properties and manipulates the chart according to user settings.
This widget is part of the Wt charts example.
Definition at line 37 of file ChartConfig.h.
ChartConfig::ChartConfig | ( | Wt::Chart::WCartesianChart * | chart, | |
Wt::WContainerWidget * | parent | |||
) |
Constructor.
Definition at line 52 of file ChartConfig.C.
00053 : WContainerWidget(parent), 00054 chart_(chart), 00055 fill_(MinimumValueFill) 00056 { 00057 PanelList *list = new PanelList(this); 00058 00059 WIntValidator *sizeValidator = new WIntValidator(200, 2000, this); 00060 sizeValidator->setMandatory(true); 00061 00062 WDoubleValidator *anyNumberValidator = new WDoubleValidator(this); 00063 anyNumberValidator->setMandatory(true); 00064 00065 WDoubleValidator *angleValidator = new WDoubleValidator(-90, 90, this); 00066 angleValidator->setMandatory(true); 00067 00068 // ---- Chart properties ---- 00069 00070 WStandardItemModel *orientation = new WStandardItemModel(0, 1, this); 00071 addEntry(orientation, "Vertical"); 00072 addEntry(orientation, "Horizontal"); 00073 00074 WTable *chartConfig = new WTable(); 00075 chartConfig->setMargin(WLength::Auto, Left | Right); 00076 00077 int row = 0; 00078 chartConfig->elementAt(row, 0)->addWidget(new WText("Title:")); 00079 titleEdit_ = new WLineEdit(chartConfig->elementAt(row, 1)); 00080 connectSignals(titleEdit_); 00081 ++row; 00082 00083 chartConfig->elementAt(row, 0)->addWidget(new WText("Width:")); 00084 chartWidthEdit_ = new WLineEdit(chartConfig->elementAt(row, 1)); 00085 chartWidthEdit_ 00086 ->setText(boost::lexical_cast<std::string>(chart_->width().value())); 00087 chartWidthEdit_->setValidator(sizeValidator); 00088 chartWidthEdit_->setMaxLength(4); 00089 connectSignals(chartWidthEdit_); 00090 ++row; 00091 00092 chartConfig->elementAt(row, 0)->addWidget(new WText("Height:")); 00093 chartHeightEdit_ = new WLineEdit(chartConfig->elementAt(row, 1)); 00094 chartHeightEdit_ 00095 ->setText(boost::lexical_cast<std::string>(chart_->height().value())); 00096 chartHeightEdit_->setValidator(sizeValidator); 00097 chartHeightEdit_->setMaxLength(4); 00098 connectSignals(chartHeightEdit_); 00099 ++row; 00100 00101 chartConfig->elementAt(row, 0)->addWidget(new WText("Orientation:")); 00102 chartOrientationEdit_ = new WComboBox(chartConfig->elementAt(row, 1)); 00103 chartOrientationEdit_->setModel(orientation); 00104 connectSignals(chartOrientationEdit_); 00105 ++row; 00106 00107 for (int i = 0; i < chartConfig->rowCount(); ++i) { 00108 chartConfig->elementAt(i, 0)->setStyleClass("tdhead"); 00109 chartConfig->elementAt(i, 1)->setStyleClass("tddata"); 00110 } 00111 00112 WPanel *p = list->addWidget("Chart properties", chartConfig); 00113 p->setMargin(WLength::Auto, Left | Right); 00114 p->resize(750, WLength::Auto); 00115 p->setMargin(20, Top | Bottom); 00116 00117 if (chart_->isLegendEnabled()) 00118 chart_->setPlotAreaPadding(200, Right); 00119 00120 // ---- Series properties ---- 00121 00122 WStandardItemModel *types = new WStandardItemModel(0, 1, this); 00123 addEntry(types, "Points"); 00124 addEntry(types, "Line"); 00125 addEntry(types, "Curve"); 00126 addEntry(types, "Bar"); 00127 addEntry(types, "Line Area"); 00128 addEntry(types, "Curve Area"); 00129 addEntry(types, "Stacked Bar"); 00130 addEntry(types, "Stacked Line Area"); 00131 addEntry(types, "Stacked Curve Area"); 00132 00133 WStandardItemModel *markers = new WStandardItemModel(0, 1, this); 00134 addEntry(markers, "None"); 00135 addEntry(markers, "Square"); 00136 addEntry(markers, "Circle"); 00137 addEntry(markers, "Cross"); 00138 addEntry(markers, "X cross"); 00139 addEntry(markers, "Triangle"); 00140 00141 WStandardItemModel *axes = new WStandardItemModel(0, 1, this); 00142 addEntry(axes, "1st Y axis"); 00143 addEntry(axes, "2nd Y axis"); 00144 00145 WStandardItemModel *labels = new WStandardItemModel(0, 1, this); 00146 addEntry(labels, "None"); 00147 addEntry(labels, "X"); 00148 addEntry(labels, "Y"); 00149 addEntry(labels, "X: Y"); 00150 00151 WTable *seriesConfig = new WTable(); 00152 seriesConfig->setMargin(WLength::Auto, Left | Right); 00153 00154 ::addHeader(seriesConfig, "Name"); 00155 ::addHeader(seriesConfig, "Enabled"); 00156 ::addHeader(seriesConfig, "Type"); 00157 ::addHeader(seriesConfig, "Marker"); 00158 ::addHeader(seriesConfig, "Y axis"); 00159 ::addHeader(seriesConfig, "Legend"); 00160 ::addHeader(seriesConfig, "Value labels"); 00161 00162 seriesConfig->rowAt(0)->setStyleClass("trhead"); 00163 00164 for (int j = 1; j < chart->model()->columnCount(); ++j) { 00165 SeriesControl sc; 00166 00167 new WText(asString(chart->model()->headerData(j)), 00168 seriesConfig->elementAt(j, 0)); 00169 00170 sc.enabledEdit = new WCheckBox(seriesConfig->elementAt(j, 1)); 00171 connectSignals(sc.enabledEdit); 00172 00173 sc.typeEdit = new WComboBox(seriesConfig->elementAt(j, 2)); 00174 sc.typeEdit->setModel(types); 00175 connectSignals(sc.typeEdit); 00176 00177 sc.markerEdit = new WComboBox(seriesConfig->elementAt(j, 3)); 00178 sc.markerEdit->setModel(markers); 00179 connectSignals(sc.markerEdit); 00180 00181 sc.axisEdit = new WComboBox(seriesConfig->elementAt(j, 4)); 00182 sc.axisEdit->setModel(axes); 00183 connectSignals(sc.axisEdit); 00184 00185 sc.legendEdit = new WCheckBox(seriesConfig->elementAt(j, 5)); 00186 connectSignals(sc.legendEdit); 00187 00188 sc.labelsEdit = new WComboBox(seriesConfig->elementAt(j, 6)); 00189 sc.labelsEdit->setModel(labels); 00190 connectSignals(sc.labelsEdit); 00191 00192 int si = chart->seriesIndexOf(j); 00193 00194 if (si != -1) { 00195 sc.enabledEdit->setChecked(); 00196 const WDataSeries& s = chart_->series(j); 00197 switch (s.type()) { 00198 case PointSeries: 00199 sc.typeEdit->setCurrentIndex(0); break; 00200 case LineSeries: 00201 sc.typeEdit->setCurrentIndex(s.fillRange() != NoFill ? 00202 (s.isStacked() ? 7 : 4) : 1); break; 00203 case CurveSeries: 00204 sc.typeEdit->setCurrentIndex(s.fillRange() != NoFill ? 00205 (s.isStacked() ? 8 : 5) : 2); break; 00206 case BarSeries: 00207 sc.typeEdit->setCurrentIndex(s.isStacked() ? 6 : 3); 00208 } 00209 00210 sc.markerEdit->setCurrentIndex((int)s.marker()); 00211 sc.legendEdit->setChecked(s.isLegendEnabled()); 00212 } 00213 00214 seriesControls_.push_back(sc); 00215 00216 seriesConfig->rowAt(j)->setStyleClass("trdata"); 00217 } 00218 00219 p = list->addWidget("Series properties", seriesConfig); 00220 p->expand(); 00221 p->setMargin(WLength::Auto, Left | Right); 00222 p->resize(750, WLength::Auto); 00223 p->setMargin(20, Top | Bottom); 00224 00225 // ---- Axis properties ---- 00226 00227 WStandardItemModel *yScales = new WStandardItemModel(0, 1, this); 00228 addEntry(yScales, "Linear scale"); 00229 addEntry(yScales, "Log scale"); 00230 00231 WStandardItemModel *xScales = new WStandardItemModel(0, 1, this); 00232 addEntry(xScales, "Categories"); 00233 addEntry(xScales, "Linear scale"); 00234 addEntry(xScales, "Log scale"); 00235 addEntry(xScales, "Date scale"); 00236 00237 WTable *axisConfig = new WTable(); 00238 axisConfig->setMargin(WLength::Auto, Left | Right); 00239 00240 ::addHeader(axisConfig, "Axis"); 00241 ::addHeader(axisConfig, "Visible"); 00242 ::addHeader(axisConfig, "Scale"); 00243 ::addHeader(axisConfig, "Automatic"); 00244 ::addHeader(axisConfig, "Minimum"); 00245 ::addHeader(axisConfig, "Maximum"); 00246 ::addHeader(axisConfig, "Gridlines"); 00247 ::addHeader(axisConfig, "Label angle"); 00248 00249 axisConfig->rowAt(0)->setStyleClass("trhead"); 00250 00251 for (int i = 0; i < 3; ++i) { 00252 const char *axisName[] = { "X axis", "1st Y axis", "2nd Y axis" }; 00253 int j = i + 1; 00254 00255 const WAxis& axis = chart_->axis(static_cast<Axis>(i)); 00256 AxisControl sc; 00257 00258 new WText(WString(axisName[i], UTF8), axisConfig->elementAt(j, 0)); 00259 00260 sc.visibleEdit = new WCheckBox(axisConfig->elementAt(j, 1)); 00261 sc.visibleEdit->setChecked(axis.isVisible()); 00262 connectSignals(sc.visibleEdit); 00263 00264 sc.scaleEdit = new WComboBox(axisConfig->elementAt(j, 2)); 00265 if (axis.scale() == CategoryScale) 00266 sc.scaleEdit->addItem("Category scale"); 00267 else { 00268 if (axis.id() == XAxis) { 00269 sc.scaleEdit->setModel(xScales); 00270 sc.scaleEdit->setCurrentIndex(axis.scale()); 00271 } else { 00272 sc.scaleEdit->setModel(yScales); 00273 sc.scaleEdit->setCurrentIndex(axis.scale() - 1); 00274 } 00275 } 00276 connectSignals(sc.scaleEdit); 00277 00278 bool autoValues 00279 = axis.minimum() == WAxis::AUTO_MINIMUM 00280 && axis.maximum() == WAxis::AUTO_MAXIMUM; 00281 00282 sc.minimumEdit = new WLineEdit(axisConfig->elementAt(j, 4)); 00283 sc.minimumEdit->setText(boost::lexical_cast<std::string>(axis.minimum())); 00284 sc.minimumEdit->setValidator(anyNumberValidator); 00285 sc.minimumEdit->setEnabled(!autoValues); 00286 connectSignals(sc.minimumEdit); 00287 00288 sc.maximumEdit = new WLineEdit(axisConfig->elementAt(j, 5)); 00289 sc.maximumEdit->setText(boost::lexical_cast<std::string>(axis.maximum())); 00290 sc.maximumEdit->setValidator(anyNumberValidator); 00291 sc.maximumEdit->setEnabled(!autoValues); 00292 connectSignals(sc.maximumEdit); 00293 00294 sc.autoEdit = new WCheckBox(axisConfig->elementAt(j, 3)); 00295 sc.autoEdit->setChecked(autoValues); 00296 connectSignals(sc.autoEdit); 00297 sc.autoEdit->checked().connect(SLOT(sc.maximumEdit, WLineEdit::disable)); 00298 sc.autoEdit->unChecked().connect(SLOT(sc.maximumEdit, WLineEdit::enable)); 00299 sc.autoEdit->checked().connect(SLOT(sc.minimumEdit, WLineEdit::disable)); 00300 sc.autoEdit->unChecked().connect(SLOT(sc.minimumEdit, WLineEdit::enable)); 00301 00302 sc.gridLinesEdit = new WCheckBox(axisConfig->elementAt(j, 6)); 00303 connectSignals(sc.gridLinesEdit); 00304 00305 sc.labelAngleEdit = new WLineEdit(axisConfig->elementAt(j, 7)); 00306 sc.labelAngleEdit->setText("0"); 00307 sc.labelAngleEdit->setValidator(angleValidator); 00308 connectSignals(sc.labelAngleEdit); 00309 00310 axisConfig->rowAt(j)->setStyleClass("trdata"); 00311 00312 axisControls_.push_back(sc); 00313 } 00314 00315 p = list->addWidget("Axis properties", axisConfig); 00316 p->setMargin(WLength::Auto, Left | Right); 00317 p->resize(750, WLength::Auto); 00318 p->setMargin(20, Top | Bottom); 00319 00320 /* 00321 * If we do not have JavaScript, then add a button to reflect changes to 00322 * the chart. 00323 */ 00324 if (!WApplication::instance()->environment().javaScript()) { 00325 WPushButton *b = new WPushButton(this); 00326 b->setText("Update chart"); 00327 b->setInline(false); // so we can add margin to center horizontally 00328 b->setMargin(WLength::Auto, Left | Right); 00329 b->clicked().connect(SLOT(this, ChartConfig::update)); 00330 } 00331 }
void ChartConfig::setValueFill | ( | Wt::Chart::FillRangeType | fill | ) |
void ChartConfig::connectSignals | ( | Wt::WFormWidget * | w | ) | [private] |
Definition at line 506 of file ChartConfig.C.
00507 { 00508 w->changed().connect(SLOT(this, ChartConfig::update)); 00509 if (dynamic_cast<WLineEdit *>(w)) 00510 w->enterPressed().connect(SLOT(this, ChartConfig::update)); 00511 }
void ChartConfig::update | ( | ) | [private] |
Definition at line 338 of file ChartConfig.C.
00339 { 00340 bool haveLegend = false; 00341 std::vector<WDataSeries> series; 00342 00343 for (int i = 1; i < chart_->model()->columnCount(); ++i) { 00344 SeriesControl& sc = seriesControls_[i-1]; 00345 00346 if (sc.enabledEdit->isChecked()) { 00347 WDataSeries s(i); 00348 00349 switch (sc.typeEdit->currentIndex()) { 00350 case 0: 00351 s.setType(PointSeries); 00352 if (sc.markerEdit->currentIndex() == 0) 00353 sc.markerEdit->setCurrentIndex(1); 00354 break; 00355 case 1: 00356 s.setType(LineSeries); 00357 break; 00358 case 2: 00359 s.setType(CurveSeries); 00360 break; 00361 case 3: 00362 s.setType(BarSeries); 00363 break; 00364 case 4: 00365 s.setType(LineSeries); 00366 s.setFillRange(fill_); 00367 break; 00368 case 5: 00369 s.setType(CurveSeries); 00370 s.setFillRange(fill_); 00371 break; 00372 case 6: 00373 s.setType(BarSeries); 00374 s.setStacked(true); 00375 break; 00376 case 7: 00377 s.setType(LineSeries); 00378 s.setFillRange(fill_); 00379 s.setStacked(true); 00380 break; 00381 case 8: 00382 s.setType(CurveSeries); 00383 s.setFillRange(fill_); 00384 s.setStacked(true); 00385 } 00386 00387 s.setMarker(static_cast<MarkerType>(sc.markerEdit->currentIndex())); 00388 00389 if (sc.axisEdit->currentIndex() == 1) { 00390 s.bindToAxis(Y2Axis); 00391 } 00392 00393 if (sc.legendEdit->isChecked()) { 00394 s.setLegendEnabled(true); 00395 haveLegend = true; 00396 } else 00397 s.setLegendEnabled(false); 00398 00399 switch (sc.labelsEdit->currentIndex()) { 00400 case 1: 00401 s.setLabelsEnabled(XAxis); 00402 break; 00403 case 2: 00404 s.setLabelsEnabled(YAxis); 00405 break; 00406 case 3: 00407 s.setLabelsEnabled(XAxis); 00408 s.setLabelsEnabled(YAxis); 00409 break; 00410 } 00411 00412 series.push_back(s); 00413 } 00414 } 00415 00416 chart_->setSeries(series); 00417 00418 for (int i = 0; i < 3; ++i) { 00419 AxisControl& sc = axisControls_[i]; 00420 WAxis& axis = chart_->axis(static_cast<Axis>(i)); 00421 00422 axis.setVisible(sc.visibleEdit->isChecked()); 00423 00424 if (sc.scaleEdit->count() != 1) { 00425 int k = sc.scaleEdit->currentIndex(); 00426 if (axis.id() != XAxis) 00427 k += 1; 00428 else { 00429 if (k == 0) 00430 chart_->setType(CategoryChart); 00431 else 00432 chart_->setType(ScatterPlot); 00433 } 00434 00435 switch (k) { 00436 case 1: 00437 axis.setScale(LinearScale); break; 00438 case 2: 00439 axis.setScale(LogScale); break; 00440 case 3: 00441 axis.setScale(DateScale); break; 00442 } 00443 } 00444 00445 if (sc.autoEdit->isChecked()) 00446 axis.setRange(WAxis::AUTO_MINIMUM, WAxis::AUTO_MAXIMUM); 00447 else { 00448 if (validate(sc.minimumEdit) && validate(sc.maximumEdit)) { 00449 double min, max; 00450 getDouble(sc.minimumEdit, min); 00451 getDouble(sc.maximumEdit, max); 00452 00453 if (axis.scale() == LogScale) 00454 if (min <= 0) 00455 min = 0.0001; 00456 00457 max = std::max(min, max); 00458 00459 axis.setRange(min, max); 00460 } 00461 00462 } 00463 00464 00465 if (validate(sc.labelAngleEdit)) { 00466 double angle; 00467 getDouble(sc.labelAngleEdit, angle); 00468 axis.setLabelAngle(angle); 00469 } 00470 00471 axis.setGridLinesEnabled(sc.gridLinesEdit->isChecked()); 00472 } 00473 00474 chart_->setTitle(titleEdit_->text()); 00475 00476 if (validate(chartWidthEdit_) && validate(chartHeightEdit_)) { 00477 double width, height; 00478 getDouble(chartWidthEdit_, width); 00479 getDouble(chartHeightEdit_, height); 00480 chart_->resize(width, height); 00481 } 00482 00483 switch (chartOrientationEdit_->currentIndex()) { 00484 case 0: 00485 chart_->setOrientation(Vertical); break; 00486 case 1: 00487 chart_->setOrientation(Horizontal); break; 00488 } 00489 00490 chart_->setLegendEnabled(haveLegend); 00491 chart_->setPlotAreaPadding(haveLegend ? 200 : 40, Right); 00492 }
bool ChartConfig::validate | ( | Wt::WFormWidget * | w | ) | [static, private] |
Definition at line 494 of file ChartConfig.C.
00495 { 00496 bool valid = w->validate() == WValidator::Valid; 00497 00498 if (!WApplication::instance()->environment().javaScript()) { 00499 w->setStyleClass(valid ? "" : "Wt-invalid"); 00500 w->setToolTip(valid ? "" : "Invalid value"); 00501 } 00502 00503 return valid; 00504 }
Wt::Chart::WCartesianChart* ChartConfig::chart_ [private] |
Definition at line 47 of file ChartConfig.h.
Wt::Chart::FillRangeType ChartConfig::fill_ [private] |
Definition at line 48 of file ChartConfig.h.
std::vector<SeriesControl> ChartConfig::seriesControls_ [private] |
std::vector<AxisControl> ChartConfig::axisControls_ [private] |
Wt::WLineEdit* ChartConfig::titleEdit_ [private] |
Definition at line 77 of file ChartConfig.h.
Wt::WLineEdit* ChartConfig::chartWidthEdit_ [private] |
Definition at line 78 of file ChartConfig.h.
Wt::WLineEdit* ChartConfig::chartHeightEdit_ [private] |
Definition at line 79 of file ChartConfig.h.
Wt::WComboBox* ChartConfig::chartOrientationEdit_ [private] |
Definition at line 80 of file ChartConfig.h.