Wt examples  3.7.1
ChartConfig.C
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008 Emweb bv, Herent, 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 #include <boost/date_time/gregorian/greg_year.hpp>
12 
13 #include <Wt/WAbstractItemModel>
14 #include <Wt/WApplication>
15 #include <Wt/WCheckBox>
16 #include <Wt/WComboBox>
17 #include <Wt/WDoubleValidator>
18 #include <Wt/WDate>
19 #include <Wt/WEnvironment>
20 #include <Wt/WIntValidator>
21 #include <Wt/WLineEdit>
22 #include <Wt/WLocale>
23 #include <Wt/WPanel>
24 #include <Wt/WPushButton>
25 #include <Wt/WStandardItemModel>
26 #include <Wt/WTable>
27 #include <Wt/WText>
28 #include <Wt/WPainterPath>
29 
30 #include <Wt/Chart/WCartesianChart>
31 
32 using namespace Wt;
33 using namespace Wt::Chart;
34 
35 namespace {
36  void addHeader(WTable *t, const char *value) {
37  t->elementAt(0, t->columnCount())->addWidget(new WText(value));
38  }
39 
40  void addEntry(WAbstractItemModel *model, const char *value) {
41  model->insertRows(model->rowCount(), 1);
42  model->setData(model->rowCount()-1, 0, boost::any(std::string(value)));
43  }
44 
45  void addEntry(WAbstractItemModel *model, const WString &value) {
46  model->insertRows(model->rowCount(), 1);
47  model->setData(model->rowCount()-1, 0, boost::any(value));
48  }
49 
50  bool getDouble(WLineEdit *edit, double& value) {
51  try {
52  value = WLocale::currentLocale().toDouble(edit->text());
53  return true;
54  } catch (...) {
55  return false;
56  }
57  }
58 
59  int seriesIndexOf(WCartesianChart* chart, int modelColumn) {
60  for (unsigned i = 0; i < chart->series().size(); ++i)
61  if (chart->series()[i]->modelColumn() == modelColumn)
62  return i;
63 
64  return -1;
65  }
66 
67  WString axisName(Axis axis, int axisId)
68  {
69  if (axis == XAxis)
70  return Wt::utf8("X Axis {1}").arg(axisId + 1);
71  else {
72  return Wt::utf8("Y axis {1}").arg(axisId + 1);
73  }
74  }
75 }
76 
78  : WContainerWidget(parent),
79  chart_(chart),
80  fill_(MinimumValueFill)
81 {
83  WBrush(WColor(0xFF, 0xFA, 0xE5)));
84 
85  PanelList *list = new PanelList(this);
86 
87  WIntValidator *sizeValidator = new WIntValidator(200, 2000, this);
88  sizeValidator->setMandatory(true);
89 
92 
93  angleValidator_ = new WDoubleValidator(-90, 90, this);
95 
96  // ---- Chart properties ----
97 
98  WStandardItemModel *orientation = new WStandardItemModel(0, 1, this);
99  addEntry(orientation, "Vertical");
100  addEntry(orientation, "Horizontal");
101 
102  WStandardItemModel *legendLocation = new WStandardItemModel(0, 1, this);
103  addEntry(legendLocation, "Outside");
104  addEntry(legendLocation, "Inside");
105 
106  WStandardItemModel *legendSide = new WStandardItemModel(0, 1, this);
107  addEntry(legendSide, "Top");
108  addEntry(legendSide, "Right");
109  addEntry(legendSide, "Bottom");
110  addEntry(legendSide, "Left");
111 
112  WStandardItemModel *legendAlignment = new WStandardItemModel(0, 1, this);
113  addEntry(legendAlignment, "AlignLeft");
114  addEntry(legendAlignment, "AlignCenter");
115  addEntry(legendAlignment, "AlignRight");
116  addEntry(legendAlignment, "AlignTop");
117  addEntry(legendAlignment, "AlignMiddle");
118  addEntry(legendAlignment, "AlignBottom");
119 
120  WTable *chartConfig = new WTable();
121  chartConfig->setMargin(WLength::Auto, Left | Right);
122 
123  int row = 0;
124  chartConfig->elementAt(row, 0)->addWidget(new WText("Title:"));
125  titleEdit_ = new WLineEdit(chartConfig->elementAt(row, 1));
127  ++row;
128 
129  chartConfig->elementAt(row, 0)->addWidget(new WText("Width:"));
130  chartWidthEdit_ = new WLineEdit(chartConfig->elementAt(row, 1));
132  ->setText(WLocale::currentLocale().toString(chart_->width().value()));
133  chartWidthEdit_->setValidator(sizeValidator);
136  ++row;
137 
138  chartConfig->elementAt(row, 0)->addWidget(new WText("Height:"));
139  chartHeightEdit_ = new WLineEdit(chartConfig->elementAt(row, 1));
141  ->setText(WLocale::currentLocale().toString(chart_->height().value()));
142  chartHeightEdit_->setValidator(sizeValidator);
145  ++row;
146 
147  chartConfig->elementAt(row, 0)->addWidget(new WText("Orientation:"));
148  chartOrientationEdit_ = new WComboBox(chartConfig->elementAt(row, 1));
149  chartOrientationEdit_->setModel(orientation);
152  ++row;
153 
154  chartConfig->elementAt(row, 0)->addWidget(new WText("Legend location:"));
155  legendLocationEdit_ = new WComboBox(chartConfig->elementAt(row, 1));
156  legendLocationEdit_->setModel(legendLocation);
159  ++row;
160 
161  chartConfig->elementAt(row, 0)->addWidget(new WText("Legend side:"));
162  legendSideEdit_ = new WComboBox(chartConfig->elementAt(row, 1));
163  legendSideEdit_->setModel(legendSide);
166  ++row;
167 
168  chartConfig->elementAt(row, 0)->addWidget(new WText("Legend alignment:"));
169  legendAlignmentEdit_ = new WComboBox(chartConfig->elementAt(row, 1));
170  legendAlignmentEdit_->setModel(legendAlignment);
173  ++row;
174 
175  chartConfig->elementAt(row, 0)->addWidget(new WText("Border:"));
176  borderEdit_ = new WCheckBox(chartConfig->elementAt(row, 1));
177  borderEdit_->setChecked(false);
179  ++row;
180 
181  for (int i = 0; i < chartConfig->rowCount(); ++i) {
182  chartConfig->elementAt(i, 0)->setStyleClass("tdhead");
183  chartConfig->elementAt(i, 1)->setStyleClass("tddata");
184  }
185 
186  WPanel *p = list->addWidget("Chart properties", chartConfig);
187  p->setMargin(WLength::Auto, Left | Right);
188  p->resize(1160, WLength::Auto);
189  p->setMargin(20, Top | Bottom);
190 
191  // ---- Series properties ----
192 
193  WStandardItemModel *types = new WStandardItemModel(0, 1, this);
194  addEntry(types, "Points");
195  addEntry(types, "Line");
196  addEntry(types, "Curve");
197  addEntry(types, "Bar");
198  addEntry(types, "Line Area");
199  addEntry(types, "Curve Area");
200  addEntry(types, "Stacked Bar");
201  addEntry(types, "Stacked Line Area");
202  addEntry(types, "Stacked Curve Area");
203 
204  WStandardItemModel *markers = new WStandardItemModel(0, 1, this);
205  addEntry(markers, "None");
206  addEntry(markers, "Square");
207  addEntry(markers, "Circle");
208  addEntry(markers, "Cross");
209  addEntry(markers, "X cross");
210  addEntry(markers, "Triangle");
211  addEntry(markers, "Pipe");
212  addEntry(markers, "Star");
213  addEntry(markers, "Inverted triangle");
214  addEntry(markers, "Asterisk");
215  addEntry(markers, "Diamond");
216 
217  xAxesModel_ = new WStandardItemModel(0, 1, this);
218  addEntry(xAxesModel_, axisName(XAxis, 0));
219 
220  yAxesModel_ = new WStandardItemModel(0, 1, this);
221  addEntry(yAxesModel_, axisName(YAxis, 0));
222  addEntry(yAxesModel_, axisName(YAxis, 1));
223 
224  WStandardItemModel *labels = new WStandardItemModel(0, 1, this);
225  addEntry(labels, "None");
226  addEntry(labels, "X");
227  addEntry(labels, "Y");
228  addEntry(labels, "X: Y");
229 
230  WTable *seriesConfig = new WTable();
231  seriesConfig->setMargin(WLength::Auto, Left | Right);
232 
233  ::addHeader(seriesConfig, "Name");
234  ::addHeader(seriesConfig, "Enabled");
235  ::addHeader(seriesConfig, "Type");
236  ::addHeader(seriesConfig, "Marker");
237  ::addHeader(seriesConfig, "X axis");
238  ::addHeader(seriesConfig, "Y axis");
239  ::addHeader(seriesConfig, "Legend");
240  ::addHeader(seriesConfig, "Shadow");
241  ::addHeader(seriesConfig, "Value labels");
242 
243  seriesConfig->rowAt(0)->setStyleClass("trhead");
244 
245  for (int j = 1; j < chart->model()->columnCount(); ++j) {
246  SeriesControl sc;
247 
248  new WText(chart->model()->headerData(j),
249  seriesConfig->elementAt(j, 0));
250 
251  sc.enabledEdit = new WCheckBox(seriesConfig->elementAt(j, 1));
253 
254  sc.typeEdit = new WComboBox(seriesConfig->elementAt(j, 2));
255  sc.typeEdit->setModel(types);
256  sc.typeEdit->setCurrentIndex(0);
258 
259  sc.markerEdit = new WComboBox(seriesConfig->elementAt(j, 3));
260  sc.markerEdit->setModel(markers);
263 
264  sc.xAxisEdit = new WComboBox(seriesConfig->elementAt(j, 4));
266  sc.xAxisEdit->setCurrentIndex(0);
268 
269  sc.yAxisEdit = new WComboBox(seriesConfig->elementAt(j, 5));
271  sc.yAxisEdit->setCurrentIndex(0);
273 
274  sc.legendEdit = new WCheckBox(seriesConfig->elementAt(j, 6));
276 
277  sc.shadowEdit = new WCheckBox(seriesConfig->elementAt(j, 7));
279 
280  sc.labelsEdit = new WComboBox(seriesConfig->elementAt(j, 8));
281  sc.labelsEdit->setModel(labels);
284 
285  int si = seriesIndexOf(chart, j);
286 
287  if (si != -1) {
288  sc.enabledEdit->setChecked();
289  const WDataSeries& s = chart_->series(j);
290  switch (s.type()) {
291  case PointSeries:
292  sc.typeEdit->setCurrentIndex(0); break;
293  case LineSeries:
294  sc.typeEdit->setCurrentIndex(s.fillRange() != NoFill ?
295  (s.isStacked() ? 7 : 4) : 1); break;
296  case CurveSeries:
297  sc.typeEdit->setCurrentIndex(s.fillRange() != NoFill ?
298  (s.isStacked() ? 8 : 5) : 2); break;
299  case BarSeries:
300  sc.typeEdit->setCurrentIndex(s.isStacked() ? 6 : 3);
301  }
302 
303  sc.markerEdit->setCurrentIndex((int)s.marker());
305  sc.shadowEdit->setChecked(s.shadow() != WShadow());
306  }
307 
308  seriesControls_.push_back(sc);
309 
310  seriesConfig->rowAt(j)->setStyleClass("trdata");
311  }
312 
313  p = list->addWidget("Series properties", seriesConfig);
314  p->expand();
315  p->setMargin(WLength::Auto, Left | Right);
316  p->resize(1160, WLength::Auto);
317  p->setMargin(20, Top | Bottom);
318 
319  // ---- Axis properties ----
320 
321  yScales_ = new WStandardItemModel(0, 1, this);
322  addEntry(yScales_, "Linear scale");
323  addEntry(yScales_, "Log scale");
324 
325  xScales_ = new WStandardItemModel(0, 1, this);
326  addEntry(xScales_, "Categories");
327  addEntry(xScales_, "Linear scale");
328  addEntry(xScales_, "Log scale");
329  addEntry(xScales_, "Date scale");
330 
331  WContainerWidget *axisConfig = new WContainerWidget();
332  axisConfig_ = new WTable(axisConfig);
333  axisConfig_->setMargin(WLength::Auto, Left | Right);
334 
335  ::addHeader(axisConfig_, "Axis");
336  ::addHeader(axisConfig_, "Visible");
337  ::addHeader(axisConfig_, "Scale");
338  ::addHeader(axisConfig_, "Automatic");
339  ::addHeader(axisConfig_, "Minimum");
340  ::addHeader(axisConfig_, "Maximum");
341  ::addHeader(axisConfig_, "Gridlines");
342  ::addHeader(axisConfig_, "Label angle");
343  ::addHeader(axisConfig_, "Title");
344  ::addHeader(axisConfig_, "Title orientation");
345  ::addHeader(axisConfig_, "Tick direction");
346  ::addHeader(axisConfig_, "Location");
347 
348  axisConfig_->rowAt(0)->setStyleClass("trhead");
349 
350  addAxis(XAxis, 0);
351  addAxis(YAxis, 0);
352  addAxis(YAxis, 1);
353 
354  WPushButton *addXAxisBtn =
355  new WPushButton(Wt::utf8("Add X axis"), axisConfig);
356  addXAxisBtn->clicked().connect(this, &ChartConfig::addXAxis);
357  WPushButton *clearXAxesBtn =
358  new WPushButton(Wt::utf8("Clear X axes"), axisConfig);
359  clearXAxesBtn->clicked().connect(this, &ChartConfig::clearXAxes);
360  WPushButton *addYAxisBtn =
361  new WPushButton(Wt::utf8("Add Y axis"), axisConfig);
362  addYAxisBtn->clicked().connect(this, &ChartConfig::addYAxis);
363  WPushButton *clearYAxesBtn =
364  new WPushButton(Wt::utf8("Clear Y axes"), axisConfig);
365  clearYAxesBtn->clicked().connect(this, &ChartConfig::clearYAxes);
366 
367  p = list->addWidget("Axis properties", axisConfig);
368  p->setMargin(WLength::Auto, Left | Right);
369  p->resize(1160, WLength::Auto);
370  p->setMargin(20, Top | Bottom);
371 
372  /*
373  * If we do not have JavaScript, then add a button to reflect changes to
374  * the chart.
375  */
376  if (!WApplication::instance()->environment().javaScript()) {
377  WPushButton *b = new WPushButton(this);
378  b->setText("Update chart");
379  b->setInline(false); // so we can add margin to center horizontally
380  b->setMargin(WLength::Auto, Left | Right);
381  b->clicked().connect(this, &ChartConfig::update);
382  }
383 }
384 
386 {
387  fill_ = fill;
388 }
389 
391 {
392  bool haveLegend = false;
393  std::vector<WDataSeries *> series;
394 
395  for (int i = 1; i < chart_->model()->columnCount(); ++i) {
396  SeriesControl& sc = seriesControls_[i-1];
397 
398  if (sc.enabledEdit->isChecked()) {
399  WDataSeries *s = new WDataSeries(i);
400 
401  switch (sc.typeEdit->currentIndex()) {
402  case 0:
403  s->setType(PointSeries);
404  if (sc.markerEdit->currentIndex() == 0)
406  break;
407  case 1:
408  s->setType(LineSeries);
409  break;
410  case 2:
411  s->setType(CurveSeries);
412  break;
413  case 3:
414  s->setType(BarSeries);
415  break;
416  case 4:
417  s->setType(LineSeries);
418  s->setFillRange(fill_);
419  break;
420  case 5:
421  s->setType(CurveSeries);
422  s->setFillRange(fill_);
423  break;
424  case 6:
425  s->setType(BarSeries);
426  s->setStacked(true);
427  break;
428  case 7:
429  s->setType(LineSeries);
430  s->setFillRange(fill_);
431  s->setStacked(true);
432  break;
433  case 8:
434  s->setType(CurveSeries);
435  s->setFillRange(fill_);
436  s->setStacked(true);
437  }
438 
439  //set WPainterPath to draw a pipe
440  if(sc.markerEdit->currentIndex() == CustomMarker){
441  WPainterPath pp = WPainterPath();
442  pp.moveTo(0, -6);
443  pp.lineTo(0, 6);
444  s->setCustomMarker(pp);
445  }
446 
447  s->setMarker(static_cast<MarkerType>(sc.markerEdit->currentIndex()));
448 
451 
452  if (sc.legendEdit->isChecked()) {
453  s->setLegendEnabled(true);
454  haveLegend = true;
455  } else
456  s->setLegendEnabled(false);
457 
458  if (sc.shadowEdit->isChecked()) {
459  s->setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
460  } else
461  s->setShadow(WShadow());
462 
463  switch (sc.labelsEdit->currentIndex()) {
464  case 1:
465  s->setLabelsEnabled(XAxis);
466  break;
467  case 2:
468  s->setLabelsEnabled(YAxis);
469  break;
470  case 3:
471  s->setLabelsEnabled(XAxis);
472  s->setLabelsEnabled(YAxis);
473  break;
474  }
475 
476  series.push_back(s);
477  }
478  }
479 
480  chart_->setSeries(series);
481 
482  for (std::size_t i = 0; i < axisControls_.size(); ++i) {
483  AxisControl& sc = axisControls_[i];
484  WAxis& axis = static_cast<int>(i) < chart_->xAxisCount() ? chart_->xAxis(i) : chart_->yAxis(i - chart_->xAxisCount());
485 
486  axis.setVisible(sc.visibleEdit->isChecked());
487 
488  if (sc.scaleEdit->count() != 1) {
489  int k = sc.scaleEdit->currentIndex();
490  if (axis.id() != XAxis)
491  k += 1;
492  else {
493  if (k == 0)
494  chart_->setType(CategoryChart);
495  else
496  chart_->setType(ScatterPlot);
497  }
498 
499  switch (k) {
500  case 1:
501  axis.setScale(LinearScale); break;
502  case 2:
503  axis.setScale(LogScale); break;
504  case 3:
505  axis.setScale(DateScale); break;
506  }
507  }
508 
509  if (sc.autoEdit->isChecked())
511  else {
512  if (axis.autoLimits() & (MinimumValue | MaximumValue)) {
513  sc.minimumEdit->setText(WLocale::currentLocale()
514  .toString(axis.minimum()));
515  sc.maximumEdit->setText(WLocale::currentLocale()
516  .toString(axis.maximum()));
517  }
518  if (validate(sc.minimumEdit) && validate(sc.maximumEdit)) {
519  double min, max;
520  getDouble(sc.minimumEdit, min);
521  getDouble(sc.maximumEdit, max);
522 
523  if (axis.scale() == LogScale)
524  if (min <= 0)
525  min = 0.0001;
526 
527  if (axis.scale() == DateScale){
528  //the number of julian days until year 1986
529  WDate dMin = WDate(1900,1,1);
530  double gregDaysMin = (double)dMin.toJulianDay();
531  //the number of julian days until year 1988
532  WDate dMax = WDate(3000,1,1);
533  double gregDaysMax = (double)dMax.toJulianDay();
534 
535  bool greg_year_validation =
536  (min > gregDaysMin &&
537  min < gregDaysMax &&
538  max > gregDaysMin &&
539  max < gregDaysMax);
540 
541  if(!greg_year_validation){
542  min = gregDaysMin;
543  max = gregDaysMax;
544  }
545  }
546 
547  axis.setRange(min, max);
548  }
549 
550  }
551 
552  if (validate(sc.labelAngleEdit)) {
553  double angle;
554  getDouble(sc.labelAngleEdit, angle);
555  axis.setLabelAngle(angle);
556  }
557 
559 
560  axis.setTitle(sc.titleEdit->text());
561 
563 
565 
566  switch (sc.locationEdit->currentIndex()) {
567  case 0:
569  break;
570  case 1:
572  break;
573  case 2:
574  axis.setLocation(ZeroValue);
575  break;
576  case 3:
577  axis.setLocation(BothSides);
578  break;
579  }
580  }
581 
583 
585  double width, height;
586  getDouble(chartWidthEdit_, width);
587  getDouble(chartHeightEdit_, height);
588  chart_->resize(width, height);
589  }
590 
591  switch (chartOrientationEdit_->currentIndex()) {
592  case 0:
593  chart_->setOrientation(Vertical); break;
594  case 1:
596  }
597 
598  chart_->setLegendEnabled(haveLegend);
599 
600  if (haveLegend) {
601  LegendLocation location = LegendOutside;
602  Side side = Right;
603  AlignmentFlag alignment = AlignMiddle;
604  switch (legendLocationEdit_->currentIndex()) {
605  case 0: location = LegendOutside; break;
606  case 1: location = LegendInside; break;
607  }
608 
609  switch (legendSideEdit_->currentIndex()) {
610  case 0: side = Top; break;
611  case 1: side = Right; break;
612  case 2: side = Bottom; break;
613  case 3: side = Left; break;
614  }
615 
616  if (side == Left || side == Right) {
619  } else {
622  }
623 
624  switch (legendAlignmentEdit_->currentIndex()) {
625  case 0: alignment = AlignLeft; break;
626  case 1: alignment = AlignCenter; break;
627  case 2: alignment = AlignRight; break;
628  case 3: alignment = AlignTop; break;
629  case 4: alignment = AlignMiddle; break;
630  case 5: alignment = AlignBottom; break;
631  }
632 
633  chart_->setLegendLocation(location, side, alignment);
634 
635  chart_->setLegendColumns((side == Top || side == Bottom ) ? 2 : 1,
636  WLength(100));
637  }
638 
639  if (borderEdit_->isChecked()) {
641  } else {
642  chart_->setBorderPen(NoPen);
643  }
644 }
645 
647 {
648  bool valid = w->validate() == WValidator::Valid;
649 
650  if (!WApplication::instance()->environment().javaScript()) {
651  w->setStyleClass(valid ? "" : "Wt-invalid");
652  w->setToolTip(valid ? "" : "Invalid value");
653  }
654 
655  return valid;
656 }
657 
659 {
660  w->changed().connect(this, &ChartConfig::update);
661  if (dynamic_cast<WLineEdit *>(w))
663 }
664 
666 {
667  int xAxis = chart_->addXAxis(new WAxis());
668  addAxis(XAxis, xAxis);
669  addEntry(xAxesModel_, axisName(XAxis, xAxis));
670  if (xAxis == 0)
671  update();
672 }
673 
675 {
676  int yAxis = chart_->addYAxis(new WAxis());
677  addAxis(YAxis, yAxis);
678  addEntry(yAxesModel_, axisName(YAxis, yAxis));
679  if (yAxis == 0)
680  update();
681 }
682 
683 void ChartConfig::addAxis(Axis ax, int axisId)
684 {
685  int j = ax == XAxis ? 1 + axisId : 1 + chart_->xAxisCount() + axisId;
686 
687  const WAxis& axis = ax == XAxis ? chart_->xAxis(axisId) : chart_->yAxis(axisId);
688  AxisControl sc;
689 
691  new WText(axisName(axis.id(), ax == XAxis ? axis.xAxisId() : axis.yAxisId()), axisConfig_->elementAt(j, 0));
692 
693  sc.visibleEdit = new WCheckBox(axisConfig_->elementAt(j, 1));
694  sc.visibleEdit->setChecked(axis.isVisible());
696 
697  sc.scaleEdit = new WComboBox(axisConfig_->elementAt(j, 2));
698  if (axis.scale() == CategoryScale)
699  sc.scaleEdit->addItem("Category scale");
700  else {
701  if (axis.id() == XAxis) {
703  sc.scaleEdit->setCurrentIndex(axis.scale());
704  } else {
706  sc.scaleEdit->setCurrentIndex(axis.scale() - 1);
707  }
708  }
710 
711  bool autoValues = axis.autoLimits() == (MinimumValue | MaximumValue);
712 
713  sc.minimumEdit = new WLineEdit(axisConfig_->elementAt(j, 4));
714  sc.minimumEdit->setText(WLocale::currentLocale()
715  .toString(axis.minimum()));
717  sc.minimumEdit->setEnabled(!autoValues);
719 
720  sc.maximumEdit = new WLineEdit(axisConfig_->elementAt(j, 5));
721  sc.maximumEdit->setText(WLocale::currentLocale()
722  .toString(axis.maximum()));
724  sc.maximumEdit->setEnabled(!autoValues);
726 
727  sc.autoEdit = new WCheckBox(axisConfig_->elementAt(j, 3));
728  sc.autoEdit->setChecked(autoValues);
730  sc.autoEdit->checked().connect(sc.maximumEdit, &WLineEdit::disable);
731  sc.autoEdit->unChecked().connect(sc.maximumEdit, &WLineEdit::enable);
732  sc.autoEdit->checked().connect(sc.minimumEdit, &WLineEdit::disable);
733  sc.autoEdit->unChecked().connect(sc.minimumEdit, &WLineEdit::enable);
734 
735  sc.gridLinesEdit = new WCheckBox(axisConfig_->elementAt(j, 6));
737 
739  sc.labelAngleEdit->setText("0");
742 
743  sc.titleEdit = new WLineEdit(axisConfig_->elementAt(j, 8));
744  sc.titleEdit->setText("");
746 
748  sc.titleOrientationEdit->addItem("Horizontal");
749  sc.titleOrientationEdit->addItem("Vertical");
752 
754  sc.tickDirectionEdit->addItem("Outwards");
755  sc.tickDirectionEdit->addItem("Inwards");
758 
759  sc.locationEdit = new WComboBox(axisConfig_->elementAt(j, 11));
760  sc.locationEdit->addItem("Minimum value");
761  sc.locationEdit->addItem("Maximum value");
762  sc.locationEdit->addItem("Zero value");
763  sc.locationEdit->addItem("Both sides");
765  if (axis.location() == MaximumValue) {
767  } else if (axis.location() == ZeroValue) {
769  }
771 
772  WPushButton *removeAxisButton =
773  new WPushButton(Wt::utf8("x"), axisConfig_->elementAt(j, 12));
774  if (ax == XAxis) {
775  removeAxisButton->clicked().connect(boost::bind(&ChartConfig::removeXAxis, this, &axis));
776  } else {
777  removeAxisButton->clicked().connect(boost::bind(&ChartConfig::removeYAxis, this, &axis));
778  }
779 
780  axisConfig_->rowAt(j)->setStyleClass("trdata");
781 
782  axisControls_.insert(axisControls_.begin() + j - 1, sc);
783 }
784 
786 {
787  int xAxis = axis->xAxisId();
788  for (std::size_t i = 0; i < chart_->series().size(); ++i) {
789  if (chart_->series()[i]->xAxis() == xAxis)
790  chart_->series()[i]->bindToXAxis(-1);
791  }
792  chart_->removeXAxis(xAxis);
793  axisConfig_->deleteRow(1 + xAxis);
794  xAxesModel_->removeRow(xAxis);
795  axisControls_.erase(axisControls_.begin() + xAxis);
796  update();
797 }
798 
800 {
801  int yAxis = axis->yAxisId();
802  for (std::size_t i = 0; i < chart_->series().size(); ++i) {
803  if (chart_->series()[i]->yAxis() == yAxis)
804  chart_->series()[i]->bindToYAxis(-1);
805  }
806  chart_->removeYAxis(yAxis);
807  axisConfig_->deleteRow(1 + chart_->xAxisCount() + yAxis);
808  yAxesModel_->removeRow(yAxis);
809  axisControls_.erase(axisControls_.begin() + chart_->xAxisCount() + yAxis);
810  update();
811 }
812 
814 {
815  if (chart_->xAxisCount() == 0)
816  return;
817 
818  for (std::size_t i = 0; i < chart_->series().size(); ++i) {
819  chart_->series()[i]->bindToXAxis(-1);
820  }
821  const int xAxisCount = chart_->xAxisCount();
822  chart_->clearXAxes();
823  for (int i = 0; i < xAxisCount; ++i) {
824  axisConfig_->deleteRow(1);
825  }
826  xAxesModel_->clear();
827  axisControls_.erase(axisControls_.begin(), axisControls_.begin() + xAxisCount);
828 }
829 
831 {
832  if (chart_->yAxisCount() == 0)
833  return;
834 
835  for (std::size_t i = 0; i < chart_->series().size(); ++i) {
836  chart_->series()[i]->bindToYAxis(-1);
837  }
838  const int yAxisCount = chart_->yAxisCount();
839  chart_->clearYAxes();
840  for (int i = 0; i < yAxisCount; ++i) {
841  axisConfig_->deleteRow(axisConfig_->rowCount() - 1);
842  }
843  yAxesModel_->clear();
844  axisControls_.resize(chart_->xAxisCount());
845 }
void setVisible(bool visible)
void expand()
Wt::WCheckBox * borderEdit_
Definition: ChartConfig.h:93
virtual void setStyleClass(const WString &styleClass) override
void setType(SeriesType t)
MarkerType marker() const
int yAxisId() const
Wt::WComboBox * xAxisEdit
Definition: ChartConfig.h:58
void lineTo(const WPointF &point)
ChartConfig(Wt::Chart::WCartesianChart *chart, Wt::WContainerWidget *parent)
Constructor.
Definition: ChartConfig.C:77
virtual void setText(const WString &text)
Wt::WValidator * angleValidator_
Definition: ChartConfig.h:97
const WString & text() const
WString & arg(const std::wstring &value)
int toJulianDay() const
Wt::Chart::FillRangeType fill_
Definition: ChartConfig.h:51
void bindToXAxis(int xAxis)
Wt::WValidator * anyNumberValidator_
Definition: ChartConfig.h:97
EventSignal< WMouseEvent > & clicked()
Wt::WComboBox * scaleEdit
Definition: ChartConfig.h:71
Wt::WLineEdit * titleEdit_
Definition: ChartConfig.h:86
void removeXAxis(const Wt::Chart::WAxis *axis)
Definition: ChartConfig.C:785
void setGridLinesEnabled(bool enabled)
Wt::Chart::WCartesianChart * chart_
Definition: ChartConfig.h:50
void addItem(const WString &text)
FillRangeType fillRange() const
void setTickDirection(TickDirection direction)
Axis id() const
double minimum() const
Wt::WTable * axisConfig_
Definition: ChartConfig.h:96
void connectSignals(Wt::WFormWidget *w)
Definition: ChartConfig.C:658
void setLocation(AxisValue value)
virtual bool insertRows(int row, int count, const WModelIndex &parent=WModelIndex())
void setShadow(const WShadow &shadow)
void setLegendStyle(const WFont &font, const WPen &border, const WBrush &background)
Wt::WCheckBox * enabledEdit
Definition: ChartConfig.h:55
Wt::WStandardItemModel * xAxesModel_
Definition: ChartConfig.h:95
bool isVisible() const
Wt::WComboBox * locationEdit
Definition: ChartConfig.h:80
Wt::WStandardItemModel * xScales_
Definition: ChartConfig.h:95
void setType(ChartType type)
Struct that holds the controls for one series.
Definition: ChartConfig.h:54
std::unique_ptr< WAxis > removeXAxis(int xAxisId)
Wt::WLineEdit * titleEdit
Definition: ChartConfig.h:77
void setMarker(MarkerType marker)
AlignmentFlag
void setLegendLocation(LegendLocation location, Side side, AlignmentFlag alignment)
Wt::WComboBox * typeEdit
Definition: ChartConfig.h:56
virtual bool setData(const WModelIndex &index, const cpp17::any &value, ItemDataRole role=ItemDataRole::Edit)
void setModel(const std::shared_ptr< WAbstractItemModel > model)
virtual int rowCount(const WModelIndex &parent=WModelIndex()) const=0
bool isLegendEnabled() const
bool setText(const WString &text)
virtual WLength height() const override
int xAxisId() const
Wt::WCheckBox * visibleEdit
Definition: ChartConfig.h:70
void removeYAxis(const Wt::Chart::WAxis *axis)
Definition: ChartConfig.C:799
void setLegendEnabled(bool enabled)
Wt::WComboBox * markerEdit
Definition: ChartConfig.h:57
virtual void setMargin(const WLength &margin, WFlags< Side > sides=AllSides) override
Wt::WLineEdit * chartWidthEdit_
Definition: ChartConfig.h:87
Struct that holds the controls for one axis.
Definition: ChartConfig.h:69
WTableCell * elementAt(int row, int column)
WFlags< AxisValue > autoLimits() const
Wt::WPanel * addWidget(const Wt::WString &text, Wt::WWidget *w)
Definition: PanelList.C:17
Wt::WComboBox * chartOrientationEdit_
Definition: ChartConfig.h:89
void setValidator(const std::shared_ptr< WValidator > &validator)
virtual WLength width() const override
Wt::WComboBox * legendLocationEdit_
Definition: ChartConfig.h:90
std::vector< SeriesControl > seriesControls_
Controls for series.
Definition: ChartConfig.h:66
void setCurrentIndex(int index)
void setSeries(std::vector< std::unique_ptr< WDataSeries > > series)
virtual void resize(const WLength &width, const WLength &height) override
void setScale(AxisScale scale)
void addXAxis()
Definition: ChartConfig.C:665
void clearXAxes()
Definition: ChartConfig.C:813
void setStyleClass(const WString &style)
WDataSeries & series(int modelColumn)
Wt::WLineEdit * minimumEdit
Definition: ChartConfig.h:73
void setMaxLength(int length)
void setTitleOrientation(const Orientation &orientation)
void setCustomMarker(const WPainterPath &path)
void setEnabled(bool enabled)
void setAutoLimits(WFlags< AxisValue > locations)
Wt::WComboBox * legendSideEdit_
Definition: ChartConfig.h:91
std::vector< AxisControl > axisControls_
Controls for axes.
Definition: ChartConfig.h:84
void update()
Definition: ChartConfig.C:390
Wt::WCheckBox * shadowEdit
Definition: ChartConfig.h:61
Wt::WComboBox * labelsEdit
Definition: ChartConfig.h:62
Wt::WStandardItemModel * yAxesModel_
Definition: ChartConfig.h:95
Wt::WComboBox * yAxisEdit
Definition: ChartConfig.h:59
void setLabelsEnabled(Axis axis, bool enabled=true)
int rowCount() const
void setValueFill(Wt::Chart::FillRangeType fill)
Definition: ChartConfig.C:385
Wt::WComboBox * tickDirectionEdit
Definition: ChartConfig.h:79
Wt::WLineEdit * labelAngleEdit
Definition: ChartConfig.h:76
void moveTo(const WPointF &point)
std::shared_ptr< WAbstractChartModel > model() const
SeriesType type() const
EventSignal & unChecked()
bool removeRow(int row, const WModelIndex &parent=WModelIndex())
Wt::WStandardItemModel * yScales_
Definition: ChartConfig.h:95
void setStacked(bool stacked)
int addXAxis(std::unique_ptr< WAxis > waxis)
void setOrientation(Orientation orientation)
void setMandatory(bool how)
void setBorderPen(const WPen &pen)
double toDouble(const WString &value) const
int currentIndex() const
bool isStacked() const
Wt::WCheckBox * legendEdit
Definition: ChartConfig.h:60
void setRange(double minimum, double maximum)
EventSignal & enterPressed()
EventSignal & changed()
virtual void resize(const WLength &width, const WLength &height) override
double value() const
virtual WTableRow * insertRow(int row, std::unique_ptr< WTableRow > tableRow=nullptr)
Wt::WCheckBox * gridLinesEdit
Definition: ChartConfig.h:75
void setLegendEnabled(bool enabled)
static const WLocale & currentLocale()
Wt::WComboBox * titleOrientationEdit
Definition: ChartConfig.h:78
int columnCount() const
AxisScale scale() const
void addYAxis()
Definition: ChartConfig.C:674
virtual void setMargin(const WLength &margin, WFlags< Side > sides=AllSides) override
Wt::WComboBox * legendAlignmentEdit_
Definition: ChartConfig.h:92
AxisValue location() const
Wt::WCheckBox * autoEdit
Definition: ChartConfig.h:72
void setChecked(bool checked)
double maximum() const
Wt::Signals::connection connect(F function)
void clearYAxes()
Definition: ChartConfig.C:830
Wt::WLineEdit * maximumEdit
Definition: ChartConfig.h:74
int addYAxis(std::unique_ptr< WAxis > waxis)
int count() const
virtual void setToolTip(const WString &text, TextFormat textFormat=TextFormat::Plain) override
void setTitle(const WString &title)
WTableRow * rowAt(int row)
void setLabelAngle(double angle)
void setFillRange(FillRangeType fillRange)
virtual void addWidget(std::unique_ptr< WWidget > widget)
virtual void setInline(bool isInline) override
void setLegendColumns(int columns, const WLength &width)
const WShadow & shadow() const
static bool validate(Wt::WFormWidget *w)
Definition: ChartConfig.C:646
std::unique_ptr< WAxis > removeYAxis(int yAxisId)
Wt::WLineEdit * chartHeightEdit_
Definition: ChartConfig.h:88
EventSignal & checked()
void setTitle(const WString &title)
virtual ValidationState validate()
void bindToYAxis(int yAxis)
void addAxis(Wt::Chart::Axis axis, int axisId)
Definition: ChartConfig.C:683

Generated on Tue Dec 15 2020 for the C++ Web Toolkit (Wt) by doxygen 1.8.13