I have a Drawer set to width 100% in a GridLayout that’s also setWidth to 100%.
layout = new GridLayout(2,5);
layout.setWidth("100%");
layout.setColumnExpandRatio(0, 0.5f);
layout.setColumnExpandRatio(1, 0.5f);
layout.setMargin(false);
layout.setSpacing(true);
setLayout(layout);
permGroupDrawer = new Drawer();
permGroupDrawer.setWidth("100%");
permGroupDrawer.setVisible(false);
layout.addComponent(permGroupDrawer,0,4,1,4);
This lays out fine each time it initially is painted, filling the full width. But if I expand the browser window, you can see the other fields repaint to the new width, but the Drawer holds its original width. And this is worse when you make the browser window narrower since the contents of the Drawer are no longer visible on the right side (get truncated).
Below is a simple video showing how the TextFields resize to fill the space, but the Drawer does not. Basically, the video expands the window, and the rest of the page expands, but the drawer does not, then make the window smaller and the opposite happens.
Aww crap :(. I can say with 98% confidence that I’ve cut a wrong corner somewhere, so it’s a bug in the Drawer… I’ll make time to take a look on it this week, and see what’s up. I already have a guess for what’s the culprit, but I’m not yet sure what that would mean when it comes to ease of fix.
As always, thanks for the excellent and detailed bug report. I’ll report back once I have something.
Just as an FYI, Jouni created a great
Animation wrapper for Vaadin that looks great, and allows anyone to create Drawer-like functionality on the server-side. I haven’t used it, but it looks nice.
Does this mean you’re going to abandon the Drawer (may not need anything more)? It would be great if this sort of widget were part of the Vaadin core, perhaps using the Animation wrapper too. This exists in plain GWT – the DisclosurePanel, so shouldn’t Vaadin have it too?
How easy/hard would it be to create a Vaadin widget that just used GWT’s DisclosurePanel? I figure somehow it’s bigger than it seems since you’d want that panel to work inside the various Vaadin panels and such and perhaps they would not work easily together (I know they generally don’t for ExtGWT and SmartGWT for example).
Well, I haven’t had any thoughts of expanding Drawer’s functionality anyways. The thought daunts me, since what I have now seems to break quite easily already. Who knows what oddities are found if I expand the functionality further…
Well, that’s why I did the component, since it’s a pretty common pattern in other GUI environments. You can always hope they integrate the Drawer into the core library, but I haven’t heard of such plans, and I guess the development guys have other stuff on their hands. You can always file for a feature request in either
UserVoice (seems a bit desolate at the moment, unfortunately) or simply file a ticket to
Vaadin’s Trac (would force them to at least consider it, and give an official opinion).
I actually started by trying to wrap the DisclosurePanel into Vaadin, but it didn’t work, since it’s not a Vaadin client-side
Container for widgets. So I had to write it from scratch.
I know you’re not really wanting to support this much, but I’ve run into a few issues that was checking to see if you could fix or if you’ve decided it’s not worth it…
I’m not sure what it would mean to build a Drawer-like feature using the Animator component, presumably still needing to have the Arrow/Caption clickable area like your Drawer does today.
Using Drawer 1.1.5 with Vaadin 6.3.4, I have noted that the Drawer component, when opened, often causes my container’s layout to add scrollbars. In my case, I’ve got a Form that contains a GridLayout and the Drawer is put inside that. This causes the Drawer to clip its contents, as if it’s working on the sizes before the scrollbars are added.
When the Drawer first renders (closed), it shows the my 100% width just fine. But when I open the Drawer, the extra height causes vertical scrollbars to appear, which then narrows/resizes the rest of the form’s display, but the Drawer doesn’t appear to take into account that the scrollbars have appeared, so it will cause the contents in the drawer to be clipped.
If I size the browser window so that the scrollbars are there all the time, the Drawer works as expected because no scrollbars are added/removed as the drawer is opened and closed.
It appears to occur when the browser is resized, either bigger or smaller, while the drawer is closed AND no vertical scrollbars are present. When it first opens, it seems to clip the contents, like they are drawn just too big to account for the scrollbars that get added when it opens. But if you resize the browser window while the Drawer is open, it resizes its components just fine. You can then close and reopen the drawer and all is fine. But if you then resize the browser window while it’s closed, the next time I open the drawer, it’s off again, even if you resize to a wider view.
My guess is that somehow when it’s opening, it gets the size before the scrollbars are added on the right hand side, and this results in them being clipped. But when the scrollbars are already there (drawer is open) and it’s resized, it gets the right values and resizes the internal components correctly too.
I hope you can discover what this is.
I hope that Vaadin will decide to add such a component to its native world since this is a pretty common UI component – maybe something built on Animator as you suggested.
I am using Drawer 1.1.5 with Vaadin 6.4.0, and when I use ?debug on my browser URL to check the layouts, if a Form that contains a Drawer is open, I get the following exception. I have no idea how to troubleshoot this exception…
(9 July update: recompiled widgetset with detailed so hopefully a bit more meaningful stack trace)
When the Form is redrawn after adding ?debug to the URL, the entire Form contents is no longer shown except for the buttons in the Form’s footer.
If the drawer is closed, no such exception is shown and the layouts report no errors.
I also noted that just a browser refresh when a Drawer is open causes the same layout problem (all components are gone), but if the Drawers are closed, the browser refresh has no issue showing my Form again.
9 July update: Wonder if somehow the Drawer is being resized (it contains TwinColSelects that use Sets) somehow before they are populated on a refresh. But when I switch from a Drawer to a Panel that contains the TwinColSelect and use the Animator to rollup/rolldown, there is no error on refresh.
If anybody is interested, I have an Animator+Panel+Button custom component that is not as “simple pretty” as the Drawer, but doesn’t have any issues with the layout, reloads, etc. I am posting the code we use for our needs on the Animator forum area since it’s really about that component.
In a new Form that I have that contains only a single Drawer component, it appears to be okay – doesn’t throw the Exception and the Drawer will draw itself on browser refresh, and if it was open, it will refresh and still be open.
But in my Form that has multiple Drawers, the VGridLayout exception is still thrown, which then causes my Form to not render.
Ugh, this is not the best way to be awaken from a vacation-induced daze Anyways, always as nice to see you David doing an excellent job debugging the bugs in my junk!
Hm, yeah, I think the drawer caches the width of its contents, so I most probably haven’t taken into account those things. As for the exception, it’s hard to say what’s wrong just by the glance I took. There was a mention of GWT animation (which I do use for the open/close), which seems a bit odd.
I had thought to use some time on Friday for CF-stuff, so apparently debugging this will be high on the priority list :). Hopefully I get my other stuff (the boring sort) done before that… I’ll report back as soon as I know something.
According to my test application The Form seems irrelevant, but GridLayout isn’t. Multiple Drawers are also irrelevant; a single Drawer is enough to replicate this problem. Appearing scrollbars or resizing windows are, too, irrelevant.
This is the component hierarchy I have.
Window
Panel
VerticalLayout
GridLayout
Drawer
I replicate your exception by starting up a fresh application instance with “?restartApplication&debug”. Then I need to open the Drawer, modify the URI to “?debug” and press enter, to refresh the application. This produces the stack trace to the debug window. Node that the “debug” URI parameter has nothing to do with the bug itself, it’s just a way to see what the exception is.
One thing I noticed while debugging this is that GridLayout seems to be key to the problem. If I remove the GL from the hierarchy, and attach the Drawer directly to the VL, no exception is thrown. This would indicate that GL has a bug. Alas, Drawer still misbehaves: Upon refresh, the Drawer re-animates the last open/close action.
The root cause seems to be that the Drawer (somehow) triggers a query to GridLayout.requestLayout(), and on line 746 of that java file either minRowHeights is null, or minRowHeights[cell.row]
evaluates to null. My bet is that the minRowHeights array is uninitialized when it’s referenced.
I guess the expected is that if you have a closed Drawer, and once you click to open the Drawer and subsequently refresh the page, it would be rendered as opened. But, in this case, the Drawer will immediate render the close->open animation.
I need to fix that graphical glitch in Drawer, but I’ll talk to the Vaadin guys about whether the GL’s behavior is a bug or not.
I’m sorry, but I am unable to reproduce the problem. Having a 100% width Drawer in my window and resizing the window while the drawer is closed doesn’t cause the drawer to render erroneously once the drawer is opened. Tested with the latest versions of FireFox, Safari, Chrome and Opera (on a mac).
Take the latest version (1.1.7) and see if you still can reproduce this problem (I wouldn’t be surprised if the previous bugs were somehow linked.) If it still reproduces, I’m going to need a more specific description of the components inside the Drawer.
1.1.6 is now equipped with a fix that doesn’t cause an exception, but the graphical glitch isn’t fixed yet in this version. The GL throwing an exception was deemed kosher, since I was using Animation wrong. But Matti thought that measures could be placed against this happening again.
Sorry to have made your return from holiday such a bummer… Thanks for your help, though, in resolving these issues, small as they are in some ways.
I have tested 1.1.7 on the page refresh item, and it is great that it no longer gets the exception and causes my Form to not render. However, if a Drawer is open when I add ?debug and refresh, it is closed, but with the arrow pointing down like it’s supposed to be open. If I then click “Force layout” on the debug window, it does the animation to show it as open. “Analyze layouts” shows no errors on my page.
If after the refresh, instead of Force Layout, I click to “close” it, it animates open, then animates closed. This was tested on IE8 and FF 3.6 and Chrome 5. I tried multiple browser refreshes, and it results in the same “open arrow” but closed panel. Clicking to open other Drawers (I have 3 in the Form) work as expected and don’t affect the “bad state” one (that is, it neither animates open nor updates the icon to a right arrow to show it’s closed).
What is interesting, though, is that I have another Form with 2 Drawers, and this issue only occurs for the first Drawer, while the second Drawer will be re-opened on a refresh.
And I have another with just one Drawer, and it won’t re-open on refresh. The one with 3 Drawers, none will reopen.
Because the Drawers are on a Form, I wonder if something I’m doing helps bring it on. The Form is part of a splitpanel with a row/object selection from a Table in the other panel, so when the Form is first created, I create a Drawer (with no contents) and setVisible(false) – in a GridLayout:
permDrawer = new Drawer();
permDrawer.setWidth(100, UNITS_PERCENTAGE);
permDrawer.setVisible(false);
layout.addComponent(permDrawer,0,4,1,4);
Then, when setItemDataSource(Item) is called with a newly selected Item (row/object), , I call a routine that creates a VerticalLayout that itself contains 5 TwinColSelects (all populated in my DefaultFieldFactory.,createField() callback) and reset the drawer’s component:
VerticalLayout permLayout = new VerticalLayout();
permLayout.setMargin(false);
permLayout.setSpacing(true);
// All 5 TwinColSelects have been populated based on the setItemDataSource BeanItem
permLayout.addComponent(permListSelect);
permLayout.addComponent(permViewDetailsSelect);
permLayout.addComponent(permCreateLikeSelect);
permLayout.addComponent(permUpdateSelect);
permLayout.addComponent(permDeleteSelect);
Is this a correct way to do it? Would I be better off creating new Drawers and replacing them in my GridLayout? I think I had done that earlier, but figured it was overkill since the Drawer was fine, just the contents of the select boxes changed.
Thanks again for getting the exception fixed, though, since that was the primary issue for me.
I am beginning to think it’s somehow related to my TabSheet, perhaps when it’s in a SplitPanel. My main Window uses a VerticalLayout that contains a header (HorizontalLayout), followed by a SplitPanel, followed by a footer (a GridLayout). The splitpanel is:
navViewSplitPanel = new SplitPanel(SplitPanel.ORIENTATION_HORIZONTAL);
navViewSplitPanel.setStyleName(ChameleonTheme.SPLITPANEL_SMALL);
navViewSplitPanel.setSplitPosition(150, SplitPanel.UNITS_PIXELS);
The left side contains a Tree for navigation, while the right side contains the TabSheet. I have a simple view that I put add using TabSheet.addTab(). This simple view is a Panel, using a VerticalLayout that contains a Label in XHTML view. The Panel has setSizeFull(), and the Panel’s content (VerticalLayout) has no margin/spacing.
I found that the Label will clip on the right margin. So I also had to use the hack of setWidth(“98%”) to make it all appear. In fact, I have a short line that is aligned right, and it is clipped when the Label is its default 100%. And it doesn’t matter how wide I make the browser window, the right aligned text just keeps moving and clipping the right side. If I make it 98%, then it all appears. ?debug analyze layouts shows no errors either way. Force layout makes no difference.
If I make the Panel 98% width, I can see a right side margin, but the label contents are clipped.
If I instead make the Panel’s VerticalLayout 98%, I get the same right side margin with clipped content.
If I instead set the Panel’s VerticalLayout to setMargin(true), I get the margins (all around), but the Label contents are clipped.
But if I make the Label 98%, nothing is clipped.
My navigation system allows me to open the View in a popup Window, instead of a Tab, and the Label is not clipped.
Nor is it clipped if I open the view in a new browser window. It’s just when it’s in my TabSheet.
By the way, it doesn’t seem to be the TabSheet itself in the SplitPanel, because TabSheet has a gray line on the top and right side that is fully visible, and if I fill up the TabSheet so it’s more than the browser window can show, it produces LEFT/RIGHT arrows to scroll the tabs, and they are not clipped.
But the content of the TabSheet tab is getting clipped, so I’d have to guess it’s in there.
So, I found the same to be true when the Form that contains the Drawers is set to 98%, it looks fine. But when 100%, it clips.
What’s interesting about the Drawer clipping is that when you open the drawer, it’s clipped. If I NARROW the browser window, it then repaints correctly (so making it smaller – or wider – solves it). Once open, resizing the browser looks fine. If I close the Drawer, then WIDEN the browser window, then reopen the Drawer, it’s clipped. And again, if I then NARROW the browser while it’s open, it will be repaint fine.
So, because I see this on the Drawer in a Form in a SplitPanel (in a Tab), but I also see it in a Label in a Panel (in a Tab), I’m guessing it’s the Tab is causing this slight calculation issue. And this occurs in both FF 3.6, IE 8 and Chrome 5, etc. so it’s not just a browser calculation issue.
I know the 98% hack is not great, but it’s what I need to do now to make it work. I am using Vaadin 6.4.1.