package org.jcon.ui.menu;

import org.jcon.ui.CommandSourceEvent;
import org.jcon.ui.CommandSourceListener;
import org.jcon.ui.WindowMgr;
import org.jcon.ui.WindowLib;
import org.jcon.param.Param;
import org.jcon.param.ParamAccessor;
import org.jcon.param.ParamStoreResource; // For unit test
import org.jcon.util.GenLib;
import org.jcon.util.service.ContainerServices;
import java.awt.*;
import java.awt.event.*;
import java.util.Enumeration;
import java.util.Vector;

/**
 * A Param driven Frame with a MenuBar and useful methods.
 *
 * @author Jack Harich
 */
public class MenuFrame implements WindowListener,
    ActionListener, ItemListener, CommandSourceListener {

//---------- Private Fields ------------------------------
private Param          param;
private Frame          frame = WindowMgr.createRegisteredFrame();
private Vector         actionListeners = new Vector();
private Vector         itemListeners = new Vector();
private MenuBarParam   menuBarParam;
private String         windowClosingCommand = "CloseRequested";
private ContainerServices containerServices;
private boolean        initialized;

//---------- Initialization ------------------------------
public MenuFrame() {
    // Init frame
    frame.addWindowListener(this);
    frame.setBackground(Color.lightGray);
}
private void configFromParam() {
    //----- Prepare Param driven JMenuBar
    menuBarParam = new MenuBarParam(this);
    menuBarParam.setContainerServices(containerServices);
    menuBarParam.setItemListener(this);
    menuBarParam.setParamVector(param.getParamVector("MenuBar"));
    frame.setMenuBar(menuBarParam.getMenuBar());
    //----- Prepare Param driven Frame
    frame.setTitle(param.getString("Title"));
    int width = param.getInt("WindowWidth");
    int height = WindowLib.getMainMenuHeight();
	frame.setSize(width, height);
	// Set location
	int x = param.getInt("WindowLeft");
	int y = param.getInt("WindowTop");
	frame.setLocation(x, y);
}
public static void main(String args[]) { // Unit test
    //for (int i = 1; i <= 3; i++) {
        MenuFrame test = new MenuFrame();

        ParamAccessor accessor = new ParamAccessor();
        accessor.setMarkerClass(test);
        accessor.setResourceName("MenuFrame_Test.parex");
        Param testParam =  new ParamStoreResource()
            .readParam(accessor);

        test.setParam(testParam);
        test.setVisible(true);
    //}
}
//---------- WindowListener Implementatons ---------------
public void windowClosing(WindowEvent e) {
    ActionEvent evt = new ActionEvent(this,
        ActionEvent.ACTION_PERFORMED, windowClosingCommand);
    sendActionEvent(evt);
}
public void windowClosed(WindowEvent e) { }
public void windowDeiconified(WindowEvent e) { }
public void windowIconified(WindowEvent e) { }
public void windowOpened(WindowEvent e) { }
public void windowActivated(WindowEvent e) { }
public void windowDeactivated(WindowEvent e) { }

//---------- ActionListener Implementation ---------------
public void actionPerformed(ActionEvent evt) {
    sendActionEvent(evt);
}
//---------- ItemListener Implementation -----------------
public void itemStateChanged(ItemEvent evt) {
    sendItemEvent(evt);
}
//---------- CommandSourceListener Implementation --------
public void commandSourceChanged(CommandSourceEvent evt) {
    menuBarParam.commandSourceChanged(evt);
}
//---------- Properties ----------------------------------
public void setContainerServices(ContainerServices containerServices) {
    this.containerServices = containerServices;
}    
//----- windowClosingCommand
/**
 * Sets the command used when the actionListener is
 * notified of a windowClosing event. The default is
 * "CloseRequested" which is often the same logical event
 * as a Close button.
 */
public void setWindowClosingCommand(String command) {
    windowClosingCommand = command;
}
public String getWindowClosingCommand() {
    return windowClosingCommand;
}
//----- title
public String getTitle() {
    return frame.getTitle();
}
public void setTitle(String title) {
    frame.setTitle(title);
}
//----- visible
public void setVisible(boolean isVisible) {
    if (! initialized) {
         configFromParam();
         initialized = true;   
    }
    frame.setVisible(isVisible);
}
public boolean isVisible() {
    return frame.isVisible();
}
//---------- ParamDriven Implementation ------ (future) --
// We don't need the interface, but we do need the methods
public void setParam(Param param) {
    this.param = param;
    // ***configFromParam();
}
public Param getParam() {
    //print(".getParam() called, param is null = " + (param == null) );
    return param;
}
public boolean applyNewParam(Param newParam) {
    Param oldParam = param;
    param = newParam;
    try {
        configFromParam();
        return true;
    } catch(Exception ex) {
        GenLib.error("MenuFrame.applyNewParam()",
            "Apply failed so rolling back.");
        // Rollback to oldParam
        param = oldParam;
        configFromParam();
        return false;
    }
}
//---------- Events --------------------------------------
//----- Pair
/**
 * Adds the listener for the MenuBar action events, plus
 * for the windowClosing translated event.
 */
public void addActionListener(ActionListener listener) {
    actionListeners.addElement(listener);
}
public void removeActionListener(ActionListener listener) {
    actionListeners.removeElement(listener);
}
//----- Pair
public void addItemListener(ItemListener listener) {
    itemListeners.addElement(listener);
}
public void removeItemListener(ItemListener listener) {
    itemListeners.removeElement(listener);
}
//---------- Public Methods ------------------------------
public void menuItemListChanged(MenuItemListEvent evt) {
    menuBarParam.menuItemListChanged(evt);
}
public void dispose() {
    frame.dispose();
}
/**
 * Useful for using our Frame in Dialogs.
 */
public Frame getFrame() {
    return frame;
}
public Enumeration getMenuBarActionCommands() {
    return menuBarParam.getActionCommands();
}
//---------- Private Methods -----------------------------
private void sendActionEvent(ActionEvent evt) {
    Vector list = new Vector();
    synchronized(this) {
        list = (Vector)actionListeners.clone();
    }
    for (int i = 0; i < list.size(); i++) {
        ActionListener listener = (ActionListener)list.elementAt(i);
        listener.actionPerformed(evt);
    }
}
private void sendItemEvent(ItemEvent evt) {
    Vector list = new Vector();
    synchronized(this) {
        list = (Vector)itemListeners.clone();
    }
    for (int i = 0; i < list.size(); i++) {
        ItemListener listener = (ItemListener)list.elementAt(i);
        listener.itemStateChanged(evt);
    }
}
//--- Std
private static void print(String text) {
    System.out.println("MenuFrame" + text);
}

} // End class
