5

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?

  • I removed my answer since it was wrong. The thing seems to be, that the `center()` is executed on client side. Do you know the width of your popup window? (Usually you have to define the width) – André Schild Apr 15 '16 at 12:20
  • No, I do not know the width of my popup window, it is dependent on the content. And as I mentioned the getWidth method on a component is not much help, as it simply return 100 %. – Rikke Bendlin Gammelmark Apr 15 '16 at 13:00

2 Answers2

3

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)
);
pbaris
  • 4,525
  • 5
  • 37
  • 61
Peti
  • 1,670
  • 1
  • 20
  • 25
1

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)");
    }
}
nyg
  • 2,380
  • 3
  • 25
  • 40
  • Unfortunately the project I am working on is not too fond of using various add-ons, especially not for such a small thing as this. I tried using CSS as well but without any luck. It seems that my only options might be to make my own custom component... – Rikke Bendlin Gammelmark Apr 18 '16 at 08:47
  • No worries, I totally understand, this kind of thing should be built into Vaadin. Maybe you can open a ticket there (dev.vaadin.com). However, I believe I have found another solution, I will post it in a bit... – nyg Apr 20 '16 at 20:21
  • Thanks, I will accept your answer. I would just have wished that the functionality was possible directly in Vaadin :-) – Rikke Bendlin Gammelmark Apr 25 '16 at 11:19