Replaceing main window

Is it a bug that the main window cannot be replaced on-the-fly?


public class Main extends Application implements ClickListener {

  @Override
  public void init() {

    setMainWindow( new Window() );

    Button button = new Button( "Replace main window" );
    button.addListener( this );

    getMainWindow().addComponent( button );
  }

  @Override
  public void buttonClick( ClickEvent event ) {
    setMainWindow( new Window( "New window" ) );
  }
}

The window is not replaced before a manual refresh. If this is the way it should be, why? I’d suggest to change this, as it doesn’t match the programmer’s expectation.

Basically the main window is the window that is shown when the application is opened for the first time. If you change the application main window you are not changing what the user sees but changing what window should be shown when the application is loaded. The user will still be in the old (main) window as you do not force him to move to the new window so he continues to see the contents of the old window. If the user refreshes the browser he will start using the new main window and see your changes, otherwise he will continue to use the old window (which is still part of the application as you now have a multi-window application).

This is a bit confusing when using only a main window but basically every window is assigned with an URL (/) and the main window is additionally assigned with the root of the application. The URL the users uses determines what Window is used in the server. For / it is the main window, for other urls it could be other windows. As each window can have its own theme and other settings a refresh/reload is required when changing windows.

Most of the time you are better off just changing the contents of the main window as this will update what the user sees and not involve any Window-magic.

If you want to force refresh of the window you can use the Window.open() method. Remember that you must do this on the ACTIVE window, not a new window. So your case would probably work using something like

    public void buttonClick(ClickEvent event) {
        Window newWindow = new Window("New window");
        getMainWindow().open(new ExternalResource(getURL()));
        setMainWindow(newWindow);
    }

but I would not recommend doing it this way…

Hi,

When reading article about
authenticating Vaadin-based applications
I got an impression that setMainWindow() could be used just as the original question implies. Can you suggest better practices for the use case described in the article.

Harri, as I recall, I wrote this article using Toolkit v5, so most likely, in that version it worked. Probably I’ll need to update an article if the current behavior is correct one.

Got around to testing some old versions today and I must say I am a bit curious in what version it has worked that way. I tested Vaadin 6.0.0, IT Mill Toolkit 5.3.0, IT Mill Toolkit 5.2.15 and IT Mill Toolkit 5.0.0 and did not get mainwindow replacing to work in any of them. However, I think it would be very handy in many cases if replacing the main window did work without doing a full refresh.

Just looked at one of my current app code, and here is how Im replacing the main window - on app startup a LoginWindow is created (this is the only window) and attached as main one, on successfull login, the new main window is set:

 
        MainWindow main = new MainWindow (); // This is the new main window we want to attach instead of old one
        main.setName ( "/" );
        addWindow ( main );
        setMainWindow ( main );

        // Login widow is the old (current) main window.
        loginWindow.open ( new ExternalResource ( main.getURL () ) );

The above code does not require manual browser refresh

I noticed that this does not work for Liferay Portlets, because the getUrl() returns null.

I came up with an other solution. That is to first remove all the components from the mainwindow. And then add all the components to the mainwindow.


public void rebuildMainWindow(Window window) {
        removeWindow(getMainWindow());
        setMainWindow(window);
    }

The only drawback is that, if an dummyUrl is invoked (when uploading). The application can no longer refresh, for some reason.


EDIT:
while debugging some other code we discovered the quickest way to repaint the main window.

I am trying to switch main windows on WebSphere Portal 6.1. Seems like I have to remove main window in order to fire refresh page and load new window (like suggested above). In that case my old window instance is removed from application. This is complicated in the situation when you actually need old window instance still available, in case “previous button”, etc.
Is there a way to invoke the same listener that is invoked while removing window from application?
Or is there any other way to handle multiple windows navigation within application level.

I just came across a really nice “Workaround”. Perhaps this is helpful for others. :bashful:

http://morevaadin.com/content/use-views-not-windows