# Copyright (C) 2001, 2002 by Intevation GmbH
# Author:
# Bernhard Herzog <bh@intevation.de>
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with Thuban for details.

"""Menu management"""

__version__ = "$Revision: 1.7 $"

from Thuban import _

class Menu:

    """Represent a menu or submenu.

    A menu has a name and a title. The name can be used to identify
    menus internally while the title is intended for use in the GUI.

    Menu items can be added with the Insert* methods.
    """

    def __init__(self, name, title, items = None):
        """Initialize the menu.

        Parameters:
           name -- the name of the menu
           title -- the (possibly localized) title of the menu
           items -- (optional) a list of menu items.

        The items list may contains strings with command names, None to
        indicate separators or Menu instances for submenus.
        """
        self.name = name
        self.title = title
        if items is None:
            self.items = []
        else:
            self.items = items

    def item_index(self, item):
        """Return the index of item in the menu.

        item -- may be the name of a non-menu entry or the
                name of a menu or a menu itself.

        Return None it item is not found.
        """
        for i in range(len(self.items)):
            temp = self.items[i]
            if temp == item:
                # this case takes care of item being the name of an
                # entry or a menu.
                return i
            elif isinstance(temp, Menu) and temp.name == item:
                # item is the name of a menu
                return i
        # Didn't find the item so return None
        return None

    def find_menu(self, name):
        """Return the submenu named name or None if no such item exists"""
        for item in self.items:
            if isinstance(item, Menu) and item.name == name:
                return item
        return None

    def InsertItem(self, item, menu = (), after = None):
        """Insert a menu item.

        Parameters:

         item -- the menu item to insert must be either a string with
                the command's name or a Menu instance.

         menu -- (optional) the submenu to insert into. It should be a
                sequence of menu names.

         after -- (optional) insert the new item after this one. after
                 should be the name of a command.
        """
        # if menu is given, get the first submenu
        if menu:
            submenu_index = self.find_menu(menu[0])
            if submenu_index is not None:
                submenu_index.InsertItem(item, menu = menu[1:], after = after)
            else:
                # the submenu doesn't exist yet. Raise an error.
                raise KeyError(_("Submenu %s doesn't exist") % menu[0])
        else:
            if after is not None:
                idx = self.item_index(after)
            else:
                idx = None

            if idx is not None:
                self.items.insert(idx + 1, item)
            else:
                self.items.append(item)

    def InsertSeparator(self, after = None):
        """Insert a separator

        after -- (optional) insert the separator after this one. after
                 should be the name of a command.
        """
        self.InsertItem(None, after = after)

    def InsertMenu(self, name, title, menu = (), after = None):
        """Insert and return a new menu.

        Parameters:

         name -- the (internal) name of the menu

         title -- the (possibly localized) title

         menu -- (optional) the submenu to insert into. It should be a
                sequence of menu names.

         after -- (optional) insert the new item after this one. after
                 should be the name of a command.
        """
        newmenu = Menu(name, title)
        self.InsertItem(newmenu, menu = menu, after = after)
        return newmenu

    def FindOrInsertMenu(self, name, title, menu = (), after = None):
        """
        Find the menu with the specified name. If found, return it.
        Else insert the menu as specified and return it.

        Parameters: See InsertMenu().
        """

        m = self.find_menu(name)
        if m is None:
            m = self.InsertMenu(name, title, menu, after)
        return m


    def SetItems(self, items):
        """Replace the contents of the menu by items."""
        self.items = items

    def RemoveItem(self, item):
        """Remove an item from the menu.

        item -- the (internal) name of the item.
        """
        i = self.item_index(item)
        if i is not None:
            self.items.pop(i)
