Multi-Window Applications

One of Echo's most unique features is its ability to conveniently manage multiple browser windows. Echo will ensure that all of the windows that an application believes to be open on the client are in fact open, and provides notification to the application when windows are closed.

This chapter demonstrates using multiple windows with an example class called WindowDemo. It extends the previous chapter's LayoutDemo class, adding a dialog box that allows the user to select an exact border size for the sample grid shown in the central pane of the browser.

When the user clicks the "Change Border Size" button in the layout demo, its ActionListener calls LayoutDemo's changeBorderSize() method. The WindowDemo class overrides this method. LayoutDemo's implementation of this method causes the border size to rotate between values of 0, 1, 2, 4, and 8 pixels. WindowDemo's overriding implementation will now provide the user with a dialog box such that s/he can precisely select a border size of between 0 and 8 pixels.

To open new windows, an application will create a new Window component and then provide it as a parameter to the addWindow() method of the EchoInstance object. In this case, WindowDemo is a subclass of EchoInstance, so it calls addWindow() directly.

When a window is "manually" closed, e.g., by using the "X" or "close" button, an event notification will immediately be sent to the application. WindowEvents will be fired to all registered WindowListeners by way of their windowClosing() methods. Additionally, the window will act on its "default close operation." The "default close operation" is a configurable property of a window used to specify what the window will do when a user attempts to close it. A developer may choose to specify that the window is automatically closed, hidden, or that no action is taken. In the case of this example, the setDefaultCloseOperation() method is invoked to configure the window to allow itself to automatically be closed by users.

If you have the Echo Tutorial Examples installed, you may run this example by visiting http://localhost:8080/EchoTutorial/windowdemo. You must change the hostname and port number if your server is not running on localhost on port 8080.

import java.util.Enumeration;

import nextapp.echo.Button;
import nextapp.echo.Color;
import nextapp.echo.ContainerPane;
import nextapp.echo.ContentPane;
import nextapp.echo.EchoInstance;
import nextapp.echo.EchoConstants;
import nextapp.echo.Filler;
import nextapp.echo.Label;
import nextapp.echo.SelectField;
import nextapp.echo.Window;

import nextapp.echo.event.ActionListener;
import nextapp.echo.event.ActionEvent;

import nextapp.echoservlet.EchoServer;

public class WindowServlet extends EchoServer {

    public EchoInstance newInstance() {
        return new WindowDemo();
    }
}

// This class extends the LayoutDemo.  It enhances it by 
// providing a user selectable border size between 0 and 8
// pixels instead of simply toggling among 0, 1, 2, 4, and 
// 8 pixels like the overriden version of changeBorderSize()
// did. It overrides only the changeBorderSize() method.  
// The  LayoutDemo object calls the changeBorderSize() 
// method when the user clicks the "Change Border Size" 
// button.  
class WindowDemo extends LayoutDemo {

    // This class needs to keep track of the state of the 
    // popup window and the select field inside of it.
    private SelectField select;
    private Window popup = null;

    // This method will be called by LayoutDemo when the
    // user clicks the "Change Border Size" button.
    public void changeBorderSize() {
    
        // If the popup window is open, close it.
        if (popup != null && popup.isVisible()) {
            popup.dispose();
        }
        
        // Create a new 300x150 popup window with the title
        // "Change Border Size"
        popup = new Window("Change Border Size");
        popup.setWidth(300);
        popup.setHeight(150);
        
        // Set the default close operation to 
        // DISPOSE_ON_CLOSE.  This will cause the popup
        // window to disappear and be destroyed if the
        // user clicks it's close button.  If you do not
        // set this attribute, the window will be reopened.
        popup.setDefaultCloseOperation(
                Window.DISPOSE_ON_CLOSE);

        // The popup window will have two panes, one which
        // contains a select field and the other which 
        // contains an Ok button.
        
        // Create the main pane.
        ContentPane mainPane = new ContentPane();
        
        mainPane.add(new Label(
                "Select a border size for the grid:"));
        mainPane.add(Filler.createVerticalStrut(10));

        // Setup the select field.  The select field can 
        // take an array of options in the form of Objects
        // as a parameter to its constructor.  It will 
        // display each object visually by calling its 
        // toString() method.
        // In this case, we create an array of strings from
        // "0" to "8".
        Object[] items = new Object[9];
        for (int index = 0; index <= 8; ++index) {
            items[index] = Integer.toString(index);
        }
        
        // Create the SelectField
        select = new SelectField(items);
        
        // Set the selected index of the SelectField to the
        // current border size of the grid.
        // The demoGrid variable is a protected instance
        // variable of LayoutDemo, which this class extends.
        select.setSelectedIndex(demoGrid.getBorderSize());
        
        mainPane.add(select);
        
        // Create the button pane.
        ContentPane buttonPane = new ContentPane();
        buttonPane.setHeight(30);
        buttonPane.setForeground(Color.WHITE);
        buttonPane.setBackground(BUTTON_PANE_BLUE);
        buttonPane.setScrollBarPolicy(
                ContentPane.SCROLL_BAR_NEVER);
        
        Button ok = new Button("Ok");
        buttonPane.add(ok);
        
        // Add an anonymous inner class as an action 
        // listener for the OK button.
        ok.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // When clicked, the selected value of the
                // select field is determined and the
                // border of the demo grid is set
                // accordingly.
                demoGrid.setBorderSize(Integer.parseInt(
                        select.getSelectedItem()
                        .toString()));
                
                // Close the popup window.
                popup.dispose();
                popup = null;
            }
        });
        
        // Create a container pane and add the main pane
        // and the button pane to it.
        ContainerPane container = new ContainerPane();
        container.setOrientation(
                ContainerPane.ORIENTATION_VERTICAL);
        container.add(mainPane);
        container.add(buttonPane);
        
        // Set the container to be the contents of the popup
        // window.
        popup.setContent(container);
                
        // Add the window to the EchoInstance using the
        // addWindow() method.  This will cause it to be 
        // opened on the user's browser.
        addWindow(popup);
    }
}