Bug #1072
closedButtons become unclickable in layouts with images and nonzero stretch factors
0%
Description
Hi,
It looks to me like WHBoxLayout and WVBoxLayout may have a bug when dealing with images. I narrowed the problem down to a test case (code below). In short, in layouts that contain an image and an element with a non-zero stretch factor, two problems appear:
1) Images are rendered across div (WContainerWidget) boundaries
2) Buttons that are placed in elements after the stretch are unclickable
The "unclickable" buttons are always unclickable on a freshly loaded browser (Firefox, Chrome, Safari). Sometimes, they can become clickable after other buttons on the page have been used.
In the test case I have a nested layout that uses a WHBoxLayout and a WVBoxLayout. Without the image, everything works fine. When the image is added, the image size seems to be ignored and it is rendered across the div boundary. Buttons in elements before the stretch element work as expected, but the button placed after it is apparently invisible to the browser. Any other widgets placed after the stretch also don't respond to events.
MyApplication::MyApplication(const WEnvironment& env):
WApplication(env)
{
useStyleSheet("CssStyleSheet.css"); //Just background-color to highlight where the divs are
//A vertical box layout fills out the root widget and contains two WContainerWidgets
WVBoxLayout* vLayout=new WVBoxLayout(root());
WContainerWidget *topContainer, *bottomContainer;
topContainer=new WContainerWidget; bottomContainer=new WContainerWidget;
vLayout->addWidget(topContainer);
vLayout->addWidget(bottomContainer);
topContainer->setStyleClass("grey");
vLayout->setStretchFactor(bottomContainer,1); //bottom container takes up all unused space
//A horizontal box layout fills out the topContainer and has four WContainerWidgets in it
WHBoxLayout* topLayout=new WHBoxLayout(topContainer);
WContainerWidget *topDiv1, *topDiv2, *topDiv3, *topDiv4;
topDiv1=new WContainerWidget; topDiv2=new WContainerWidget;
topDiv3=new WContainerWidget; topDiv4=new WContainerWidget;
topLayout->addWidget(topDiv1);
topLayout->addWidget(topDiv2);
topLayout->addWidget(topDiv3);
topLayout->addWidget(topDiv4);
topLayout->setStretchFactor(topDiv3,1); //Third WContainerWidget takes up all unused space
//An image is placed into the first top WContainerWidget
//Without the image, the bug does not show up
WImage* image=new WImage("Blue rectangle.jpg",topDiv1); //?? Image is rendered across the div boundary!
//Three buttons are added to containers 2,3, and 4. The one after the stretched element (topDiv3)
//Is unclickable
WPushButton *button2, *button3, *button4;
button2=new WPushButton(WString("Button 2"),topDiv2); //Clickable
button3=new WPushButton(WString("Button 3"),topDiv3); //Clickable
button4=new WPushButton(WString("Button 4"),topDiv4); //Unclickable!!
}
Files
Updated by Koen Deforche about 13 years ago
- Status changed from New to InProgress
- Assignee set to Koen Deforche
- Target version set to 3.2.0
Hey,
I couldn't reproduce this problem with the latest git version though (I tried Chrome, firefox and IE), so I would have to assume that this was solved.
Regards,
koen
Updated by Peter K about 13 years ago
- File Firefox_result.png Firefox_result.png added
- File IE9_result.png IE9_result.png added
Hi Koen,
Even with the latest git version, I can reproduce the bug by pasting the above code into the "Hello World" example... Attached are the images of the incorrectly rendered page in Firefox (bug present, unclickable button 4) and IE9 (no bug). The bug shows on Firefox, Chrome and Safari, but IE9 does not have it for some reason.
Loading the page in IE9 before loading it in Firefox fixes the issue in Firefox until the browser is closed (I don't know how that is possible!).
Also, to see the bug, the image file (here, "Blue_rectangle.jpg") must be in the executable's current directory. If the image is not found and not rendered, the bug will not show up.
I can always see the bug on the page by closing all browsers and then loading Firefox, Chrome or Safari.
Could it be a problem in the Windows build? My WT build is Win64 (with ZLIB and OpenSSL).
Thanks,
Peter
Updated by Koen Deforche about 13 years ago
- Target version changed from 3.2.0 to 3.2.1
Updated by Koen Deforche about 13 years ago
- Status changed from InProgress to Feedback
Hey,
I've managed to reproduce the problem. The reason is that the layout requires active size management, and this is computed before the image has been loaded. Resizing the window, for example, fixes this.
I'm not sure how to fix this without adverse side effects --- catching the onload signal of all images contained in a layout manager seems like overkill and could be a disaster when you have mnay images.
A workaround is to explicitly set a size to the image. In that way you also avoid possible flicker caused by reflowing the page when the image gets loaded.
Regards,
koen
Updated by Peter K about 13 years ago
I see... Setting the image size is fine as a solution, but the problem is that the application may not always know the size, right?
Just random ideas from the top of my head:
1) Is it possible to delay computing the layout until all the images have loaded?
2) Can I trigger recomputing the layout after everything on the page has loaded? (just like resizing the page does?)
Thank you,
Peter
Updated by Koen Deforche about 13 years ago
Hey,
Unfortunately, it is not that simple --- there is no catch all event handler for image loading and thus one needs to add handlers to every image --- something which is even more difficult because some images may also be part of XHTML that is not generated by Wt.
For 2) we could indeed document a method. The way you can do this is:
app->doJavaScript("window.onresize();");
Regards,
koen
Updated by Peter K about 13 years ago
Thanks, that solves it. It might be a good idea to add something to the documentation about this potential pitfall (Maybe to WImage and WBoxLayout sections?).
Regards,
Peter
Updated by Koen Deforche about 13 years ago
- Status changed from Feedback to Resolved
Hey,
Good idea. I added a note in the WBoxLayout documentation.
Regards,
koen