|
#include <thread>
|
|
#include <chrono>
|
|
#include <Wt/WApplication>
|
|
#include <Wt/WComboBox>
|
|
#include <Wt/WPushButton>
|
|
#include <Wt/WStandardItem>
|
|
#include <Wt/WStandardItemModel>
|
|
#include <Wt/WText>
|
|
#include <Wt/Chart/WCartesianChart>
|
|
|
|
using namespace Wt;
|
|
|
|
namespace {
|
|
const int MAX_ROWS = 20;
|
|
const int DELAY_DATA_MS = 5;
|
|
}
|
|
|
|
class NonStandardItemModel : public WStandardItemModel
|
|
{
|
|
public:
|
|
NonStandardItemModel(int rows, int columns, WObject *parent=0) :
|
|
WStandardItemModel(rows, columns, parent) { }
|
|
|
|
boost::any data(const WModelIndex &index, int role=DisplayRole) const override
|
|
{
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(DELAY_DATA_MS));
|
|
return WStandardItemModel::data(index, role);
|
|
}
|
|
};
|
|
|
|
class TestApplication : public WApplication
|
|
{
|
|
public:
|
|
TestApplication(const WEnvironment& env);
|
|
~TestApplication() { }
|
|
|
|
private:
|
|
bool zoomedIn_ = true;
|
|
Chart::WCartesianChart *chart_ = nullptr;
|
|
};
|
|
|
|
TestApplication::TestApplication(const WEnvironment& env) : WApplication(env)
|
|
{
|
|
setTitle("WCartesianChart Zoom Update Test");
|
|
|
|
new WText("<h5>Press 'Zoom Toggle' to switch between 2.0 and 1.0 zoom. See notes below.</h5>", root());
|
|
|
|
auto button = new WPushButton("Zoom Toggle", root());
|
|
auto button_log = new WPushButton("Log Only", root());
|
|
|
|
auto chartModel = new NonStandardItemModel(MAX_ROWS, 2, this);
|
|
|
|
chart_ = new Chart::WCartesianChart(Chart::ScatterPlot, root());
|
|
chart_->resize(400, 400);
|
|
chart_->setAutoLayoutEnabled();
|
|
chart_->setZoomEnabled();
|
|
chart_->setPanEnabled();
|
|
chart_->setModel(chartModel);
|
|
chart_->setXSeriesColumn(0);
|
|
chart_->addSeries(Chart::WDataSeries(1, Chart::PointSeries));
|
|
chart_->axis(Chart::XAxis).setRange(0.0, MAX_ROWS*2.0 + 1.0);
|
|
chart_->axis(Chart::YAxis).setRange(0.0, MAX_ROWS*2.0 + 1.0);
|
|
for (int i = 0; i < MAX_ROWS; ++i) {
|
|
std::string tooltip = "tool tip number " + boost::lexical_cast<std::string>(i + 1);
|
|
chartModel->setData(chartModel->index(i, 0), i + 1);
|
|
chartModel->setData(chartModel->index(i, 1), i + 1);
|
|
chartModel->setData(chartModel->index(i, 1), tooltip, ToolTipRole);
|
|
}
|
|
|
|
chart_->axis(Chart::XAxis).setZoom(2.0);
|
|
chart_->axis(Chart::YAxis).setZoom(2.0);
|
|
|
|
new WText(
|
|
"<h5>Notes:</h5>"
|
|
"<p>Because this test program is timing dependent, it may behave differently "
|
|
"on different systems. In testing with Wt 3.3.5-rc2 on at least one system, "
|
|
"the following could be observed:</p>"
|
|
"<ol>"
|
|
"<li>A quick mousedown/mouseup on 'Zoom Toggle' will first paint the expected "
|
|
"update, then revert it. This behavior is similar to what is observed when responding to "
|
|
"a selectionChanged() signal on a WTableView.</li>"
|
|
"<li>A long mousedown on 'Zoom Toggle' will paint the expected update and "
|
|
"it will not be reverted on mouseup.</li>"
|
|
"<li>Interactive panning or zooming followed by pressing 'Log Only' repaints "
|
|
"the entire chart. This is potentially expensive in CPU/bandwidth and is "
|
|
"not in direct response to user interaction where a delay might be expected.</li>"
|
|
"</ol>"
|
|
, root());
|
|
|
|
button->mouseWentDown().connect(std::bind([this] {
|
|
if (!zoomedIn_) {
|
|
chart_->axis(Chart::XAxis).setZoom(2.0);
|
|
chart_->axis(Chart::YAxis).setZoom(2.0);
|
|
chart_->axis(Chart::XAxis).setPan(0.0);
|
|
chart_->axis(Chart::YAxis).setPan(0.0);
|
|
// chart_->update();
|
|
zoomedIn_ = true;
|
|
log("test") << "Zoom Toggle button down, zooming in";
|
|
}
|
|
else {
|
|
chart_->axis(Chart::XAxis).setZoom(1.0);
|
|
chart_->axis(Chart::YAxis).setZoom(1.0);
|
|
chart_->axis(Chart::XAxis).setPan(0.0);
|
|
chart_->axis(Chart::YAxis).setPan(0.0);
|
|
// chart->update();
|
|
zoomedIn_ = false;
|
|
log("test") << "Zoom Toggle button down, zooming out";
|
|
}
|
|
}));
|
|
|
|
button->mouseWentUp().connect(std::bind([this] {
|
|
log("test") << "Zoom Toggle button mouse up";
|
|
}));
|
|
|
|
button_log->clicked().connect(std::bind([this] {
|
|
log("test") << "Log Only button clicked";
|
|
}));
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
return WRun(argc, argv, [](const WEnvironment& env) {return new TestApplication(env);});
|
|
}
|