PopupButton not repainting when replace contents of layout

I am using PopupButton 1.2.1 under Vaadin 6.7.5, and I set it’s component to be a VerticalLayout that contains some buttons.

When the button is pressed, in the buttonClick(ClickEvent) callback, I do some processing and then recreate a new set of buttons in the VerticalLayout like this in brief:

popupButtonLayout.removeAllComponents();

create one or more Buttons, each with a new ClickListener(), and then add that button to the popupButtonLayout.

What I found is that the new buttons are not being displayed. The PopupButton shows no buttons (not even the original ones), so it seems to have handled the removeAllComponents() as expected, but it’s not showing the new buttons I put in that VerticalLayout after that.

Just for grins, I added popupButton.requestRepaintAll() to see what it would do, and I found in debug that PopupButton does tell the VerticalLayout (it’s component) to requestRepaint() and the layout sees all of the new buttons I’ve added and tells them to repaint. But the new buttons do not appear when I click on the popup button. I don’t think I need to call the requestRepaintAll() since when I add the new buttons to the VerticalLayout, it already calls the repaint request on them.

So, it seems to be something to do with PopupButton / VerticalLayout that is not actually handling this as I’d like.

Any ideas what might be causing this?

I don’t know if there’s a subtle bug in PopupButton based on the problem I had above (removing the components from the VerticalLayout set as the component of the PopupButton), but the work-around is straightforward enough.

Instead of removing all components from the layout, I remove all components from the PopupButton itself (which removes my VerticalLayout), then create and populate the VerticalLayout and set that as the component for the PopupButton. Now it refreshes as expected.

Also, not sure, but PopupButton.setComponent (and addComponent) both just replace the ‘component’ object with the parameter passed in, but it doesn’t do the same logic that removeComponent() does if an existing component is already set. Also, if you pass a null component to setComponent/addComponent, it’ll get a null pointer exception.

I’ve tweaked the subject on this thread a bit because I have now found that the PopupButton layout is not updating “well.” That is, I have a PopupButton that has a VerticalLayout as its contents, and that VerticalLayout contains a Tree. I have an Action on the Tree item so that a new node can be created, for example.

What happens is the new node is created, but it’s not shown when I next open the popup button. But if I collapse the tree and then re-open it, the new item is shown (so it really is there!).

I think this is similar to the original but I had when I would empty the layout and rebuild it, but I worked around that by removing the layout entirely and putting an all new layout in. I guess I could do the same here, but with my Tree (rather than 2-3 buttons), that sounds “expensive”.

I think PopupButton has some sort of issue not refreshing its contents when it is changed as the result of clicking on an item in its popup layout that results in the layout changing. (This was tested again under 6.7.6.)

Perhaps I have found the issue.

Because most operations done in the popup button’s layout involve actions that take place and then the popup button should be auto-closed, we do something like the following in our “action handler”:

((PopupButton)getParent().getParent()).setPopupVisible(false);

I think that maybe because we turn off the popup, the updates are not shown, often even on the next open of the popup button. In this latest case, that’s what happens until I close-reopen the tree node, then the new node appears.

I think that if the popup layout is both changed and then make not visible in the same action handler, the layout change is not being reflected on the next open of the popup. Does that make sense? I suspect the fact I make it not visible is causing the other layout changes to not be sent to the browser or otherwise maintained in the client’s widget state.