Wt examples  4.9.0
Loading...
Searching...
No Matches
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:
[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.
 
void setValueFill (Wt::Chart::FillRangeType fill)
 

Private Member Functions

void connectSignals (Wt::WFormWidget *w)
 
void update ()
 
void addXAxis ()
 
void addYAxis ()
 
void addAxis (Wt::Chart::Axis axis, int axisId)
 
void removeXAxis (const Wt::Chart::WAxis *axis)
 
void removeYAxis (const Wt::Chart::WAxis *axis)
 
void clearXAxes ()
 
void clearYAxes ()
 

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.
 
std::vector< AxisControlaxisControls_
 Controls for axes.
 
Wt::WLineEdit * titleEdit_
 
Wt::WLineEdit * chartWidthEdit_
 
Wt::WLineEdit * chartHeightEdit_
 
Wt::WComboBox * chartOrientationEdit_
 
Wt::WComboBox * legendLocationEdit_
 
Wt::WComboBox * legendSideEdit_
 
Wt::WComboBox * legendAlignmentEdit_
 
Wt::WCheckBox * borderEdit_
 
std::shared_ptr< Wt::WStandardItemModel > xAxesModel_
 
std::shared_ptr< Wt::WStandardItemModel > yAxesModel_
 
std::shared_ptr< Wt::WStandardItemModel > xScales_
 
std::shared_ptr< Wt::WStandardItemModel > yScales_
 
Wt::WTable * axisConfig_
 
std::shared_ptr< Wt::WValidator > anyNumberValidator_
 
std::shared_ptr< Wt::WValidator > angleValidator_
 

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 40 of file ChartConfig.h.

Constructor & Destructor Documentation

◆ ChartConfig()

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

Constructor.

Definition at line 76 of file ChartConfig.C.

77 : WContainerWidget(),
78 chart_(chart),
79 fill_(FillRangeType::MinimumValue)
80{
81 chart_->setLegendStyle(chart_->legendFont(), WPen(WColor("black")),
82 WBrush(WColor(0xFF, 0xFA, 0xE5)));
83
84 PanelList *list = this->addWidget(std::make_unique<PanelList>());
85
86 std::shared_ptr<WIntValidator> sizeValidator
87 = std::make_shared<WIntValidator>(200,2000);
88 sizeValidator->setMandatory(true);
89
90 anyNumberValidator_ = std::make_shared<WDoubleValidator>();
91 anyNumberValidator_->setMandatory(true);
92
93 angleValidator_ = std::make_shared<WDoubleValidator>(-90, 90);
94 angleValidator_->setMandatory(true);
95
96 // ---- Chart properties ----
97
98 std::shared_ptr<WStandardItemModel> orientation
99 = std::make_shared<WStandardItemModel>(0,1);
100 addEntry(orientation, "Vertical");
101 addEntry(orientation, "Horizontal");
102
103 std::shared_ptr<WStandardItemModel> legendLocation
104 = std::make_shared<WStandardItemModel>(0,1);
105 addEntry(legendLocation, "Outside");
106 addEntry(legendLocation, "Inside");
107
108 std::shared_ptr<WStandardItemModel> legendSide
109 = std::make_shared<WStandardItemModel>(0,1);
110 addEntry(legendSide, "Top");
111 addEntry(legendSide, "Right");
112 addEntry(legendSide, "Bottom");
113 addEntry(legendSide, "Left");
114
115 std::shared_ptr<WStandardItemModel> legendAlignment
116 = std::make_shared<WStandardItemModel>(0,1);
117 addEntry(legendAlignment, "AlignLeft");
118 addEntry(legendAlignment, "AlignCenter");
119 addEntry(legendAlignment, "AlignRight");
120 addEntry(legendAlignment, "AlignTop");
121 addEntry(legendAlignment, "AlignMiddle");
122 addEntry(legendAlignment, "AlignBottom");
123
124 std::unique_ptr<WTable> chartConfig
125 = std::make_unique<WTable>();
126 chartConfig->setMargin(WLength::Auto, Side::Left | Side::Right);
127
128 int row = 0;
129 chartConfig->elementAt(row, 0)->addWidget(std::make_unique<WText>("Title:"));
130 titleEdit_ = chartConfig->elementAt(row,1)->addWidget(std::make_unique<WLineEdit>());
132 ++row;
133
134 chartConfig->elementAt(row, 0)->addWidget(std::make_unique<WText>("Width:"));
135 chartWidthEdit_ = chartConfig->elementAt(row,1)->addWidget(std::make_unique<WLineEdit>());
137 ->setText(WLocale::currentLocale().toString(chart_->width().value()));
138 chartWidthEdit_->setValidator(sizeValidator);
139 chartWidthEdit_->setMaxLength(4);
141 ++row;
142
143 chartConfig->elementAt(row, 0)->addWidget(std::make_unique<WText>("Height:"));
144 chartHeightEdit_ = chartConfig->elementAt(row,1)->addWidget(std::make_unique<WLineEdit>());
146 ->setText(WLocale::currentLocale().toString(chart_->height().value()));
147 chartHeightEdit_->setValidator(sizeValidator);
148 chartHeightEdit_->setMaxLength(4);
150 ++row;
151
152 chartConfig->elementAt(row, 0)->addWidget(std::make_unique<WText>("Orientation:"));
153 chartOrientationEdit_ = chartConfig->elementAt(row,1)->addWidget(std::make_unique<WComboBox>());
154 chartOrientationEdit_->setModel(orientation);
155 chartOrientationEdit_->setCurrentIndex(0);
157 ++row;
158
159 chartConfig->elementAt(row, 0)->addWidget(std::make_unique<WText>("Legend location:"));
160 legendLocationEdit_ = chartConfig->elementAt(row,1)->addWidget(std::make_unique<WComboBox>());
161 legendLocationEdit_->setModel(legendLocation);
162 legendLocationEdit_->setCurrentIndex(0);
164 ++row;
165
166 chartConfig->elementAt(row, 0)->addWidget(std::make_unique<WText>("Legend side:"));
167 legendSideEdit_ = chartConfig->elementAt(row,1)->addWidget(std::make_unique<WComboBox>());
168 legendSideEdit_->setModel(legendSide);
169 legendSideEdit_->setCurrentIndex(1);
171 ++row;
172
173 chartConfig->elementAt(row, 0)->addWidget(std::make_unique<WText>("Legend alignment:"));
174 legendAlignmentEdit_ = chartConfig->elementAt(row,1)->addWidget(std::make_unique<WComboBox>());
175 legendAlignmentEdit_->setModel(legendAlignment);
176 legendAlignmentEdit_->setCurrentIndex(4);
178 ++row;
179
180 chartConfig->elementAt(row, 0)->addWidget(std::make_unique<WText>("Border:"));
181 borderEdit_ = chartConfig->elementAt(row,1)->addWidget(std::make_unique<WCheckBox>());
182 borderEdit_->setChecked(false);
184 ++row;
185
186 for (int i = 0; i < chartConfig->rowCount(); ++i) {
187 chartConfig->elementAt(i, 0)->setStyleClass("tdhead");
188 chartConfig->elementAt(i, 1)->setStyleClass("tddata");
189 }
190
191 WPanel *p = list->addWidget("Chart properties", std::move(chartConfig));
192 p->setMargin(WLength::Auto, Side::Left | Side::Right);
193 p->resize(1160, WLength::Auto);
194 p->setMargin(20, Side::Top | Side::Bottom);
195
196 // ---- Series properties ----
197
198 std::shared_ptr<WStandardItemModel> types
199 = std::make_shared<WStandardItemModel>(0,1);
200 addEntry(types, "Points");
201 addEntry(types, "Line");
202 addEntry(types, "Curve");
203 addEntry(types, "Bar");
204 addEntry(types, "Line Area");
205 addEntry(types, "Curve Area");
206 addEntry(types, "Stacked Bar");
207 addEntry(types, "Stacked Line Area");
208 addEntry(types, "Stacked Curve Area");
209
210 std::shared_ptr<WStandardItemModel> markers
211 = std::make_shared<WStandardItemModel>(0,1);
212 addEntry(markers, "None");
213 addEntry(markers, "Square");
214 addEntry(markers, "Circle");
215 addEntry(markers, "Cross");
216 addEntry(markers, "X cross");
217 addEntry(markers, "Triangle");
218 addEntry(markers, "Pipe");
219 addEntry(markers, "Star");
220 addEntry(markers, "Inverted triangle");
221 addEntry(markers, "Asterisk");
222 addEntry(markers, "Diamond");
223
224 xAxesModel_ = std::make_shared<WStandardItemModel>(0, 1);
225 addEntry(xAxesModel_, axisName(Axis::X, 0));
226
227 yAxesModel_ = std::make_shared<WStandardItemModel>(0, 1);
228 addEntry(yAxesModel_, axisName(Axis::Y, 0));
229 addEntry(yAxesModel_, axisName(Axis::Y, 1));
230
231 std::shared_ptr<WStandardItemModel> labels
232 = std::make_shared<WStandardItemModel>(0,1);
233 addEntry(labels, "None");
234 addEntry(labels, "X");
235 addEntry(labels, "Y");
236 addEntry(labels, "X: Y");
237
238 std::unique_ptr<WTable> seriesConfig
239 = std::make_unique<WTable>();
240 WTable *seriesConfigPtr = seriesConfig.get();
241 seriesConfig->setMargin(WLength::Auto, Side::Left | Side::Right);
242 ::addHeader(seriesConfigPtr, "Name");
243 ::addHeader(seriesConfigPtr, "Enabled");
244 ::addHeader(seriesConfigPtr, "Type");
245 ::addHeader(seriesConfigPtr, "Marker");
246 ::addHeader(seriesConfigPtr, "X axis");
247 ::addHeader(seriesConfigPtr, "Y axis");
248 ::addHeader(seriesConfigPtr, "Legend");
249 ::addHeader(seriesConfigPtr, "Shadow");
250 ::addHeader(seriesConfigPtr, "Value labels");
251
252 seriesConfig->rowAt(0)->setStyleClass("trhead");
253
254 for (int j = 1; j < chart->model()->columnCount(); ++j) {
255 SeriesControl sc;
256
257 seriesConfig->elementAt(j,0)->addWidget(std::make_unique<WText>(chart->model()->headerData(j)));
258
259 sc.enabledEdit = seriesConfig->elementAt(j,1)->addWidget(std::make_unique<WCheckBox>());
260 connectSignals(sc.enabledEdit);
261
262 sc.typeEdit = seriesConfig->elementAt(j,2)->addWidget(std::make_unique<WComboBox>());
263 sc.typeEdit->setModel(types);
264 sc.typeEdit->setCurrentIndex(0);
265 connectSignals(sc.typeEdit);
266
267 sc.markerEdit = seriesConfig->elementAt(j,3)->addWidget(std::make_unique<WComboBox>());
268 sc.markerEdit->setModel(markers);
269 sc.markerEdit->setCurrentIndex(0);
270 connectSignals(sc.markerEdit);
271
272 sc.xAxisEdit = seriesConfig->elementAt(j, 4)->addNew<WComboBox>();
273 sc.xAxisEdit->setModel(xAxesModel_);
274 sc.xAxisEdit->setCurrentIndex(0);
275 connectSignals(sc.xAxisEdit);
276
277 sc.yAxisEdit = seriesConfig->elementAt(j, 5)->addNew<WComboBox>();
278 sc.yAxisEdit->setModel(yAxesModel_);
279 sc.yAxisEdit->setCurrentIndex(0);
280 connectSignals(sc.yAxisEdit);
281
282 sc.legendEdit = seriesConfig->elementAt(j, 6)->addWidget(std::make_unique<WCheckBox>());
283 connectSignals(sc.legendEdit);
284
285 sc.shadowEdit = seriesConfig->elementAt(j, 7)->addWidget(std::make_unique<WCheckBox>());
286 connectSignals(sc.shadowEdit);
287
288 sc.labelsEdit = seriesConfig->elementAt(j, 8)->addWidget(std::make_unique<WComboBox>());
289 sc.labelsEdit->setModel(labels);
290 sc.labelsEdit->setCurrentIndex(0);
291 connectSignals(sc.labelsEdit);
292
293 int si = seriesIndexOf(chart, j);
294
295 if (si != -1) {
296 sc.enabledEdit->setChecked();
297 const WDataSeries& s = chart_->series(j);
298 switch (s.type()) {
299 case SeriesType::Point:
300 sc.typeEdit->setCurrentIndex(0); break;
301 case SeriesType::Line:
302 sc.typeEdit->setCurrentIndex(s.fillRange() != FillRangeType::None ?
303 (s.isStacked() ? 7 : 4) : 1); break;
304 case SeriesType::Curve:
305 sc.typeEdit->setCurrentIndex(s.fillRange() != FillRangeType::None ?
306 (s.isStacked() ? 8 : 5) : 2); break;
307 case SeriesType::Bar:
308 sc.typeEdit->setCurrentIndex(s.isStacked() ? 6 : 3);
309 }
310
311 sc.markerEdit->setCurrentIndex((int)s.marker());
312 sc.legendEdit->setChecked(s.isLegendEnabled());
313 sc.shadowEdit->setChecked(s.shadow() != WShadow());
314 }
315
316 seriesControls_.push_back(sc);
317
318 seriesConfig->rowAt(j)->setStyleClass("trdata");
319 }
320
321 p = list->addWidget("Series properties", std::move(seriesConfig));
322 p->expand();
323 p->setMargin(WLength::Auto, Side::Left | Side::Right);
324 p->resize(1160, WLength::Auto);
325 p->setMargin(20, Side::Top | Side::Bottom);
326
327 // ---- Axis properties ----
328
329 yScales_ = std::make_shared<WStandardItemModel>(0, 1);
330 addEntry(yScales_, "Linear scale");
331 addEntry(yScales_, "Log scale");
332
333 xScales_ = std::make_shared<WStandardItemModel>(0, 1);
334 addEntry(xScales_, "Categories");
335 addEntry(xScales_, "Linear scale");
336 addEntry(xScales_, "Log scale");
337 addEntry(xScales_, "Date scale");
338
339 auto axisConfig = std::make_unique<WContainerWidget>();
340 axisConfig_ = axisConfig->addNew<WTable>();
341 axisConfig_->setMargin(WLength::Auto, Side::Left | Side::Right);
342
343 ::addHeader(axisConfig_, "Axis");
344 ::addHeader(axisConfig_, "Visible");
345 ::addHeader(axisConfig_, "Scale");
346 ::addHeader(axisConfig_, "Automatic");
347 ::addHeader(axisConfig_, "Minimum");
348 ::addHeader(axisConfig_, "Maximum");
349 ::addHeader(axisConfig_, "Gridlines");
350 ::addHeader(axisConfig_, "Label angle");
351 ::addHeader(axisConfig_, "Title");
352 ::addHeader(axisConfig_, "Title orientation");
353 ::addHeader(axisConfig_, "Tick direction");
354 ::addHeader(axisConfig_, "Location");
355
356 axisConfig_->rowAt(0)->setStyleClass("trhead");
357
358 addAxis(Axis::X, 0);
359 addAxis(Axis::Y, 0);
360 addAxis(Axis::Y, 1);
361
362 WPushButton *addXAxisBtn =
363 axisConfig->addNew<WPushButton>(Wt::utf8("Add X axis"));
364 addXAxisBtn->clicked().connect(this, &ChartConfig::addXAxis);
365 WPushButton *clearXAxesBtn =
366 axisConfig->addNew<WPushButton>(Wt::utf8("Clear X axes"));
367 clearXAxesBtn->clicked().connect(this, &ChartConfig::clearXAxes);
368 WPushButton *addYAxisBtn =
369 axisConfig->addNew<WPushButton>(utf8("Add Y axis"));
370 addYAxisBtn->clicked().connect(this, &ChartConfig::addYAxis);
371 WPushButton *clearYAxesBtn =
372 axisConfig->addNew<WPushButton>(utf8("Clear Y axes"));
373 clearYAxesBtn->clicked().connect(this, &ChartConfig::clearYAxes);
374
375 p = list->addWidget("Axis properties", std::move(axisConfig));
376 p->setMargin(WLength::Auto, Side::Left | Side::Right);
377 p->resize(1160, WLength::Auto);
378 p->setMargin(20, Side::Top | Side::Bottom);
379
380 /*
381 * If we do not have JavaScript, then add a button to reflect changes to
382 * the chart.
383 */
384 if (!WApplication::instance()->environment().javaScript()) {
385 auto *b = this->addWidget(std::make_unique<WPushButton>());
386 b->setText("Update chart");
387 b->setInline(false); // so we can add margin to center horizontally
388 b->setMargin(WLength::Auto, Side::Left | Side::Right);
389 b->clicked().connect(this, &ChartConfig::update);
390 }
391}
std::vector< SeriesControl > seriesControls_
Controls for series.
Definition: ChartConfig.h:66
void addAxis(Wt::Chart::Axis axis, int axisId)
Definition: ChartConfig.C:692
Wt::WComboBox * legendAlignmentEdit_
Definition: ChartConfig.h:92
Wt::WComboBox * legendLocationEdit_
Definition: ChartConfig.h:90
std::shared_ptr< Wt::WValidator > angleValidator_
Definition: ChartConfig.h:97
Wt::WTable * axisConfig_
Definition: ChartConfig.h:96
Wt::WComboBox * legendSideEdit_
Definition: ChartConfig.h:91
std::shared_ptr< Wt::WValidator > anyNumberValidator_
Definition: ChartConfig.h:97
Wt::WLineEdit * chartWidthEdit_
Definition: ChartConfig.h:87
Wt::WLineEdit * titleEdit_
Definition: ChartConfig.h:86
void addYAxis()
Definition: ChartConfig.C:683
std::shared_ptr< Wt::WStandardItemModel > xAxesModel_
Definition: ChartConfig.h:95
void connectSignals(Wt::WFormWidget *w)
Definition: ChartConfig.C:667
Wt::Chart::WCartesianChart * chart_
Definition: ChartConfig.h:50
void clearYAxes()
Definition: ChartConfig.C:839
std::shared_ptr< Wt::WStandardItemModel > xScales_
Definition: ChartConfig.h:95
void clearXAxes()
Definition: ChartConfig.C:822
Wt::Chart::FillRangeType fill_
Definition: ChartConfig.h:51
void addXAxis()
Definition: ChartConfig.C:674
void update()
Definition: ChartConfig.C:398
Wt::WCheckBox * borderEdit_
Definition: ChartConfig.h:93
Wt::WLineEdit * chartHeightEdit_
Definition: ChartConfig.h:88
std::shared_ptr< Wt::WStandardItemModel > yAxesModel_
Definition: ChartConfig.h:95
Wt::WComboBox * chartOrientationEdit_
Definition: ChartConfig.h:89
std::shared_ptr< Wt::WStandardItemModel > yScales_
Definition: ChartConfig.h:95
Wt::WPanel * addWidget(const Wt::WString &text, std::unique_ptr< Wt::WWidget > w)
Definition: PanelList.C:17

Member Function Documentation

◆ addAxis()

void ChartConfig::addAxis ( Wt::Chart::Axis  axis,
int  axisId 
)
private

Definition at line 692 of file ChartConfig.C.

693{
694 int j = ax == Axis::X ? 1 + axisId : 1 + chart_->xAxisCount() + axisId;
695
696 const WAxis& axis = ax == Axis::X ? chart_->xAxis(axisId) : chart_->yAxis(axisId);
697 AxisControl sc;
698
699 axisConfig_->insertRow(j);
700 axisConfig_->elementAt(j, 0)->addNew<WText>(axisName(axis.id(), axis.yAxisId()));
701
702 sc.visibleEdit = axisConfig_->elementAt(j, 1)->addNew<WCheckBox>();
703 sc.visibleEdit->setChecked(axis.isVisible());
704 connectSignals(sc.visibleEdit);
705
706 sc.scaleEdit = axisConfig_->elementAt(j, 2)->addNew<WComboBox>();
707 if (axis.scale() == AxisScale::Discrete)
708 sc.scaleEdit->addItem("Discrete scale");
709 else {
710 if (axis.id() == Axis::X) {
711 sc.scaleEdit->setModel(xScales_);
712 sc.scaleEdit->setCurrentIndex(static_cast<int>(axis.scale()));
713 } else {
714 sc.scaleEdit->setModel(yScales_);
715 sc.scaleEdit->setCurrentIndex(static_cast<int>(axis.scale()) - 1);
716 }
717 }
718 connectSignals(sc.scaleEdit);
719
720 bool autoValues = axis.autoLimits() == (AxisValue::Minimum | AxisValue::Maximum);
721
722 sc.minimumEdit = axisConfig_->elementAt(j, 4)->addNew<WLineEdit>();
723 sc.minimumEdit->setText(WLocale::currentLocale()
724 .toString(axis.minimum()));
725 sc.minimumEdit->setValidator(anyNumberValidator_);
726 sc.minimumEdit->setEnabled(!autoValues);
727 connectSignals(sc.minimumEdit);
728
729 sc.maximumEdit = axisConfig_->elementAt(j, 5)->addNew<WLineEdit>();
730 sc.maximumEdit->setText(WLocale::currentLocale()
731 .toString(axis.maximum()));
732 sc.maximumEdit->setValidator(anyNumberValidator_);
733 sc.maximumEdit->setEnabled(!autoValues);
734 connectSignals(sc.maximumEdit);
735
736 sc.autoEdit = axisConfig_->elementAt(j, 3)->addNew<WCheckBox>();
737 sc.autoEdit->setChecked(autoValues);
738 connectSignals(sc.autoEdit);
739 sc.autoEdit->checked().connect(sc.maximumEdit, &WLineEdit::disable);
740 sc.autoEdit->unChecked().connect(sc.maximumEdit, &WLineEdit::enable);
741 sc.autoEdit->checked().connect(sc.minimumEdit, &WLineEdit::disable);
742 sc.autoEdit->unChecked().connect(sc.minimumEdit, &WLineEdit::enable);
743
744 sc.gridLinesEdit = axisConfig_->elementAt(j, 6)->addNew<WCheckBox>();
745 connectSignals(sc.gridLinesEdit);
746
747 sc.labelAngleEdit = axisConfig_->elementAt(j, 7)->addNew<WLineEdit>();
748 sc.labelAngleEdit->setText("0");
749 sc.labelAngleEdit->setValidator(angleValidator_);
750 connectSignals(sc.labelAngleEdit);
751
752 sc.titleEdit = axisConfig_->elementAt(j, 8)->addNew<WLineEdit>();
753 sc.titleEdit->setText("");
754 connectSignals(sc.titleEdit);
755
756 sc.titleOrientationEdit = axisConfig_->elementAt(j, 9)->addNew<WComboBox>();
757 sc.titleOrientationEdit->addItem("Horizontal");
758 sc.titleOrientationEdit->addItem("Vertical");
759 sc.titleOrientationEdit->setCurrentIndex(0);
760 connectSignals(sc.titleOrientationEdit);
761
762 sc.tickDirectionEdit = axisConfig_->elementAt(j, 10)->addNew<WComboBox>();
763 sc.tickDirectionEdit->addItem("Outwards");
764 sc.tickDirectionEdit->addItem("Inwards");
765 sc.tickDirectionEdit->setCurrentIndex(0);
766 connectSignals(sc.tickDirectionEdit);
767
768 sc.locationEdit = axisConfig_->elementAt(j, 11)->addNew<WComboBox>();
769 sc.locationEdit->addItem("Minimum value");
770 sc.locationEdit->addItem("Maximum value");
771 sc.locationEdit->addItem("Zero value");
772 sc.locationEdit->addItem("Both sides");
773 sc.locationEdit->setCurrentIndex(0);
774 if (axis.location() == AxisValue::Maximum) {
775 sc.locationEdit->setCurrentIndex(1);
776 } else if (axis.location() == AxisValue::Zero) {
777 sc.locationEdit->setCurrentIndex(2);
778 }
779 connectSignals(sc.locationEdit);
780
781 WPushButton *removeAxisButton =
782 axisConfig_->elementAt(j, 12)->addNew<WPushButton>(utf8("x"));
783 if (ax == Axis::X) {
784 removeAxisButton->clicked().connect(std::bind(&ChartConfig::removeXAxis, this, &axis));
785 } else {
786 removeAxisButton->clicked().connect(std::bind(&ChartConfig::removeYAxis, this, &axis));
787 }
788
789 axisConfig_->rowAt(j)->setStyleClass("trdata");
790
791 axisControls_.insert(axisControls_.begin() + j - 1, sc);
792}
void removeXAxis(const Wt::Chart::WAxis *axis)
Definition: ChartConfig.C:794
void removeYAxis(const Wt::Chart::WAxis *axis)
Definition: ChartConfig.C:808
std::vector< AxisControl > axisControls_
Controls for axes.
Definition: ChartConfig.h:84

◆ addXAxis()

void ChartConfig::addXAxis ( )
private

Definition at line 674 of file ChartConfig.C.

675{
676 int xAxis = chart_->addXAxis(std::make_unique<WAxis>());
677 addAxis(Axis::X, xAxis);
678 addEntry(xAxesModel_, axisName(Axis::X, xAxis));
679 if (xAxis == 0)
680 update();
681}

◆ addYAxis()

void ChartConfig::addYAxis ( )
private

Definition at line 683 of file ChartConfig.C.

684{
685 int yAxis = chart_->addYAxis(std::make_unique<WAxis>());
686 addAxis(Axis::Y, yAxis);
687 addEntry(yAxesModel_, axisName(Axis::Y, yAxis));
688 if (yAxis == 0)
689 update();
690}

◆ clearXAxes()

void ChartConfig::clearXAxes ( )
private

Definition at line 822 of file ChartConfig.C.

823{
824 if (chart_->xAxisCount() == 0)
825 return;
826
827 for (std::size_t i = 0; i < chart_->series().size(); ++i) {
828 chart_->series()[i]->bindToXAxis(-1);
829 }
830 const int xAxisCount = chart_->xAxisCount();
831 chart_->clearXAxes();
832 for (int i = 0; i < xAxisCount; ++i) {
833 axisConfig_->removeRow(1);
834 }
835 xAxesModel_->clear();
836 axisControls_.erase(axisControls_.begin(), axisControls_.begin() + xAxisCount);
837}

◆ clearYAxes()

void ChartConfig::clearYAxes ( )
private

Definition at line 839 of file ChartConfig.C.

840{
841 if (chart_->yAxisCount() == 0)
842 return;
843
844 for (std::size_t i = 0; i < chart_->series().size(); ++i) {
845 chart_->series()[i]->bindToYAxis(-1);
846 }
847 const int yAxisCount = chart_->yAxisCount();
848 chart_->clearYAxes();
849 for (int i = 0; i < yAxisCount; ++i) {
850 axisConfig_->removeRow(axisConfig_->rowCount() - 1);
851 }
852 yAxesModel_->clear();
853 axisControls_.resize(chart_->xAxisCount());
854}

◆ connectSignals()

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

Definition at line 667 of file ChartConfig.C.

668{
669 w->changed().connect(this, &ChartConfig::update);
670 if (dynamic_cast<WLineEdit *>(w))
671 w->enterPressed().connect(this, &ChartConfig::update);
672}

◆ removeXAxis()

void ChartConfig::removeXAxis ( const Wt::Chart::WAxis *  axis)
private

Definition at line 794 of file ChartConfig.C.

795{
796 int xAxis = axis->xAxisId();
797 for (std::size_t i = 0; i < chart_->series().size(); ++i) {
798 if (chart_->series()[i]->xAxis() == xAxis)
799 chart_->series()[i]->bindToXAxis(-1);
800 }
801 chart_->removeXAxis(xAxis);
802 axisConfig_->removeRow(1 + xAxis);
803 xAxesModel_->removeRow(xAxis);
804 axisControls_.erase(axisControls_.begin() + xAxis);
805 update();
806}

◆ removeYAxis()

void ChartConfig::removeYAxis ( const Wt::Chart::WAxis *  axis)
private

Definition at line 808 of file ChartConfig.C.

809{
810 int yAxis = axis->yAxisId();
811 for (std::size_t i = 0; i < chart_->series().size(); ++i) {
812 if (chart_->series()[i]->yAxis() == yAxis)
813 chart_->series()[i]->bindToYAxis(-1);
814 }
815 chart_->removeYAxis(yAxis);
816 axisConfig_->removeRow(1 + chart_->xAxisCount() + yAxis);
817 yAxesModel_->removeRow(yAxis);
818 axisControls_.erase(axisControls_.begin() + chart_->xAxisCount() + yAxis);
819 update();
820}

◆ setValueFill()

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

Definition at line 393 of file ChartConfig.C.

394{
395 fill_ = fill;
396}

◆ update()

void ChartConfig::update ( )
private

Definition at line 398 of file ChartConfig.C.

399{
400 bool haveLegend = false;
401 std::vector<std::unique_ptr<WDataSeries>> series;
402
403 for (int i = 1; i < chart_->model()->columnCount(); ++i) {
404 SeriesControl& sc = seriesControls_[i-1];
405
406 if (sc.enabledEdit->isChecked()) {
407 std::unique_ptr<WDataSeries> s
408 = std::make_unique<WDataSeries>(i);
409
410 switch (sc.typeEdit->currentIndex()) {
411 case 0:
412 s->setType(SeriesType::Point);
413 if (sc.markerEdit->currentIndex() == 0)
414 sc.markerEdit->setCurrentIndex(1);
415 break;
416 case 1:
417 s->setType(SeriesType::Line);
418 break;
419 case 2:
420 s->setType(SeriesType::Curve);
421 break;
422 case 3:
423 s->setType(SeriesType::Bar);
424 break;
425 case 4:
426 s->setType(SeriesType::Line);
427 s->setFillRange(fill_);
428 break;
429 case 5:
430 s->setType(SeriesType::Curve);
431 s->setFillRange(fill_);
432 break;
433 case 6:
434 s->setType(SeriesType::Bar);
435 s->setStacked(true);
436 break;
437 case 7:
438 s->setType(SeriesType::Line);
439 s->setFillRange(fill_);
440 s->setStacked(true);
441 break;
442 case 8:
443 s->setType(SeriesType::Curve);
444 s->setFillRange(fill_);
445 s->setStacked(true);
446 }
447
448 //set WPainterPath to draw a pipe
449 if(sc.markerEdit->currentIndex() == static_cast<int>(MarkerType::Custom)){ //was customMarker before
450 WPainterPath pp = WPainterPath();
451 pp.moveTo(0, -6);
452 pp.lineTo(0, 6);
453 s->setCustomMarker(pp);
454 }
455
456 s->setMarker(static_cast<MarkerType>(sc.markerEdit->currentIndex()));
457
458 s->bindToXAxis(sc.xAxisEdit->currentIndex());
459 s->bindToYAxis(sc.yAxisEdit->currentIndex());
460
461 if (sc.legendEdit->isChecked()) {
462 s->setLegendEnabled(true);
463 haveLegend = true;
464 } else
465 s->setLegendEnabled(false);
466
467 if (sc.shadowEdit->isChecked()) {
468 s->setShadow(WShadow(3, 3, WColor(0, 0, 0, 127), 3));
469 } else
470 s->setShadow(WShadow());
471
472 switch (sc.labelsEdit->currentIndex()) {
473 case 1:
474 s->setLabelsEnabled(Axis::X);
475 break;
476 case 2:
477 s->setLabelsEnabled(Axis::Y);
478 break;
479 case 3:
480 s->setLabelsEnabled(Axis::X);
481 s->setLabelsEnabled(Axis::Y);
482 break;
483 }
484
485 series.push_back(std::move(s));
486 }
487 }
488
489 chart_->setSeries(std::move(series));
490
491 for (std::size_t i = 0; i < axisControls_.size(); ++i) {
492 AxisControl& sc = axisControls_[i];
493 WAxis& axis = static_cast<int>(i) < chart_->xAxisCount() ? chart_->xAxis(i) : chart_->yAxis(i - chart_->xAxisCount());
494
495 axis.setVisible(sc.visibleEdit->isChecked());
496
497 if (sc.scaleEdit->count() != 1) {
498 int k = sc.scaleEdit->currentIndex();
499 if (axis.id() != Axis::X)
500 k += 1;
501 else {
502 if (k == 0)
503 chart_->setType(ChartType::Category);
504 else
505 chart_->setType(ChartType::Scatter);
506 }
507
508 switch (k) {
509 case 1:
510 axis.setScale(AxisScale::Linear); break;
511 case 2:
512 axis.setScale(AxisScale::Log); break;
513 case 3:
514 axis.setScale(AxisScale::Date); break;
515 }
516 }
517
518 if (sc.autoEdit->isChecked())
519 axis.setAutoLimits(AxisValue::Minimum | AxisValue::Maximum);
520 else {
521 if (!(axis.autoLimits() & (AxisValue::Minimum | AxisValue::Maximum)).empty()) {
522 sc.minimumEdit->setText(WLocale::currentLocale()
523 .toString(axis.minimum()));
524 sc.maximumEdit->setText(WLocale::currentLocale()
525 .toString(axis.maximum()));
526 }
527 if (validate(sc.minimumEdit) && validate(sc.maximumEdit)) {
528 double min, max;
529 getDouble(sc.minimumEdit, min);
530 getDouble(sc.maximumEdit, max);
531
532 if (axis.scale() == AxisScale::Log)
533 if (min <= 0)
534 min = 0.0001;
535
536 if (axis.scale() == AxisScale::Date){
537 //the number of julian days until year 1986
538 WDate dMin = WDate(1900,1,1);
539 double gregDaysMin = (double)dMin.toJulianDay();
540 //the number of julian days until year 1988
541 WDate dMax = WDate(3000,1,1);
542 double gregDaysMax = (double)dMax.toJulianDay();
543
544 bool greg_year_validation =
545 (min > gregDaysMin &&
546 min < gregDaysMax &&
547 max > gregDaysMin &&
548 max < gregDaysMax);
549
550 if(!greg_year_validation){
551 min = gregDaysMin;
552 max = gregDaysMax;
553 }
554 }
555
556 axis.setRange(min, max);
557 }
558
559 }
560
561 if (validate(sc.labelAngleEdit)) {
562 double angle;
563 getDouble(sc.labelAngleEdit, angle);
564 axis.setLabelAngle(angle);
565 }
566
567 axis.setGridLinesEnabled(sc.gridLinesEdit->isChecked());
568
569 axis.setTitle(sc.titleEdit->text());
570
571 axis.setTitleOrientation(sc.titleOrientationEdit->currentIndex() == 0 ? Orientation::Horizontal : Orientation::Vertical);
572
573 axis.setTickDirection(sc.tickDirectionEdit->currentIndex() == 0 ? TickDirection::Outwards : TickDirection::Inwards);
574
575 switch (sc.locationEdit->currentIndex()) {
576 case 0:
577 axis.setLocation(AxisValue::Minimum);
578 break;
579 case 1:
580 axis.setLocation(AxisValue::Maximum);
581 break;
582 case 2:
583 axis.setLocation(AxisValue::Zero);
584 break;
585 case 3:
586 axis.setLocation(AxisValue::Both);
587 break;
588 }
589 }
590
591 chart_->setTitle(titleEdit_->text());
592
594 double width, height;
595 getDouble(chartWidthEdit_, width);
596 getDouble(chartHeightEdit_, height);
597 chart_->resize(width, height);
598 }
599
600 switch (chartOrientationEdit_->currentIndex()) {
601 case 0:
602 chart_->setOrientation(Orientation::Vertical); break;
603 case 1:
604 chart_->setOrientation(Orientation::Horizontal); break;
605 }
606
607 chart_->setLegendEnabled(haveLegend);
608
609 if (haveLegend) {
610 LegendLocation location = LegendLocation::Outside;
611 Side side = Side::Right;
612 AlignmentFlag alignment = AlignmentFlag::Middle;
613 switch (legendLocationEdit_->currentIndex()) {
614 case 0: location = LegendLocation::Outside; break;
615 case 1: location = LegendLocation::Inside; break;
616 }
617
618 switch (legendSideEdit_->currentIndex()) {
619 case 0: side = Side::Top; break;
620 case 1: side = Side::Right; break;
621 case 2: side = Side::Bottom; break;
622 case 3: side = Side::Left; break;
623 }
624
625 if (side == Side::Left || side == Side::Right) {
626 if (legendAlignmentEdit_->currentIndex() < 3)
627 legendAlignmentEdit_->setCurrentIndex(4);
628 } else {
629 if (legendAlignmentEdit_->currentIndex() >= 3)
630 legendAlignmentEdit_->setCurrentIndex(2);
631 }
632
633 switch (legendAlignmentEdit_->currentIndex()) {
634 case 0: alignment = AlignmentFlag::Left; break;
635 case 1: alignment = AlignmentFlag::Center; break;
636 case 2: alignment = AlignmentFlag::Right; break;
637 case 3: alignment = AlignmentFlag::Top; break;
638 case 4: alignment = AlignmentFlag::Middle; break;
639 case 5: alignment = AlignmentFlag::Bottom; break;
640 }
641
642 chart_->setLegendLocation(location, side, alignment);
643
644 chart_->setLegendColumns((side == Side::Top || side == Side::Bottom ) ? 2 : 1,
645 WLength(100));
646 }
647
648 if (borderEdit_->isChecked()) {
649 chart_->setBorderPen(WPen());
650 } else {
651 chart_->setBorderPen(PenStyle::None);
652 }
653}
static bool validate(Wt::WFormWidget *w)
Definition: ChartConfig.C:655

◆ validate()

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

Definition at line 655 of file ChartConfig.C.

656{
657 bool valid = w->validate() == ValidationState::Valid;
658
659 if (!WApplication::instance()->environment().javaScript()) {
660 w->setStyleClass(valid ? "" : "Wt-invalid");
661 w->setToolTip(valid ? "" : "Invalid value");
662 }
663
664 return valid;
665}

Member Data Documentation

◆ angleValidator_

std::shared_ptr<Wt::WValidator> ChartConfig::angleValidator_
private

Definition at line 97 of file ChartConfig.h.

◆ anyNumberValidator_

std::shared_ptr<Wt::WValidator> ChartConfig::anyNumberValidator_
private

Definition at line 97 of file ChartConfig.h.

◆ axisConfig_

Wt::WTable* ChartConfig::axisConfig_
private

Definition at line 96 of file ChartConfig.h.

◆ axisControls_

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

Controls for axes.

Definition at line 84 of file ChartConfig.h.

◆ borderEdit_

Wt::WCheckBox* ChartConfig::borderEdit_
private

Definition at line 93 of file ChartConfig.h.

◆ chart_

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

Definition at line 50 of file ChartConfig.h.

◆ chartHeightEdit_

Wt::WLineEdit* ChartConfig::chartHeightEdit_
private

Definition at line 88 of file ChartConfig.h.

◆ chartOrientationEdit_

Wt::WComboBox* ChartConfig::chartOrientationEdit_
private

Definition at line 89 of file ChartConfig.h.

◆ chartWidthEdit_

Wt::WLineEdit* ChartConfig::chartWidthEdit_
private

Definition at line 87 of file ChartConfig.h.

◆ fill_

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

Definition at line 51 of file ChartConfig.h.

◆ legendAlignmentEdit_

Wt::WComboBox* ChartConfig::legendAlignmentEdit_
private

Definition at line 92 of file ChartConfig.h.

◆ legendLocationEdit_

Wt::WComboBox* ChartConfig::legendLocationEdit_
private

Definition at line 90 of file ChartConfig.h.

◆ legendSideEdit_

Wt::WComboBox* ChartConfig::legendSideEdit_
private

Definition at line 91 of file ChartConfig.h.

◆ seriesControls_

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

Controls for series.

Definition at line 66 of file ChartConfig.h.

◆ titleEdit_

Wt::WLineEdit* ChartConfig::titleEdit_
private

Definition at line 86 of file ChartConfig.h.

◆ xAxesModel_

std::shared_ptr<Wt::WStandardItemModel> ChartConfig::xAxesModel_
private

Definition at line 95 of file ChartConfig.h.

◆ xScales_

std::shared_ptr<Wt::WStandardItemModel> ChartConfig::xScales_
private

Definition at line 95 of file ChartConfig.h.

◆ yAxesModel_

std::shared_ptr<Wt::WStandardItemModel> ChartConfig::yAxesModel_
private

Definition at line 95 of file ChartConfig.h.

◆ yScales_

std::shared_ptr<Wt::WStandardItemModel> ChartConfig::yScales_
private

Definition at line 95 of file ChartConfig.h.


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