Bug #13861
closedWTabWidget does not size contents correctly when inserted with ContentLoading::Lazy
100%
Description
This behavior started after Wt 4.11.1 and is present in current version Wt 4.12.0. I use many WTabWidgets that are stretched to maximum size in layouts and this issue breakes my entire GUI.
If a tab is added with ContentLoading::Lazy the contents aren't rendered to full size of the surrounding WTabWidget upon first selection (see attached image). Switching between tabs or resizing the browser window leads to a refresh to the correct size.
This refers to current version Wt 4.12.0 on Windows 10; I see this behavior in Firefox and Edge. If compiled with Wt 4.11.1 or earlier this issue is not there.
Sample code that shows the problem:
#include <Wt/WApplication.h>
#include <Wt/WBootstrap5Theme.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WVBoxLayout.h>
#include <Wt/WText.h>
#include <Wt/WTabWidget.h>
#include <Wt/WPanel.h>
using namespace Wt;
std::unique_ptr<WPanel> createDummyPanel(WString title)
{
auto panel = std::make_unique<WPanel>();
auto cont = panel->setCentralWidget(std::make_unique<WContainerWidget>());
cont->decorationStyle().setBackgroundColor(WColor("lightblue"));
cont->addNew<WText>(title);
return panel;
}
std::unique_ptr<WApplication> createHelloApplication(const WEnvironment &env)
{
auto app = std::make_unique<WApplication>(env);
auto theme = std::make_shared<WBootstrap5Theme>();
app->setTheme(theme);
auto vl = app->root()->setLayout(std::make_unique<WVBoxLayout>());
auto tabs = vl->addWidget(std::make_unique<WTabWidget>(), 1);
tabs->addTab(createDummyPanel("Content 1 - Should be Full-Size"), "Tab 1", ContentLoading::Lazy);
// Problem:
// Tab2 isn't rendered full-size on first selection, due to ContentLoading::Lazy
// Tab3 with ContentLoading::Eager is okay
tabs->addTab(createDummyPanel("Content 2 - Should be Full-Size"), "Tab 2", ContentLoading::Lazy);
tabs->addTab(createDummyPanel("Content 3 - Should be Full-Size"), "Tab 3", ContentLoading::Eager);
vl->addWidget(std::make_unique<WText>("Bottom"));
return app;
}
int main(int argc, char *argv[])
{
return Wt::WRun(argc, argv, &createHelloApplication);
}
Files
Updated by Stefan Bn 8 months ago
In addition: I see the same behavior when a WMenu is used togehter with a WStackedWidget. When the stacked contents are added using deferCreate, then the size of the content with strechted layout is not shown full size upon first selection. Resizing the browser window only a little bit refreshs the view and the widgets jump to correct size.
auto dummyMenuItem = menu->addItem("Dummy Item", deferCreate(std::bind(&DumyView::createView, this)));
Updated by Stefan Bn 7 months ago
I did a little more research and I'm wondering why nobody else notices this. It's dramatic since it concerns the initial sizing of all WLayout that are inserted using ContentLoading::Lazy or deferCreate.
This behavior started in Wt 4.11.4 (previous version 4.11.3 is okay, but had the browser-freeze issue). So I assume this is somehow related to this issue/solution:
StdGridLayoutImpl2.js: ensure resizing stretchable items does not loop
https://redmine.emweb.be/issues/13685
Updated by Stefan Bn 7 months ago
I did a comparison of Wt 4.11.3 and 4.11.4:
https://github.com/emweb/wt/compare/4.11.3...4.11.4
There are changes in src/Wt/WStackedWidget.C and src/Wt/WMenu.C regarding the conditions for the events currentWidgetChanged, e.g.:
// Only emit if the item has changed, or if emitting has not yet happened.
if ((hasChanged || !hasEmittedChanged_) && currentIndex_ >= 0) {
if (loadPolicies_[currentIndex_] == ContentLoading::Lazy) {
// Lazy loaded widgets are wrapped in a WContainerWidget
WContainerWidget* container = dynamic_cast<WContainerWidget*>(currentWidget());
if (container->count() > 0) {
currentWidgetChanged().emit(container->widget(0));
hasEmittedChanged_ = true;
}
} else {
currentWidgetChanged().emit(currentWidget());
hasEmittedChanged_ = true;
}
}
}
In WStackedWidget it's now more restrictive if (container->count() > 0), maybe Lazy or deferred widgets don't get a signal due to this?
In WMenu the code-section that emits the currentWidgetChanged signal was completely removed.
Updated by Matthias Van Ceulebroeck 5 months ago
- Status changed from New to InProgress
- Assignee set to Matthias Van Ceulebroeck
- Target version set to 4.12.2
Updated by Matthias Van Ceulebroeck 5 months ago
- Status changed from InProgress to Review
- Assignee changed from Matthias Van Ceulebroeck to Romain Mardulyn
Updated by Matthias Van Ceulebroeck 5 months ago
- Status changed from Review to Implemented @Emweb
- Assignee changed from Romain Mardulyn to Matthias Van Ceulebroeck
- % Done changed from 0 to 100
Updated by Christian Meyer 2 months ago
There is another Issue when adding with Lazy Loading:
the first Item is not Styled as active. not even after switching between tabs.
Running on 4.12.1, tested with Code from the Widget Gallery
Updated by Romain Mardulyn 21 days ago
- Status changed from Implemented @Emweb to Closed