Wt examples  4.0.2
Classes | Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
ChartConfig Class Reference

A class that allows configuration of a cartesian chart. More...

#include <ChartConfig.h>

Inheritance diagram for ChartConfig:
Inheritance graph
[legend]

Classes

struct  AxisControl
 Struct that holds the controls for one axis. More...
 
struct  SeriesControl
 Struct that holds the controls for one series. More...
 

Public Member Functions

 ChartConfig (Wt::Chart::WCartesianChart *chart)
 Constructor. More...
 
void setValueFill (Wt::Chart::FillRangeType fill)
 

Private Member Functions

void connectSignals (Wt::WFormWidget *w)
 
void update ()
 

Static Private Member Functions

static bool validate (Wt::WFormWidget *w)
 

Private Attributes

Wt::Chart::WCartesianChart * chart_
 
Wt::Chart::FillRangeType fill_
 
std::vector< SeriesControlseriesControls_
 Controls for series. More...
 
std::vector< AxisControlaxisControls_
 Controls for axes. More...
 
Wt::WLineEdit * titleEdit_
 
Wt::WLineEdit * chartWidthEdit_
 
Wt::WLineEdit * chartHeightEdit_
 
Wt::WComboBox * chartOrientationEdit_
 
Wt::WComboBox * legendLocationEdit_
 
Wt::WComboBox * legendSideEdit_
 
Wt::WComboBox * legendAlignmentEdit_
 
Wt::WCheckBox * borderEdit_
 

Detailed Description

A class that allows configuration of a cartesian chart.

This widget provides forms for configuring chart, series, and axis properties and manipulates the chart according to user settings.

This widget is part of the Wt charts example.

Definition at line 37 of file ChartConfig.h.

Constructor & Destructor Documentation

◆ ChartConfig()

ChartConfig::ChartConfig ( Wt::Chart::WCartesianChart *  chart)

Constructor.

Definition at line 62 of file ChartConfig.C.

63  : WContainerWidget(),
64  chart_(chart),
65  fill_(FillRangeType::MinimumValue)
66 {
67  chart_->setLegendStyle(chart_->legendFont(), WPen(WColor("black")),
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);
127  chartWidthEdit_->setMaxLength(4);
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);
136  chartHeightEdit_->setMaxLength(4);
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);
143  chartOrientationEdit_->setCurrentIndex(0);
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);
150  legendLocationEdit_->setCurrentIndex(0);
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);
157  legendSideEdit_->setCurrentIndex(1);
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);
164  legendAlignmentEdit_->setCurrentIndex(4);
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>());
245  connectSignals(sc.enabledEdit);
246 
247  sc.typeEdit = seriesConfig->elementAt(j,2)->addWidget(cpp14::make_unique<WComboBox>());
248  sc.typeEdit->setModel(types);
249  sc.typeEdit->setCurrentIndex(0);
250  connectSignals(sc.typeEdit);
251 
252  sc.markerEdit = seriesConfig->elementAt(j,3)->addWidget(cpp14::make_unique<WComboBox>());
253  sc.markerEdit->setModel(markers);
254  sc.markerEdit->setCurrentIndex(0);
255  connectSignals(sc.markerEdit);
256 
257  sc.axisEdit = seriesConfig->elementAt(j,4)->addWidget(cpp14::make_unique<WComboBox>());
258  sc.axisEdit->setModel(axes);
259  sc.axisEdit->setCurrentIndex(0);
260  connectSignals(sc.axisEdit);
261 
262  sc.legendEdit = seriesConfig->elementAt(j, 5)->addWidget(cpp14::make_unique<WCheckBox>());
263  connectSignals(sc.legendEdit);
264 
265  sc.shadowEdit = seriesConfig->elementAt(j,6)->addWidget(cpp14::make_unique<WCheckBox>());
266  connectSignals(sc.shadowEdit);
267 
268  sc.labelsEdit = seriesConfig->elementAt(j,7)->addWidget(cpp14::make_unique<WComboBox>());
269  sc.labelsEdit->setModel(labels);
270  sc.labelsEdit->setCurrentIndex(0);
271  connectSignals(sc.labelsEdit);
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:
282  sc.typeEdit->setCurrentIndex(s.fillRange() != FillRangeType::None ?
283  (s.isStacked() ? 7 : 4) : 1); break;
284  case SeriesType::Curve:
285  sc.typeEdit->setCurrentIndex(s.fillRange() != FillRangeType::None ?
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());
292  sc.legendEdit->setChecked(s.isLegendEnabled());
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());
352  connectSignals(sc.visibleEdit);
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  }
367  connectSignals(sc.scaleEdit);
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);
376  connectSignals(sc.minimumEdit);
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);
383  connectSignals(sc.maximumEdit);
384 
385  sc.autoEdit = axisConfig->elementAt(j,3)->addWidget(cpp14::make_unique<WCheckBox>());
386  sc.autoEdit->setChecked(autoValues);
387  connectSignals(sc.autoEdit);
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>());
394  connectSignals(sc.gridLinesEdit);
395 
396  sc.labelAngleEdit = axisConfig->elementAt(j,7)->addWidget(cpp14::make_unique<WLineEdit>());
397  sc.labelAngleEdit->setText("0");
398  sc.labelAngleEdit->setValidator(angleValidator);
399  connectSignals(sc.labelAngleEdit);
400 
401  sc.titleEdit = axisConfig->elementAt(j,8)->addWidget(cpp14::make_unique<WLineEdit>());
402  sc.titleEdit->setText("");
403  connectSignals(sc.titleEdit);
404 
405  sc.titleOrientationEdit = axisConfig->elementAt(j,9)->addWidget(cpp14::make_unique<WComboBox>());
406  sc.titleOrientationEdit->addItem("Horizontal");
407  sc.titleOrientationEdit->addItem("Vertical");
408  sc.titleOrientationEdit->setCurrentIndex(0);
409  connectSignals(sc.titleOrientationEdit);
410 
411  sc.tickDirectionEdit = axisConfig->elementAt(j,10)->addWidget(cpp14::make_unique<WComboBox>());
412  sc.tickDirectionEdit->addItem("Outwards");
413  sc.tickDirectionEdit->addItem("Inwards");
414  sc.tickDirectionEdit->setCurrentIndex(0);
415  connectSignals(sc.tickDirectionEdit);
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");
422  sc.locationEdit->setCurrentIndex(0);
423  if (axis.location() == AxisValue::Zero) {
424  sc.locationEdit->setCurrentIndex(2);
425  }
426  connectSignals(sc.locationEdit);
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 }
Wt::WCheckBox * borderEdit_
Definition: ChartConfig.h:89
Wt::Chart::FillRangeType fill_
Definition: ChartConfig.h:48
Wt::WLineEdit * titleEdit_
Definition: ChartConfig.h:82
Wt::Chart::WCartesianChart * chart_
Definition: ChartConfig.h:47
void connectSignals(Wt::WFormWidget *w)
Definition: ChartConfig.C:726
Wt::WLineEdit * chartWidthEdit_
Definition: ChartConfig.h:83
Wt::WPanel * addWidget(const Wt::WString &text, std::unique_ptr< Wt::WWidget > w)
Definition: PanelList.C:17
Wt::WComboBox * chartOrientationEdit_
Definition: ChartConfig.h:85
Wt::WComboBox * legendLocationEdit_
Definition: ChartConfig.h:86
std::vector< SeriesControl > seriesControls_
Controls for series.
Definition: ChartConfig.h:62
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::WComboBox * legendAlignmentEdit_
Definition: ChartConfig.h:88
Wt::WLineEdit * chartHeightEdit_
Definition: ChartConfig.h:84

Member Function Documentation

◆ connectSignals()

void ChartConfig::connectSignals ( Wt::WFormWidget *  w)
private

Definition at line 726 of file ChartConfig.C.

727 {
728  w->changed().connect(this, &ChartConfig::update);
729  if (dynamic_cast<WLineEdit *>(w))
730  w->enterPressed().connect(this, &ChartConfig::update);
731 }
void update()
Definition: ChartConfig.C:456

◆ setValueFill()

void ChartConfig::setValueFill ( Wt::Chart::FillRangeType  fill)

Definition at line 451 of file ChartConfig.C.

452 {
453  fill_ = fill;
454 }
Wt::Chart::FillRangeType fill_
Definition: ChartConfig.h:48

◆ update()

void ChartConfig::update ( )
private

Definition at line 456 of file ChartConfig.C.

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)
472  sc.markerEdit->setCurrentIndex(1);
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)
562  chart_->setType(ChartType::Category);
563  else
564  chart_->setType(ChartType::Scatter);
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())
578  axis.setAutoLimits(AxisValue::Minimum | AxisValue::Maximum);
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 
626  axis.setGridLinesEnabled(sc.gridLinesEdit->isChecked());
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:
636  axis.setLocation(AxisValue::Minimum);
637  break;
638  case 1:
639  axis.setLocation(AxisValue::Maximum);
640  break;
641  case 2:
642  axis.setLocation(AxisValue::Zero);
643  break;
644  case 3:
645  axis.setLocation(AxisValue::Both);
646  break;
647  }
648  }
649 
650  chart_->setTitle(titleEdit_->text());
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) {
669  LegendLocation location = LegendLocation::Outside;
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) {
685  if (legendAlignmentEdit_->currentIndex() < 3)
686  legendAlignmentEdit_->setCurrentIndex(4);
687  } else {
688  if (legendAlignmentEdit_->currentIndex() >= 3)
689  legendAlignmentEdit_->setCurrentIndex(2);
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()) {
708  chart_->setBorderPen(WPen());
709  } else {
710  chart_->setBorderPen(PenStyle::None);
711  }
712 }
Wt::WCheckBox * borderEdit_
Definition: ChartConfig.h:89
Wt::Chart::FillRangeType fill_
Definition: ChartConfig.h:48
Wt::WLineEdit * titleEdit_
Definition: ChartConfig.h:82
Wt::Chart::WCartesianChart * chart_
Definition: ChartConfig.h:47
Wt::WLineEdit * chartWidthEdit_
Definition: ChartConfig.h:83
Wt::WComboBox * chartOrientationEdit_
Definition: ChartConfig.h:85
Wt::WComboBox * legendLocationEdit_
Definition: ChartConfig.h:86
std::vector< SeriesControl > seriesControls_
Controls for series.
Definition: ChartConfig.h:62
Wt::WComboBox * legendSideEdit_
Definition: ChartConfig.h:87
std::vector< AxisControl > axisControls_
Controls for axes.
Definition: ChartConfig.h:80
Wt::WComboBox * legendAlignmentEdit_
Definition: ChartConfig.h:88
static bool validate(Wt::WFormWidget *w)
Definition: ChartConfig.C:714
Wt::WLineEdit * chartHeightEdit_
Definition: ChartConfig.h:84

◆ validate()

bool ChartConfig::validate ( Wt::WFormWidget *  w)
staticprivate

Definition at line 714 of file ChartConfig.C.

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 }

Member Data Documentation

◆ axisControls_

std::vector<AxisControl> ChartConfig::axisControls_
private

Controls for axes.

Definition at line 80 of file ChartConfig.h.

◆ borderEdit_

Wt::WCheckBox* ChartConfig::borderEdit_
private

Definition at line 89 of file ChartConfig.h.

◆ chart_

Wt::Chart::WCartesianChart* ChartConfig::chart_
private

Definition at line 47 of file ChartConfig.h.

◆ chartHeightEdit_

Wt::WLineEdit* ChartConfig::chartHeightEdit_
private

Definition at line 84 of file ChartConfig.h.

◆ chartOrientationEdit_

Wt::WComboBox* ChartConfig::chartOrientationEdit_
private

Definition at line 85 of file ChartConfig.h.

◆ chartWidthEdit_

Wt::WLineEdit* ChartConfig::chartWidthEdit_
private

Definition at line 83 of file ChartConfig.h.

◆ fill_

Wt::Chart::FillRangeType ChartConfig::fill_
private

Definition at line 48 of file ChartConfig.h.

◆ legendAlignmentEdit_

Wt::WComboBox* ChartConfig::legendAlignmentEdit_
private

Definition at line 88 of file ChartConfig.h.

◆ legendLocationEdit_

Wt::WComboBox* ChartConfig::legendLocationEdit_
private

Definition at line 86 of file ChartConfig.h.

◆ legendSideEdit_

Wt::WComboBox* ChartConfig::legendSideEdit_
private

Definition at line 87 of file ChartConfig.h.

◆ seriesControls_

std::vector<SeriesControl> ChartConfig::seriesControls_
private

Controls for series.

Definition at line 62 of file ChartConfig.h.

◆ titleEdit_

Wt::WLineEdit* ChartConfig::titleEdit_
private

Definition at line 82 of file ChartConfig.h.


The documentation for this class was generated from the following files:

Generated on Thu Mar 15 2018 for the C++ Web Toolkit (Wt) by doxygen 1.8.14