package org.jcon.ui;

import org.jcon.util.GenLib;
import java.util.Hashtable;
import java.awt.event.ActionListener;

import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu; // extends JMenuItem
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

/**
 * A convenience wrapper for a JPopupMenu. Its most useful
 * feature is the ability to enable/disable menu items by
 * using their command.
 *
 * NOTE - Command and menu names must be unique.
 *
 * @author Jack Harich
 */
public class JPopupMenuHelper {

//---------- Private Fields ------------------------------
private JPopupMenu     popup = new JPopupMenu();
private ActionListener actionListener;

// Key = command, Object = JMenuItem
private Hashtable items = new Hashtable();

//---------- Public Methods ------------------------------
//---------- Initialization
/**
 * Sets the ActionListener to receive ActionEvents for the
 * popup's items. This MUST be set before adding items.
 */
public void setActionListener(ActionListener actionListener) {
    this.actionListener = actionListener;
}
/**
 * Adds a JMenuItem to the popup top level.
 */
public void addItem(String text, String command) {
    JMenuItem item = new JMenuItem(text);
    popup.add(item);
    addItem(command, item);
}
/**
 * Adds a JCheckBoxMenuItem to the popup top level.
 */
public void addCheckBox(String text, String command) {
    JMenuItem item = new JCheckBoxMenuItem(text);
    popup.add(item);
    addItem(command, item);
}
/**
 * Adds a JMenu to the popup top level.
 */
 public void addMenu(String text, String menuName) {
    JMenu menu = new JMenu(text);
    popup.add(menu);
    addItem(menuName, menu);
 }
/**
 * Adds a JMenuItem to the JMenu previously added named
 * menuName.
 */
public void addItemToMenu(String text, String command,
        String menuName) {
    JMenu menu = getMenu(menuName);
    if (menu == null) return;

    JMenuItem item = new JMenuItem(text);
    menu.add(item);
    addItem(command, item);
}
/**
 * Adds a JCheckBoxMenuItem to the JMenu previously added
 * named menuName.
 */
public void addCheckBoxToMenu(String text, String command,
        String menuName) {
    JMenu menu = getMenu(menuName);
    if (menu == null) return;

    JMenuItem item = new JCheckBoxMenuItem(text);
    menu.add(item);
    addItem(command, item);
}
/**
 * Adds a JMenu to the JMenu previously added named
 * @param menuName.
 */
public void addMenuToMenu(String text, String menuName) {
    JMenu parentMenu = getMenu(menuName);
    if (parentMenu == null) return;

    JMenu menu = new JMenu(text);
    parentMenu.add(menu);
    addItem(menuName, menu);
}
/**
 * Adds a separator to the previously added menu named
 * @param menuName.
 */
public void addSeparatorToMenu(String menuName) {
    JMenu menu = getMenu(menuName);
    if (menu == null) return;

    menu.addSeparator();
}
/**
 * Adds a separator to the popup top level. A separator is
 * not to be confused with at seperator. :>)
 */
public void addSeparator() {
    popup.addSeparator();
}
//---------- Other
public JPopupMenu getPopup() {
    return popup;
}
public void setEnabled(String command, boolean enabled) {
    JMenuItem item = getMenuItem(command);
    if (item != null) item.setEnabled(enabled);
}
public void setEnabledMenu(String menuName, boolean enabled) {
    JMenu menu = getMenu(menuName);
    if (menu != null) menu.setEnabled(enabled);
}
//----- CheckBox items
public boolean isSelected(String command) {
    JCheckBoxMenuItem item = getCheckBoxItem(command);
    if (item != null) {
        return item.isSelected();    
    } else {
        throw new IllegalArgumentException("CheckBox command '" + command + "' not found.");
    }
}
public void setSelected(String command, boolean selected) {
    JCheckBoxMenuItem item = getCheckBoxItem(command);
    if (item != null) item.setSelected(selected);
}
//---------- Private Methods -----------------------------
// Asserts command is unique
private boolean addItem(String command, JMenuItem item) {
    if (items.get(command) != null) {
        GenLib.error("JPopupMenuHelper.addItem()",
            "Item command '" + command + "' has already been added.\n"
            + "Commands must be unique per popup.");
        return false;
    } else {
        item.setActionCommand(command);
        item.addActionListener(actionListener);
        items.put(command, item);
        return true;
    }
}
private JMenu getMenu(String menuName) {
    JMenu menu = (JMenu)items.get(menuName);
    if (menu == null) {
        GenLib.error("JPopupMenuHelper.getMenu()",
            "Cannot find menuName '" + menuName + "'.");
        return null;
    } else {
        return menu;
    }
}
// Note JMenu extends JMenuItem, so cast is upward
private JMenuItem getMenuItem(String command) {
    JMenuItem item = (JMenuItem)items.get(command);
    if (item == null) {
        GenLib.error("JPopupMenuHelper.getMenuItem()",
            "Cannot find command '" + command + "'.");
        return null;
    } else {
        return item;
    }
}
private JCheckBoxMenuItem getCheckBoxItem(String command) {
    JCheckBoxMenuItem item = (JCheckBoxMenuItem)items.get(command);
    if (item == null) {
        GenLib.error("JPopupMenuHelper.getCheckBoxItem()",
            "Cannot find command '" + command + "'.");
        return null;
    } else {
        return item;
    }
}
//--- Std
private static void print(String text) {
    System.out.println(text);
}

} // End class
