# -*- 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
#
#-------------------------------------------------------------------------------


"""
"""


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


import string
import Tix
from Tkconstants import *


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


from Base.Common import *
import Base.Toolbox as Tool
import Base.Dialog as Dialog
import Base.TkPage as TkPage


#-------------------------------------------------------------------------------
# Multi-selection string
#-------------------------------------------------------------------------------


MULTISEL = "********"


#-------------------------------------------------------------------------------
# Hlist multi-selection class
#-------------------------------------------------------------------------------


class MultiSelect:
    """
    This class is design in order to manage the storage of the selected items in
    the Hlist.
    """
    def __init__(self, case, Hlist):
        """
        Constructor
        """
        self.case  = case
        self.Hlist = Hlist


    def _initList(self):
        """
        For each mouse selection we reinitialize all lists.
        """
        self.nameL = []
        self.name_scalL = []
        self.typeCoeffL = []
        self.coeffL = []

        self.mdl = UserScalarPropertiesModel(self.case)


    def scalarInfo(self, entry):
        """
        Return info from the argument entry.
        """
# Here we must call the tk function directly without passing in
# Tix.py, because of a bug in tix8.1 in the Hlist.item_cget function

        t = PageText()
        h = self.Hlist
        name      = h.tk.call(h, 'item', 'cget', entry, 0, '-text')
        name_scal = h.tk.call(h, 'item', 'cget', entry, 1, '-text')
        coeff     = h.tk.call(h, 'item', 'cget', entry, 2, '-text')

        return name, name_scal, float(coeff)


    def setItems(self, entriesL):
        """
        Store values when a new selection is done.
        """
        self._initList()

        for entry in entriesL:
            name, name_scal, coeff = self.scalarInfo(entry)
            self.nameL.append(name)
            self.name_scalL.append(name_scal)
            self.coeffL.append(coeff)

            list = self.mdl.mgetListUserScalars()
            for scalar in list:
                if self.mdl.mgetLabelScalar(scalar) == name_scal:
                    typC = self.mdl.mgetTypeCoeff(scalar)
                    self.typeCoeffL.append(typC)


    def getItems(self):
        """
        Return all the lists.
        """
        return self.nameL, self.name_scalL, self.typeCoeffL, self.coeffL


    def widgetText(self):
        """
        Find the right texts for the widget layout.
        """
        name, name_scal  = self.nameL[0], self.name_scalL[0]
        typeCoeff = self.typeCoeffL[0]
        coeff = self.coeffL[0]

        for i in self.nameL:
            if name != i: name = MULTISEL
        for i in self.name_scalL:
            if name_scal != i: name_scal = MULTISEL
        for i in self.typeCoeffL:
            if typeCoeff != i: typeCoeff = MULTISEL
        for i in self.coeffL:
            if coeff != i: coeff = MULTISEL

        return name, name_scal, typeCoeff, coeff



#-------------------------------------------------------------------------------
# User scalar properties model class
#-------------------------------------------------------------------------------


class UserScalarPropertiesModel(TkPage.Page):
    """
    """
    def __init__(self, case):
        """
        Constructor
        """
        self.case = case
        self.node_add_scalar  = self.case.xmlGetNode('additional_scalars')


    def mgetListUserScalars(self):
        """
        Get list of scalar'nodes
        """
        return self.node_add_scalar.xmlGetNodeList('scalar', type='user')


    def mgetLabelScalar(self, node):
        """
        Input the new label in scalar's node
        """
        return node['label']


    def mgetTypeCoeff(self, node):
        """
        Get Type of property of the scalar  
        """
        type = node.xmlGetNode('property', 'name', 'label')
        type_C = type['choice']
        return type_C


    def mgetVarianceScalar(self, node):
        """
        Get Type of property of the scalar  
        """
        vari = node.xmlGetString('variance')
        return vari


    def mgetCoeffValue(self, node):
        """
        Get Type of property of the scalar  
        """
        node_property = node.xmlGetNode('property', 'name')
        label = node_property['label']
        coeff_value = node_property.xmlGetDouble('initial_value')
        if not coeff_value: 
            # pour l'instant, on initialise à 0. Plus tard, on pourra initialiser 
            # à la viscosité du fluide 
            coeff_value = 1.0
            self.msetInitialValue(node_property, coeff_value)

        return label, coeff_value


    def mgetNodeProperty(self, node):
        """
        Get node of node'property
        """
        node_prop = node.xmlGetNode('property')
        return node_prop


    def msetStatusPrintAndRecordStatus(self, node, valchoice):
        """
        Set status of listing_printing and postprocessing_recording
        if choice is variable
        """
        node['choice'] = valchoice
        if node['choice'] == "variable":
            if node.xmlGetNode('listing_printing'): 
                node.xmlRemoveChild('listing_printing')
            if node.xmlGetNode('postprocessing_recording'):
                node.xmlRemoveChild('postprocessing_recording')
        elif node['choice'] == "constant":
            node.xmlInitNode('listing_printing')['status'] = "off"
            node.xmlInitNode('postprocessing_recording')['status'] = "off"


    def msetInitialValue(self, node, val):
        """
        Set initial value ty of the scalar's propety
        """
        node.xmlSetData('initial_value', val)


    def msetZoneInitialValue(self, node, nameZone, value):
        """
        set initial value on the nameZone zone
        """
        node_init = node.xmlInitChildNode('initial_value', zone=nameZone)
        node_init.xmlSetTextNode(value)


#-------------------------------------------------------------------------------
# Main class
#-------------------------------------------------------------------------------


class UserScalarPropertiesView(TkPage.Page):
    """
    Class to open Define User Scalars Page.
    """

    def _dependsPages(self, name):
        """
        Construction of the list of dependencies Pages.
        """
        self.case[name]['depends'] = ['bounda/scalar']


    def _pageControl(self):
        """
        Default value settings.
        """
        self.selectedEntry = None
        self.currentEntry = None
        self.entriesNumber = 0

        self.mdl = UserScalarPropertiesModel(self.case)


    def _make_style(self):
        """
        Define beautiful style in order to display columns in the Hlist.
        """
        self.style={}

        self.style['header'] = Tix.DisplayStyle(Tix.TEXT,
                                                refwindow=self.lf1,
                                                anchor=CENTER,
                                                justify=CENTER,
                                                padx=5, pady=2,
                                                font=fB)
        self.style['style'+'b'] = Tix.DisplayStyle(Tix.TEXT,
                                                   refwindow=self.lf1,
                                                   padx=5,
                                                   selectforeground='#fefefe',
                                                   font=fB)
        self.style['style'] = Tix.DisplayStyle(Tix.TEXT,
                                               refwindow=self.lf1,
                                               padx=5, anchor=CENTER,
                                               selectforeground='#fefefe',
                                               font=fN)


    def _tkControlVariables(self):
        """
        Tkinter variables declaration.
        """
        self.typeCoeff = Tix.StringVar()
        self.coeff     = Tix.StringVar()
        self.diffCoeff = Tix.StringVar()


    def eraseEntries(self, event=None):
        """
        Delete all caracters in the entries.
        """
        self.value.delete(0, END)


    def insertHlist(self, name, name_scal, coeff):
        """
        Create the item Hlist associated with the new boundary definition
        and update the listBox
        """
        self.stbar.busy()
        t = PageText()

        self.entriesNumber = self.entriesNumber +1
        self.scal_num = 'item' + repr(self.entriesNumber)

        self.h.hlist.add(self.scal_num, itemtype=Tix.TEXT, text=name,
                         style=self.style['style'+'b'])

        self.h.hlist.item_create(self.scal_num, 1, itemtype=Tix.TEXT, 
                                 text=name_scal, style=self.style['style'])

        self.h.hlist.item_create(self.scal_num, 2, itemtype=Tix.TEXT, 
                                 text="%g"%(coeff), style=self.style['style'])

        self.stbar.idle()
        return name


    def replaceHlist(self, item, name, name_scal, coeff):
        """
        Update the 'item' into the Hlist.
        """
        self.stbar.busy()
        t = PageText()

        self.h.hlist.item_configure(item, 0, itemtype=Tix.TEXT, text=name,
                                    style=self.style['style'+'b'])
        self.h.hlist.item_configure(item, 1, itemtype=Tix.TEXT,
                                    text=name_scal, style=self.style['style'])

        self.h.hlist.item_configure(item, 2, itemtype=Tix.TEXT,
                                    text=coeff, style=self.style['style'])

        self.stbar.idle()


    def selectHlistAll(self):
        """
        Fonction for the Popup Menu.
        Select everything in the Hlist.
        """
#        self.reloadHlist()
        try:
            first = 'item' + repr(1)
            last  = 'item' + repr(self.entriesNumber)
            self.h.hlist.selection_set(first, last)
            self.currentEntry = None
            self.selectHlist()
        except:
            pass


    def cancelSelection(self):
        """
        Fonction for the Popup Menu.
        Blank the selection.
        """
        self.h.hlist.selection_clear()
        self.eraseEntries()
        self.currentEntry = None
        self.selectHlist()


    def selectHlist(self, entry=None):
        """
        Browsecmd:
        Every single Clik on the Button1 of the mouse send TWO signal to the GUI
        the first one when man push the button, and the second one when the
        button gets back.

        Command:
        Every double-Click and Return send only ONE signal to the GUI.
        """
        self.selectedEntry = self.h.hlist.info_selection()

        if self.selectedEntry and self.currentEntry != self.selectedEntry:
            self.currentEntry = self.selectedEntry
            self.select.setItems(self.currentEntry)

            name, name_scal, typeCoeff, coeff_value = self.select.widgetText()

            if typeCoeff == MULTISEL:
                self.f3.pack_forget()
                self.bu.config(state=DISABLED)
                self.bu.menubutton.config(text=typeCoeff)
            else:
                self.f3.pack_forget()
                self.bu.config(state=NORMAL)
                self.bu.config(value=typeCoeff)
            self.value.delete(0,END)
            self.value.insert(0,coeff_value)
            self.value.icursor(END)


    def getTypeCoeff(self, event=None):
        """
        """
        if not self.currentEntry: return
        self.stbar.busy()
        if not self.typeCoeff.get(): self.typeCoeff.set('constant')

        if self.typeCoeff.get() == 'constant':
            self.l21.grid_forget()
            self.l22.grid(row=0, column=2, padx=5)
            self.f3.pack_forget()
        else:
            self.l21.grid(row=0, column=2, padx=5)
            self.l22.grid_forget()
            self.f3.pack(side=TOP, fill=X)

        name, name_scal, typeCoeff, coeff_old = self.select.getItems()
        for i in range(len(self.currentEntry)):
            list = self.mdl.mgetListUserScalars()
            for scalar in list:
                if self.mdl.mgetLabelScalar(scalar) == name_scal[i]:
                    nodeProp = self.mdl.mgetNodeProperty(scalar)
                    if nodeProp:
                        self.mdl.msetStatusPrintAndRecordStatus(nodeProp, self.typeCoeff.get())

        self.stbar.idle()


    def isFloat(self, entry, var):
        """
        Verify if the 'entry' contents a float. If not, signal an error
        and return None.
        """
        try:
            double = float(var.get())
        except:
            self.check2.error(entry)
            double = None

        return double


    def string2float(self, entry, var):
        """
        If the StringVar() 'var' associated to the 'entry', is not a 'MULTISEL',
        convert it to a float.
        """
        self.check2.begin(entry)

        # Several selections in Hlist
        #
        if self.currentEntry and len(self.currentEntry) > 1:
            if var.get() != MULTISEL:
                double = self.isFloat(entry, var)
            else:
                double = MULTISEL

        # Only one selection in Hlist
        #
        else:
            double = self.isFloat(entry, var)

        return double


    def getDiffCoeff(self, event=None):
        """
        """
        if not self.diffCoeff.get(): self.diffCoeff.set('0.0')
        return self.string2float(self.value, self.diffCoeff)


    def addCoeff(self, event=None):
        """
        Upload contents of the definition widget when the "Create" button is pushed.
        """
        if not self.currentEntry: return
        self.stbar.busy()

        name, name_scal, typeCoeff, coeff_old = self.select.getItems()

        coeff_new = self.getDiffCoeff()
        for i in range(len(self.currentEntry)):
            list = self.mdl.mgetListUserScalars()
            for scalar in list:
                if self.mdl.mgetLabelScalar(scalar) == name_scal[i]:
                    if coeff_new == MULTISEL: coeff = coeff_old[i]
                    else: coeff = coeff_new

                    self.replaceHlist(self.currentEntry[i], name[i], name_scal[i], coeff)
                    nodeProp = self.mdl.mgetNodeProperty(scalar)
                    if nodeProp:
                        self.mdl.msetInitialValue(nodeProp, coeff)

        self.eraseEntries()
        self.currentEntry = None
        self.selectHlist()
        self.stbar.idle()


    def _createWidgets(self):

        t = PageText()

        self.lf1 = Tix.LabelFrame(self.myPage, bd=2, label=t.TITLE, relief=FLAT)
        self.lf1.label.config(font=fT)
        self.lf1.pack(side=TOP, fill=X, padx=10, pady=10)

# Put a simple hierarchy into the Hlist (two levels).

        self.h = Tix.ScrolledHList(self.lf1.frame, options=
                                   'hlist.columns 4 hlist.header 1 ' )
        self.h.config(scrollbar="auto +y")
        self.h.hlist.config(selectmode='extended', browsecmd=self.selectHlist,
                            bg=wm['hlistbackground'])
        self.h.hsb.config(width=10, bd=1)
        self.h.vsb.config(width=10, bd=1)
        self.h.pack(padx=10, pady=10, side=TOP)

        self.balloon.bind_widget(self.h.hlist, statusmsg=t.MSG_HLIST)

# Create the headers

        self._make_style()

        self.h.hlist.header_create(0, itemtype=Tix.TEXT, text=t.NAME,
                                   style=self.style['header'])
        self.h.hlist.header_create(1, itemtype=Tix.TEXT, text=t.SCALAR,
                                   style=self.style['header'])
        self.h.hlist.header_create(2, itemtype=Tix.TEXT, text=t.COEFF,
                                   style=self.style['header'])

# Notice that we use 3 columns in the Hlist widget. This way when the user
# expands the windows wide, the right side of the header doesn't look
# chopped off. The following line ensures that the 3 column header is
# not shown unless the Hlist window is wider than its contents.

        self.h.hlist.column_width(3,0)

# Let configure the appearance of the Hlist subwidget 

        self.h.hlist.config(separator='.', width=42, height=11,
                            drawbranch=0,  indent=10)

# width of the columns

        self.h.hlist.column_width(0, chars=14)
        self.h.hlist.column_width(1, chars=14)
        self.h.hlist.column_width(2, chars=14)

# Create the mouse selection instance

        self.select = MultiSelect(self.case, self.h.hlist)

# Popup Menu of Tree 

        pm = Tix.PopupMenu(self.h.hlist, title=t.POPUP, state=NORMAL)
        pm.bind_widget(self.h.hlist)
        pm.menu.add_separator()
        pm.menu.add_command(label=t.SELECT_ALL, command=self.selectHlistAll)
        pm.menu.add_command(label=t.UNSELECT, command=self.cancelSelection)
        pm.menu.m1 = Tix.Menu(pm.menu)

# Separator

        s = Tix.Frame(self.lf1.frame, height=2, bd=2, relief=SUNKEN)
        s.pack(side=TOP, fill=X)

# Create Label and entry
        f2 = Tix.Frame(self.lf1.frame, relief=FLAT)
        f2.pack(side=TOP, fill=X)

        #f1 = Tix.Frame(self.lf1.frame, relief=FLAT)
        f1 = Tix.Frame(f2, relief=FLAT)
        f1.pack(side=TOP, fill=X)

        self.l1 = Tix.Label(f1, text=t.COEFF)
        self.l1.grid(row=0, column=0, ipadx=5)


        self.bu = Tix.OptionMenu(f1, options='menubutton.width 40')
        self.bu.menubutton.config(bd=2, width=8, relief=RAISED)
        self.bu.add_command('constant', label=t.CONSTANT)
        #self.bu.add_separator('')
        self.bu.add_command('variable', label=t.VARIABLE)
        self.bu.grid(row=0, column=1,padx=15, pady=15)
        self.bu.config(variable=self.typeCoeff, command=self.getTypeCoeff)

        self.balloon.bind_widget(self.bu, statusmsg=t.MSG_COEFF,
                                 balloonmsg=t.KEYWORD+' ISCALT, ISCSTH')

# Separator
#        s = Tix.Frame(self.lf1.frame, height=2, bd=2, relief=SUNKEN)
#        s.pack(side=TOP, fill=X)


        self.l21 = Tix.Label(f1, text=t.INIT_VALUE)
        self.l22 = Tix.Label(f1, text=t.VALUE)
        self.l23 = Tix.Label(f1, text=t.UNIT)

        self.value = Tix.Entry(f1, bd=2, width=12, textvariable =self.diffCoeff )
        self.value.grid(row=0, column=4, padx=0, pady=15)
        self.value.event_add("<<Event>>", "<Return>", "<Leave>", "<FocusOut>")
        self.value.bind("<<Event>>", self.addCoeff )

        self.balloon.bind_widget(self.value, balloonmsg=t.KEYWORD+'VISLSO/RO0')

        self.l23.grid(row=0, column=5,padx=5)
 

        #f3 = Tix.Frame(self.lf1.frame, relief=FLAT)
        self.f3 = Tix.Frame(f2, relief=FLAT)
        self.f3.pack(side=TOP, fill=X)
        self.l3 = Tix.Label(self.f3, bd=2, relief=FLAT, text=t.FORTRAN, \
                            width=40,foreground='blue', font=fL)
        self.l3.grid(pady=10)


    def _initializeWidgets(self):
        """
        """
        t = PageText()
        self.cancelSelection()
        self.entriesNumber = 0

        #nodeList = self.node_user_sca.xmlGetNodeList('scalar')
        nodeList = self.mdl.mgetListUserScalars()

        for scalar in nodeList:
            name = self.mdl.mgetLabelScalar(scalar)
            vari = self.mdl.mgetVarianceScalar(scalar)

            if not vari: 
                label, coeff_value = self.mdl.mgetCoeffValue(scalar)
                id = self.insertHlist(label, name, coeff_value)

        self.f3.pack_forget()
        self.bu.config(value='constant')


#-------------------------------------------------------------------------------
# Text and messages for this page
#-------------------------------------------------------------------------------


class PageText:
    """
    Storage of all texts and messages for this page.
    """
    def __init__(self):
        
        # 1) Texts
        #
        if Tool.GuiParam.lang == 'fr':
            self.KEYWORD          = "Mot clé Code_SATURNE : "
            self.TITLE            = "Coefficient de diffusivité des Scalaires Utilisateurs"
            self.DEFINITION       = "DEFINITION\nINITIALISATION"
            self.NAME             = "Nom"
            self.SCALAR           = "Scalaire\nassocié"
            self.COEFF            = "Coefficient\nde diffusion"
            self.VARIANCE         = "Variance"
            self.ADD              = "Valider"
            self.CONSTANT         = "Constant"
            self.VARIABLE         = "Variable"
            self.INIT_VALUE       = "Valeur\ninitiale"
            self.VALUE            = "Valeur de\nréference"
            self.UNIT             = "m2/s"
            self.FORTRAN          = "Vous devez remplir USPHYV.F"
            self.POPUP            = "Menu popup"
            self.SELECT_ALL       = "Tout sélectionner"
            self.UNSELECT         = "Désélectionner"
        else:
            self.KEYWORD          = "Code_SATURNE Keyword: "
            self.TITLE            = "User Scalar Diffusion Coefficient"
            self.DEFINITION       = "DEFINITION\nINITIALIZATION"
            self.NAME             = "Name"
            self.SCALAR           = "Associated\nScalar"
            self.COEFF            = "Diffusion\nCoefficient"
            self.VARIANCE         = "Variance"
            self.ADD              = "Validate"
            self.CONSTANT         = "Constant"
            self.VARIABLE         = "Variable"
            self.INIT_VALUE       = "Initial\nvalue"
            self.VALUE            = "Reference\nvalue"
            self.UNIT             = "m2/s"
            self.FORTRAN          = "You must complete USPHYV.F"
            self.POPUP            = "Menu popup"
            self.SELECT_ALL       = "Select all"
            self.UNSELECT         = "Désélectionner"

        # 2) Messages
        #
        if Tool.GuiParam.lang == 'fr':
            self.MSG_COEFF     = "Sélectionner variable ou constant"
            self.MSG_HLIST     = "Cliquer le bouton droit pour "       +\
                                 "le menu contextuel."
        else:
            self.MSG_COEFF     = "Select variable or constant"
            self.MSG_HLIST     = "Click right button for popup menu."


#-------------------------------------------------------------------------------
# End
#-------------------------------------------------------------------------------


syntax highlighted by Code2HTML, v. 0.9.1