Wt examples  3.3.12
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 #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 yAxis)
68  {
69  if (axis == XAxis)
70  return Wt::utf8("X Axis");
71  else {
72  return Wt::utf8("Y axis {1}").arg(yAxis + 1);
73  }
74  }
75 }
76 
77 ChartConfig::ChartConfig(WCartesianChart *chart, WContainerWidget *parent)
78  : WContainerWidget(parent),
79  chart_(chart),
80  fill_(MinimumValueFill)
81 {
82  chart_->setLegendStyle(chart_->legendFont(), WPen(black),
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 
90  anyNumberValidator_ = new WDoubleValidator(this);
91  anyNumberValidator_->setMandatory(true);
92 
93  angleValidator_ = new WDoubleValidator(-90, 90, this);
94  angleValidator_->setMandatory(true);
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);
134  chartWidthEdit_->setMaxLength(4);
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);
143  chartHeightEdit_->setMaxLength(4);
145  ++row;
146 
147  chartConfig->elementAt(row, 0)->addWidget(new WText("Orientation:"));
148  chartOrientationEdit_ = new WComboBox(chartConfig->elementAt(row, 1));
149  chartOrientationEdit_->setModel(orientation);
150  chartOrientationEdit_->setCurrentIndex(0);
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);
157  legendLocationEdit_->setCurrentIndex(0);
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);
164  legendSideEdit_->setCurrentIndex(1);
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);
171  legendAlignmentEdit_->setCurrentIndex(4);
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  yAxesModel_ = new WStandardItemModel(0, 1, this);
218  addEntry(yAxesModel_, axisName(YAxis, 0));
219  addEntry(yAxesModel_, axisName(YAxis, 1));
220 
221  WStandardItemModel *labels = new WStandardItemModel(0, 1, this);
222  addEntry(labels, "None");
223  addEntry(labels, "X");
224  addEntry(labels, "Y");
225  addEntry(labels, "X: Y");
226 
227  WTable *seriesConfig = new WTable();
228  seriesConfig->setMargin(WLength::Auto, Left | Right);
229 
230  ::addHeader(seriesConfig, "Name");
231  ::addHeader(seriesConfig, "Enabled");
232  ::addHeader(seriesConfig, "Type");
233  ::addHeader(seriesConfig, "Marker");
234  ::addHeader(seriesConfig, "Y axis");
235  ::addHeader(seriesConfig, "Legend");
236  ::addHeader(seriesConfig, "Shadow");
237  ::addHeader(seriesConfig, "Value labels");
238 
239  seriesConfig->rowAt(0)->setStyleClass("trhead");
240 
241  for (int j = 1; j < chart->model()->columnCount(); ++j) {
242  SeriesControl sc;
243 
244  new WText(chart->model()->headerData(j),
245  seriesConfig->elementAt(j, 0));
246 
247  sc.enabledEdit = new WCheckBox(seriesConfig->elementAt(j, 1));
249 
250  sc.typeEdit = new WComboBox(seriesConfig->elementAt(j, 2));
251  sc.typeEdit->setModel(types);
252  sc.typeEdit->setCurrentIndex(0);
254 
255  sc.markerEdit = new WComboBox(seriesConfig->elementAt(j, 3));
256  sc.markerEdit->setModel(markers);
257  sc.markerEdit->setCurrentIndex(0);
259 
260  sc.axisEdit = new WComboBox(seriesConfig->elementAt(j, 4));
261  sc.axisEdit->setModel(yAxesModel_);
262  sc.axisEdit->setCurrentIndex(0);
264 
265  sc.legendEdit = new WCheckBox(seriesConfig->elementAt(j, 5));
267 
268  sc.shadowEdit = new WCheckBox(seriesConfig->elementAt(j, 6));
270 
271  sc.labelsEdit = new WComboBox(seriesConfig->elementAt(j, 7));
272  sc.labelsEdit->setModel(labels);
273  sc.labelsEdit->setCurrentIndex(0);
275 
276  int si = seriesIndexOf(chart, j);
277 
278  if (si != -1) {
279  sc.enabledEdit->setChecked();
280  const WDataSeries& s = chart_->series(j);
281  switch (s.type()) {
282  case PointSeries:
283  sc.typeEdit->setCurrentIndex(0); break;
284  case LineSeries:
285  sc.typeEdit->setCurrentIndex(s.fillRange() != NoFill ?
286  (s.isStacked() ? 7 : 4) : 1); break;
287  case CurveSeries:
288  sc.typeEdit->setCurrentIndex(s.fillRange() != NoFill ?
289  (s.isStacked() ? 8 : 5) : 2); break;
290  case BarSeries:
291  sc.typeEdit->setCurrentIndex(s.isStacked() ? 6 : 3);
292  }
293 
294  sc.markerEdit->setCurrentIndex((int)s.marker());
295  sc.legendEdit->setChecked(s.isLegendEnabled());
296  sc.shadowEdit->setChecked(s.shadow() != WShadow());
297  }
298 
299  seriesControls_.push_back(sc);
300 
301  seriesConfig->rowAt(j)->setStyleClass("trdata");
302  }
303 
304  p = list->addWidget("Series properties", seriesConfig);
305  p->expand();
306  p->setMargin(WLength::Auto, Left | Right);
307  p->resize(1160, WLength::Auto);
308  p->setMargin(20, Top | Bottom);
309 
310  // ---- Axis properties ----
311 
312  yScales_ = new WStandardItemModel(0, 1, this);
313  addEntry(yScales_, "Linear scale");
314  addEntry(yScales_, "Log scale");
315 
316  xScales_ = new WStandardItemModel(0, 1, this);
317  addEntry(xScales_, "Categories");
318  addEntry(xScales_, "Linear scale");
319  addEntry(xScales_, "Log scale");
320  addEntry(xScales_, "Date scale");
321 
322  WContainerWidget *axisConfig = new WContainerWidget();
323  axisConfig_ = new WTable(axisConfig);
324  axisConfig_->setMargin(WLength::Auto, Left | Right);
325 
326  ::addHeader(axisConfig_, "Axis");
327  ::addHeader(axisConfig_, "Visible");
328  ::addHeader(axisConfig_, "Scale");
329  ::addHeader(axisConfig_, "Automatic");
330  ::addHeader(axisConfig_, "Minimum");
331  ::addHeader(axisConfig_, "Maximum");
332  ::addHeader(axisConfig_, "Gridlines");
333  ::addHeader(axisConfig_, "Label angle");
334  ::addHeader(axisConfig_, "Title");
335  ::addHeader(axisConfig_, "Title orientation");
336  ::addHeader(axisConfig_, "Tick direction");
337  ::addHeader(axisConfig_, "Location");
338 
339  axisConfig_->rowAt(0)->setStyleClass("trhead");
340 
341  addAxis(XAxis, 0);
342  addAxis(YAxis, 0);
343  addAxis(YAxis, 1);
344 
345  WPushButton *addAxisBtn =
346  new WPushButton(Wt::utf8("Add Y axis"), axisConfig);
347  addAxisBtn->clicked().connect(this, &ChartConfig::addYAxis);
348  WPushButton *clearAxesBtn =
349  new WPushButton(Wt::utf8("Clear Y axes"), axisConfig);
350  clearAxesBtn->clicked().connect(this, &ChartConfig::clearYAxes);
351 
352  p = list->addWidget("Axis properties", axisConfig);
353  p->setMargin(WLength::Auto, Left | Right);
354  p->resize(1160, WLength::Auto);
355  p->setMargin(20, Top | Bottom);
356 
357  /*
358  * If we do not have JavaScript, then add a button to reflect changes to
359  * the chart.
360  */
361  if (!WApplication::instance()->environment().javaScript()) {
362  WPushButton *b = new WPushButton(this);
363  b->setText("Update chart");
364  b->setInline(false); // so we can add margin to center horizontally
365  b->setMargin(WLength::Auto, Left | Right);
366  b->clicked().connect(this, &ChartConfig::update);
367  }
368 }
369 
370 void ChartConfig::setValueFill(FillRangeType fill)
371 {
372  fill_ = fill;
373 }
374 
376 {
377  bool haveLegend = false;
378  std::vector<WDataSeries *> series;
379 
380  for (int i = 1; i < chart_->model()->columnCount(); ++i) {
381  SeriesControl& sc = seriesControls_[i-1];
382 
383  if (sc.enabledEdit->isChecked()) {
384  WDataSeries *s = new WDataSeries(i);
385 
386  switch (sc.typeEdit->currentIndex()) {
387  case 0:
388  s->setType(PointSeries);
389  if (sc.markerEdit->currentIndex() == 0)
390  sc.markerEdit->setCurrentIndex(1);
391  break;
392  case 1:
393  s->setType(LineSeries);
394  break;
395  case 2:
396  s->setType(CurveSeries);
397  break;
398  case 3:
399  s->setType(BarSeries);
400  break;
401  case 4:
402  s->setType(LineSeries);
403  s->setFillRange(fill_);
404  break;
405  case 5:
406  s->setType(CurveSeries);
407  s->setFillRange(fill_);
408  break;
409  case 6:
410  s->setType(BarSeries);
411  s->setStacked(true);
412  break;
413  case 7:
414  s->setType(LineSeries);
415  s->setFillRange(fill_);
416  s->setStacked(true);
417  break;
418  case 8:
419  s->setType(CurveSeries);
420  s->setFillRange(fill_);
421  s->setStacked(true);
422  }
423 
424  //set WPainterPath to draw a pipe
425  if(sc.markerEdit->currentIndex() == CustomMarker){
426  WPainterPath pp = WPainterPath();
427  pp.moveTo(0, -6);
428  pp.lineTo(0, 6);
429  s->setCustomMarker(pp);
430  }
431 
432  s->setMarker(static_cast<MarkerType>(sc.markerEdit->currentIndex()));
433 
434  s->bindToYAxis(sc.axisEdit->currentIndex());
435 
436  if (sc.legendEdit->isChecked()) {
437  s->setLegendEnabled(true);
438  haveLegend = true;
439  } else
440  s->setLegendEnabled(false);
441 
442  if (sc.shadowEdit->isChecked()) {
443  s->setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
444  } else
445  s->setShadow(WShadow());
446 
447  switch (sc.labelsEdit->currentIndex()) {
448  case 1:
449  s->setLabelsEnabled(XAxis);
450  break;
451  case 2:
452  s->setLabelsEnabled(YAxis);
453  break;
454  case 3:
455  s->setLabelsEnabled(XAxis);
456  s->setLabelsEnabled(YAxis);
457  break;
458  }
459 
460  series.push_back(s);
461  }
462  }
463 
464  chart_->setSeries(series);
465 
466  for (std::size_t i = 0; i < axisControls_.size(); ++i) {
467  AxisControl& sc = axisControls_[i];
468  WAxis& axis = i == 0 ? chart_->axis(XAxis) : chart_->yAxis(i - 1);
469 
470  axis.setVisible(sc.visibleEdit->isChecked());
471 
472  if (sc.scaleEdit->count() != 1) {
473  int k = sc.scaleEdit->currentIndex();
474  if (axis.id() != XAxis)
475  k += 1;
476  else {
477  if (k == 0)
478  chart_->setType(CategoryChart);
479  else
480  chart_->setType(ScatterPlot);
481  }
482 
483  switch (k) {
484  case 1:
485  axis.setScale(LinearScale); break;
486  case 2:
487  axis.setScale(LogScale); break;
488  case 3:
489  axis.setScale(DateScale); break;
490  }
491  }
492 
493  if (sc.autoEdit->isChecked())
494  axis.setAutoLimits(MinimumValue | MaximumValue);
495  else {
496  if (axis.autoLimits() & (MinimumValue | MaximumValue)) {
497  sc.minimumEdit->setText(WLocale::currentLocale()
498  .toString(axis.minimum()));
499  sc.maximumEdit->setText(WLocale::currentLocale()
500  .toString(axis.maximum()));
501  }
502  if (validate(sc.minimumEdit) && validate(sc.maximumEdit)) {
503  double min, max;
504  getDouble(sc.minimumEdit, min);
505  getDouble(sc.maximumEdit, max);
506 
507  if (axis.scale() == LogScale)
508  if (min <= 0)
509  min = 0.0001;
510 
511  if (axis.scale() == DateScale){
512  //the number of julian days until year 1986
513  WDate dMin = WDate(1900,1,1);
514  double gregDaysMin = (double)dMin.toJulianDay();
515  //the number of julian days until year 1988
516  WDate dMax = WDate(3000,1,1);
517  double gregDaysMax = (double)dMax.toJulianDay();
518 
519  bool greg_year_validation =
520  (min > gregDaysMin &&
521  min < gregDaysMax &&
522  max > gregDaysMin &&
523  max < gregDaysMax);
524 
525  if(!greg_year_validation){
526  min = gregDaysMin;
527  max = gregDaysMax;
528  }
529  }
530 
531  axis.setRange(min, max);
532  }
533 
534  }
535 
536  if (validate(sc.labelAngleEdit)) {
537  double angle;
538  getDouble(sc.labelAngleEdit, angle);
539  axis.setLabelAngle(angle);
540  }
541 
542  axis.setGridLinesEnabled(sc.gridLinesEdit->isChecked());
543 
544  axis.setTitle(sc.titleEdit->text());
545 
546  axis.setTitleOrientation(sc.titleOrientationEdit->currentIndex() == 0 ? Horizontal : Vertical);
547 
548  axis.setTickDirection(sc.tickDirectionEdit->currentIndex() == 0 ? Outwards : Inwards);
549 
550  switch (sc.locationEdit->currentIndex()) {
551  case 0:
552  axis.setLocation(MinimumValue);
553  break;
554  case 1:
555  axis.setLocation(MaximumValue);
556  break;
557  case 2:
558  axis.setLocation(ZeroValue);
559  break;
560  case 3:
561  axis.setLocation(BothSides);
562  break;
563  }
564  }
565 
566  chart_->setTitle(titleEdit_->text());
567 
569  double width, height;
570  getDouble(chartWidthEdit_, width);
571  getDouble(chartHeightEdit_, height);
572  chart_->resize(width, height);
573  }
574 
575  switch (chartOrientationEdit_->currentIndex()) {
576  case 0:
577  chart_->setOrientation(Vertical); break;
578  case 1:
579  chart_->setOrientation(Horizontal); break;
580  }
581 
582  chart_->setLegendEnabled(haveLegend);
583 
584  if (haveLegend) {
585  LegendLocation location = LegendOutside;
586  Side side = Right;
587  AlignmentFlag alignment = AlignMiddle;
588  switch (legendLocationEdit_->currentIndex()) {
589  case 0: location = LegendOutside; break;
590  case 1: location = LegendInside; break;
591  }
592 
593  switch (legendSideEdit_->currentIndex()) {
594  case 0: side = Top; break;
595  case 1: side = Right; break;
596  case 2: side = Bottom; break;
597  case 3: side = Left; break;
598  }
599 
600  if (side == Left || side == Right) {
601  if (legendAlignmentEdit_->currentIndex() < 3)
602  legendAlignmentEdit_->setCurrentIndex(4);
603  } else {
604  if (legendAlignmentEdit_->currentIndex() >= 3)
605  legendAlignmentEdit_->setCurrentIndex(2);
606  }
607 
608  switch (legendAlignmentEdit_->currentIndex()) {
609  case 0: alignment = AlignLeft; break;
610  case 1: alignment = AlignCenter; break;
611  case 2: alignment = AlignRight; break;
612  case 3: alignment = AlignTop; break;
613  case 4: alignment = AlignMiddle; break;
614  case 5: alignment = AlignBottom; break;
615  }
616 
617  chart_->setLegendLocation(location, side, alignment);
618 
619  chart_->setLegendColumns((side == Top || side == Bottom ) ? 2 : 1,
620  WLength(100));
621  }
622 
623  if (borderEdit_->isChecked()) {
624  chart_->setBorderPen(WPen());
625  } else {
626  chart_->setBorderPen(NoPen);
627  }
628 }
629 
630 bool ChartConfig::validate(WFormWidget *w)
631 {
632  bool valid = w->validate() == WValidator::Valid;
633 
634  if (!WApplication::instance()->environment().javaScript()) {
635  w->setStyleClass(valid ? "" : "Wt-invalid");
636  w->setToolTip(valid ? "" : "Invalid value");
637  }
638 
639  return valid;
640 }
641 
642 void ChartConfig::connectSignals(WFormWidget *w)
643 {
644  w->changed().connect(this, &ChartConfig::update);
645  if (dynamic_cast<WLineEdit *>(w))
646  w->enterPressed().connect(this, &ChartConfig::update);
647 }
648 
650 {
651  int yAxis = chart_->addYAxis(new WAxis());
652  addAxis(YAxis, yAxis);
653  addEntry(yAxesModel_, axisName(YAxis, yAxis));
654  if (yAxis == 0)
655  update();
656 }
657 
658 void ChartConfig::addAxis(Axis ax, int yAxis)
659 {
660  int j = ax == XAxis ? 1 : yAxis + 2;
661 
662  const WAxis& axis = ax == XAxis ? chart_->axis(XAxis) : chart_->yAxis(yAxis);
663  AxisControl sc;
664 
665  new WText(axisName(axis.id(), axis.yAxisId()), axisConfig_->elementAt(j, 0));
666 
667  sc.visibleEdit = new WCheckBox(axisConfig_->elementAt(j, 1));
668  sc.visibleEdit->setChecked(axis.isVisible());
670 
671  sc.scaleEdit = new WComboBox(axisConfig_->elementAt(j, 2));
672  if (axis.scale() == CategoryScale)
673  sc.scaleEdit->addItem("Category scale");
674  else {
675  if (axis.id() == XAxis) {
676  sc.scaleEdit->setModel(xScales_);
677  sc.scaleEdit->setCurrentIndex(axis.scale());
678  } else {
679  sc.scaleEdit->setModel(yScales_);
680  sc.scaleEdit->setCurrentIndex(axis.scale() - 1);
681  }
682  }
684 
685  bool autoValues = axis.autoLimits() == (MinimumValue | MaximumValue);
686 
687  sc.minimumEdit = new WLineEdit(axisConfig_->elementAt(j, 4));
688  sc.minimumEdit->setText(WLocale::currentLocale()
689  .toString(axis.minimum()));
690  sc.minimumEdit->setValidator(anyNumberValidator_);
691  sc.minimumEdit->setEnabled(!autoValues);
693 
694  sc.maximumEdit = new WLineEdit(axisConfig_->elementAt(j, 5));
695  sc.maximumEdit->setText(WLocale::currentLocale()
696  .toString(axis.maximum()));
697  sc.maximumEdit->setValidator(anyNumberValidator_);
698  sc.maximumEdit->setEnabled(!autoValues);
700 
701  sc.autoEdit = new WCheckBox(axisConfig_->elementAt(j, 3));
702  sc.autoEdit->setChecked(autoValues);
704  sc.autoEdit->checked().connect(sc.maximumEdit, &WLineEdit::disable);
705  sc.autoEdit->unChecked().connect(sc.maximumEdit, &WLineEdit::enable);
706  sc.autoEdit->checked().connect(sc.minimumEdit, &WLineEdit::disable);
707  sc.autoEdit->unChecked().connect(sc.minimumEdit, &WLineEdit::enable);
708 
709  sc.gridLinesEdit = new WCheckBox(axisConfig_->elementAt(j, 6));
711 
712  sc.labelAngleEdit = new WLineEdit(axisConfig_->elementAt(j, 7));
713  sc.labelAngleEdit->setText("0");
714  sc.labelAngleEdit->setValidator(angleValidator_);
716 
717  sc.titleEdit = new WLineEdit(axisConfig_->elementAt(j, 8));
718  sc.titleEdit->setText("");
720 
721  sc.titleOrientationEdit = new WComboBox(axisConfig_->elementAt(j, 9));
722  sc.titleOrientationEdit->addItem("Horizontal");
723  sc.titleOrientationEdit->addItem("Vertical");
724  sc.titleOrientationEdit->setCurrentIndex(0);
726 
727  sc.tickDirectionEdit = new WComboBox(axisConfig_->elementAt(j, 10));
728  sc.tickDirectionEdit->addItem("Outwards");
729  sc.tickDirectionEdit->addItem("Inwards");
730  sc.tickDirectionEdit->setCurrentIndex(0);
732 
733  sc.locationEdit = new WComboBox(axisConfig_->elementAt(j, 11));
734  sc.locationEdit->addItem("Minimum value");
735  sc.locationEdit->addItem("Maximum value");
736  sc.locationEdit->addItem("Zero value");
737  sc.locationEdit->addItem("Both sides");
738  sc.locationEdit->setCurrentIndex(0);
739  if (axis.location() == MaximumValue) {
740  sc.locationEdit->setCurrentIndex(1);
741  } else if (axis.location() == ZeroValue) {
742  sc.locationEdit->setCurrentIndex(2);
743  }
745 
746  if (ax != XAxis) {
747  WPushButton *removeAxisButton =
748  new WPushButton(Wt::utf8("x"), axisConfig_->elementAt(j, 12));
749  removeAxisButton->clicked().connect(boost::bind(&ChartConfig::removeYAxis, this, &axis));
750  }
751 
752  axisConfig_->rowAt(j)->setStyleClass("trdata");
753 
754  axisControls_.push_back(sc);
755 }
756 
757 void ChartConfig::removeYAxis(const WAxis *axis)
758 {
759  int yAxis = axis->yAxisId();
760  for (std::size_t i = 0; i < chart_->series().size(); ++i) {
761  if (chart_->series()[i]->yAxis() == yAxis)
762  chart_->series()[i]->bindToYAxis(-1);
763  }
764  chart_->removeYAxis(yAxis);
765  axisConfig_->deleteRow(yAxis + 2);
766  yAxesModel_->removeRow(yAxis);
767  axisControls_.erase(axisControls_.begin() + yAxis + 1);
768  update();
769 }
770 
772 {
773  if (chart_->yAxisCount() == 0)
774  return;
775 
776  for (std::size_t i = 0; i < chart_->series().size(); ++i) {
777  chart_->series()[i]->bindToYAxis(-1);
778  }
779  chart_->clearYAxes();
780  while (axisConfig_->rowCount() > 2)
781  axisConfig_->deleteRow(2);
782  yAxesModel_->clear();
783  axisControls_.resize(1);
784 }
std::vector< SeriesControl > seriesControls_
Controls for series.
Definition: ChartConfig.h:65
Wt::WComboBox * legendAlignmentEdit_
Definition: ChartConfig.h:91
ChartConfig(Wt::Chart::WCartesianChart *chart, Wt::WContainerWidget *parent)
Constructor.
Definition: ChartConfig.C:77
Wt::WComboBox * legendLocationEdit_
Definition: ChartConfig.h:89
Wt::WTable * axisConfig_
Definition: ChartConfig.h:95
Wt::WComboBox * legendSideEdit_
Definition: ChartConfig.h:90
void addAxis(Wt::Chart::Axis axis, int yAxis)
Definition: ChartConfig.C:658
Wt::WStandardItemModel * yScales_
Definition: ChartConfig.h:94
void setValueFill(Wt::Chart::FillRangeType fill)
Definition: ChartConfig.C:370
Wt::WLineEdit * chartWidthEdit_
Definition: ChartConfig.h:86
Wt::WLineEdit * titleEdit_
Definition: ChartConfig.h:85
void removeYAxis(const Wt::Chart::WAxis *axis)
Definition: ChartConfig.C:757
void addYAxis()
Definition: ChartConfig.C:649
static bool validate(Wt::WFormWidget *w)
Definition: ChartConfig.C:630
Wt::WStandardItemModel * xScales_
Definition: ChartConfig.h:94
void connectSignals(Wt::WFormWidget *w)
Definition: ChartConfig.C:642
Wt::WValidator * angleValidator_
Definition: ChartConfig.h:96
Wt::Chart::WCartesianChart * chart_
Definition: ChartConfig.h:50
std::vector< AxisControl > axisControls_
Controls for axes.
Definition: ChartConfig.h:83
void clearYAxes()
Definition: ChartConfig.C:771
Wt::Chart::FillRangeType fill_
Definition: ChartConfig.h:51
Wt::WValidator * anyNumberValidator_
Definition: ChartConfig.h:96
void update()
Definition: ChartConfig.C:375
Wt::WCheckBox * borderEdit_
Definition: ChartConfig.h:92
Wt::WLineEdit * chartHeightEdit_
Definition: ChartConfig.h:87
Wt::WComboBox * chartOrientationEdit_
Definition: ChartConfig.h:88
Wt::WStandardItemModel * yAxesModel_
Definition: ChartConfig.h:94
Wt::WPanel * addWidget(const Wt::WString &text, Wt::WWidget *w)
Definition: PanelList.C:17
Struct that holds the controls for one axis.
Definition: ChartConfig.h:68
Wt::WLineEdit * maximumEdit
Definition: ChartConfig.h:73
Wt::WComboBox * tickDirectionEdit
Definition: ChartConfig.h:78
Wt::WLineEdit * titleEdit
Definition: ChartConfig.h:76
Wt::WLineEdit * labelAngleEdit
Definition: ChartConfig.h:75
Wt::WComboBox * titleOrientationEdit
Definition: ChartConfig.h:77
Wt::WCheckBox * gridLinesEdit
Definition: ChartConfig.h:74
Wt::WLineEdit * minimumEdit
Definition: ChartConfig.h:72
Wt::WComboBox * locationEdit
Definition: ChartConfig.h:79
Wt::WComboBox * scaleEdit
Definition: ChartConfig.h:70
Wt::WCheckBox * visibleEdit
Definition: ChartConfig.h:69
Wt::WCheckBox * autoEdit
Definition: ChartConfig.h:71
Struct that holds the controls for one series.
Definition: ChartConfig.h:54
Wt::WComboBox * markerEdit
Definition: ChartConfig.h:57
Wt::WComboBox * labelsEdit
Definition: ChartConfig.h:61
Wt::WComboBox * axisEdit
Definition: ChartConfig.h:58
Wt::WCheckBox * enabledEdit
Definition: ChartConfig.h:55
Wt::WCheckBox * legendEdit
Definition: ChartConfig.h:59
Wt::WCheckBox * shadowEdit
Definition: ChartConfig.h:60
Wt::WComboBox * typeEdit
Definition: ChartConfig.h:56

Generated on Mon Sep 5 2022 for the C++ Web Toolkit (Wt) by doxygen 1.9.1