PopupButton component

Have you tried to use other add-ons with Maven? Do they work?

Hi, Henri! Thank you for the component. I use it and meet the problem with setWidget inside PopupLayout when newPopupComponent is VVerticalLayout:

public void updateFromUIDL(final UIDL uidl) {
			if (Util.isCached(uidl.getChildUIDL(0))) {
				return;
			}

			Paintable newPopupComponent = client.getPaintable(uidl
					.getChildUIDL(0));
			if (!newPopupComponent.equals(getPaintable())) {
				if (getPaintable() != null) {
					client.unregisterPaintable(getPaintable());
				}
				setWidget((Widget) newPopupComponent);
			}
			getPaintable().updateFromUIDL(uidl.getChildUIDL(0), client);
		}

VVerticalLayout try to invoke client method, when I do the following in server-side:


		final PopupButtonContainerWidth open = new PopupButtonContainerWidth("");
		open.setImmediate(true);
		open.addPopupVisibilityListener(new org.vaadin.hene.popupbutton.PopupButtonContainerWidth.PopupVisibilityListener() {
			
			@Override
			public void popupVisibilityChange(
					org.vaadin.hene.popupbutton.PopupButtonContainerWidth.PopupVisibilityEvent event) {
				if( event.isPopupVisible() )
					open.addComponent(multiSelectControl);
				else
					open.removeComponent(multiSelectControl);
				open.requestRepaintAll();
			}
		});

where multiSelectControl is verticalLayout with TreeTable and TextField. You can try it using the following example with minor modification:
TreeTableBug

I would appreciate you for any hints.

Thanks in advance,
Anatoly

It would be nice if the shadow component could also be modified.

For example, when the developer does this:

popupbutton.addStyleName("bubble") 

and this is at the moment seen in HTML code in the actual popup overlay element as:

v-popupbutton-popup-bubble

, this would also be added to the overlay’s shadow component as class name:

v-shadow-bubble

with regards, Marko.

Hi Marko,

you are correct, that feature would be useful. I’ll try to add it to the next release of PopupButton.

-Henri

Hi,
First of all - great add-on! :slight_smile: It works very good. I have a problem with it though. My case is the following: I’m implementing a button bar which is basically a CssLayout, where I put my buttons. The thing is that I want to have a button count threshold, so if I have more than 5 buttons, the rest shall be hidden into the PopupButton. So far so good. When the buttons become too many I try to remove the button from the CssLayout and add it into the PopupButton container. The problem occures when I try to hide some button, that has already been added to the CssLayout and I just want to move it to the popup, then the button is not visualized. If the button that I try to add is let’s say “new”, I mean it has not been added anywhere before that, it is properly shown in the popup. Also I made an experiment If I “open” (popup.setPopupVisible(true)) the popup right after I add the button, it is also properly shown. Any ideas ?

Regards! :slight_smile:

Would be great if you can prepare a small test application that demonstrates the problem.

Hi Henri,
I prepared a demo app, I tried to simplify as much as possible and in the same time preserve the approach that I use, because that might be the problem.

Here is the application:


package com.example.popupbuttonproblem;


import com.vaadin.Application;
import com.vaadin.ui.Button;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;


public class PopupbuttonproblemApplication
    extends Application
    implements Button.ClickListener
{

    private Button hideInPopup;
    private Button unhide;
    private Button button1;
    private Button button2;
    private Button button3;
    private Button button4;
    private Button button5;

    private Segment segment;


    @Override
    public void init()
    {
        Window mainWindow = new Window("Popupbuttonproblem Application");
        setMainWindow(mainWindow);
        button1 = new Button("Button 1");
        button2 = new Button("Button 2");
        button3 = new Button("Button 3");
        button4 = new Button("Button 4");
        button5 = new Button("Button 5");

        disableSomeButtons();

        segment = new Segment();
        segment.setButtonsThreshold(2);
        segment.addButton(button1);
        segment.addButton(button2);
        segment.addButton(button3);
        segment.addButton(button4);
        segment.addButton(button5);

        hideInPopup = new Button("Enable More Buttons", this);
        unhide = new Button("Disable buttons", this);

        mainWindow.addComponent(segment);
        mainWindow.addComponent(hideInPopup);
        mainWindow.addComponent(unhide);
        segment.recalculateLayout();
    }


    private void disableSomeButtons()
    {
        button1.setVisible(false);
        button2.setVisible(false);
        button5.setVisible(false);
    }


    private void enableSomeButtons()
    {
        button1.setVisible(true);
        button2.setVisible(true);
        button5.setVisible(true);

    }


    @Override
    public void buttonClick(ClickEvent event)
    {
        if (event.getButton().equals(hideInPopup))
        {
            enableSomeButtons();
        }
        else if (event.getButton().equals(unhide))
        {
            disableSomeButtons();
        }
        segment.recalculateLayout();
    }

}

What it does is basically create a new “Segment” which is my button bar and add some buttons in the button bar. Then I have two buttons “Enable More Buttons” and “Disable Buttons” that in a nutshell enable and disable some of the buttons and call Segment.recalculateLayout(), so when enabled the buttons become too many and some of them are hidden into the popup.

Here is the code of the Segment class:


package com.example.popupbuttonproblem;


import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;

import org.apache.commons.collections.IteratorUtils;
import org.vaadin.hene.popupbutton.PopupButton;

import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;

public class Segment
    extends CssLayout
{
    private static final long serialVersionUID = -3927863829208310646L;
    private static int DEFAULT_BUTTONS_THRESHOLD = 5;
    private int buttonsThreshold;
    private PopupButton popup;
    private VerticalLayout popupLayout;
    private LinkedHashSet<AbstractComponent> buttonsSet;

    public Segment()
    {
        setImmediate(true);
        buttonsSet = new LinkedHashSet<AbstractComponent>();

    }

    public void addButton(Button button)
    {
        if (!(button instanceof PopupButton))
        {
            buttonsSet.add(button);
        }
    }

    private ArrayList<AbstractComponent> getVisibleButtons()
    {
        Component c = null;
        ArrayList<AbstractComponent> visibleButtons = new ArrayList<AbstractComponent>();
        for (Iterator<AbstractComponent> iterator = buttonsSet.iterator(); iterator.hasNext();)
        {
            c = iterator.next();
            if (c.isVisible())
            {
                visibleButtons.add((AbstractComponent)c);
            }
        }
        return visibleButtons;
    }

    public void setButtonsThreshold(int threshold)
    {
        buttonsThreshold = threshold;
    }

    private int getButtonsThreshold()
    {
        if (buttonsThreshold > 0)
        {
            return buttonsThreshold;
        }
        return DEFAULT_BUTTONS_THRESHOLD;
    }

    public void recalculateLayout()
    {
        removeAllComponents();
        if (popupLayout != null)
        {
            popupLayout.removeAllComponents();
        }

        ArrayList<AbstractComponent> visibleButtons = getVisibleButtons();
        if (visibleButtons.size() > getButtonsThreshold())
        {
            popup = null;
            for (int j = 0; j < getButtonsThreshold(); j++)
            {
                addComponent((Button)IteratorUtils.toArray(visibleButtons.iterator())[j]
);
            }
            for (int j = getButtonsThreshold(); j < visibleButtons.size(); j++)
            {
                hideInPopup((Button)IteratorUtils.toArray(visibleButtons.iterator())[j]
);
            }
        }
        else
        {
            for (int j = 0; j < visibleButtons.size(); j++)
            {
                addComponent((Button)IteratorUtils.toArray(visibleButtons.iterator())[j]
);
            }
        }
    }


    private void hideInPopup(Button button)
    {
        if (popup == null || !popup.isVisible())
        {
            popup = addPopupButton("More");
        }
        addButton(button, popup);
    }


    public void addButton(Button b, final PopupButton popupButton)
    {
        if (popupLayout != null)
        {
            popupLayout.addComponent(b);
        }
        b.addListener(new ClickListener()
        {
            private static final long serialVersionUID = 4170589828529711781L;


            @Override
            public void buttonClick(ClickEvent event)
            {
                popupButton.setPopupVisible(false);
            }
        });
        popupButton.requestRepaintRequests();
    }


    public PopupButton addPopupButton(String caption)
    {
        popup = new PopupButton(caption);
        popup.setImmediate(true);
        popupLayout = new VerticalLayout();
        popupLayout.setWidth("80px");
        popup.setComponent(popupLayout);
        addComponent(popup);
        return popup;
    }
}

In a nutshell here I keep a set of all buttons that could be available for the button bar. From that set I get the buttons that are visible for the moment and if their count is more than the threshold I create a PopupButton and hide them into it. That logic is in method recalculateLayout().
So what happens when the app is started. Fist only “Button 3” and “Button 4” are visible. After clicking button “Enable More Buttons” “Button 1”, “Button 2” and “Button 5” are enabled, so the visible buttons become more than the treshold so the popup appears and it should contain “Button 3”, “Button 4” and “Button 5”. The problem is that “Button 3” and “Button 4” are not displayed properly, because they have been added to the CssLayot and then moved to the popup. And “Button 5” is displayed properly, because it has never been added before.

I’m sorry for the long post, I know it sounds a little bit confusing. I attach the war, so you could run it and take a closer look.
Thaks for the help, I appreciate it ! :slight_smile:
12270.war (6.03 MB)

I was able to solve the problem by adding a PopupVisibilityListener and within it I call event.getPopupButton().requestRepaintAll();


        popup.addPopupVisibilityListener(new PopupVisibilityListener()
        {
            
            public void popupVisibilityChange(PopupVisibilityEvent event)
            {
                if(event.isPopupVisible())
                {
                    event.getPopupButton().requestRepaintAll();
                }
            }
        });

Regards,
Blagovest

Hi, quick question.
I have a Form and an OpenLayers map wrapped in a Horizontal Layout as PopupButton content.
The first time i open the popup everything looks fine, but if i close it and open it again the map layers are not visible, I can only see the PanZoom and LayerSwitcher.
I tried the requestRepaintAll() solution and it does not even show the Popup content anymore.
map.requestRepaint has no effect either.

What do you think the problem is and how should i go about solving it?

Hi Henri, first of all thanks for this useful component!
Here’s my question: You wrote, the button opens its components above itself, when there’s not enough space below it. Where is this issue checked? I’d like to force my content always to be displayed below my button. Or any other hints?

Greetings, Guy

That’s checked in the
client-side code
.

Hello,

When I add PopupButton on panel which is scrollable,
and then open pop up and then scroll panel up or down with mouse wheel,
pop up is not moving with the content on panel which is below.
Pop up is fixed on its position inside browser.

I would like that pop up window is moving with the scrolled panel content below.

Is that any solution to force pop up to move together with the panel content while scrolling with mouse wheel,
or at least is there any solution to close pop up on mouse wheel.

Thanks for your response in advance,
best regards,
Dragan

Hello,
Can anyone help me to set the popup indicator right aligned, as you can see in the figure, it’s not right aligned ! I tried “float: right;” but not working fine !
12611.png

how can i add and remove component from PopupButton dynamic? it is not working, when i dynamic create and remove component.demo code:


        PopupButton switchButton = new PopupButton("dynamic test");
        switchButton.setStyleName(BaseTheme.BUTTON_LINK);        
        this.addComponent(switchButton);

        final HorizontalLayout buttonLayout = new HorizontalLayout();
        switchButton.setComponent(buttonLayout);

        buttonLayout.setSpacing(true);
        buttonLayout.setMargin(true);
        buttonLayout.addComponent(new Button("Button-One"));
        buttonLayout.addComponent(new Button("Button-Two"));

        Button addButton = new Button("add component");
        addButton.addListener(new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent event) {
                buttonLayout.addComponent(new Button("Button-X"));
            }
        });
        
        Button removeButton = new Button("remove component");
        removeButton.addListener(new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent event) {
                buttonLayout.removeAllComponent();
            }
        });
        
        

Hi, will be there newer version of this plugin for Vaadin 7.0.0beta11 (or RC1, when it’s out) in the near future? I use this useful component in my application which I’m currently migrating to Vaadin 7. The plugin version 2.1.0 works for beta9 and beta11 after some source code changes (via Vaadin migration guide), but in beta11, popup layout is broken and Vaadin Buttons added to popup aren’t shown like pushable components. Screenshots from PopupButton Plugin Demo in version beta9 and beta11:
12704.png
12705.png
12706.png
12707.png

Henri,

are you planning to port this to Vaadin 7 beta11/RC anytime soon? My FilteringTable add-on is kind of depending on it :slight_smile: I tried the alpha version but could not make it function properly with the V7RC (although tbh I didn’t put that much effort into it).

-tepi

hi henry… ur addon is great i just develop a POC on thst its working fine …but while using it in myapplication i am unable to useit… in place of button some text is showing …like
a tree structure
like as follows…

Widgetset does not contain implementation for org.vaadin.hene.popupbutton.PopupButton. Check its @ClientWidget mapping, widgetsets GWT module description file and re-compile your widgetset. In case you have downloaded a vaadin add-on package, you might want to refer to add-on instructions. Unrendered UIDL:
-Unrendered UIDL
-org.vaadin.hene.popupbutton.PopupButton(NO CLIENT IMPLEMENTATION FOUND) id=PID93 caption=here click position=auto xoffset=0 yoffset=0
-variables

You have to compile a widgetset for your application that contains PopupButton. Information about how to do it can be found from the forum or for example from
here
.

thanks henry…
its working …
actually i forgot to set the compilation…
its a nice add-on

Hey Henri,

Acutally the popup closes when I click somewhere outside the popup.
I would like to switch this behaviour to only close the popup when a my ClickListener is fired.

In all other cases the popup should stay visible.

THX
Oliver