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