Wt examples  4.0.0
ChartConfig.C
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008 Emweb bvba, Kessel-Lo, Belgium.
3  *
4  * See the LICENSE file for terms of use.
5  */
6 
7 #include "ChartConfig.h"
8 #include "PanelList.h"
9 
10 #include <iostream>
11 
12 #include <Wt/WAbstractItemModel.h>
13 #include <Wt/WApplication.h>
14 #include <Wt/WCheckBox.h>
15 #include <Wt/WComboBox.h>
16 #include <Wt/WDoubleValidator.h>
17 #include <Wt/WDate.h>
18 #include <Wt/WEnvironment.h>
19 #include <Wt/WIntValidator.h>
20 #include <Wt/WLineEdit.h>
21 #include <Wt/WLocale.h>
22 #include <Wt/WPanel.h>
23 #include <Wt/WPushButton.h>
24 #include <Wt/WStandardItemModel.h>
25 #include <Wt/WTable.h>
26 #include <Wt/WText.h>
27 #include <Wt/WPainterPath.h>
28 
29 #include <Wt/Chart/WCartesianChart.h>
30 
31 using namespace Wt;
32 using namespace Wt::Chart;
33 
34 namespace {
35  void addHeader(WTable *t, const char *value) {
36  t->elementAt(0, t->columnCount())->addWidget(cpp14::make_unique<WText>(value));
37  }
38 
39  void addEntry(std::shared_ptr<WAbstractItemModel> model, const char *value) {
40  model->insertRows(model->rowCount(), 1);
41  model->setData(model->rowCount()-1, 0, cpp17::any(std::string(value)));
42  }
43 
44  bool getDouble(WLineEdit *edit, double& value) {
45  try {
46  value = WLocale::currentLocale().toDouble(edit->text());
47  return true;
48  } catch (...) {
49  return false;
50  }
51  }
52 
53  int seriesIndexOf(WCartesianChart* chart, int modelColumn) {
54  for (unsigned i = 0; i < chart->series().size(); ++i)
55  if (chart->series()[i]->modelColumn() == modelColumn)
56  return i;
57 
58  return -1;
59  }
60 }
61 
63  : WContainerWidget(),
64  chart_(chart),
66 {
68  WBrush(WColor(0xFF, 0xFA, 0xE5)));
69 
70  PanelList *list = this->addWidget(cpp14::make_unique<PanelList>());
71 
72  std::shared_ptr<WIntValidator> sizeValidator
73  = std::make_shared<WIntValidator>(200,2000);
74  sizeValidator->setMandatory(true);
75 
76  std::shared_ptr<WDoubleValidator> anyNumberValidator
77  = std::make_shared<WDoubleValidator>();
78  anyNumberValidator->setMandatory(true);
79 
80  std::shared_ptr<WDoubleValidator> angleValidator
81  = std::make_shared<WDoubleValidator>(-90,90);
82  angleValidator->setMandatory(true);
83 
84  // ---- Chart properties ----
85 
86  std::shared_ptr<WStandardItemModel> orientation
87  = std::make_shared<WStandardItemModel>(0,1);
88  addEntry(orientation, "Vertical");
89  addEntry(orientation, "Horizontal");
90 
91  std::shared_ptr<WStandardItemModel> legendLocation
92  = std::make_shared<WStandardItemModel>(0,1);
93  addEntry(legendLocation, "Outside");
94  addEntry(legendLocation, "Inside");
95 
96  std::shared_ptr<WStandardItemModel> legendSide
97  = std::make_shared<WStandardItemModel>(0,1);
98  addEntry(legendSide, "Top");
99  addEntry(legendSide, "Right");
100  addEntry(legendSide, "Bottom");
101  addEntry(legendSide, "Left");
102 
103  std::shared_ptr<WStandardItemModel> legendAlignment
104  = std::make_shared<WStandardItemModel>(0,1);
105  addEntry(legendAlignment, "AlignLeft");
106  addEntry(legendAlignment, "AlignCenter");
107  addEntry(legendAlignment, "AlignRight");
108  addEntry(legendAlignment, "AlignTop");
109  addEntry(legendAlignment, "AlignMiddle");
110  addEntry(legendAlignment, "AlignBottom");
111 
112  std::unique_ptr<WTable> chartConfig
113  = cpp14::make_unique<WTable>();
114  chartConfig->setMargin(WLength::Auto, Side::Left | Side::Right);
115 
116  int row = 0;
117  chartConfig->elementAt(row, 0)->addWidget(cpp14::make_unique<WText>("Title:"));
118  titleEdit_ = chartConfig->elementAt(row,1)->addWidget(cpp14::make_unique<WLineEdit>());
120  ++row;
121 
122  chartConfig->elementAt(row, 0)->addWidget(cpp14::make_unique<WText>("Width:"));
123  chartWidthEdit_ = chartConfig->elementAt(row,1)->addWidget(cpp14::make_unique<WLineEdit>());
125  ->setText(WLocale::currentLocale().toString(chart_->width().value()));
126  chartWidthEdit_->setValidator(sizeValidator);
129  ++row;
130 
131  chartConfig->elementAt(row, 0)->addWidget(cpp14::make_unique<WText>("Height:"));
132  chartHeightEdit_ = chartConfig->elementAt(row,1)->addWidget(cpp14::make_unique<WLineEdit>());
134  ->setText(WLocale::currentLocale().toString(chart_->height().value()));
135  chartHeightEdit_->setValidator(sizeValidator);
138  ++row;
139 
140  chartConfig->elementAt(row, 0)->addWidget(cpp14::make_unique<WText>("Orientation:"));
141  chartOrientationEdit_ = chartConfig->elementAt(row,1)->addWidget(cpp14::make_unique<WComboBox>());
142  chartOrientationEdit_->setModel(orientation);
145  ++row;
146 
147  chartConfig->elementAt(row, 0)->addWidget(cpp14::make_unique<WText>("Legend location:"));
148  legendLocationEdit_ = chartConfig->elementAt(row,1)->addWidget(cpp14::make_unique<WComboBox>());
149  legendLocationEdit_->setModel(legendLocation);
152  ++row;
153 
154  chartConfig->elementAt(row, 0)->addWidget(cpp14::make_unique<WText>("Legend side:"));
155  legendSideEdit_ = chartConfig->elementAt(row,1)->addWidget(cpp14::make_unique<WComboBox>());
156  legendSideEdit_->setModel(legendSide);
159  ++row;
160 
161  chartConfig->elementAt(row, 0)->addWidget(cpp14::make_unique<WText>("Legend alignment:"));
162  legendAlignmentEdit_ = chartConfig->elementAt(row,1)->addWidget(cpp14::make_unique<WComboBox>());
163  legendAlignmentEdit_->setModel(legendAlignment);
166  ++row;
167 
168  chartConfig->elementAt(row, 0)->addWidget(cpp14::make_unique<WText>("Border:"));
169  borderEdit_ = chartConfig->elementAt(row,1)->addWidget(cpp14::make_unique<WCheckBox>());
170  borderEdit_->setChecked(false);
172  ++row;
173 
174  for (int i = 0; i < chartConfig->rowCount(); ++i) {
175  chartConfig->elementAt(i, 0)->setStyleClass("tdhead");
176  chartConfig->elementAt(i, 1)->setStyleClass("tddata");
177  }
178 
179  WPanel *p = list->addWidget("Chart properties", std::move(chartConfig));
180  p->setMargin(WLength::Auto, Side::Left | Side::Right);
181  p->resize(1080, WLength::Auto);
182  p->setMargin(20, Side::Top | Side::Bottom);
183 
184  // ---- Series properties ----
185 
186  std::shared_ptr<WStandardItemModel> types
187  = std::make_shared<WStandardItemModel>(0,1);
188  addEntry(types, "Points");
189  addEntry(types, "Line");
190  addEntry(types, "Curve");
191  addEntry(types, "Bar");
192  addEntry(types, "Line Area");
193  addEntry(types, "Curve Area");
194  addEntry(types, "Stacked Bar");
195  addEntry(types, "Stacked Line Area");
196  addEntry(types, "Stacked Curve Area");
197 
198  std::shared_ptr<WStandardItemModel> markers
199  = std::make_shared<WStandardItemModel>(0,1);
200  addEntry(markers, "None");
201  addEntry(markers, "Square");
202  addEntry(markers, "Circle");
203  addEntry(markers, "Cross");
204  addEntry(markers, "X cross");
205  addEntry(markers, "Triangle");
206  addEntry(markers, "Pipe");
207  addEntry(markers, "Star");
208  addEntry(markers, "Inverted triangle");
209  addEntry(markers, "Asterisk");
210  addEntry(markers, "Diamond");
211 
212  std::shared_ptr<WStandardItemModel> axes
213  = std::make_shared<WStandardItemModel>(0,1);
214  addEntry(axes, "1st Y axis");
215  addEntry(axes, "2nd Y axis");
216 
217  std::shared_ptr<WStandardItemModel> labels
218  = std::make_shared<WStandardItemModel>(0,1);
219  addEntry(labels, "None");
220  addEntry(labels, "X");
221  addEntry(labels, "Y");
222  addEntry(labels, "X: Y");
223 
224  std::unique_ptr<WTable> seriesConfig
225  = cpp14::make_unique<WTable>();
226  WTable *seriesConfigPtr = seriesConfig.get();
227  seriesConfig->setMargin(WLength::Auto, Side::Left | Side::Right);
228  ::addHeader(seriesConfigPtr, "Name");
229  ::addHeader(seriesConfigPtr, "Enabled");
230  ::addHeader(seriesConfigPtr, "Type");
231  ::addHeader(seriesConfigPtr, "Marker");
232  ::addHeader(seriesConfigPtr, "Y axis");
233  ::addHeader(seriesConfigPtr, "Legend");
234  ::addHeader(seriesConfigPtr, "Shadow");
235  ::addHeader(seriesConfigPtr, "Value labels");
236 
237  seriesConfig->rowAt(0)->setStyleClass("trhead");
238 
239  for (int j = 1; j < chart->model()->columnCount(); ++j) {
240  SeriesControl sc;
241 
242  seriesConfig->elementAt(j,0)->addWidget(cpp14::make_unique<WText>(chart->model()->headerData(j)));
243 
244  sc.enabledEdit = seriesConfig->elementAt(j,1)->addWidget(cpp14::make_unique<WCheckBox>());
246 
247  sc.typeEdit = seriesConfig->elementAt(j,2)->addWidget(cpp14::make_unique<WComboBox>());
248  sc.typeEdit->setModel(types);
249  sc.typeEdit->setCurrentIndex(0);
251 
252  sc.markerEdit = seriesConfig->elementAt(j,3)->addWidget(cpp14::make_unique<WComboBox>());
253  sc.markerEdit->setModel(markers);
256 
257  sc.axisEdit = seriesConfig->elementAt(j,4)->addWidget(cpp14::make_unique<WComboBox>());
258  sc.axisEdit->setModel(axes);
259  sc.axisEdit->setCurrentIndex(0);
261 
262  sc.legendEdit = seriesConfig->elementAt(j, 5)->addWidget(cpp14::make_unique<WCheckBox>());
264 
265  sc.shadowEdit = seriesConfig->elementAt(j,6)->addWidget(cpp14::make_unique<WCheckBox>());
267 
268  sc.labelsEdit = seriesConfig->elementAt(j,7)->addWidget(cpp14::make_unique<WComboBox>());
269  sc.labelsEdit->setModel(labels);
272 
273  int si = seriesIndexOf(chart, j);
274 
275  if (si != -1) {
276  sc.enabledEdit->setChecked();
277  const WDataSeries& s = chart_->series(j);
278  switch (s.type()) {
279  case SeriesType::Point:
280  sc.typeEdit->setCurrentIndex(0); break;
281  case SeriesType::Line:
283  (s.isStacked() ? 7 : 4) : 1); break;
284  case SeriesType::Curve:
286  (s.isStacked() ? 8 : 5) : 2); break;
287  case SeriesType::Bar:
288  sc.typeEdit->setCurrentIndex(s.isStacked() ? 6 : 3);
289  }
290 
291  sc.markerEdit->setCurrentIndex((int)s.marker());
293  sc.shadowEdit->setChecked(s.shadow() != WShadow());
294  }
295 
296  seriesControls_.push_back(sc);
297 
298  seriesConfig->rowAt(j)->setStyleClass("trdata");
299  }
300 
301  p = list->addWidget("Series properties", std::move(seriesConfig));
302  p->expand();
303  p->setMargin(WLength::Auto, Side::Left | Side::Right);
304  p->resize(1080, WLength::Auto);
305  p->setMargin(20, Side::Top | Side::Bottom);
306 
307  // ---- Axis properties ----
308 
309  std::shared_ptr<WStandardItemModel> yScales
310  = std::make_shared<WStandardItemModel>(0,1);
311  addEntry(yScales, "Linear scale");
312  addEntry(yScales, "Log scale");
313 
314  std::shared_ptr<WStandardItemModel> xScales
315  = std::make_shared<WStandardItemModel>(0,1);
316  addEntry(xScales, "Categories");
317  addEntry(xScales, "Linear scale");
318  addEntry(xScales, "Log scale");
319  addEntry(xScales, "Date scale");
320 
321  std::unique_ptr<WTable> axisConfig
322  = cpp14::make_unique<WTable>();
323  axisConfig->setMargin(WLength::Auto, Side::Left | Side::Right);
324  WTable *axisConfigPtr = axisConfig.get();
325 
326  ::addHeader(axisConfigPtr, "Axis");
327  ::addHeader(axisConfigPtr, "Visible");
328  ::addHeader(axisConfigPtr, "Scale");
329  ::addHeader(axisConfigPtr, "Automatic");
330  ::addHeader(axisConfigPtr, "Minimum");
331  ::addHeader(axisConfigPtr, "Maximum");
332  ::addHeader(axisConfigPtr, "Gridlines");
333  ::addHeader(axisConfigPtr, "Label angle");
334  ::addHeader(axisConfigPtr, "Title");
335  ::addHeader(axisConfigPtr, "Title orientation");
336  ::addHeader(axisConfigPtr, "Tick direction");
337  ::addHeader(axisConfigPtr, "Location");
338 
339  axisConfig->rowAt(0)->setStyleClass("trhead");
340 
341  for (int i = 0; i < 3; ++i) {
342  const char *axisName[] = { "X axis", "1st Y axis", "2nd Y axis" };
343  int j = i + 1;
344 
345  const WAxis& axis = chart_->axis(static_cast<Axis>(i));
346  AxisControl sc;
347 
348  axisConfig->elementAt(j,0)->addWidget(cpp14::make_unique<WText>(WString(axisName[i], CharEncoding::UTF8)));
349 
350  sc.visibleEdit = axisConfig->elementAt(j,1)->addWidget(cpp14::make_unique<WCheckBox>());
351  sc.visibleEdit->setChecked(axis.isVisible());
353 
354  sc.scaleEdit = axisConfig->elementAt(j,2)->addWidget(cpp14::make_unique<WComboBox>());
355  if (axis.scale() == AxisScale::Discrete)
356  sc.scaleEdit->addItem("Discrete scale");
357  else {
358  if (axis.id() == Axis::X) {
359  sc.scaleEdit->setModel(xScales);
360 
361  sc.scaleEdit->setCurrentIndex(static_cast<int>(axis.scale()));
362  } else {
363  sc.scaleEdit->setModel(yScales);
364  sc.scaleEdit->setCurrentIndex(static_cast<int>(axis.scale()) - 1);
365  }
366  }
368 
369  bool autoValues = axis.autoLimits() == (AxisValue::Minimum | AxisValue::Maximum);
370 
371  sc.minimumEdit = axisConfig->elementAt(j,4)->addWidget(cpp14::make_unique<WLineEdit>());
372  sc.minimumEdit->setText(WLocale::currentLocale()
373  .toString(axis.minimum()));
374  sc.minimumEdit->setValidator(anyNumberValidator);
375  sc.minimumEdit->setEnabled(!autoValues);
377 
378  sc.maximumEdit = axisConfig->elementAt(j,5)->addWidget(cpp14::make_unique<WLineEdit>());
379  sc.maximumEdit->setText(WLocale::currentLocale()
380  .toString(axis.maximum()));
381  sc.maximumEdit->setValidator(anyNumberValidator);
382  sc.maximumEdit->setEnabled(!autoValues);
384 
385  sc.autoEdit = axisConfig->elementAt(j,3)->addWidget(cpp14::make_unique<WCheckBox>());
386  sc.autoEdit->setChecked(autoValues);
388  sc.autoEdit->checked().connect(sc.maximumEdit, &WLineEdit::disable);
389  sc.autoEdit->unChecked().connect(sc.maximumEdit, &WLineEdit::enable);
390  sc.autoEdit->checked().connect(sc.minimumEdit, &WLineEdit::disable);
391  sc.autoEdit->unChecked().connect(sc.minimumEdit, &WLineEdit::enable);
392 
393  sc.gridLinesEdit = axisConfig->elementAt(j,6)->addWidget(cpp14::make_unique<WCheckBox>());
395 
396  sc.labelAngleEdit = axisConfig->elementAt(j,7)->addWidget(cpp14::make_unique<WLineEdit>());
397  sc.labelAngleEdit->setText("0");
398  sc.labelAngleEdit->setValidator(angleValidator);
400 
401  sc.titleEdit = axisConfig->elementAt(j,8)->addWidget(cpp14::make_unique<WLineEdit>());
402  sc.titleEdit->setText("");
404 
405  sc.titleOrientationEdit = axisConfig->elementAt(j,9)->addWidget(cpp14::make_unique<WComboBox>());
406  sc.titleOrientationEdit->addItem("Horizontal");
407  sc.titleOrientationEdit->addItem("Vertical");
410 
411  sc.tickDirectionEdit = axisConfig->elementAt(j,10)->addWidget(cpp14::make_unique<WComboBox>());
412  sc.tickDirectionEdit->addItem("Outwards");
413  sc.tickDirectionEdit->addItem("Inwards");
416 
417  sc.locationEdit = axisConfig->elementAt(j,11)->addWidget(cpp14::make_unique<WComboBox>());
418  sc.locationEdit->addItem("Minimum value");
419  sc.locationEdit->addItem("Maximum value");
420  sc.locationEdit->addItem("Zero value");
421  sc.locationEdit->addItem("Both sides");
423  if (axis.location() == AxisValue::Zero) {
425  }
427 
428  axisConfig->rowAt(j)->setStyleClass("trdata");
429 
430  axisControls_.push_back(sc);
431  }
432 
433  p = list->addWidget("Axis properties", std::move(axisConfig));
434  p->setMargin(WLength::Auto, Side::Left | Side::Right);
435  p->resize(1080, WLength::Auto);
436  p->setMargin(20, Side::Top | Side::Bottom);
437 
438  /*
439  * If we do not have JavaScript, then add a button to reflect changes to
440  * the chart.
441  */
442  if (!WApplication::instance()->environment().javaScript()) {
443  auto *b = this->addWidget(cpp14::make_unique<WPushButton>());
444  b->setText("Update chart");
445  b->setInline(false); // so we can add margin to center horizontally
446  b->setMargin(WLength::Auto, Side::Left | Side::Right);
447  b->clicked().connect(this, &ChartConfig::update);
448  }
449 }
450 
452 {
453  fill_ = fill;
454 }
455 
457 {
458  bool haveLegend = false;
459  std::vector<std::unique_ptr<WDataSeries>> series;
460 
461  for (int i = 1; i < chart_->model()->columnCount(); ++i) {
462  SeriesControl& sc = seriesControls_[i-1];
463 
464  if (sc.enabledEdit->isChecked()) {
465  std::unique_ptr<WDataSeries> s
466  = cpp14::make_unique<WDataSeries>(i);
467 
468  switch (sc.typeEdit->currentIndex()) {
469  case 0:
470  s->setType(SeriesType::Point);
471  if (sc.markerEdit->currentIndex() == 0)
473  break;
474  case 1:
475  s->setType(SeriesType::Line);
476  break;
477  case 2:
478  s->setType(SeriesType::Curve);
479  break;
480  case 3:
481  s->setType(SeriesType::Bar);
482  break;
483  case 4:
484  s->setType(SeriesType::Line);
485  s->setFillRange(fill_);
486  break;
487  case 5:
488  s->setType(SeriesType::Curve);
489  s->setFillRange(fill_);
490  break;
491  case 6:
492  s->setType(SeriesType::Bar);
493  s->setStacked(true);
494  break;
495  case 7:
496  s->setType(SeriesType::Line);
497  s->setFillRange(fill_);
498  s->setStacked(true);
499  break;
500  case 8:
501  s->setType(SeriesType::Curve);
502  s->setFillRange(fill_);
503  s->setStacked(true);
504  }
505 
506  //set WPainterPath to draw a pipe
507  if(sc.markerEdit->currentIndex() == static_cast<int>(MarkerType::Custom)){ //was customMarker before
508  WPainterPath pp = WPainterPath();
509  pp.moveTo(0, -6);
510  pp.lineTo(0, 6);
511  s->setCustomMarker(pp);
512  }
513 
514  s->setMarker(static_cast<MarkerType>(sc.markerEdit->currentIndex()));
515 
516  if (sc.axisEdit->currentIndex() == 1) {
517  s->bindToAxis(Axis::Y2);
518  }
519 
520  if (sc.legendEdit->isChecked()) {
521  s->setLegendEnabled(true);
522  haveLegend = true;
523  } else
524  s->setLegendEnabled(false);
525 
526  if (sc.shadowEdit->isChecked()) {
527  s->setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
528  } else
529  s->setShadow(WShadow());
530 
531  switch (sc.labelsEdit->currentIndex()) {
532  case 1:
533  s->setLabelsEnabled(Axis::X);
534  break;
535  case 2:
536  s->setLabelsEnabled(Axis::Y);
537  break;
538  case 3:
539  s->setLabelsEnabled(Axis::X);
540  s->setLabelsEnabled(Axis::Y);
541  break;
542  }
543 
544  series.push_back(std::move(s));
545  }
546  }
547 
548  chart_->setSeries(std::move(series));
549 
550  for (int i = 0; i < 3; ++i) {
551  AxisControl& sc = axisControls_[i];
552  WAxis& axis = chart_->axis(static_cast<Axis>(i));
553 
554  axis.setVisible(sc.visibleEdit->isChecked());
555 
556  if (sc.scaleEdit->count() != 1) {
557  int k = sc.scaleEdit->currentIndex();
558  if (axis.id() != Axis::X)
559  k += 1;
560  else {
561  if (k == 0)
563  else
565  }
566 
567  switch (k) {
568  case 1:
569  axis.setScale(AxisScale::Linear); break;
570  case 2:
571  axis.setScale(AxisScale::Log); break;
572  case 3:
573  axis.setScale(AxisScale::Date); break;
574  }
575  }
576 
577  if (sc.autoEdit->isChecked())
579  else {
580  if (!(axis.autoLimits() & (AxisValue::Minimum | AxisValue::Maximum)).empty()) {
581  sc.minimumEdit->setText(WLocale::currentLocale()
582  .toString(axis.minimum()));
583  sc.maximumEdit->setText(WLocale::currentLocale()
584  .toString(axis.maximum()));
585  }
586  if (validate(sc.minimumEdit) && validate(sc.maximumEdit)) {
587  double min, max;
588  getDouble(sc.minimumEdit, min);
589  getDouble(sc.maximumEdit, max);
590 
591  if (axis.scale() == AxisScale::Log)
592  if (min <= 0)
593  min = 0.0001;
594 
595  if (axis.scale() == AxisScale::Date){
596  //the number of julian days until year 1986
597  WDate dMin = WDate(1900,1,1);
598  double gregDaysMin = (double)dMin.toJulianDay();
599  //the number of julian days until year 1988
600  WDate dMax = WDate(3000,1,1);
601  double gregDaysMax = (double)dMax.toJulianDay();
602 
603  bool greg_year_validation =
604  (min > gregDaysMin &&
605  min < gregDaysMax &&
606  max > gregDaysMin &&
607  max < gregDaysMax);
608 
609  if(!greg_year_validation){
610  min = gregDaysMin;
611  max = gregDaysMax;
612  }
613  }
614 
615  axis.setRange(min, max);
616  }
617 
618  }
619 
620  if (validate(sc.labelAngleEdit)) {
621  double angle;
622  getDouble(sc.labelAngleEdit, angle);
623  axis.setLabelAngle(angle);
624  }
625 
627 
628  axis.setTitle(sc.titleEdit->text());
629 
630  axis.setTitleOrientation(sc.titleOrientationEdit->currentIndex() == 0 ? Orientation::Horizontal : Orientation::Vertical);
631 
632  axis.setTickDirection(sc.tickDirectionEdit->currentIndex() == 0 ? TickDirection::Outwards : TickDirection::Inwards);
633 
634  switch (sc.locationEdit->currentIndex()) {
635  case 0:
637  break;
638  case 1:
640  break;
641  case 2:
643  break;
644  case 3:
646  break;
647  }
648  }
649 
651 
653  double width, height;
654  getDouble(chartWidthEdit_, width);
655  getDouble(chartHeightEdit_, height);
656  chart_->resize(width, height);
657  }
658 
659  switch (chartOrientationEdit_->currentIndex()) {
660  case 0:
661  chart_->setOrientation(Orientation::Vertical); break;
662  case 1:
663  chart_->setOrientation(Orientation::Horizontal); break;
664  }
665 
666  chart_->setLegendEnabled(haveLegend);
667 
668  if (haveLegend) {
670  Side side = Side::Right;
671  AlignmentFlag alignment = AlignmentFlag::Middle;
672  switch (legendLocationEdit_->currentIndex()) {
673  case 0: location = LegendLocation::Outside; break;
674  case 1: location = LegendLocation::Inside; break;
675  }
676 
677  switch (legendSideEdit_->currentIndex()) {
678  case 0: side = Side::Top; break;
679  case 1: side = Side::Right; break;
680  case 2: side = Side::Bottom; break;
681  case 3: side = Side::Left; break;
682  }
683 
684  if (side == Side::Left || side == Side::Right) {
687  } else {
690  }
691 
692  switch (legendAlignmentEdit_->currentIndex()) {
693  case 0: alignment = AlignmentFlag::Left; break;
694  case 1: alignment = AlignmentFlag::Center; break;
695  case 2: alignment = AlignmentFlag::Right; break;
696  case 3: alignment = AlignmentFlag::Top; break;
697  case 4: alignment = AlignmentFlag::Middle; break;
698  case 5: alignment = AlignmentFlag::Bottom; break;
699  }
700 
701  chart_->setLegendLocation(location, side, alignment);
702 
703  chart_->setLegendColumns((side == Side::Top || side == Side::Bottom ) ? 2 : 1,
704  WLength(100));
705  }
706 
707  if (borderEdit_->isChecked()) {
709  } else {
710  chart_->setBorderPen(PenStyle::None);
711  }
712 }
713 
715 {
716  bool valid = w->validate() == ValidationState::Valid;
717 
718  if (!WApplication::instance()->environment().javaScript()) {
719  w->setStyleClass(valid ? "" : "Wt-invalid");
720  w->setToolTip(valid ? "" : "Invalid value");
721  }
722 
723  return valid;
724 }
725 
727 {
728  w->changed().connect(this, &ChartConfig::update);
729  if (dynamic_cast<WLineEdit *>(w))
731 }
void setVisible(bool visible)
void expand()
ChartConfig(Wt::Chart::WCartesianChart *chart)
Constructor.
Definition: ChartConfig.C:62
Wt::WCheckBox * borderEdit_
Definition: ChartConfig.h:89
virtual void setStyleClass(const WString &styleClass) override
void lineTo(const WPointF &point)
MarkerType marker() const
virtual void setText(const WString &text)
Wt::WComboBox * axisEdit
Definition: ChartConfig.h:55
bool isLegendEnabled() const
Wt::Chart::FillRangeType fill_
Definition: ChartConfig.h:48
Wt::WComboBox * scaleEdit
Definition: ChartConfig.h:67
Wt::WLineEdit * titleEdit_
Definition: ChartConfig.h:82
void setGridLinesEnabled(bool enabled)
Wt::Chart::WCartesianChart * chart_
Definition: ChartConfig.h:47
void addItem(const WString &text)
void setTickDirection(TickDirection direction)
void connectSignals(Wt::WFormWidget *w)
Definition: ChartConfig.C:726
double minimum() const
void setLocation(AxisValue value)
const WString & text() const
AxisScale scale() const
int count() const
WAxis & axis(Axis axis)
void setLegendStyle(const WFont &font, const WPen &border, const WBrush &background)
int currentIndex() const
Wt::WCheckBox * enabledEdit
Definition: ChartConfig.h:52
Wt::WComboBox * locationEdit
Definition: ChartConfig.h:76
void setType(ChartType type)
Struct that holds the controls for one series.
Definition: ChartConfig.h:51
Wt::WLineEdit * titleEdit
Definition: ChartConfig.h:73
AxisValue location() const
void setSeries(std::vector< std::unique_ptr< WDataSeries >> series)
AlignmentFlag
void setLegendLocation(LegendLocation location, Side side, AlignmentFlag alignment)
Wt::WComboBox * typeEdit
Definition: ChartConfig.h:53
int modelColumn() const
int toJulianDay() const
void setModel(const std::shared_ptr< WAbstractItemModel > model)
virtual WLength height() const override
Wt::Signals::connection connect(const F &function)
Wt::WCheckBox * visibleEdit
Definition: ChartConfig.h:66
bool isStacked() const
Wt::WComboBox * markerEdit
Definition: ChartConfig.h:54
virtual void setMargin(const WLength &margin, WFlags< Side > sides=AllSides) override
Wt::WLineEdit * chartWidthEdit_
Definition: ChartConfig.h:83
Struct that holds the controls for one axis.
Definition: ChartConfig.h:65
WTableCell * elementAt(int row, int column)
Wt::WPanel * addWidget(const Wt::WString &text, std::unique_ptr< Wt::WWidget > w)
Definition: PanelList.C:17
Wt::WComboBox * chartOrientationEdit_
Definition: ChartConfig.h:85
void setValidator(const std::shared_ptr< WValidator > &validator)
virtual WLength width() const override
Wt::WComboBox * legendLocationEdit_
Definition: ChartConfig.h:86
std::vector< SeriesControl > seriesControls_
Controls for series.
Definition: ChartConfig.h:62
void setCurrentIndex(int index)
Axis id() const
virtual void resize(const WLength &width, const WLength &height) override
void setScale(AxisScale scale)
WDataSeries & series(int modelColumn)
WFlags< AxisValue > autoLimits() const
Wt::WLineEdit * minimumEdit
Definition: ChartConfig.h:69
std::shared_ptr< WAbstractChartModel > model() const
void setMaxLength(int length)
void setTitleOrientation(const Orientation &orientation)
FillRangeType fillRange() const
void setEnabled(bool enabled)
void setAutoLimits(WFlags< AxisValue > locations)
Wt::WComboBox * legendSideEdit_
Definition: ChartConfig.h:87
std::vector< AxisControl > axisControls_
Controls for axes.
Definition: ChartConfig.h:80
void update()
Definition: ChartConfig.C:456
Wt::WCheckBox * shadowEdit
Definition: ChartConfig.h:57
Wt::WComboBox * labelsEdit
Definition: ChartConfig.h:58
bool isVisible() const
void setValueFill(Wt::Chart::FillRangeType fill)
Definition: ChartConfig.C:451
Wt::WComboBox * tickDirectionEdit
Definition: ChartConfig.h:75
Wt::WLineEdit * labelAngleEdit
Definition: ChartConfig.h:72
double value() const
void moveTo(const WPointF &point)
EventSignal & unChecked()
void setOrientation(Orientation orientation)
double maximum() const
void setBorderPen(const WPen &pen)
Wt::WCheckBox * legendEdit
Definition: ChartConfig.h:56
void setRange(double minimum, double maximum)
EventSignal & enterPressed()
EventSignal & changed()
virtual void resize(const WLength &width, const WLength &height) override
Wt::WCheckBox * gridLinesEdit
Definition: ChartConfig.h:71
void setLegendEnabled(bool enabled)
static const WLocale & currentLocale()
Wt::WComboBox * titleOrientationEdit
Definition: ChartConfig.h:74
virtual void setMargin(const WLength &margin, WFlags< Side > sides=AllSides) override
Wt::WComboBox * legendAlignmentEdit_
Definition: ChartConfig.h:88
int columnCount() const
Wt::WCheckBox * autoEdit
Definition: ChartConfig.h:68
void setChecked(bool checked)
Wt::WLineEdit * maximumEdit
Definition: ChartConfig.h:70
virtual void setToolTip(const WString &text, TextFormat textFormat=TextFormat::Plain) override
void setTitle(const WString &title)
void setLabelAngle(double angle)
virtual void addWidget(std::unique_ptr< WWidget > widget)
void setLegendColumns(int columns, const WLength &width)
static bool validate(Wt::WFormWidget *w)
Definition: ChartConfig.C:714
Wt::WLineEdit * chartHeightEdit_
Definition: ChartConfig.h:84
double toDouble(const WString &value) const
EventSignal & checked()
void setTitle(const WString &title)
const WShadow & shadow() const
virtual ValidationState validate()
SeriesType type() const

Generated on Mon Sep 4 2017 for the C++ Web Toolkit (Wt) by doxygen 1.8.11