Bug #13861
openWTabWidget 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 WTabWidget
s 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 3 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 about 2 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 about 2 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 4 days 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 about 4 hours ago
- Status changed from InProgress to Review
- Assignee changed from Matthias Van Ceulebroeck to Romain Mardulyn
Updated by Matthias Van Ceulebroeck about 4 hours ago
- Status changed from Review to Implemented @Emweb
- Assignee changed from Romain Mardulyn to Matthias Van Ceulebroeck
- % Done changed from 0 to 100