When initially loading a WStackedWidget, all the content is set to a hidden state, with only the first item being visible.
Upon selecting a different index, that widget is made visible, and the previous one is hidden.
Now, on initially loading it may happen that with more complex content (e.g. an additional (StdGrid) layout manager), the content is not all propagated correctly to become visible.
This is only the case the first time the widget is loaded. Once it is made hidden and then visible again, it does correctly show.
Seemingly this happens because StdGridLayoutImpl2::createElement()
/ StdWidgetItemImpl::createDomElement()
sets the visibility:hidden
attribute. This is not correctly removed when the item's parent is set as the current active widget.
The same issue is present with a WMenu holding the same content in its stack if it is loaded eagerly.
#include <Wt/WApplication.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WEnvironment.h>
#include <Wt/WGridLayout.h>
#include <Wt/WMenu.h>
#include <Wt/WPushButton.h>
#include <Wt/WServer.h>
#include <Wt/WStackedWidget.h>
#include <Wt/WText.h>
#include <Wt/WVBoxLayout.h>
#include <string>
class CMachineInfo : public Wt::WContainerWidget
{
public:
CMachineInfo(std::string strMachine, std::string strConfig, std::string strModel)
{
addStyleClass("machine-info");
Wt::WGridLayout* grid = setLayout(std::make_unique<Wt::WGridLayout>());
auto pt = std::make_unique<Wt::WText>("Machine:");
grid->addWidget(std::move(pt), 0, 0);
pt = std::make_unique<Wt::WText>(strMachine);
grid->addWidget(std::move(pt), 0, 1);
pt = std::make_unique<Wt::WText>("Config:");
grid->addWidget(std::move(pt), 1, 0);
pt = std::make_unique<Wt::WText>(strConfig);
grid->addWidget(std::move(pt), 1, 1);
pt = std::make_unique<Wt::WText>("Model:");
grid->addWidget(std::move(pt), 2, 0);
pt = std::make_unique<Wt::WText>(strModel);
grid->addWidget(std::move(pt), 2, 1);
}
};
class CTestReportsView : public Wt::WContainerWidget
{
public:
CTestReportsView()
{
Wt::WVBoxLayout* vBox = setLayout(std::make_unique<Wt::WVBoxLayout>());
auto mi1 = std::make_unique<CMachineInfo>("M1", "1", "O.OO");
auto mi2 = std::make_unique<CMachineInfo>("M2", "2", "OO.O");
auto mi3 = std::make_unique<CMachineInfo>("M3", "3", "OOO.");
vBox->insertWidget(0, std::move(mi1), 1);
vBox->insertWidget(1, std::move(mi2), 1);
vBox->insertWidget(2, std::move(mi3), 0);
}
};
class StackApplication : public Wt::WApplication
{
public:
StackApplication(const Wt::WEnvironment& env)
: Wt::WApplication(env)
{
Wt::WStackedWidget* wid_MainViewStack = root()->addNew<Wt::WStackedWidget>();
wid_MainViewStack->setMargin(15, Wt::Side::Top);
wid_MainViewStack->addNew<Wt::WText>("Hello");
wid_MainViewStack->addNew<CTestReportsView>();
auto btn = root()->addNew<Wt::WPushButton>("Go to next");
btn->clicked().connect([this, wid_MainViewStack] {
wid_MainViewStack->setCurrentIndex(nextIndex_++);
if (nextIndex_ == 2) {
nextIndex_ = 0;
}
});
auto menuStack = root()->addNew<Wt::WStackedWidget>();
auto menu = root()->addNew<Wt::WMenu>(menuStack);
menu->addItem("Item 1", std::make_unique<Wt::WText>("Hello"));
menu->addItem("Item 3", std::make_unique<CTestReportsView>(), Wt::ContentLoading::Lazy);
menu->addItem("Item 4", std::make_unique<CTestReportsView>(), Wt::ContentLoading::Eager);
}
private:
int nextIndex_ = 1;
};
int main(int argc, char** argv)
{
Wt::WRun(argc, argv, [](const Wt::WEnvironment& env) { return std::make_unique<StackApplication>(env); });
}