Wt examples 3.1.10
|
00001 /* 00002 * Copyright (C) 2008 Emweb bvba, Kessel-Lo, Belgium. 00003 * 00004 * See the LICENSE file for terms of use. 00005 */ 00006 00007 #include "ChartConfig.h" 00008 #include "PanelList.h" 00009 00010 #include <iostream> 00011 #include <boost/lexical_cast.hpp> 00012 00013 #include <Wt/WAbstractItemModel> 00014 #include <Wt/WApplication> 00015 #include <Wt/WCheckBox> 00016 #include <Wt/WComboBox> 00017 #include <Wt/WDoubleValidator> 00018 #include <Wt/WEnvironment> 00019 #include <Wt/WIntValidator> 00020 #include <Wt/WLineEdit> 00021 #include <Wt/WPanel> 00022 #include <Wt/WPushButton> 00023 #include <Wt/WStandardItemModel> 00024 #include <Wt/WTable> 00025 #include <Wt/WText> 00026 00027 #include <Wt/Chart/WCartesianChart> 00028 00029 using namespace Wt; 00030 using namespace Wt::Chart; 00031 00032 namespace { 00033 void addHeader(WTable *t, const char *value) { 00034 t->elementAt(0, t->columnCount())->addWidget(new WText(value)); 00035 } 00036 00037 void addEntry(WAbstractItemModel *model, const char *value) { 00038 model->insertRows(model->rowCount(), 1); 00039 model->setData(model->rowCount()-1, 0, boost::any(std::string(value))); 00040 } 00041 00042 bool getDouble(WLineEdit *edit, double& value) { 00043 try { 00044 value = boost::lexical_cast<double>(edit->text().toUTF8()); 00045 return true; 00046 } catch (...) { 00047 return false; 00048 } 00049 } 00050 00051 int seriesIndexOf(WCartesianChart* chart, int modelColumn) { 00052 for (unsigned i = 0; i < chart->series().size(); ++i) 00053 if (chart->series()[i].modelColumn() == modelColumn) 00054 return i; 00055 00056 return -1; 00057 } 00058 } 00059 00060 ChartConfig::ChartConfig(WCartesianChart *chart, WContainerWidget *parent) 00061 : WContainerWidget(parent), 00062 chart_(chart), 00063 fill_(MinimumValueFill) 00064 { 00065 chart_->setLegendStyle(chart_->legendFont(), WPen(black), 00066 WBrush(WColor(0xFF, 0xFA, 0xE5))); 00067 chart->initLayout(); 00068 00069 PanelList *list = new PanelList(this); 00070 00071 WIntValidator *sizeValidator = new WIntValidator(200, 2000, this); 00072 sizeValidator->setMandatory(true); 00073 00074 WDoubleValidator *anyNumberValidator = new WDoubleValidator(this); 00075 anyNumberValidator->setMandatory(true); 00076 00077 WDoubleValidator *angleValidator = new WDoubleValidator(-90, 90, this); 00078 angleValidator->setMandatory(true); 00079 00080 // ---- Chart properties ---- 00081 00082 WStandardItemModel *orientation = new WStandardItemModel(0, 1, this); 00083 addEntry(orientation, "Vertical"); 00084 addEntry(orientation, "Horizontal"); 00085 00086 WStandardItemModel *legendLocation = new WStandardItemModel(0, 1, this); 00087 addEntry(legendLocation, "Outside"); 00088 addEntry(legendLocation, "Inside"); 00089 00090 WStandardItemModel *legendSide = new WStandardItemModel(0, 1, this); 00091 addEntry(legendSide, "Top"); 00092 addEntry(legendSide, "Right"); 00093 addEntry(legendSide, "Bottom"); 00094 addEntry(legendSide, "Left"); 00095 00096 WStandardItemModel *legendAlignment = new WStandardItemModel(0, 1, this); 00097 addEntry(legendAlignment, "AlignLeft"); 00098 addEntry(legendAlignment, "AlignCenter"); 00099 addEntry(legendAlignment, "AlignRight"); 00100 addEntry(legendAlignment, "AlignTop"); 00101 addEntry(legendAlignment, "AlignMiddle"); 00102 addEntry(legendAlignment, "AlignBottom"); 00103 00104 WTable *chartConfig = new WTable(); 00105 chartConfig->setMargin(WLength::Auto, Left | Right); 00106 00107 int row = 0; 00108 chartConfig->elementAt(row, 0)->addWidget(new WText("Title:")); 00109 titleEdit_ = new WLineEdit(chartConfig->elementAt(row, 1)); 00110 connectSignals(titleEdit_); 00111 ++row; 00112 00113 chartConfig->elementAt(row, 0)->addWidget(new WText("Width:")); 00114 chartWidthEdit_ = new WLineEdit(chartConfig->elementAt(row, 1)); 00115 chartWidthEdit_ 00116 ->setText(boost::lexical_cast<std::string>(chart_->width().value())); 00117 chartWidthEdit_->setValidator(sizeValidator); 00118 chartWidthEdit_->setMaxLength(4); 00119 connectSignals(chartWidthEdit_); 00120 ++row; 00121 00122 chartConfig->elementAt(row, 0)->addWidget(new WText("Height:")); 00123 chartHeightEdit_ = new WLineEdit(chartConfig->elementAt(row, 1)); 00124 chartHeightEdit_ 00125 ->setText(boost::lexical_cast<std::string>(chart_->height().value())); 00126 chartHeightEdit_->setValidator(sizeValidator); 00127 chartHeightEdit_->setMaxLength(4); 00128 connectSignals(chartHeightEdit_); 00129 ++row; 00130 00131 chartConfig->elementAt(row, 0)->addWidget(new WText("Orientation:")); 00132 chartOrientationEdit_ = new WComboBox(chartConfig->elementAt(row, 1)); 00133 chartOrientationEdit_->setModel(orientation); 00134 connectSignals(chartOrientationEdit_); 00135 ++row; 00136 00137 chartConfig->elementAt(row, 0)->addWidget(new WText("Legend location:")); 00138 legendLocationEdit_ = new WComboBox(chartConfig->elementAt(row, 1)); 00139 legendLocationEdit_->setModel(legendLocation); 00140 connectSignals(legendLocationEdit_); 00141 ++row; 00142 00143 chartConfig->elementAt(row, 0)->addWidget(new WText("Legend side:")); 00144 legendSideEdit_ = new WComboBox(chartConfig->elementAt(row, 1)); 00145 legendSideEdit_->setModel(legendSide); 00146 legendSideEdit_->setCurrentIndex(1); 00147 connectSignals(legendSideEdit_); 00148 ++row; 00149 00150 chartConfig->elementAt(row, 0)->addWidget(new WText("Legend alignment:")); 00151 legendAlignmentEdit_ = new WComboBox(chartConfig->elementAt(row, 1)); 00152 legendAlignmentEdit_->setModel(legendAlignment); 00153 legendAlignmentEdit_->setCurrentIndex(4); 00154 connectSignals(legendAlignmentEdit_); 00155 ++row; 00156 00157 for (int i = 0; i < chartConfig->rowCount(); ++i) { 00158 chartConfig->elementAt(i, 0)->setStyleClass("tdhead"); 00159 chartConfig->elementAt(i, 1)->setStyleClass("tddata"); 00160 } 00161 00162 WPanel *p = list->addWidget("Chart properties", chartConfig); 00163 p->setMargin(WLength::Auto, Left | Right); 00164 p->resize(750, WLength::Auto); 00165 p->setMargin(20, Top | Bottom); 00166 00167 if (chart_->isLegendEnabled()) 00168 chart_->setPlotAreaPadding(200, Right); 00169 00170 // ---- Series properties ---- 00171 00172 WStandardItemModel *types = new WStandardItemModel(0, 1, this); 00173 addEntry(types, "Points"); 00174 addEntry(types, "Line"); 00175 addEntry(types, "Curve"); 00176 addEntry(types, "Bar"); 00177 addEntry(types, "Line Area"); 00178 addEntry(types, "Curve Area"); 00179 addEntry(types, "Stacked Bar"); 00180 addEntry(types, "Stacked Line Area"); 00181 addEntry(types, "Stacked Curve Area"); 00182 00183 WStandardItemModel *markers = new WStandardItemModel(0, 1, this); 00184 addEntry(markers, "None"); 00185 addEntry(markers, "Square"); 00186 addEntry(markers, "Circle"); 00187 addEntry(markers, "Cross"); 00188 addEntry(markers, "X cross"); 00189 addEntry(markers, "Triangle"); 00190 00191 WStandardItemModel *axes = new WStandardItemModel(0, 1, this); 00192 addEntry(axes, "1st Y axis"); 00193 addEntry(axes, "2nd Y axis"); 00194 00195 WStandardItemModel *labels = new WStandardItemModel(0, 1, this); 00196 addEntry(labels, "None"); 00197 addEntry(labels, "X"); 00198 addEntry(labels, "Y"); 00199 addEntry(labels, "X: Y"); 00200 00201 WTable *seriesConfig = new WTable(); 00202 seriesConfig->setMargin(WLength::Auto, Left | Right); 00203 00204 ::addHeader(seriesConfig, "Name"); 00205 ::addHeader(seriesConfig, "Enabled"); 00206 ::addHeader(seriesConfig, "Type"); 00207 ::addHeader(seriesConfig, "Marker"); 00208 ::addHeader(seriesConfig, "Y axis"); 00209 ::addHeader(seriesConfig, "Legend"); 00210 ::addHeader(seriesConfig, "Shadow"); 00211 ::addHeader(seriesConfig, "Value labels"); 00212 00213 seriesConfig->rowAt(0)->setStyleClass("trhead"); 00214 00215 for (int j = 1; j < chart->model()->columnCount(); ++j) { 00216 SeriesControl sc; 00217 00218 new WText(asString(chart->model()->headerData(j)), 00219 seriesConfig->elementAt(j, 0)); 00220 00221 sc.enabledEdit = new WCheckBox(seriesConfig->elementAt(j, 1)); 00222 connectSignals(sc.enabledEdit); 00223 00224 sc.typeEdit = new WComboBox(seriesConfig->elementAt(j, 2)); 00225 sc.typeEdit->setModel(types); 00226 connectSignals(sc.typeEdit); 00227 00228 sc.markerEdit = new WComboBox(seriesConfig->elementAt(j, 3)); 00229 sc.markerEdit->setModel(markers); 00230 connectSignals(sc.markerEdit); 00231 00232 sc.axisEdit = new WComboBox(seriesConfig->elementAt(j, 4)); 00233 sc.axisEdit->setModel(axes); 00234 connectSignals(sc.axisEdit); 00235 00236 sc.legendEdit = new WCheckBox(seriesConfig->elementAt(j, 5)); 00237 connectSignals(sc.legendEdit); 00238 00239 sc.shadowEdit = new WCheckBox(seriesConfig->elementAt(j, 6)); 00240 connectSignals(sc.shadowEdit); 00241 00242 sc.labelsEdit = new WComboBox(seriesConfig->elementAt(j, 7)); 00243 sc.labelsEdit->setModel(labels); 00244 connectSignals(sc.labelsEdit); 00245 00246 int si = seriesIndexOf(chart, j); 00247 00248 if (si != -1) { 00249 sc.enabledEdit->setChecked(); 00250 const WDataSeries& s = chart_->series(j); 00251 switch (s.type()) { 00252 case PointSeries: 00253 sc.typeEdit->setCurrentIndex(0); break; 00254 case LineSeries: 00255 sc.typeEdit->setCurrentIndex(s.fillRange() != NoFill ? 00256 (s.isStacked() ? 7 : 4) : 1); break; 00257 case CurveSeries: 00258 sc.typeEdit->setCurrentIndex(s.fillRange() != NoFill ? 00259 (s.isStacked() ? 8 : 5) : 2); break; 00260 case BarSeries: 00261 sc.typeEdit->setCurrentIndex(s.isStacked() ? 6 : 3); 00262 } 00263 00264 sc.markerEdit->setCurrentIndex((int)s.marker()); 00265 sc.legendEdit->setChecked(s.isLegendEnabled()); 00266 sc.shadowEdit->setChecked(s.shadow() != WShadow()); 00267 } 00268 00269 seriesControls_.push_back(sc); 00270 00271 seriesConfig->rowAt(j)->setStyleClass("trdata"); 00272 } 00273 00274 p = list->addWidget("Series properties", seriesConfig); 00275 p->expand(); 00276 p->setMargin(WLength::Auto, Left | Right); 00277 p->resize(750, WLength::Auto); 00278 p->setMargin(20, Top | Bottom); 00279 00280 // ---- Axis properties ---- 00281 00282 WStandardItemModel *yScales = new WStandardItemModel(0, 1, this); 00283 addEntry(yScales, "Linear scale"); 00284 addEntry(yScales, "Log scale"); 00285 00286 WStandardItemModel *xScales = new WStandardItemModel(0, 1, this); 00287 addEntry(xScales, "Categories"); 00288 addEntry(xScales, "Linear scale"); 00289 addEntry(xScales, "Log scale"); 00290 addEntry(xScales, "Date scale"); 00291 00292 WTable *axisConfig = new WTable(); 00293 axisConfig->setMargin(WLength::Auto, Left | Right); 00294 00295 ::addHeader(axisConfig, "Axis"); 00296 ::addHeader(axisConfig, "Visible"); 00297 ::addHeader(axisConfig, "Scale"); 00298 ::addHeader(axisConfig, "Automatic"); 00299 ::addHeader(axisConfig, "Minimum"); 00300 ::addHeader(axisConfig, "Maximum"); 00301 ::addHeader(axisConfig, "Gridlines"); 00302 ::addHeader(axisConfig, "Label angle"); 00303 00304 axisConfig->rowAt(0)->setStyleClass("trhead"); 00305 00306 for (int i = 0; i < 3; ++i) { 00307 const char *axisName[] = { "X axis", "1st Y axis", "2nd Y axis" }; 00308 int j = i + 1; 00309 00310 const WAxis& axis = chart_->axis(static_cast<Axis>(i)); 00311 AxisControl sc; 00312 00313 new WText(WString(axisName[i], UTF8), axisConfig->elementAt(j, 0)); 00314 00315 sc.visibleEdit = new WCheckBox(axisConfig->elementAt(j, 1)); 00316 sc.visibleEdit->setChecked(axis.isVisible()); 00317 connectSignals(sc.visibleEdit); 00318 00319 sc.scaleEdit = new WComboBox(axisConfig->elementAt(j, 2)); 00320 if (axis.scale() == CategoryScale) 00321 sc.scaleEdit->addItem("Category scale"); 00322 else { 00323 if (axis.id() == XAxis) { 00324 sc.scaleEdit->setModel(xScales); 00325 sc.scaleEdit->setCurrentIndex(axis.scale()); 00326 } else { 00327 sc.scaleEdit->setModel(yScales); 00328 sc.scaleEdit->setCurrentIndex(axis.scale() - 1); 00329 } 00330 } 00331 connectSignals(sc.scaleEdit); 00332 00333 bool autoValues = axis.autoLimits() == (MinimumValue | MaximumValue); 00334 00335 sc.minimumEdit = new WLineEdit(axisConfig->elementAt(j, 4)); 00336 sc.minimumEdit->setText(boost::lexical_cast<std::string>(axis.minimum())); 00337 sc.minimumEdit->setValidator(anyNumberValidator); 00338 sc.minimumEdit->setEnabled(!autoValues); 00339 connectSignals(sc.minimumEdit); 00340 00341 sc.maximumEdit = new WLineEdit(axisConfig->elementAt(j, 5)); 00342 sc.maximumEdit->setText(boost::lexical_cast<std::string>(axis.maximum())); 00343 sc.maximumEdit->setValidator(anyNumberValidator); 00344 sc.maximumEdit->setEnabled(!autoValues); 00345 connectSignals(sc.maximumEdit); 00346 00347 sc.autoEdit = new WCheckBox(axisConfig->elementAt(j, 3)); 00348 sc.autoEdit->setChecked(autoValues); 00349 connectSignals(sc.autoEdit); 00350 sc.autoEdit->checked().connect(sc.maximumEdit, &WLineEdit::disable); 00351 sc.autoEdit->unChecked().connect(sc.maximumEdit, &WLineEdit::enable); 00352 sc.autoEdit->checked().connect(sc.minimumEdit, &WLineEdit::disable); 00353 sc.autoEdit->unChecked().connect(sc.minimumEdit, &WLineEdit::enable); 00354 00355 sc.gridLinesEdit = new WCheckBox(axisConfig->elementAt(j, 6)); 00356 connectSignals(sc.gridLinesEdit); 00357 00358 sc.labelAngleEdit = new WLineEdit(axisConfig->elementAt(j, 7)); 00359 sc.labelAngleEdit->setText("0"); 00360 sc.labelAngleEdit->setValidator(angleValidator); 00361 connectSignals(sc.labelAngleEdit); 00362 00363 axisConfig->rowAt(j)->setStyleClass("trdata"); 00364 00365 axisControls_.push_back(sc); 00366 } 00367 00368 p = list->addWidget("Axis properties", axisConfig); 00369 p->setMargin(WLength::Auto, Left | Right); 00370 p->resize(750, WLength::Auto); 00371 p->setMargin(20, Top | Bottom); 00372 00373 /* 00374 * If we do not have JavaScript, then add a button to reflect changes to 00375 * the chart. 00376 */ 00377 if (!WApplication::instance()->environment().javaScript()) { 00378 WPushButton *b = new WPushButton(this); 00379 b->setText("Update chart"); 00380 b->setInline(false); // so we can add margin to center horizontally 00381 b->setMargin(WLength::Auto, Left | Right); 00382 b->clicked().connect(this, &ChartConfig::update); 00383 } 00384 } 00385 00386 void ChartConfig::setValueFill(FillRangeType fill) 00387 { 00388 fill_ = fill; 00389 } 00390 00391 void ChartConfig::update() 00392 { 00393 bool haveLegend = false; 00394 std::vector<WDataSeries> series; 00395 00396 for (int i = 1; i < chart_->model()->columnCount(); ++i) { 00397 SeriesControl& sc = seriesControls_[i-1]; 00398 00399 if (sc.enabledEdit->isChecked()) { 00400 WDataSeries s(i); 00401 00402 switch (sc.typeEdit->currentIndex()) { 00403 case 0: 00404 s.setType(PointSeries); 00405 if (sc.markerEdit->currentIndex() == 0) 00406 sc.markerEdit->setCurrentIndex(1); 00407 break; 00408 case 1: 00409 s.setType(LineSeries); 00410 sc.markerEdit->setCurrentIndex(0); 00411 break; 00412 case 2: 00413 s.setType(CurveSeries); 00414 sc.markerEdit->setCurrentIndex(0); 00415 break; 00416 case 3: 00417 s.setType(BarSeries); 00418 sc.markerEdit->setCurrentIndex(0); 00419 break; 00420 case 4: 00421 s.setType(LineSeries); 00422 s.setFillRange(fill_); 00423 sc.markerEdit->setCurrentIndex(0); 00424 break; 00425 case 5: 00426 s.setType(CurveSeries); 00427 s.setFillRange(fill_); 00428 sc.markerEdit->setCurrentIndex(0); 00429 break; 00430 case 6: 00431 s.setType(BarSeries); 00432 s.setStacked(true); 00433 sc.markerEdit->setCurrentIndex(0); 00434 break; 00435 case 7: 00436 s.setType(LineSeries); 00437 s.setFillRange(fill_); 00438 s.setStacked(true); 00439 sc.markerEdit->setCurrentIndex(0); 00440 break; 00441 case 8: 00442 s.setType(CurveSeries); 00443 s.setFillRange(fill_); 00444 s.setStacked(true); 00445 sc.markerEdit->setCurrentIndex(0); 00446 } 00447 00448 s.setMarker(static_cast<MarkerType>(sc.markerEdit->currentIndex())); 00449 00450 if (sc.axisEdit->currentIndex() == 1) { 00451 s.bindToAxis(Y2Axis); 00452 } 00453 00454 if (sc.legendEdit->isChecked()) { 00455 s.setLegendEnabled(true); 00456 haveLegend = true; 00457 } else 00458 s.setLegendEnabled(false); 00459 00460 if (sc.shadowEdit->isChecked()) { 00461 s.setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3)); 00462 } else 00463 s.setShadow(WShadow()); 00464 00465 switch (sc.labelsEdit->currentIndex()) { 00466 case 1: 00467 s.setLabelsEnabled(XAxis); 00468 break; 00469 case 2: 00470 s.setLabelsEnabled(YAxis); 00471 break; 00472 case 3: 00473 s.setLabelsEnabled(XAxis); 00474 s.setLabelsEnabled(YAxis); 00475 break; 00476 } 00477 00478 series.push_back(s); 00479 } 00480 } 00481 00482 chart_->setSeries(series); 00483 00484 for (int i = 0; i < 3; ++i) { 00485 AxisControl& sc = axisControls_[i]; 00486 WAxis& axis = chart_->axis(static_cast<Axis>(i)); 00487 00488 axis.setVisible(sc.visibleEdit->isChecked()); 00489 00490 if (sc.scaleEdit->count() != 1) { 00491 int k = sc.scaleEdit->currentIndex(); 00492 if (axis.id() != XAxis) 00493 k += 1; 00494 else { 00495 if (k == 0) 00496 chart_->setType(CategoryChart); 00497 else 00498 chart_->setType(ScatterPlot); 00499 } 00500 00501 switch (k) { 00502 case 1: 00503 axis.setScale(LinearScale); break; 00504 case 2: 00505 axis.setScale(LogScale); break; 00506 case 3: 00507 axis.setScale(DateScale); break; 00508 } 00509 } 00510 00511 if (sc.autoEdit->isChecked()) 00512 axis.setAutoLimits(MinimumValue | MaximumValue); 00513 else { 00514 if (validate(sc.minimumEdit) && validate(sc.maximumEdit)) { 00515 double min, max; 00516 getDouble(sc.minimumEdit, min); 00517 getDouble(sc.maximumEdit, max); 00518 00519 if (axis.scale() == LogScale) 00520 if (min <= 0) 00521 min = 0.0001; 00522 00523 axis.setRange(min, max); 00524 } 00525 00526 } 00527 00528 if (validate(sc.labelAngleEdit)) { 00529 double angle; 00530 getDouble(sc.labelAngleEdit, angle); 00531 axis.setLabelAngle(angle); 00532 } 00533 00534 axis.setGridLinesEnabled(sc.gridLinesEdit->isChecked()); 00535 } 00536 00537 chart_->setTitle(titleEdit_->text()); 00538 00539 if (validate(chartWidthEdit_) && validate(chartHeightEdit_)) { 00540 double width, height; 00541 getDouble(chartWidthEdit_, width); 00542 getDouble(chartHeightEdit_, height); 00543 chart_->resize(width, height); 00544 } 00545 00546 switch (chartOrientationEdit_->currentIndex()) { 00547 case 0: 00548 chart_->setOrientation(Vertical); break; 00549 case 1: 00550 chart_->setOrientation(Horizontal); break; 00551 } 00552 00553 chart_->setLegendEnabled(haveLegend); 00554 00555 if (haveLegend) { 00556 LegendLocation location = LegendOutside; 00557 Side side = Right; 00558 AlignmentFlag alignment = AlignMiddle; 00559 00560 switch (legendLocationEdit_->currentIndex()) { 00561 case 0: location = LegendOutside; break; 00562 case 1: location = LegendInside; break; 00563 } 00564 00565 switch (legendSideEdit_->currentIndex()) { 00566 case 0: side = Top; break; 00567 case 1: side = Right; break; 00568 case 2: side = Bottom; break; 00569 case 3: side = Left; break; 00570 } 00571 00572 if (side == Left || side == Right) { 00573 if (legendAlignmentEdit_->currentIndex() < 3) 00574 legendAlignmentEdit_->setCurrentIndex(4); 00575 } else { 00576 if (legendAlignmentEdit_->currentIndex() >= 3) 00577 legendAlignmentEdit_->setCurrentIndex(2); 00578 } 00579 00580 switch (legendAlignmentEdit_->currentIndex()) { 00581 case 0: alignment = AlignLeft; break; 00582 case 1: alignment = AlignCenter; break; 00583 case 2: alignment = AlignRight; break; 00584 case 3: alignment = AlignTop; break; 00585 case 4: alignment = AlignMiddle; break; 00586 case 5: alignment = AlignBottom; break; 00587 } 00588 00589 chart_->setLegendLocation(location, side, alignment); 00590 00591 chart_->setLegendColumns((side == Top || side == Bottom ) ? 2 : 1, 00592 WLength(100)); 00593 } 00594 00595 for (unsigned i = 0; i < 4; ++i) { 00596 Side sides[] = { Top, Right, Bottom, Left }; 00597 00598 bool legendRoom = 00599 haveLegend 00600 && chart_->legendLocation() == LegendOutside 00601 && chart_->legendSide() == sides[i]; 00602 00603 int padding; 00604 00605 if (i % 2 == 0) 00606 padding = legendRoom ? 80 : 40; 00607 else 00608 padding = legendRoom ? 200 : 80; 00609 00610 chart_->setPlotAreaPadding(padding, sides[i]); 00611 } 00612 } 00613 00614 bool ChartConfig::validate(WFormWidget *w) 00615 { 00616 bool valid = w->validate() == WValidator::Valid; 00617 00618 if (!WApplication::instance()->environment().javaScript()) { 00619 w->setStyleClass(valid ? "" : "Wt-invalid"); 00620 w->setToolTip(valid ? "" : "Invalid value"); 00621 } 00622 00623 return valid; 00624 } 00625 00626 void ChartConfig::connectSignals(WFormWidget *w) 00627 { 00628 w->changed().connect(this, &ChartConfig::update); 00629 if (dynamic_cast<WLineEdit *>(w)) 00630 w->enterPressed().connect(this, &ChartConfig::update); 00631 }