/*
 File:  Async.java
 A Java application to demonstrate how to handle AWT events in a separate thread
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
/**
 * This class demonstrates one method for handling AWT events
 * in a separate thread. Although most JVMs today will start a
 * separate thread for each user generated event, the programmer
 * does not have direct access to this thread and cannot easily
 * manipulate it.  For example if an event caused a network connection
 * and put up a modal dialog window to show the status of the connection,
 * the thread handling the event would block preventing the processing
 * of the newtwork connection to occur.  By staring a separate thread for
 * this network processing then it would be easy for the user to do
 * things like cancelling this processing via subsequent user actions.
 *
 * This example also shows how an anonymous class can be used to
 * accompish this off-level processing in a straightforward and
 * simple manner.
 *
 * This class extends Frame and puts up a window that has some
 * Menu options. 
 */

public class Async extends Frame implements ActionListener {

    // Menu options
    private MenuItem action1MI, action2MI, exitMI;

    // Thread used to do asynchronous processing
    private Thread aThread;

    // Services performed as a result of menu item action
    static final int ACTION_1 = 0;
    static final int ACTION_2 = 1;
    static final int EXIT     = 2;

    /**
     * This constructor creates our Frame and adds
     * all of its Menu components. It also sizes and
     * shows a new AsynchronousEventSample
     *
     */
    public Async() {
        super("Async Sample");

        // Create the menus
        MenuBar menubar = new MenuBar();
        Menu file = new Menu("File");
        action1MI = new MenuItem("Action 1");
        action2MI = new MenuItem("Action 2");
        exitMI  = new MenuItem("Exit");

        file.add(action1MI);
        file.add(action2MI);
        file.addSeparator();
        file.add(exitMI);

        menubar.add(file);

        setMenuBar(menubar);

        // Set up the event handling
        action1MI.addActionListener(this);
        action2MI.addActionListener(this);
        exitMI.addActionListener(this);
        
        addWindowListener(new WL());
        
        // Size and show the frame
        // pack() causes subcomponents of a window to be laid out 
        // at their preferred sizes
        pack();
        setSize(350,350);
        setVisible(true);
    }

    /**
     * This Window Listener supports the click of the "close X" 
     * at the top-right of the window.
     */
    class WL extends WindowAdapter {
        public void windowClosing(WindowEvent e) {
            System.out.println("User clicked on File|Exit or the 'close X'...");
            handleEventAsynchronous(EXIT);
        }
    }

    /**
     * Creates a new instance of Async which causes it 
     * to be shown and respond to menu events.
     */
    public static void main(String [] args) {
        Async f = new Async();
    }

    /**
     * Handles the events generated by selecting menu items. 
     * Required for ActionListener interface implementation.
     *
     * @see java.awt.event.ActionListener
     *
    */
    public void actionPerformed(ActionEvent event) {
        String command = event.getActionCommand();
        if (command.equals(action1MI.getLabel())) {
            handleEventAsynchronous(ACTION_1);
        } else if (command.equals(action2MI.getLabel())) {
            handleEventAsynchronous(ACTION_2);
        } else if (command.equals(exitMI.getLabel())) {
            handleEventAsynchronous(EXIT);
        }
    }

    // Called when the user selects the "Action 1 and Action 2" menu options.
    // Prints a simple message to the console
    private void action1() {
        System.out.println("Handling Action 1 event asynchronously...");
    }

    private void action2() {
            System.out.println("Handling Action 2 event asynchronously...");
    }


    // Called when the user selects the "Exit" menu option
    // Prints a simple message then removes the Frame from the
    // user's desktop
    private void exit() {
        System.out.println("Handling Exit event asynchronously");
        System.out.println("Exiting...");
        dispose();
        System.exit(0);
    }

    // Handles the menu item events in a separate thread

    private void handleEventAsynchronous(final int service) {

        // This anonymous class is used to handle menu events in a
        // separate thread.  It implements the Runnable interface
        // and provides the required run() method.  Note that it 
        // has access to the private instance variables and methods 
        // and that it of type Runnable which can be used in the 
        // constructor for a new thread.

        aThread = new Thread(new Runnable() {
                        public void run () {
                            switch (service) {
                            case ACTION_1:
                                action1();
                                break;
                            case ACTION_2:
                                action2();
                                break;
                            case EXIT:
                                exit();
                                break;
                            }  // end of switch
                        }  // end of run()
                    }  // end of new Runnable()
        );

        // Start the asynchronous processing
        aThread.start();
    }
}
