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 52 of file ChartConfig.C.

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


Member Function Documentation

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

Definition at line 333 of file ChartConfig.C.

00334 {
00335   fill_ = fill;
00336 }

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

Definition at line 506 of file ChartConfig.C.

00507 {
00508   w->changed().connect(SLOT(this, ChartConfig::update));
00509   if (dynamic_cast<WLineEdit *>(w))
00510     w->enterPressed().connect(SLOT(this, ChartConfig::update));
00511 }

void ChartConfig::update (  )  [private]

Definition at line 338 of file ChartConfig.C.

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

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

Definition at line 494 of file ChartConfig.C.

00495 {
00496   bool valid = w->validate() == WValidator::Valid;
00497 
00498   if (!WApplication::instance()->environment().javaScript()) {
00499     w->setStyleClass(valid ? "" : "Wt-invalid");
00500     w->setToolTip(valid ? "" : "Invalid value");
00501   }
00502 
00503   return valid;
00504 }


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 Sep 1 17:51:23 2009 for Wt by doxygen 1.5.6