Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Horizontally centering a popup window in Vaadin

Tags:

vaadin

vaadin7

I have added a popup window to my main UI as follows:

Window component = new Window();
UI.getCurrent().addWindow(component);

Now, I want my popup to be centered horizontally and e.g. 40 pixels from the top of the screen. As far as I can see Vaadin has 4 methods for positioning my window.

component.center()
component.setPosition(x, y)
component.setPositionX(x)
component.setPositionY(y)

None of these are really what I want. I was hoping at first that setPositionY might help me. This does allow me to get the right distance from the top, but the x-position is now set to 0, where I wanted it to be centered.

The setPosition might have helped if I was able to calculate what the x-position should be, but this would require me to know the width of the component in pixels, but component.getWidth just tells me 100%.

Next I tried to use CSS styling on the component, writing and explicit css rule and adding it to the component with addStyleName. It seems though that Vaadin overrides whatever I wrote in my css with its own defaults...

Any ideas how to get my Window component positioned correctly?

like image 751
Rikke Bendlin Gammelmark Avatar asked Oct 19 '22 11:10

Rikke Bendlin Gammelmark


2 Answers

I used the methods getBrowserWindowWidth() and getBrowserWindowHeight() from the com.vaadin.server.Page class for this.

I centered my "log" window horizontally in the lower part of the browser window with

myWindow.setHeight("30%");
myWindow.setWidth("96%");
myWindow.setPosition(
    (int) (Page.getCurrent().getBrowserWindowWidth() * 0.02),
    (int) (Page.getCurrent().getBrowserWindowHeight() * 0.65)
);
like image 141
Peti Avatar answered Oct 21 '22 05:10

Peti


Solution 1: Use SizeReporter

Indeed, setPositionY() will reset the window's centered property to false. As the width of your pop-up and that of your browser window are not know before they appear on the screen, the only way I know to get those values is to use the SizeReporter add-on. Its use is quite straightforward:

public class MyUI extends UI {

    private Window popUp;

    private SizeReporter popUpSizeReporter;
    private SizeReporter windowSizeReporter;

    @Override
    protected void init(VaadinRequest request) {

        Button button = new Button("Content button");
        VerticalLayout layout = new VerticalLayout(button);
        layout.setMargin(true);

        popUp = new Window("Pop-up", layout);
        popUp.setPositionY(40);

        addWindow(popUp);

        popUpSizeReporter = new SizeReporter(popUp);
        popUpSizeReporter.addResizeListenerOnce(this::centerPopUp);

        windowSizeReporter = new SizeReporter(this);
        windowSizeReporter.addResizeListenerOnce(this::centerPopUp);
    }

    private void centerPopUp(ComponentResizeEvent event) {

        int popUpWidth = popUpSizeReporter.getWidth();
        int windowWidth = windowSizeReporter.getWidth();

        if (popUpWidth == -1 || windowWidth == -1) {
            return;
        }

        popUp.setPositionX((windowWidth - popUpWidth) / 2);
    }
}

This piece of code will be okay as long as you don't resize the pop-up. If you do, it will not be automatically recentered. If you replace addResizeListenerOnce() by addResizeListener() then it will automatically recenter the pop-up but you'll get some "UI glitches" as the add-on sends resize events almost continually while you're resizing your pop-up...

You could try to do it using CSS, but I personally avoid CSS as much as I can with Vaadin :).

You'll need to recompile the widgetset after you've added the add-on as a dependency.

Solution 2: Use com.vaadin.ui.JavaScript

I won't vouch for the portability of this solution but I guess it will work on most modern browsers.

public class MyUI extends UI {

    private Window popUp;

    @Override
    protected void init(VaadinRequest request) {

        Button button = new Button("Content button");
        VerticalLayout layout = new VerticalLayout(button);
        layout.setMargin(true);

        popUp = new Window("Pop-up", layout);
        popUp.setPositionY(40);
        popUp.addStyleName("window-center");

        addWindow(popUp);

        // Add a JS function that can be called from the client.
        JavaScript.getCurrent().addFunction("centerWindow", args -> {
            popUp.setPositionX((int) ((args.getNumber(1) - args.getNumber(0)) / 2));
        });

        // Execute the function now. In real code you might want to execute the function just after the window is displayed, probably in your enter() method.
        JavaScript.getCurrent().execute("centerWindow(document.getElementsByClassName('window-center')[0].offsetWidth, window.innerWidth)");
    }
}
like image 25
nyg Avatar answered Oct 21 '22 04:10

nyg