ChartConfig Class Reference
[Charts example]

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

#include <ChartConfig.h>

Inheritance diagram for ChartConfig:

Inheritance graph
[legend]

List of all members.

Public Member Functions

 ChartConfig (Wt::Chart::WCartesianChart *chart, Wt::WContainerWidget *parent)
 Constructor.
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::WCartesianChartchart_
Wt::Chart::FillRangeType fill_
std::vector< SeriesControlseriesControls_
 Controls for series.
std::vector< AxisControlaxisControls_
 Controls for axes.
Wt::WLineEdittitleEdit_
Wt::WLineEditchartWidthEdit_
Wt::WLineEditchartHeightEdit_
Wt::WComboBoxchartOrientationEdit_

Classes

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


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 ( Wt::Chart::WCartesianChart chart,
Wt::WContainerWidget parent 
)

Constructor.

Definition at line 60 of file ChartConfig.C.

00061   : WContainerWidget(parent),
00062     chart_(chart),
00063     fill_(MinimumValueFill)
00064 {
00065   PanelList *list = new PanelList(this);
00066 
00067   WIntValidator *sizeValidator = new WIntValidator(200, 2000, this);
00068   sizeValidator->setMandatory(true);
00069 
00070   WDoubleValidator *anyNumberValidator = new WDoubleValidator(this);
00071   anyNumberValidator->setMandatory(true);
00072 
00073   WDoubleValidator *angleValidator = new WDoubleValidator(-90, 90, this);
00074   angleValidator->setMandatory(true);
00075 
00076   // ---- Chart properties ----
00077 
00078   WStandardItemModel *orientation = new WStandardItemModel(0, 1, this);
00079   addEntry(orientation, "Vertical");
00080   addEntry(orientation, "Horizontal");
00081 
00082   WTable *chartConfig = new WTable();
00083   chartConfig->setMargin(WLength::Auto, Left | Right);
00084 
00085   int row = 0;
00086   chartConfig->elementAt(row, 0)->addWidget(new WText("Title:"));
00087   titleEdit_ = new WLineEdit(chartConfig->elementAt(row, 1));
00088   connectSignals(titleEdit_);
00089   ++row;
00090 
00091   chartConfig->elementAt(row, 0)->addWidget(new WText("Width:"));
00092   chartWidthEdit_ = new WLineEdit(chartConfig->elementAt(row, 1));
00093   chartWidthEdit_
00094     ->setText(boost::lexical_cast<std::string>(chart_->width().value()));
00095   chartWidthEdit_->setValidator(sizeValidator);
00096   chartWidthEdit_->setMaxLength(4);
00097   connectSignals(chartWidthEdit_);
00098   ++row;
00099 
00100   chartConfig->elementAt(row, 0)->addWidget(new WText("Height:"));
00101   chartHeightEdit_ = new WLineEdit(chartConfig->elementAt(row, 1));
00102   chartHeightEdit_
00103     ->setText(boost::lexical_cast<std::string>(chart_->height().value()));
00104   chartHeightEdit_->setValidator(sizeValidator);
00105   chartHeightEdit_->setMaxLength(4);
00106   connectSignals(chartHeightEdit_);
00107   ++row;
00108 
00109   chartConfig->elementAt(row, 0)->addWidget(new WText("Orientation:"));
00110   chartOrientationEdit_ = new WComboBox(chartConfig->elementAt(row, 1));
00111   chartOrientationEdit_->setModel(orientation);
00112   connectSignals(chartOrientationEdit_);
00113   ++row;
00114 
00115   for (int i = 0; i < chartConfig->rowCount(); ++i) {
00116     chartConfig->elementAt(i, 0)->setStyleClass("tdhead");
00117     chartConfig->elementAt(i, 1)->setStyleClass("tddata");
00118   }
00119 
00120   WPanel *p = list->addWidget("Chart properties", chartConfig);
00121   p->setMargin(WLength::Auto, Left | Right);
00122   p->resize(750, WLength::Auto);
00123   p->setMargin(20, Top | Bottom);
00124 
00125   if (chart_->isLegendEnabled())
00126     chart_->setPlotAreaPadding(200, Right);
00127 
00128   // ---- Series properties ----
00129 
00130   WStandardItemModel *types = new WStandardItemModel(0, 1, this);
00131   addEntry(types, "Points");
00132   addEntry(types, "Line");
00133   addEntry(types, "Curve");
00134   addEntry(types, "Bar");
00135   addEntry(types, "Line Area");
00136   addEntry(types, "Curve Area");
00137   addEntry(types, "Stacked Bar");
00138   addEntry(types, "Stacked Line Area");
00139   addEntry(types, "Stacked Curve Area");
00140 
00141   WStandardItemModel *markers = new WStandardItemModel(0, 1, this);
00142   addEntry(markers, "None");
00143   addEntry(markers, "Square");
00144   addEntry(markers, "Circle");
00145   addEntry(markers, "Cross");
00146   addEntry(markers, "X cross");
00147   addEntry(markers, "Triangle");
00148 
00149   WStandardItemModel *axes = new WStandardItemModel(0, 1, this);
00150   addEntry(axes, "1st Y axis");
00151   addEntry(axes, "2nd Y axis");
00152 
00153   WStandardItemModel *labels = new WStandardItemModel(0, 1, this);
00154   addEntry(labels, "None");
00155   addEntry(labels, "X");
00156   addEntry(labels, "Y");
00157   addEntry(labels, "X: Y");
00158 
00159   WTable *seriesConfig = new WTable();
00160   seriesConfig->setMargin(WLength::Auto, Left | Right);
00161 
00162   ::addHeader(seriesConfig, "Name");
00163   ::addHeader(seriesConfig, "Enabled");
00164   ::addHeader(seriesConfig, "Type");
00165   ::addHeader(seriesConfig, "Marker");
00166   ::addHeader(seriesConfig, "Y axis");
00167   ::addHeader(seriesConfig, "Legend");
00168   ::addHeader(seriesConfig, "Value labels");
00169 
00170   seriesConfig->rowAt(0)->setStyleClass("trhead");
00171 
00172   for (int j = 1; j < chart->model()->columnCount(); ++j) {
00173     SeriesControl sc;
00174 
00175     new WText(asString(chart->model()->headerData(j)),
00176               seriesConfig->elementAt(j, 0));
00177 
00178     sc.enabledEdit = new WCheckBox(seriesConfig->elementAt(j, 1));
00179     connectSignals(sc.enabledEdit);
00180 
00181     sc.typeEdit = new WComboBox(seriesConfig->elementAt(j, 2));
00182     sc.typeEdit->setModel(types);
00183     connectSignals(sc.typeEdit);
00184 
00185     sc.markerEdit = new WComboBox(seriesConfig->elementAt(j, 3));
00186     sc.markerEdit->setModel(markers);
00187     connectSignals(sc.markerEdit);
00188 
00189     sc.axisEdit = new WComboBox(seriesConfig->elementAt(j, 4));
00190     sc.axisEdit->setModel(axes);
00191     connectSignals(sc.axisEdit);
00192 
00193     sc.legendEdit = new WCheckBox(seriesConfig->elementAt(j, 5));
00194     connectSignals(sc.legendEdit);
00195 
00196     sc.labelsEdit = new WComboBox(seriesConfig->elementAt(j, 6));
00197     sc.labelsEdit->setModel(labels);
00198     connectSignals(sc.labelsEdit);
00199 
00200     int si = seriesIndexOf(chart, j);
00201 
00202     if (si != -1) {
00203       sc.enabledEdit->setChecked();
00204       const WDataSeries& s = chart_->series(j);
00205       switch (s.type()) {
00206       case PointSeries:
00207         sc.typeEdit->setCurrentIndex(0); break;
00208       case LineSeries:
00209         sc.typeEdit->setCurrentIndex(s.fillRange() != NoFill ?
00210                                      (s.isStacked() ? 7 : 4) : 1); break;
00211       case CurveSeries:
00212         sc.typeEdit->setCurrentIndex(s.fillRange() != NoFill ?
00213                                      (s.isStacked() ? 8 : 5) : 2); break;
00214       case BarSeries:
00215         sc.typeEdit->setCurrentIndex(s.isStacked() ? 6 : 3);
00216       }
00217 
00218       sc.markerEdit->setCurrentIndex((int)s.marker());
00219       sc.legendEdit->setChecked(s.isLegendEnabled());
00220     }
00221 
00222     seriesControls_.push_back(sc);
00223 
00224     seriesConfig->rowAt(j)->setStyleClass("trdata");
00225   }
00226 
00227   p = list->addWidget("Series properties", seriesConfig);
00228   p->expand();
00229   p->setMargin(WLength::Auto, Left | Right);
00230   p->resize(750, WLength::Auto);
00231   p->setMargin(20, Top | Bottom);
00232 
00233   // ---- Axis properties ----
00234 
00235   WStandardItemModel *yScales = new WStandardItemModel(0, 1, this);
00236   addEntry(yScales, "Linear scale");
00237   addEntry(yScales, "Log scale");
00238 
00239   WStandardItemModel *xScales = new WStandardItemModel(0, 1, this);
00240   addEntry(xScales, "Categories");
00241   addEntry(xScales, "Linear scale");
00242   addEntry(xScales, "Log scale");
00243   addEntry(xScales, "Date scale");
00244 
00245   WTable *axisConfig = new WTable();
00246   axisConfig->setMargin(WLength::Auto, Left | Right);
00247 
00248   ::addHeader(axisConfig, "Axis");
00249   ::addHeader(axisConfig, "Visible");
00250   ::addHeader(axisConfig, "Scale");
00251   ::addHeader(axisConfig, "Automatic");
00252   ::addHeader(axisConfig, "Minimum");
00253   ::addHeader(axisConfig, "Maximum");
00254   ::addHeader(axisConfig, "Gridlines");
00255   ::addHeader(axisConfig, "Label angle");
00256 
00257   axisConfig->rowAt(0)->setStyleClass("trhead");
00258 
00259   for (int i = 0; i < 3; ++i) {
00260     const char *axisName[] = { "X axis", "1st Y axis", "2nd Y axis" };
00261     int j = i + 1;
00262 
00263     const WAxis& axis = chart_->axis(static_cast<Axis>(i));
00264     AxisControl sc;
00265 
00266     new WText(WString(axisName[i], UTF8), axisConfig->elementAt(j, 0));
00267 
00268     sc.visibleEdit = new WCheckBox(axisConfig->elementAt(j, 1));
00269     sc.visibleEdit->setChecked(axis.isVisible());
00270     connectSignals(sc.visibleEdit);
00271 
00272     sc.scaleEdit = new WComboBox(axisConfig->elementAt(j, 2));
00273     if (axis.scale() == CategoryScale)
00274       sc.scaleEdit->addItem("Category scale");
00275     else {
00276       if (axis.id() == XAxis) {
00277         sc.scaleEdit->setModel(xScales);
00278         sc.scaleEdit->setCurrentIndex(axis.scale());
00279       } else {
00280         sc.scaleEdit->setModel(yScales);
00281         sc.scaleEdit->setCurrentIndex(axis.scale() - 1);
00282       }
00283     }
00284     connectSignals(sc.scaleEdit);
00285 
00286     bool autoValues
00287       =    axis.minimum() == WAxis::AUTO_MINIMUM
00288         && axis.maximum() == WAxis::AUTO_MAXIMUM;
00289 
00290     sc.minimumEdit = new WLineEdit(axisConfig->elementAt(j, 4));
00291     sc.minimumEdit->setText(boost::lexical_cast<std::string>(axis.minimum()));
00292     sc.minimumEdit->setValidator(anyNumberValidator);
00293     sc.minimumEdit->setEnabled(!autoValues);
00294     connectSignals(sc.minimumEdit);
00295 
00296     sc.maximumEdit = new WLineEdit(axisConfig->elementAt(j, 5));
00297     sc.maximumEdit->setText(boost::lexical_cast<std::string>(axis.maximum()));
00298     sc.maximumEdit->setValidator(anyNumberValidator);
00299     sc.maximumEdit->setEnabled(!autoValues);
00300     connectSignals(sc.maximumEdit);
00301 
00302     sc.autoEdit = new WCheckBox(axisConfig->elementAt(j, 3));
00303     sc.autoEdit->setChecked(autoValues);
00304     connectSignals(sc.autoEdit);
00305     sc.autoEdit->checked().connect(SLOT(sc.maximumEdit, WLineEdit::disable));
00306     sc.autoEdit->unChecked().connect(SLOT(sc.maximumEdit, WLineEdit::enable));
00307     sc.autoEdit->checked().connect(SLOT(sc.minimumEdit, WLineEdit::disable));
00308     sc.autoEdit->unChecked().connect(SLOT(sc.minimumEdit, WLineEdit::enable));
00309 
00310     sc.gridLinesEdit = new WCheckBox(axisConfig->elementAt(j, 6));
00311     connectSignals(sc.gridLinesEdit);
00312 
00313     sc.labelAngleEdit = new WLineEdit(axisConfig->elementAt(j, 7));
00314     sc.labelAngleEdit->setText("0");
00315     sc.labelAngleEdit->setValidator(angleValidator);
00316     connectSignals(sc.labelAngleEdit);
00317 
00318     axisConfig->rowAt(j)->setStyleClass("trdata");
00319 
00320     axisControls_.push_back(sc);
00321   }
00322 
00323   p = list->addWidget("Axis properties", axisConfig);
00324   p->setMargin(WLength::Auto, Left | Right);
00325   p->resize(750, WLength::Auto);
00326   p->setMargin(20, Top | Bottom);
00327 
00328   /*
00329    * If we do not have JavaScript, then add a button to reflect changes to
00330    * the chart.
00331    */
00332   if (!WApplication::instance()->environment().javaScript()) {
00333     WPushButton *b = new WPushButton(this);
00334     b->setText("Update chart");
00335     b->setInline(false); // so we can add margin to center horizontally
00336     b->setMargin(WLength::Auto, Left | Right);
00337     b->clicked().connect(SLOT(this, ChartConfig::update));
00338   }
00339 }


Member Function Documentation

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

Definition at line 341 of file ChartConfig.C.

00342 {
00343   fill_ = fill;
00344 }

void ChartConfig::connectSignals ( Wt::WFormWidget w  )  [private]

Definition at line 511 of file ChartConfig.C.

00512 {
00513   w->changed().connect(SLOT(this, ChartConfig::update));
00514   if (dynamic_cast<WLineEdit *>(w))
00515     w->enterPressed().connect(SLOT(this, ChartConfig::update));
00516 }

void ChartConfig::update (  )  [private]

Definition at line 346 of file ChartConfig.C.

00347 {
00348   bool haveLegend = false;
00349   std::vector<WDataSeries> series;
00350 
00351   for (int i = 1; i < chart_->model()->columnCount(); ++i) {
00352     SeriesControl& sc = seriesControls_[i-1];
00353 
00354     if (sc.enabledEdit->isChecked()) {
00355       WDataSeries s(i);
00356 
00357       switch (sc.typeEdit->currentIndex()) {
00358       case 0:
00359         s.setType(PointSeries);
00360         if (sc.markerEdit->currentIndex() == 0)
00361           sc.markerEdit->setCurrentIndex(1);
00362         break;
00363       case 1:
00364         s.setType(LineSeries);
00365         break;
00366       case 2:
00367         s.setType(CurveSeries);
00368         break;
00369       case 3:
00370         s.setType(BarSeries);
00371         break;
00372       case 4:
00373         s.setType(LineSeries);
00374         s.setFillRange(fill_);
00375         break;
00376       case 5:
00377         s.setType(CurveSeries);
00378         s.setFillRange(fill_);
00379         break;
00380       case 6:
00381         s.setType(BarSeries);
00382         s.setStacked(true);
00383         break;
00384       case 7:
00385         s.setType(LineSeries);
00386         s.setFillRange(fill_);
00387         s.setStacked(true);
00388         break;
00389       case 8:
00390         s.setType(CurveSeries);
00391         s.setFillRange(fill_);
00392         s.setStacked(true);     
00393       }
00394 
00395       s.setMarker(static_cast<MarkerType>(sc.markerEdit->currentIndex()));
00396 
00397       if (sc.axisEdit->currentIndex() == 1) {
00398         s.bindToAxis(Y2Axis);
00399       }
00400 
00401       if (sc.legendEdit->isChecked()) {
00402         s.setLegendEnabled(true);
00403         haveLegend = true;
00404       } else
00405         s.setLegendEnabled(false);
00406 
00407       switch (sc.labelsEdit->currentIndex()) {
00408       case 1:
00409         s.setLabelsEnabled(XAxis);
00410         break;
00411       case 2:
00412         s.setLabelsEnabled(YAxis);
00413         break;
00414       case 3:
00415         s.setLabelsEnabled(XAxis);      
00416         s.setLabelsEnabled(YAxis);
00417         break;
00418       }
00419 
00420       series.push_back(s);
00421     }
00422   }
00423 
00424   chart_->setSeries(series);
00425 
00426   for (int i = 0; i < 3; ++i) {
00427     AxisControl& sc = axisControls_[i];
00428     WAxis& axis = chart_->axis(static_cast<Axis>(i));
00429 
00430     axis.setVisible(sc.visibleEdit->isChecked());
00431 
00432     if (sc.scaleEdit->count() != 1) {
00433       int k = sc.scaleEdit->currentIndex();
00434       if (axis.id() != XAxis)
00435         k += 1;
00436       else {
00437         if (k == 0)
00438           chart_->setType(CategoryChart);
00439         else
00440           chart_->setType(ScatterPlot);
00441       }
00442 
00443       switch (k) {
00444       case 1:
00445         axis.setScale(LinearScale); break;
00446       case 2:
00447         axis.setScale(LogScale); break;
00448       case 3:
00449         axis.setScale(DateScale); break;
00450       }
00451     }
00452 
00453     if (sc.autoEdit->isChecked())
00454       axis.setRange(WAxis::AUTO_MINIMUM, WAxis::AUTO_MAXIMUM);
00455     else {
00456       if (validate(sc.minimumEdit) && validate(sc.maximumEdit)) {
00457         double min, max;
00458         getDouble(sc.minimumEdit, min);
00459         getDouble(sc.maximumEdit, max);
00460 
00461         if (axis.scale() == LogScale)
00462           if (min <= 0)
00463             min = 0.0001;
00464 
00465         axis.setRange(min, max);
00466       }
00467 
00468     }
00469 
00470     if (validate(sc.labelAngleEdit)) {
00471       double angle;
00472       getDouble(sc.labelAngleEdit, angle);
00473       axis.setLabelAngle(angle);
00474     }
00475 
00476     axis.setGridLinesEnabled(sc.gridLinesEdit->isChecked());
00477   }
00478 
00479   chart_->setTitle(titleEdit_->text());
00480 
00481   if (validate(chartWidthEdit_) && validate(chartHeightEdit_)) {
00482     double width, height;
00483     getDouble(chartWidthEdit_, width);
00484     getDouble(chartHeightEdit_, height);
00485     chart_->resize(width, height);
00486   }
00487 
00488   switch (chartOrientationEdit_->currentIndex()) {
00489   case 0:
00490     chart_->setOrientation(Vertical); break;
00491   case 1:
00492     chart_->setOrientation(Horizontal); break;
00493   }
00494 
00495   chart_->setLegendEnabled(haveLegend);
00496   chart_->setPlotAreaPadding(haveLegend ? 200 : 40, Right);
00497 }

bool ChartConfig::validate ( Wt::WFormWidget w  )  [static, private]

Definition at line 499 of file ChartConfig.C.

00500 {
00501   bool valid = w->validate() == WValidator::Valid;
00502 
00503   if (!WApplication::instance()->environment().javaScript()) {
00504     w->setStyleClass(valid ? "" : "Wt-invalid");
00505     w->setToolTip(valid ? "" : "Invalid value");
00506   }
00507 
00508   return valid;
00509 }


Member Data Documentation

Definition at line 47 of file ChartConfig.h.

Definition at line 48 of file ChartConfig.h.

Controls for series.

Definition at line 61 of file ChartConfig.h.

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

Controls for axes.

Definition at line 75 of file ChartConfig.h.

Definition at line 77 of file ChartConfig.h.

Definition at line 78 of file ChartConfig.h.

Definition at line 79 of file ChartConfig.h.

Definition at line 80 of file ChartConfig.h.


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

Generated on Tue Nov 3 15:34:40 2009 for Wt by doxygen 1.5.6