# -*- coding: iso-8859-1 -*-
#
#-------------------------------------------------------------------------------
#                    Code_Saturne version 1.3
#                    ------------------------
#
#
#     This file is part of the Code_Saturne User Interface, element of the
#     Code_Saturne CFD tool.
#
#     Copyright (C) 1998-2007 EDF S.A., France
#
#     contact: saturne-support@edf.fr
#
#     The Code_Saturne User Interface is free software; you can redistribute it
#     and/or modify it under the terms of the GNU General Public License
#     as published by the Free Software Foundation; either version 2 of
#     the License, or (at your option) any later version.
#
#     The Code_Saturne User Interface 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 General Public License for more details.
#
#     You should have received a copy of the GNU General Public License
#     along with the Code_Saturne Kernel; if not, write to the
#     Free Software Foundation, Inc.,
#     51 Franklin St, Fifth Floor,
#     Boston, MA  02110-1301  USA
#
#-------------------------------------------------------------------------------

"""
This module defines basic classes used for the Pages construction.

This module defines the following classes:
- DataValidator2
- Callback
- Page
"""

#-------------------------------------------------------------------------------
# Library modules import
#-------------------------------------------------------------------------------


import Tix
from Tkconstants import *
import tkMessageBox


#-------------------------------------------------------------------------------
# Application modules import
#-------------------------------------------------------------------------------


from Common import *
import Toolbox


#-------------------------------------------------------------------------------
# Module utility classes and functions 
#-------------------------------------------------------------------------------


class DataValidator2:
    """
    Validate the data.
    """
    def _blank(self, entry):
        """
        Blank the entry selectbackground
        """
        entry.config(background=wm['textbackground'])
        entry.config(foreground=wm['textforeground'])


    def _cancelJob(self):
        """
        Delete the callback id of the 'after' request
        """
        try:
            self.entry.after_cancel(self._job_id)
            self._blank(self.entry)
        except:
            pass


    def begin(self, entry):
        """
        Color the entry contains in green.
        """
        self._cancelJob()
        entry.config(background=wm['selectvalidate'])
        entry.config(selectbackground=wm['selectbackground'])
        entry.config(selectforeground=wm['selectforeground'])

        # Call function 'self._blank' once after 0,3 seconds.
        #
        self.entry = entry
        self._job_id = self.entry.after(300, self._blank, self.entry)


    def error(self, entry):
        """
        Make a BEEP and color the entry contains in red.
        """
        self._cancelJob()

        if Toolbox.GuiParam.beep == 'on':
            entry.bell()

        entry.selection_range(0,END)
        entry.config(selectbackground=wm['selecterror'])
        entry.config(selectforeground=wm['selectforeground'])


    def _error(self, entry, Error, text=""):
        """
        1) Make a BEEP and color the entry contains in red,
        2) If the entry contains nothing, a '?' is set in a red background
        """
        self.error(entry)
        if entry.index(END) == 0:
            entry.insert(END,'000')
            entry.config(selectbackground=wm['selecterror'])
            entry.config(selectforeground=wm['selectforeground'])
            entry.selection_range(0,END)
        return 0


    def hasType(self, entry, var):
        """
        This method validates the Type of the value, when an error
        occurs, an exception TypeError is raised. This value must
        be an instance fron IntVar(), DoubleVar(), or StringVar().
        """
        self.begin(entry)
        try:
            data = var.get()
            return 1
        except:
            return self._error(entry, TypeError, "value has not the good type")


    def isPositive(self, entry, var):
        """
        This method validates the positivity of the value, when an error
        occurs, an exception ValueError is raised.
        """
        if self.hasType(entry, var):
            if var.get() < 0:
                return self._error(entry, ValueError, "value must be positive")
            else:
                return 1
        else:
            return 0


    def isSPositive(self, entry, var):
        """
        This method validates the strict Positivity of the value, when an error
        occurs, an exception ValueError is raised.
        """
        if self.hasType(entry, var):
            if var.get() <= 0:
                return self._error(entry, ValueError, "value must be positive or zero")
            else:
                return 1
        else:
            return 0


    def isBetween(self, entry, var, min=None, max=None):
        """
        This method validates the min/max of the value, when an error
        occurs, an exception ValueError is raised.
        """
        if self.hasType(entry, var):
            if min != None and var.get() < min:
                return self._error(entry, ValueError, "value must be greater than %s" % repr(min))
            if max != None and var.get() > max: 
                return self._error(entry, ValueError, "value must be lower than %s" % repr(max))
            else:
	        return 1
        else:
            return 0


class Callback:
    """
    Code stolen from: "wikipython.tuxfamily.org"
    La classe suivante permet de pré-enregistrer des paramètres pour une
    fonction, puis d'appeler la fonction avec les paramètres enregistrés
    suivis d'éventuels paramètres supplémentaires précisés lors de l'appel
    effectif. Elle est très utile pour spécifier des commandes ou bindings
    Tkinter, mais peut également servir à chaque fois qu'on doit passer une
    fonction en paramètre.
    """
    def __init__(self, callback, *firstArgs):
        self.__callback = callback
        self.__firstArgs = firstArgs

    def __call__(self, *args):
        apply(self.__callback, self.__firstArgs + args)


#-------------------------------------------------------------------------------
# Page class : Constructor and initialization
#-------------------------------------------------------------------------------


class Page(Tix.Frame):
    """
    This class is intended as a base class for Page widgets layout.
    """        
    def __init__(self, master, case,
                 stbar=None, tree=None, study=None, class_=None ):
        """
        Initialize a dialog.
        Arguments:
        master  -- the parent window : the ScrooledFrame of the paned window
        case    -- object which contains parameters the the Code_Saturne case
        stbar   -- status bar for status message and balloon widget
        tree    -- Tree Navigator
        study   -- study bar for study and case name display
        class_  -- new widget class name
        """
        if class_:
            Tix.Frame.__init__(master, class_=class_)
        else:
            Tix.Frame.__init__(self, master)

        # Main initialization
        #
        self.master = master.fr2.p2.fr.window
        self.case   = case
        self.study  = study
        self.check2  = DataValidator2()

        # Background initialization
        #
        self.bg = self.master.cget("bg")

        # Fonts.
        #
        Toolbox.setupFontDefault(self)

        # Main Frame for Page widgets layout
        #
        self.myPage = Tix.Frame(self.master, relief=FLAT, bg=self.bg)
        self.myPage.pack(fill=BOTH)


        # Look for the status bar and the balloon widget
        #
        if stbar:
            self.stbar = stbar
            self.balloon = Tix.Balloon(self.master,
                                       statusbar=self.stbar.label,
                                       borderwidth=1,
                                       background='black')
            self.balloon.message.config(bg=wm['background'])
            self.stbar.clear()
 
        # Page entries incrementation and dependencies verification
        #
        name = self.case['currentPage']
        self.case[name]['num_entry'] = self.case[name]['num_entry'] + 1
        self._dependsPages(name)
        #if tree != None:
        self.myTree = tree
# FIXME: mark the dependent pages
##        if self.myTree != None:
##            pass
# FIXME
# FIXME: 
##            for page in self.case[name]['depends']:
##                print page
##                if self.case[page]['num_entry']:
##                    self.myTree.setRedFile(page)
# FIXME

        # Tkinter variables declaration
        #
        self._tkControlVariables()

        # Data for page control
        #
        self._pageControl()

        # Page layout
        #
        self._createWidgets()

        # Widgets initialization
        #
        self._initializeWidgets()
# TODO: TODELETE
##        self.sequence()
# TODELETE


    #
    # construction hooks

    def _dependsPages(self, name):
        """
        Construction of the list of dependencies Pages
        By default, it does nothing. You should override it.
        """
        self.case[name]['depends'] = []


    def _tkControlVariables(self):
        """
        Tkinter variable declaration.
        This method should be overridden, and is called by the __init__ method.
        """
        pass


    def _pageControl(self):
        """
        Xml node declaration and supplementary default value settings.
        You should override it if necessary.
        """
        pass


    def _createWidgets(self):
        """
        Create the Page body.
        This method should be overridden, and is called by the __init__ method.
        """
        pass

# TODO: TODELETE
##    def sequence(self):
##        """
##        Bind the dialog window with 'Echap'.
##        This reload all the default value.
##        You should override it if necessary.
##        """
##        self.bind("<Escape>", self._initializeWidgets)
# TODELETE


    def _initializeWidgets(self):
        """
        Extract resquested informations from the XML document.
        This informations are used to initialize the widgets.
        By default, it does nothing. You should override it.
        """
        pass

    #
    # usefull method

    def _scrollHandler(self, entry, *L):
        """
        Making an Entry widget scrollable.
        Code stolen from:
        New Mexico Tech Computer Center, "Tkinter reference", p28
        """
        op, howMany = L[0], L[1]

        if op =="scroll":
            units = L[2]
            entry.xview_scroll(howMany, units)
        elif op == "moveto":
            entry.xview_moveto(howMany)


#-------------------------------------------------------------------------------
# End of TkPage
#-------------------------------------------------------------------------------


syntax highlighted by Code2HTML, v. 0.9.1