/* class JMenuBar
 *
 * Copyright (C) 2001-2003  R M Pitman
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package charvax.swing;

import charva.awt.*;
import charva.awt.event.KeyEvent;


/**
 * An implementation of a menubar.
 */
public class JMenuBar
        extends Container {

    /**
     * Create a new menu bar
     */
    public JMenuBar() {
        /* The menubar is always offset from the origin of its parent
         * JFrame by (1, 1).
         */
        super._origin = new Point(1, 1);
    }

    /**
     * Appends the specified menu to the end of the JMenuBar.
     *
     * @param menu_ the menu to be added.
     * @return the menu that was added.
     */
    public JMenu add(JMenu menu_) {
        JMenu jmenu = (JMenu) menu_;
        super.add(jmenu);
        return jmenu;
    }

    /**
     * Returns the number of menus in the menubar.
     */
    public int getMenuCount() {
        return super.getComponentCount();
    }

    /**
     * Returns the menu at the specified index.
     */
    public JMenu getMenu(int index_) {
        return (JMenu) super.getComponent(index_);
    }

    /**
     * Returns the menu that has the specified text label.
     */
    public JMenu getMenu(String text_) {
        for (int i = 0; i < getMenuCount(); i++) {
            JMenu menu = getMenu(i);
            if (menu.getText().equals(text_)) {
                return menu;
            }
        }
        throw new IllegalArgumentException("menubar does not contain menu \"" + text_ + "\"");
    }

    /**
     * Draw this menubar.
     */
    public void draw() {
        /* Get the absolute origin of this component.
         */
        Point origin = getLocationOnScreen();

        Toolkit term = Toolkit.getDefaultToolkit();

        int colorpair = getCursesColor();

        /* Build a horizontal line of spaces extending across the top
         * of the frame.
         */
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < getSize().width; i++) {
            buf.append(' ');
        }
        term.setCursor(origin);
        term.addString(buf.toString(), Toolkit.A_REVERSE, colorpair);

        Component[] menus = super.getComponents();
        int x = 0;
        for (int i = 0; i < menus.length; i++) {
            menus[i].setLocation(x, 0);
            menus[i].draw();
            x += menus[i].getWidth();
        }
    }

    /**
     * Processes key events occurring on this object by dispatching them
     * to any registered KeyListener objects.
     */
    public void processKeyEvent(KeyEvent ke_) {
//        Toolkit term = Toolkit.getDefaultToolkit();

        int key = ke_.getKeyCode();
        if (key == '\t') {
            getParent().nextFocus();
            ke_.consume();
            return;
        } else if (key == KeyEvent.VK_BACK_TAB) {
            getParent().previousFocus();
            ke_.consume();
            return;
        } else if (key == KeyEvent.VK_RIGHT) {
            Component currentFocus = super.getCurrentFocus();
            int menuCount = getMenuCount();
            int i = 0;
            for (i = 0; i < menuCount; i++) {
                if (currentFocus == super.getComponent(i))
                    break;
            }
            if (i == menuCount - 1)
                i = 0;
            else
                i++;
            getMenu(i).requestFocus();
            ke_.consume();
        } else if (key == KeyEvent.VK_LEFT) {
            Component currentFocus = super.getCurrentFocus();
            int menuCount = getMenuCount();
            int i = 0;
            for (i = 0; i < menuCount; i++) {
                if (currentFocus == super.getComponent(i))
                    break;
            }
            if (i == 0)
                i = menuCount - 1;
            else
                i--;
            getMenu(i).requestFocus();
            ke_.consume();
        } else {
            /* Check if one of the mnemonic keys was pressed.
             * Note that the user can press a lowercase or an uppercase
             * key.
             */
            char keyLower = Character.toLowerCase((char) key);
            for (int i = 0; i < super._components.size(); i++) {
                JMenu menu = getMenu(i);
                if (menu != null) {
                    if (menu.getMnemonic() == -1)
                        continue;   // this menu doesn't have a mnemonic

                    char mnemonicLower =
                            Character.toLowerCase((char) menu.getMnemonic());
                    if (keyLower == mnemonicLower) {
                        menu.doClick();
                        ke_.consume();
                        return;
                    }
                }
            }

            // Pass the KeyEvent on to the JMenu that originated it.
            super.processKeyEvent(ke_);
        }
    }

    public Dimension minimumSize() {
        int width = 0;
        for (int i = 0; i < getMenuCount(); i++) {
            width += getMenu(i).getText().length() + 1;
        }

        return new Dimension(width, 1);
    }

    public Dimension getSize() {
        return new Dimension(this.getWidth(), getHeight());
    }

    public int getWidth() {
        // get the width of our parent JFrame.
        Container parent = getParent();
        if (parent == null) {
            throw new IllegalComponentStateException("can't get menubar size before " +
                    "it has been added to a frame");
        }

        int parentwidth = parent.getWidth() - 2;
        int minwidth = minimumSize().width;
        int width = (parentwidth > minwidth) ? parentwidth : minwidth;
        return width;
    }

    public int getHeight() {
        return 1;
    }

    /**
     * Output a text description of the menubar.
     */
    public void debug(int level_) {
        for (int i = 0; i < level_; i++)
            System.err.print("    ");
        System.err.println(this.toString());
    }

    public String toString() {
        return "JMenuBar";
    }

    /**
     * Returns the index of the menu containing the point at the specified
     * screen coordinates, or -1 if no menu contains the point.
     */
    private int getMenuAt(int x, int y) {
        Point origin = getLocationOnScreen();
        int index = origin.x;
        for (int i = 0; i < getMenuCount(); i++) {
            String menutext = getMenu(i).getText();
            index += (menutext.length() + 1);
            if (x < index)
                return i;
        }
        return -1;
    }

    //====================================================================
    // PACKAGE-PRIVATE METHODS

    /**
     * Computes the absolute screen position for the specified JMenu.
     * This is a Charva-specific package-private method called by
     * the JMenu that wants to pop itself up. It is required because
     * JMenuBar is not implemented as a subclass of Container.
     * It is not intended to be called by application programmers.
     */
    Point getPopupMenuLocation(JMenu menu_) {
        /* Get the origin of this menubar
         */
        Point origin = getLocationOnScreen();

        int offset = 0;
        for (int i = 0; i < getMenuCount(); i++) {
            JMenu menu = getMenu(i);
            if (menu == menu_) {
                return origin.addOffset(offset, 1);
            }
            String menutext = menu.getText();
            offset += menutext.length() + 1;
        }
        throw new IllegalArgumentException("specified menu not in menubar");
    }

    //====================================================================
    // INSTANCE VARIABLES

}
