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

"""
Command Objects.

Command objects represent a command that a user can invoke and act as
mediators between the GUI and the application.

This module also defines a command registry that maps command names to
command objects.
"""

__version__ = "$Revision: 1.4 $"


from types import TupleType


class Command:

    """
    Represent a single command.

    A command is identified by a name, it has a title (used in menu
    items and buttons, etc) and a callable object that can be invoked
    with the context as a single parameter. The context is an object
    with a few public attributes for the application object, the session
    and the main window.

    Additionally, a command may have functions that can determine
    whether the command can be invoked or whether it is checked in case
    of a toggled command. These functions are called with just the
    context as parameters.
    """
    
    args = ()
    kwargs = None
    sensitive  = None
    checked = None
    dyntext = None

    def __init__(self, name, title, function, helptext = "", icon = "",
                 args = (), kwargs = None,
                 sensitive = None, checked = None, dyntext = None):
        self.name = name
        self.title = title
        self.function = function
        self.helptext = helptext
        self.icon = icon
        if args != ():
            if type(args) != TupleType:
                args = (args,)
            self.args = args
        if kwargs is not None:
            self.kwargs = kwargs
        if sensitive is not None:
            self.sensitive = sensitive
        if checked is not None:
            self.checked = checked
        if dyntext is not None:
            self.dyntext = dyntext

    def Name(self):
        return self.name

    def Title(self):
        return self.title

    def HelpText(self):
        return self.helptext

    def Icon(self):
        return self.icon

    def Sensitive(self, context):
        if self.sensitive is not None:
            return self.sensitive(context)
        return 1

    def Checked(self, context):
        if self.checked is not None:
            return self.checked(context)
        return 0 # XXX raise an exception?

    def IsCheckCommand(self):
        return self.checked is not None

    def DynText(self, context):
        if self.dyntext is not None:
            return self.dyntext(context)
        return self.Title()

    def HasDynText(self):
        return self.dyntext is not None

    def IsDynamic(self):
        """Return true if the command is in any way dynamic"""
        return (self.sensitive is not None
                or self.checked is not None
                or self.dyntext is not None)

    def IsTool(self):
        """Return whether the command represents a tool.

        This default implementation always returns 0.
        """
        return 0

    def Execute(self, context, args = ()):
        kw = self.kwargs
        if kw is None:
            kw = {}
        if type(args) != TupleType:
            args = (args,)
        #print self.name, self.args, args
        apply(self.function, (context,) + self.args + args, kw)

class ToolCommand(Command):

    """A command tool activating a tool"""

    def IsTool(self):
        """Return whether the command represents a tool, i.e. always 1"""
        return 1


class CommandRegistry:

    """
    A CommandRegistry maps command names to command objects
    """

    def __init__(self):
        self.registry = {}

    def Add(self, script):
        self.registry[script.name] = script

    def AddFunction(self, name, title, function, args = (), sensitive = None):
        self.Add(Command(name, title, function, args = args,
                         sensitive = sensitive))

    def Command(self, name):
        return self.registry.get(name, None)



# The central command registry
registry = CommandRegistry()
