|
#include <Wt/WServer>
|
|
#include <Wt/WStackedWidget>
|
|
#include <Wt/WAnimation>
|
|
#include <Wt/WTimer>
|
|
#include <Wt/WText>
|
|
#include <Wt/WBreak>
|
|
#include <Wt/WTable>
|
|
#include <Wt/WPushButton>
|
|
#include <Wt/WBootstrapTheme>
|
|
|
|
using namespace Wt;
|
|
|
|
class TestApplication : public WApplication
|
|
{
|
|
public:
|
|
TestApplication(const WEnvironment& env);
|
|
|
|
private:
|
|
void step();
|
|
void start_stepping(int anim_time);
|
|
WColor col_color(int col);
|
|
|
|
static constexpr int Cell_Width {16};
|
|
static constexpr int Cell_Height {16};
|
|
static constexpr int Table_Cols {48};
|
|
static constexpr int Table_Rows {20};
|
|
static constexpr int Table_Width {Table_Cols * Cell_Width};
|
|
static constexpr int Table_Height {Table_Rows * Cell_Height};
|
|
static constexpr int Column_Group {6};
|
|
static constexpr int Step_Time {2000};
|
|
static const int Animation_Time[];
|
|
|
|
WBootstrapTheme bs_theme_;
|
|
WStackedWidget* sw_ {nullptr};
|
|
WTimer timer_;
|
|
int anim_time_ { Animation_Time[0] };
|
|
int cnt_ {0};
|
|
WText* status_ {nullptr};
|
|
};
|
|
|
|
const int TestApplication::Animation_Time[] {50, 1000, 3000};
|
|
|
|
TestApplication::TestApplication(const WEnvironment& env) : WApplication(env)
|
|
{
|
|
setTitle("Stuttering WStackedWidget Animations");
|
|
setTheme(&bs_theme_);
|
|
|
|
WContainerWidget *w = new WContainerWidget(root());
|
|
new WText("<b>NOTES:</b><br/>"
|
|
"Look for stuttering transitions at 1000ms, particularly with FireFox...<br/>"
|
|
"Content stops being displayed when animation time exceeds step time, at 3000ms.<br/><br/>", w);
|
|
|
|
for (auto anim_time: Animation_Time) {
|
|
auto pb = new WPushButton((boost::lexical_cast<std::string>(anim_time) + " ms."), w);
|
|
pb->clicked().connect(std::bind(&TestApplication::start_stepping, this, anim_time));
|
|
}
|
|
|
|
new WBreak(w);
|
|
|
|
status_ = new WText(w);
|
|
|
|
new WBreak(w);
|
|
|
|
sw_ = new WStackedWidget(w);
|
|
sw_->setMargin(30, Top);
|
|
sw_->resize(Table_Width, Table_Height);
|
|
|
|
for (int i = 0; i < 2; ++i) {
|
|
auto t0 = new WTable();
|
|
t0->resize(Table_Width, Table_Height);
|
|
for (int r = 0; r < Table_Rows; ++r) {
|
|
for (int c = 0; c < Table_Cols; ++c) {
|
|
auto w0 = t0->elementAt(r, c);
|
|
w0->resize(Cell_Width, Cell_Height);
|
|
}
|
|
}
|
|
sw_->addWidget(t0);
|
|
}
|
|
|
|
timer_.timeout().connect(this, &TestApplication::step);
|
|
timer_.setInterval(Step_Time);
|
|
timer_.start();
|
|
start_stepping(Animation_Time[0]);
|
|
}
|
|
|
|
void TestApplication::start_stepping(int anim_time)
|
|
{
|
|
anim_time_ = anim_time;
|
|
static const int step_time {Step_Time};
|
|
status_->setText("Step Time: " + boost::lexical_cast<std::string>(step_time) +
|
|
"ms, <b>Animation Time: " + boost::lexical_cast<std::string>(anim_time) + "ms</b>");
|
|
}
|
|
|
|
void TestApplication::step() {
|
|
int next_index = 1 - sw_->currentIndex();
|
|
|
|
auto t = dynamic_cast<WTable*>(sw_->widget(next_index));
|
|
|
|
for (int r = 0; r < Table_Rows; ++r) {
|
|
for (int c = 0; c < Table_Cols; ++c) {
|
|
t->elementAt(r, c)->decorationStyle().setBackgroundColor(col_color(c));
|
|
}
|
|
}
|
|
|
|
sw_->setTransitionAnimation(WAnimation(WAnimation::Fade, WAnimation::Linear, anim_time_));
|
|
sw_->setCurrentIndex(next_index);
|
|
++cnt_;
|
|
}
|
|
|
|
WColor TestApplication::col_color(int col) {
|
|
// sequence active columns through colors: red, blue, green (at 50% alpha)
|
|
if ((col % Column_Group) == (cnt_ % Column_Group))
|
|
return WColor(!(col % 3) * 256, !((col + 1) % 3) * 256, !((col + 2) % 3) * 256,128);
|
|
else
|
|
return WColor(white);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
return WRun(argc, argv, [](const WEnvironment& env) {return new TestApplication(env);});
|
|
}
|