//*****************************************************************************
/*
** FILE:   xu_MenuItemElement.java
**
** (c) 1998 Steve Withall.
**
** HISTORY:
**    07May98  stevew  Created.
*/
package xu;

import xg.xg_Element;
import xg.xg_Node;
import xg.xg_VerificationException;

import eh.eh_Debug;

import com.sun.java.swing.Action;
import com.sun.java.swing.ImageIcon;
import com.sun.java.swing.JButton;
import com.sun.java.swing.JCheckBoxMenuItem;
import com.sun.java.swing.JMenuItem;
import com.sun.java.swing.JRadioButtonMenuItem;

//*****************************************************************************
/** An XML element to represent a Swing menu item.
 */
public class xu_MenuItemElement extends xg_Element
{
    /** The menu item created by this element. */
    protected JMenuItem        TheMenuItem      = null;

    /** The element type name normally used in XML for this sort of element. */
    public final static String RegisteredName   = "MenuItem";

    /** The name of the attribute which holds the ID of this menu item. */
    public final static String IdAttName        = "Name";

    /** The name of the attribute which holds the label to put on this menu item. */
    public final static String LabelAttName     = "Label";

    // Values relating to the type of menu item to create.
    /** The name of the attribute which holds the type of this menu item. */
    public final static String TypeAttName      = "Type";

    /** If Type="Normal", we create a plain JMenuItem. (This is the default if the
     *  'Type' attribute is omitted.) */
    public final static String NormalTypeName   = "Normal";

    /** If Type="Checkbox", we create a JCheckBoxMenuItem. */
    public final static String CheckBoxTypeName = "CheckBox";

    /** If Type="Radio", we create a JRadioButtonMenuItem. */
    public final static String RadioTypeName    = "Radio";

    // Values relating to the state of the menu item.
    /** The name of the attribute which holds the type of this menu item. */
    public final static String StateAttName     = "State";

    /** If a checkbox or radio button menu item has a State attribute with this
     *  value, its state will be set to true. */
    public final static String StateTrueValue   = "true";

    //*****************************************************************************
    /** Construct a menu item element with no name.
     */
    public xu_MenuItemElement()
    {
    }

    //*****************************************************************************
    /** Construct a menu item with a name.
     *
     *  @param  InputNodeName  The name of the element
     */
    public xu_MenuItemElement(String InputNodeName)
    {
        super(InputNodeName);
    }

    //*****************************************************************************
    /** <p>Verify that this node is correct (ie. internally correct and/or
     *  consistent with other nodes - such as its parent). The node is OK iff it
     *  has a 'Name' attribute, has a valid 'Type' attribute ("Normal", "CheckBox"
     *  or "Radio" - defaulting to "Normal" if this attribute is omitted), it lives
     *  inside a "FrameConfig", and it has a 'Label' attribute.</p>
     *
     *  @exception  xg_VerificationException  Description of verification problem
     */
    public void verify() throws xg_VerificationException
    {
        eh_Debug.add(8, "xu_MenuItemElement.verify: Verify '" + toString() + "'");

        // Obtain the menu item's ID from the "Name" attribute.
        String  NameValue = getAttributeValueVerified(IdAttName);

        Action  MenuItemAction = getAction(NameValue);
        createMenuItem(NameValue, MenuItemAction);  // Create dependent on the "Type" attribute

        if (MenuItemAction != null)
        {
            TheMenuItem.addActionListener(MenuItemAction);
            setItemIcon(MenuItemAction);
  	    }

        // Obtain the menu item's text from the "Label" attribute.
        String  LabelValue = getAttributeValueVerified(LabelAttName);
        TheMenuItem.setText(LabelValue);
    }

    //*****************************************************************************
    /** <p>Get from the parent document (if there is one) the named action.</p>
     *
     *  @param  InputActionName  The name of the required action
     */
    public Action getAction(String  InputActionName)
    {
        eh_Debug.add(8, "xu_MenuItemElement.getAction: Get action '"
                              + InputActionName + "' from frame config document");

        // Retrieve the document this menu item belongs to.
        Action   MenuItemAction = null;
        xg_Node  RootNode       = getRootNode();
        if (    RootNode == null
             || !(RootNode instanceof xu_FrameConfigDocument) )
            eh_Debug.add(3, "Menu item '" + InputActionName
                               + "'not within a 'xu_FrameConfigDocument',"
                               + "  so cannot retrieve associated Action");
        else
        {
            // Retrieve this menu item's associated Action from the FrameConfig.
            xu_FrameConfigDocument  ConfigDocument = (xu_FrameConfigDocument)RootNode;
            MenuItemAction = ConfigDocument.getAction(InputActionName);
  	    }

        return MenuItemAction;
    }

    //*****************************************************************************
    /** <p>Create a menu item. The 'Type' attribute determines whether we should
     *  create a normal, checkbox or radio button item (defaulting to normal if the
     *  'Type' attribute is omitted).</p>
     *
     *  @param      InputItemName The name of the menu item
     *  @param      InputAction   The action associated with this menu item (if there
     *                            is one).
     *  @exception  xg_VerificationException  Description of verification problem
     */
    protected void createMenuItem(String  InputItemName,
                                  Action  InputAction) throws xg_VerificationException
    {
        eh_Debug.add(8, "xu_MenuItemElement.createMenuItem:");
        String   TypeValue = getAttributeValue(TypeAttName);
        if (    TypeValue == null
             || TypeValue.equals(NormalTypeName) )
            createNormalMenuItem(InputItemName, InputAction);
        else if (TypeValue.equals(CheckBoxTypeName) )
            createCheckBoxMenuItem(InputAction);
        else if (TypeValue.equals(RadioTypeName) )
            createRadioMenuItem(InputAction);
        else
            throw new xg_VerificationException("Menu item type '" + TypeValue + "' invalid",
                                               getStartOffset(),
                                               getEndOffset() );
    }

    //*****************************************************************************
    /** Create a normal menu item (an instance of xu_MenuItem, which is basically
     *  just a JMenuItem - although it holds the attributes of this element).
     *
     *  @param  InputItemName  The name of the menu item
     *  @param  InputAction    The action associated with this menu item (if any).
     */
    protected void createNormalMenuItem(String  InputItemName,
                                        Action  InputAction)
    {
        xu_MenuItem  NewNormalMenuItem = new xu_MenuItem();
        NewNormalMenuItem.setAttList(ElementAttList);
        TheMenuItem = NewNormalMenuItem;
//        TheMenuItem = new JMenuItem();
        if (InputAction == null)
   	    {
   	        // Can't find an action with this name - so disable the menu option.
            eh_Debug.add(3, "xu_MenuItemElement.createNormalMenuItem: Cannot find action '"
                                  + InputItemName + "', so disable menu item");
  	        TheMenuItem.setEnabled(false);
  	    }
    }

    //*****************************************************************************
    /** Create a check box menu item.
     *
     *  @param  InputAction  The action associated with this menu item (if any).
     */
    protected void createCheckBoxMenuItem(Action  InputAction)
    {
        JCheckBoxMenuItem  NewCheckBoxMenuItem = new JCheckBoxMenuItem();
        TheMenuItem = NewCheckBoxMenuItem;
        boolean  StateFlag = setActionState(InputAction);
        NewCheckBoxMenuItem.setState(StateFlag);
    }

    //*****************************************************************************
    /** Create a radio button menu item.
     *
     *  @param  InputAction  The action associated with this menu item (if any).
     */
    protected void createRadioMenuItem(Action  InputAction)
    {
        JRadioButtonMenuItem  NewRadioButtonMenuItem = new JRadioButtonMenuItem();
        TheMenuItem = NewRadioButtonMenuItem;
        boolean  StateFlag = setActionState(InputAction);
        NewRadioButtonMenuItem.setSelected(StateFlag);
    }

    //*****************************************************************************
    /** Retrieve the boolean 'State' attribute, and set the state of the InputAction
     *  if it is an xu_CheckBoxAction.
     *
     *  @param  InputAction  The action associated with this menu item (if any).
     */
    protected boolean setActionState(Action  InputAction)
    {
        boolean  StateFlag = getState();
        if (    (InputAction != null)
             && InputAction instanceof xu_CheckBoxAction)
            ((xu_CheckBoxAction)InputAction).setState(StateFlag);
        return StateFlag;
    }

    //*****************************************************************************
    /** <p>Set this menu item's icon image from the icon image in its action (if
     *  the action has one).</p>
     *
     *  @param  InputAction  The action from which to obtain the image
     */
    protected void setItemIcon(Action  InputAction)
    {
        eh_Debug.add(8, "xu_MenuItemElement.setItemIcon");
        Object  ActionImageObject = InputAction.getValue(xu_ActionElement.ImageAttName);
        if (    ActionImageObject != null
    	     && ActionImageObject instanceof ImageIcon)
    	{
    	    TheMenuItem.setHorizontalTextPosition(JButton.RIGHT);
    	    TheMenuItem.setIcon((ImageIcon)ActionImageObject);
  	    }
    }

    //*****************************************************************************
    /** Get the logical value of the "State" attribute. It is true if it exists and
     *  has the value "true", and false otherwise
     *
     *  @return  true if 'State="true"'; false otherwise
     */
    public boolean getState()
    {
        boolean  LogicalState = false;
        String  StateValue = getAttributeValue(StateAttName);
        if (    (StateValue != null)
             && StateValue.equals(StateTrueValue) )
            LogicalState = true;
        return LogicalState;
    }

    //*****************************************************************************
    /** Get the menu item created by this element.
     *
     *  @return  The menu item itself
     */
    public JMenuItem getMenuItem()
    {
        return TheMenuItem;
    }

    //*****************************************************************************
    /** Get a summary descriptive string suitable for display in the tree view or
     *  elsewhere.
     *
     *  @return  A description suitable for display in the tree view
     */
    public String toString()
    {
        return (NodeName + " element '" + NodeName + "'");
    }
}

//*****************************************************************************
