# -*- 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 the thermal scalar management.

This module contains the following classes and function:
- DefBCModel
- MultiSelect
- DefBCView
- PageText
- DefBCTestCase
"""


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


import sys
import Tix, unittest
from Tkconstants import *
import tkFileDialog

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

from Base.Common import *
import Base.Toolbox as Tool
import Base.Dialog as Dialog
import Base.TkPage as TkPage
from Pages.RadiativeBoundaries import RadiativeBoundariesModel

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


_MULTISEL = "************"

#-------------------------------------------------------------------------------
# Thermal scalar model class
#-------------------------------------------------------------------------------


class DefBCModel:
    """
    """
    def __init__(self, case):
        """
        Constuctor.
        """
        self.case = case
        self.node_scalar   = self.case.xmlGetNode('additional_scalars')
        self.node_bc       = self.case.xmlGetNode('boundary_conditions')
        self.node_def      = self.node_bc.xmlInitNode('boundary_definition')


##    def defaultDefBCValues(self):
##        """
##        Return in a dictionnary which contains default values
##        """
##        default = {}
##        default['choice'] = "dirichlet"
##        return default


    def getLists(self):
        """
        Return the list of reference and group found in XML file under
        boundary definitions
        """
        refList   = self.node_def.xmlGetIntList('reference')
        groupList = self.node_def.xmlGetStringList('group')
        return refList, groupList


    def setBoundaries(self, nature, label, reference, group):
        """
        Add to the XML doc the new values.
        """
        # 1 - In < boundary_definition > markup : creation of the nature markup
        # and the reference and/or group markup
        node = self.node_def.xmlInitNode(nature, label=label)
        reflist, grlist = self.getLists()
        
        # TODO : voir xmlSetData a la place de xmlAddChild +xmlSetTextNode
        if reference and reference not in reflist: 
            node.xmlAddChild('reference').xmlSetTextNode(reference)
        if group and group not in grlist: 
            node.xmlAddChild('group').xmlSetTextNode(group)

        # 2 - In < boundary_conditions > markup : creation of the nature markup
        # with the default values for velocity, turbulence, pressure and scalars
        node_cond = self.node_bc.xmlInitChildNode(nature, label=label)

        # if nature = 'wall', if thermal radiation, creation with default 
        # values for radiative transfer (NP 27-12-06)
        if nature == 'wall':
            ray_model = RadiativeBoundariesModel(self.case).getRadiativeTransfertModel()
            if ray_model != 'off':
                RadiativeBoundariesModel(self.case).getTypeOfCondition(label)

        if nature == 'inlet':
            self.initCondInletVelocity(node_cond)
            from Turbulence import TurbulenceModel
            list = TurbulenceModel(self.case).getTurbulenceVariable()
            del TurbulenceModel
            if list: 
                self.initCondTurbulence(node_cond, '1.0')

        from ThermalScalar import ThermalScalarModel
        thermal = ThermalScalarModel(self.case).getThermalScalar()
        l,u = ThermalScalarModel(self.case).getThermalScalarLabel()
        del ThermalScalarModel

        if nature in ('inlet','outlet'):
            if thermal !=  'off' :
                self.setCondTherm(node_cond, 'dirichlet', thermal, l, '0.0')

            self.setCondScalar(node_cond, 'dirichlet', '0')    


    def initCondInletVelocity(self, node):
        """
        Initialization velocity's boundary conditions for inlet
        """
        c = node.xmlInitNode('velocity_pressure', 'choice') 
        if not c['choice']: 
            self.setDirichletVelocity(node, '0.0', '0.0', '0.0')


    def setDirichletVelocity(self, node, u, v, w):
        """
        Put thermal scalar node for <type label> under boundary conditions
        """
        n = node.xmlGetNode('velocity_pressure', 'choice')
        n['choice'] = 'dirichlet'
        n.xmlInitNode('dirichlet', name='velocity_U').xmlSetTextNode(u)
        n.xmlInitNode('dirichlet', name='velocity_V').xmlSetTextNode(v)
        n.xmlInitNode('dirichlet', name='velocity_W').xmlSetTextNode(w)


    def initCondTurbulence(self, node, value):
        """
        Initialization turbulence's boundary conditions
        """
        c = node.xmlInitNode('turbulence', 'choice')
        if not c['choice']:
            c['choice'] = "hydraulic_diameter"
            c.xmlSetData('hydraulic_diameter', value)


    def setDirichletTurbulence(self, node, tag, value):
        """
        Put thermal scalar node for <type label> under boundary conditions
        """
        n = node.xmlGetNode('turbulence', 'choice')
        n['choice'] = 'dirichlet'
        n.xmlInitNode('dirichlet', name=tag).xmlSetTextNode(value)


    def setCondTherm(self, node, choice, model, label, value):
        """
        Put thermal scalar node for <type label> under boundary conditions
        """
        list = []
        list = node.xmlGetChildNodeList('scalar', type ="off")
        old_th = node.xmlGetChildNode('scalar', type='thermal')
        if not old_th: 
            node.xmlInitChildNode('scalar', choice=choice, label=label, name=model, type='thermal').xmlSetData(choice, value)
        elif old_th: 
            old_model = old_th['name']
            if old_model != model:
                old_th['type'] = 'off'
                trouve = 0
                if list:
                    for n in list:
                        if n['name'] == model: 
                            trouve = 1
                            n['type'] = 'thermal'
                if trouve ==0: 
                    node.xmlInitChildNode('scalar', choice=choice, label=label, name=model, type='thermal').xmlSetData(choice, value)


    def setCondScalar(self, node, choice, value):
        """
        Put scalar nodes for <type label> under boundary conditions
        """
        for scal in self.node_scalar.xmlGetNodeList('scalar'):
            label = scal['label']
            type = scal['type']
            n = node.xmlGetChildNode('scalar', label=label, type=type)
            if not n:
                node.xmlInitChildNode('scalar', choice=choice, label=label, type=type).xmlSetData(choice,value)


    def getStrLists(self):
        """
        Return the list of strings reference and group found in XML file under
        boundary definitions
        """
        refList   = self.node_def.xmlGetStringList('reference')
        groupList = self.node_def.xmlGetStringList('group')
        return refList, groupList


    def getStrListsNode(self, node):
        """
        Return the list of strings reference and group found in XML file under
        boundary definitions
        """
        refList   = node.xmlGetStringList('reference')
        groupList = node.xmlGetStringList('group')
        return refList, groupList


    def getLabelNode(self, node):
        """
        Return the label of node  found in XML file under
        boundary definitions
        """
        label = node['label']
        return label


    def getListNode(self, type, label):
        """
        Return the list of nodes type-label found in XML file under
        boundary definitions
        """
        if label == 'none':
            listnode = self.node_def.xmlGetNodeList(type)   
        else:
            listnode = self.node_def.xmlGetNodeList(type, label=label)
        return listnode


    def getStatus(self, node, ref):
        """
        Return the list of nodes type-label found in XML file under
        boundary definitions
        """
        for n in node.xmlGetNodeList('reference'):
            if n.xmlGetTextNode() == str(ref): n['status']='todelete'
        for n in node.xmlGetNodeList('group'):
            if n.xmlGetTextNode() == group: n['status']='todelete'


    def getTypeLabelForRef(self, node, ref):
        """
        Return type-label for a reference found in XML file under
        boundary definitions
        """
        type = ""
        label = ""
        if node.xmlGetTextNode() == str(ref):
            type = node.el.parentNode.tagName
            label = node._inst(node.el.parentNode)['label']
        return type, label


    def RemoveType(self, type, label):
        """
        Remove nodes reference or group found in XML file under
        boundary definitions
        """    
        self.node_def.xmlRemoveChild(type, label=label)


    def RemoveRef(self, node):
        """
        Remove nodes reference or group found in XML file under
        boundary definitions
        """
        self.node_def.xmlRemoveChild('reference', status='todelete')
        self.node_def.xmlRemoveChild('group',   status='todelete')
        if not node.xmlGetNodeList('reference') and \
            not node.xmlGetNodeList('group'):node.xmlRemoveNode()


    def Cancel(self, node, ref):
        """
        Remove nodes  found in XML file under boundary definitions
        """
        for n in node.xmlGetNodeList('reference'):
            if n.xmlGetTextNode() == str(ref): n.xmlRemoveNode()
        for n in node.xmlGetNodeList('group'):
            if n.xmlGetTextNode() == group: n.xmlRemoveNode()
        if not node.xmlGetNodeList('reference') and \
             not node.xmlGetNodeList('group'):node.xmlRemoveNode()


    def setCase(self, tag):
        """
        Put value in self.case in XML file 
        """
        self.case['define_boundary_layout'] = tag


    def getCase(self):
        """
        Put value in self.case in XML file 
        """
        return self.case['define_boundary_layout']


    def getCurrentPage(self):
        """
        Put value in self.case in XML file 
        """   
        return self.case['currentPage']


#-------------------------------------------------------------------------------
# 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, Hlist, typeList, typeColor):
        """
        Constructor
        """
        self.Hlist = Hlist
        self.typeList  = typeList
        self.typeColor = typeColor


    def _initList(self):
        """
        For each mouse selection we do reinitialize all lists.
        """
        self.labelL = []
        self.typeL  = []
        self.refL   = []
        self.groupL = []


    def boundaryInfo(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
        #
        h = self.Hlist
        label = h.tk.call(h, 'item', 'cget', entry, 0, '-text')
        type  = h.tk.call(h, 'item', 'cget', entry, 1, '-text')
        ref   = h.tk.call(h, 'item', 'cget', entry, 2, '-text')
        group = h.tk.call(h, 'item', 'cget', entry, 3, '-text')
        
        if ref == "--": ref =""
        if group == "--": group =""

        for key in self.typeList.keys():
            if self.typeList[key] == type: type = key

        return label, type, ref, group


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

        for entry in entriesL:
            label, type, ref, group = self.boundaryInfo(entry)
            self.labelL.append(label)
            self.typeL.append(type)
            self.refL.append(ref)
            self.groupL.append(group)


    def backgroundColor(self):
        """
        Find the right color for the selection background.
        """
        type = self.typeL[0]
        for i in self.typeL:
            if type == i:
                iok = 1
            else:
                iok = 0

        if iok:
            self.Hlist.config(selectbackground=self.typeColor[type])
        else:
            self.Hlist.config(selectbackground=wm['selectbackground'])


    def widgetText(self):
        """
        Find the right texts for the widget layout.
        """
        label, type = self.labelL[0], self.typeL[0]

        for i in self.labelL:
            if label != i: label = _MULTISEL
        for i in self.typeL:
            if type  != i: type  = _MULTISEL


        if len(self.labelL) == 1:
            ref   = self.refL[0]
            group = self.groupL[0]
        else:
            ref   = string.join(self.refL," ")
            group = string.join(self.groupL," ")            

        return label, type, ref, group

#-------------------------------------------------------------------------------
# Main View Class
#-------------------------------------------------------------------------------


class DefBCView(TkPage.Page):
    """
    Class to open Turbulence Page.
    """
    def _tkControlVariables(self):
        """
        Tkinter variables declaration.
        """
        self.label = Tix.StringVar()
        self.group = Tix.StringVar()
        self.type  = Tix.StringVar()
        self.color = Tix.StringVar()


    def _pageControl(self):
        """
        Instantiate the definition boundary modelling class.
        """
        self.mdl = DefBCModel(self.case)

        # Definition of boundaries types
        #
        t = PageText()
        self.typeList =  {'wall':      t.WALL      ,
                          'inlet':     t.INLET     ,
                          'outlet':    t.OUTLET    ,
                          'symmetry':  t.SYMMETRY  }

        # Definition of color
        #
        self.typeColor = {'wall':      "blue"   ,
                          'inlet':     "red"    ,
                          'outlet':    "brown"  ,
                          'symmetry':  "green"  }

        # Number of types
        #
        self.typeNumber = {}
        for type in self.typeList.keys():
            self.typeNumber[type] = 0

        #  Initialize variables concerning the display of the Hlist
        #
        self.selectedEntry = None
        self.currentEntry = None
        self.entriesNumber = 0


    def getType(self, event=None):
        """
        Return the selected type of boundary condition. Whatever the language,
        type is allways in ('wall','inlet','outlet','symmetry').
        """
        type = self.type.get()
        for key in self.typeList.keys():
            if self.typeList[key] == type: type = key
        return type


    def getLabel(self, event=None):
        """
        Return the name of the boundary condition. It 's not allowed to have
        blank or not ASCII caracters in this name.
        """
        return  string.join(string.split(self.label.get()), '_')


    def getReference(self, event=None):
        """
        Return a string with references and perhaps some words.
        The separation will be done later.
        """
        return self.color.get()


    def getGroup(self, event=None):
        """
        Return the name of a group. It 's not allowed to have
        blank or not ASCII caracters in this name.
        """
        return string.join(string.split(self.group.get()), '_')


    def eraseEntries(self, event=None):
        """
        This button is for delete all caracters in the three entries.
        """
        self.e1.delete(0, END)
        self.e2.delete(0, END)
        self.e3.delete(0, END)


    def insertHlist(self, type, label, ref, group):
        """
        Create the item Hlist associated with the new boundary definition.
        """
        self.stbar.busy()

        self.entriesNumber = self.entriesNumber +1
        self.typeNumber[type] = self.typeNumber[type] +1
        if not label: label = type + "_" + repr(self.typeNumber[type])
        if not ref: ref = "--"
        if not group: group = "--"

        name = 'item' + repr(self.entriesNumber)

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

        self.h.hlist.item_create(name, 1, itemtype=Tix.TEXT,
                                 text=self.typeList[type],
                                 style=self.style[type])

        self.h.hlist.item_create(name, 2, itemtype=Tix.TEXT,
                                 text=ref,
                                 style=self.style[type])
            
        self.h.hlist.item_create(name, 3, itemtype=Tix.TEXT,
                                 text=group,
                                 style=self.style[type])

        self.stbar.idle()
        return label


    def createHlist(self, event=None):
        """
        Upload the contents of the definition widget
        when the 'create' button is pushed.
        Checking consistency of values and interpreting
        complexe entry for reference if necessary.
        """
        self.stbar.busy()

        type  = self.getType()
        label = self.getLabel()
        color = self.getReference()
        group = self.getGroup()

        # Verify that the reference or group is unique.
        #
        refList,groupList = self.mdl.getLists()

        # Reading references and add to Hlist
        #
        if color and not group:
            for c in string.split(color):
                try:
                    ref = int(c)
                    if not ref in refList:
                        name = self.insertHlist(type, label, ref, group)
                        self.mdl.setBoundaries(type, name, ref, group)
                        refList,groupList = self.mdl.getLists()
                except:
                    pass

        # Reading groups and add to Hlist
        # But I don't Know how to do...
        #
# TODO
##        if group:
##            if not group in groupList:
##                name = self.insertHlist(type, label, color, group)
##                self.xmlsetBoundaries(type, name, color, group)
##                refList, groupList = self.mdl.getLists()
# TODO

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


    def replaceHlist(self, node, entry, type, label, ref, group):
        """
        Add the item Hlist associated with the new boundary definition.
        """
        self.stbar.busy()

        self.typeNumber[type] = self.typeNumber[type] +1

        #self.mdl.setBoundaries(type, label, ref, group)

        # Update the Hlist
        #
        if not ref: ref = "--"
        if not group: group = "--"
        self.h.hlist.item_configure(entry, 0, text=label, style=self.style[type+'b'])
        self.h.hlist.item_configure(entry, 1, text=self.typeList[type], style=self.style[type])
        self.h.hlist.item_configure(entry, 2, text=ref, style=self.style[type])
        self.h.hlist.item_configure(entry, 3, text=group, style=self.style[type])
        self.h.hlist.config(selectbackground=self.typeColor[type])

        self.stbar.idle()


    def setEditedValueHlist(self, node, entry, old_label, old_type, old_ref, old_group):
        """
        Checking consistency of values and interpreting
        complexe entry for reference if necessary.
        """
        new_label = self.getLabel()
        if new_label == _MULTISEL or not new_label:
            new_label = old_label

        new_type = self.b1.menubutton['text']
        if new_type == _MULTISEL:
            new_type = old_type
        else:
            new_type = self.getType()

        if len(self.currentEntry) == 1:
            new_refL   = self.getReference()
            new_groups = self.getGroup()
        else:
            new_refL   = old_ref
            new_groups = old_group

        if not new_refL and not new_groups: return

        # Verify that the reference or group is unique.
        #
        refList,groupList = self.mdl.getLists()
        
        # Reading references and add to Hlist
        #
        cpt = 0
        if new_refL and not new_groups:

            # Search if the old reference is still present.
            #
            if old_ref in string.split(new_refL):
                cpt = 1
                self.typeNumber[old_type] = self.typeNumber[old_type] -1
                self.mdl.setBoundaries(new_type, new_label, old_ref, new_groups)
                self.replaceHlist(node, entry, new_type, new_label, old_ref, new_groups)
                refList,groupList = self.mdl.getLists()
                
            # Put the other references
            #
            for color in string.split(new_refL):
                try:
                    ref = int(color)
                    if not ref in refList and not cpt:
                        cpt = 1
                        self.typeNumber[old_type] = self.typeNumber[old_type] -1
                        self.mdl.setBoundaries(new_type, new_label, ref, new_groups)
                        self.replaceHlist(node, entry, new_type, new_label, ref, new_groups)
                        refList,groupList = self.mdl.getLists()
                        
                    if not ref in refList and cpt:
                        self.mdl.setBoundaries(new_type, new_label, ref, new_groups)
                        self.insertHlist(new_type, new_label, ref, new_groups)
                        refList,groupList = self.mdl.getLists()
                        
                except:
                    pass

        # Reading groups and add to Hlist
        # But I don't Know how to do...
        #
# TODO
##        if new_groups:
##            if not new_groups in groupList:
##                self.mdl.setBoundaries(new_type, new_label, new_refL, new_group)
##                self.replaceHlist(node, entry, new_type, new_label, new_refL, new_group)
##                groupList = self.boundary.xmlGetIntList('group')
# TODO


    def editHlist(self, event=None):
        """
        Modify previous selected entries. A new node is created with
        the new specifications and the previous ChildNodes are cloned
        in order to taking into account the user's boundary conditions
        if they exist.
        """
        if not self.currentEntry: return
        self.stbar.busy()
        t = PageText()
        for entry in self.currentEntry:
            label, type, ref, group = self.select.boundaryInfo(entry)
            for node in self.mdl.getListNode(type,label) :
                self.mdl.getStatus(node, ref)
                self.setEditedValueHlist(node, entry, label, type, ref, group)
                self.mdl.RemoveRef(node)
        name = self.mdl.getCurrentPage()
        self.currentEntry = None
        self.selectHlist()
        self.stbar.idle()


    def cancelHlist(self, event=None):
        """
        Just delete the current selected entries from the Hlist and
        of course from the XML file.
        """
        if not self.currentEntry: return
        self.stbar.busy()
        for entry in self.currentEntry:
            label, type, ref, group = self.select.boundaryInfo(entry)

            # Find the node to delete in the XML doc and mark it
            #
            for node in self.mdl.getListNode(type,label):

                self.mdl.Cancel(node,ref)

            # Delete boundary region from the Hlist
            #
            self.entriesNumber = self.entriesNumber -1
            self.typeNumber[type] = self.typeNumber[type] -1
            self.h.hlist.delete_entry(entry)

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


    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 not self.selectedEntry:
          self.l2.config(state=NORMAL)
          self.e2.config(state=NORMAL)
          self.e2.delete(0,END)
# TODO
##          self.l3.config(state=NORMAL)
##          self.e3.config(state=NORMAL)
##          self.e3.delete(0,END)
# TODO

        elif self.currentEntry != self.selectedEntry:

            self.currentEntry = self.selectedEntry
            self.select.setItems(self.currentEntry)
            self.select.backgroundColor()
            label, type, ref, group = self.select.widgetText()

            # Update all widgets
            #
            if type == _MULTISEL:
                self.b1.menubutton.config(text=type)
            else:
                self.b1.config(value=self.typeList[type])

            self.e1.delete(0,END)
            self.e1.insert(0,label)
            self.e1.icursor(END)

            self.l2.config(state=NORMAL)
            self.e2.config(state=NORMAL)
# TODO
##            self.l3.config(state=NORMAL)
##            self.e3.config(state=NORMAL)
# TODO

            if len(self.currentEntry) > 1:
                self.e2.delete(0,END)
                self.e2.insert(0,ref)
                self.e2.icursor(END)

                self.e3.delete(0,END)
                self.e3.insert(0,group)
                self.e3.icursor(END)

                self.l2.config(state=DISABLED)
                self.l3.config(state=DISABLED)
                self.e2.config(state=DISABLED)
                self.e3.config(state=DISABLED)
            else:
                self.e2.delete(0,END)
                self.e2.insert(0,ref)
                self.e2.icursor(END)

                self.e3.delete(0,END)
                self.e3.insert(0,group)
                self.e3.icursor(END)


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

        self.style['header'] = Tix.DisplayStyle(Tix.TEXT,
                                                refwindow=self.w1,
                                                anchor=CENTER,
                                                padx=5, pady=2,
                                                font=fB)

        for type in self.typeList.keys():
            self.style[type+'b'] = Tix.DisplayStyle(Tix.TEXT,
                                                    refwindow=self.w1,
                                                    padx=5,
                                                    fg=self.typeColor[type],
                                                    selectforeground='#fefefe',
                                                    font=fB)
            self.style[type] = Tix.DisplayStyle(Tix.TEXT,
                                                refwindow=self.w1,
                                                anchor=CENTER,
                                                padx=5,
                                                fg=self.typeColor[type],
                                                selectforeground='#fefefe',
                                                font=fN)


    def selectHlistAll(self):
        """
        Fonction for the Popup Menu.
        Select everything in the Hlist.
        """
        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.l2.config(state=NORMAL)
        self.e2.config(state=NORMAL)
# TODO
##        self.l3.config(state=NORMAL)
##        self.e3.config(state=NORMAL)
# TODO
        self.b1.config(value=self.type.get())
        self.currentEntry = None
        self.eraseEntries()


    def typeSelection(self, type):
        """
        Fonction for the Popup Menu.
        Select item in the Hlist by type.
        WARNING: the Tix function self.h.hlist.selection_includes(entry)
        doesn't work. One has to use self.h.hlist.selection_set(entry).
        """
        self.cancelSelection()

        entriesList = []
        for num in range(1, self.entriesNumber +1):
            entry = 'item' + repr(num)
            l, t, r, g = self.select.boundaryInfo(entry)
            if type == t:
                entriesList.append(entry)

        if entriesList:
            for entry in entriesList:
                self.h.hlist.selection_set(entry)
            self.currentEntry = None
            self.selectHlist()


    def typeSortOut(self):
        """
        Method for the Popup Menu and the _initializeWidgets method.
        Sort out items in Hlist by their type.
        """
        self.cancelSelection()
        self.entriesNumber = 0
        try:
            self.h.hlist.delete_all()
        except:
            pass

        for type in self.typeList.keys():
            for node in self.mdl.getListNode(type,'none'):
                label = self.mdl.getLabelNode(node)
                refList,groupList = self.mdl.getStrListsNode(node)
                if refList or groupList:
                    for ref in refList:
                        group = ""
                        self.insertHlist(type, label, ref, group)
                    for group in groupList:
                        ref = ""
                        self.insertHlist(type, label, ref, group)
                else:
                    self.mdl.RemoveType(type,label)
                
        self.mdl.setCase("byType")


    def refSortOut(self):
        """
        Method for the Popup Menu and the _initializeWidgets method.
        Sort out items in Hlist by their reference.
        The proposed algorithm is not very beautyfull.
        May be someone wants to improve it?
        """
        self.entriesNumber = 0
        self.cancelSelection()
        try:
            self.h.hlist.delete_all()
        except:
            pass

        intRefList = []
        refList, groupList = self.mdl.getStrLists()
        
        if refList:
            for ref in refList:
                intRefList.append(int(ref))
            intRefList.sort()

            for ref in intRefList:
                for node in self.mdl.getListNode('reference', 'none'):
                    type,label = self.mdl.getTypeLabelForRef(node,ref)
#TODO: group
                    if type or label:
                        self.insertHlist(type, label, ref, "--")
#TODO group

        self.mdl.setCase("byReference")



    def verifyFile(self,  event=None):
        """
        Page 2 : Verify if the chosen file is correct
        """
        t = PageText()
        self.file_name = ""
        tk_fopen = tkFileDialog.askopenfilename

        dir = self.case['resu_path']

        self.file_name = tk_fopen (title=t.FIC_ENV,
                              initialdir=dir,
                              filetypes=[("All files","*")])              ,

        if self.file_name[0]: 
            f = open(self.file_name[0], 'r')
            lines = f.readlines()
            f.close()

            for i in range(len(lines)):
                index = string.find(lines[i], "processeur")
                if index != -1:
                    str1 = "finition des familles de faces et cellules"
                    break
                else:
                    str1 = "Definition of face and cell families"

            j=0
            for i in range(len(lines)):
                index = string.rfind(lines[i], str1)
                if index != -1: 
                    j = i
                    break

            if j == 0:
                Dialog.ShowInfo(self.master, title=t.INFO, text=t.BAD_FILE)
                return None
            else:
                return self.file_name


    def searchListEnv(self, event=None):
        """
        Page 2 : Research the listing of envelop to pick colors of faces ...
        """
        file_name = self.verifyFile()
        if not file_name: return

        t = PageText()
        self.stbar.busy()

        badList = []

        if file_name[0]: 
            f = open(file_name[0], 'r')
            lines = f.readlines()
            f.close()

            for i in range(len(lines)):
                index = string.rfind(lines[i], "processeur")
                if index != -1:
                    str1 = "finition des familles de faces et cellules"
                    str2 = "Nombre de faces de bord"
                    str3 = 'Famille'
                    str4 = 'Couleur'
                    str5 = 'Couleur '
                    break
                else:
                    str1 = "Definition of face and cell families"
                    str2 = "Number of boundary faces"
                    str3 = 'Family'
                    str4 = 'Color'
                    str5 = 'Color '

            for i in range(len(lines)):
                index = string.rfind(lines[i], str1)
                if index != -1: 
                    j = i
                    break

            for n in range(j,len(lines),1):
                index = string.rfind(lines[n], str2)
                if index != -1:
                    for m in range(n,j,-1):
                        if string.rfind(lines[m], str3) != -1: break
                        if string.rfind(lines[m], str4) != -1: 
                            coul = string.split(lines[m], str5)
                            for cl in coul[1:]:
                                ref = string.split(cl,'\n')[0]
                                l = ""
                                gr = ""
                                refList,groupList = self.mdl.getLists()
                                if ref: 
                                    ref = int(ref)
                                    if not ref in refList: 
                                        name = self.insertHlist('wall', l, ref, gr)
                                        self.mdl.setBoundaries('wall', name, ref, gr)
                                        refList,groupList = self.mdl.getLists()
                                    else: 
                                        badList.append(ref)

        if badList: 
            Dialog.ShowInfo(self.master, title=t.INFO, text=t.FACES_BORD+str(badList))

        self.stbar.idle()


    def _createWidgets(self):
        """
        Create the Page layout.
        """
        t = PageText()

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

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


        # Put a simple hierachy into the Hlist (two levels).
        #
        self.h = Tix.ScrolledHList(self.w1, options='hlist.columns 5 hlist.header 1 ' )
        self.h.config(scrollbar="auto +y +x")

        # selectmode='extended' -> multi select with <Shift> and <Ctrl>
        # selectmode='multiple' -> multi select only with <Shift>
        #
        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(expand=1, fill=BOTH, padx=10, pady=10, side=TOP)

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

        # First some styles for the headers
        #
        self._make_style()

        # Create the headers
        #
        self.h.hlist.header_create(0, itemtype=Tix.TEXT, text=t.LABEL,
                                   style=self.style['header'])
        self.h.hlist.header_create(1, itemtype=Tix.TEXT, text=t.TYPE,
                                   style=self.style['header'])
        self.h.hlist.header_create(2, itemtype=Tix.TEXT, text=t.REF,
                                   style=self.style['header'])
        self.h.hlist.header_create(3, itemtype=Tix.TEXT, text=t.GROUP,
                                   style=self.style['header'])

        # Notice that we use 5 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 5 column header is
        # not shown unless the Hlist window is wider than its contents.
        #
        self.h.hlist.column_width(4,0)

        # Let configure the appearance of the Hlist subwidget 
        #
        self.h.hlist.config(separator='.', width=25, height=11, drawbranch=0, indent=10)

        # Let configure the width of the columns
        #
        self.h.hlist.column_width(0, chars=16)
        self.h.hlist.column_width(1, chars=9)
        self.h.hlist.column_width(2, chars=12)
        self.h.hlist.column_width(3, chars=16)

        # Create the mouse selection instance
        #
        self.select = MultiSelect(self.h.hlist, self.typeList, self.typeColor)

        # 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)
        pm.menu.add_cascade(label=t.SELECT_TYPE, menu=pm.menu.m1)
        for key in self.typeList.keys():
            pm.menu.m1.add_command(label=self.typeList[key],
                                   command=TkPage.Callback(self.typeSelection, key))
        pm.menu.add_separator()
        pm.menu.m2 = Tix.Menu(pm.menu)
        pm.menu.add_cascade(label=t.SORT_OUT, menu=pm.menu.m2)
        pm.menu.m2.add_command(label=t.REF, command=self.refSortOut)
# TODO
##        pm.menu.m2.add_command(label=t.BY_LABEL_ALPHA)
##        pm.menu.m2.add_command(label=t.BY_GROUP_ALPHA)
# TODO
        pm.menu.m2.add_command(label=t.TYPE, command=self.typeSortOut)
# TODO
##        pm.menu.add_separator()
##        pm.menu.m3 = Tix.Menu(pm.menu)
##        pm.menu.add_cascade(label=t.OPTION, menu=pm.menu.m3)
##        pm.menu.m3.add_command(label=t.BGCOLOR)
# TODO


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

        # NoteBook and tabs layout
        #
        nb = Tix.NoteBook(lf1.frame, background=self.bg)
        nb.pack(expand=1, side=TOP, fill=X, padx=10, pady=10)
        #nb.configure(highlightbackground='#d9d9d9')
        #nb.configure(highlightcolor='Black')
    
        nb.nbframe.config(background=self.bg, backpagecolor=self.bg)
        nb.nbframe.config(focuscolor=self.bg, inactivebackground=wm['inactivebackground'])
        nb.nbframe.config(relief=RAISED)
        nb.nbframe.config(font=fT, tabpadx='2', tabpady='1')
        nb.add('page1', anchor='center', label=t.MANUAL_TITLE)
        nb.add('page2', anchor='center', label=t.AUTO_TITLE)
        ### for next version :
        ###nb.add('page3', anchor='center', label=t.VISU_TITLE)

        # NoteBook Page 1
        #
        nb.page1.configure(bg=self.bg)

        f1 = Tix.Frame(nb.page1, relief=FLAT)
        f1.pack(side=TOP, fill=X)

        l1 = Tix.Label(f1, text=t.LABEL)
        self.l2 = Tix.Label(f1, text=t.REF)
        self.l3 = Tix.Label(f1, text=t.GROUP)
        l4 = Tix.Label(f1, text=t.TYPE)

        l1.grid(row=0, column=0, padx=3, pady=5, sticky=E)
        self.l2.grid(row=1, column=0, padx=3, pady=5, sticky=E)
        self.l3.grid(row=2, column=0, padx=3, pady=5, sticky=E)
        l4.grid(row=3, column=0, padx=3, pady=5, sticky=E)

        self.e1 = Tix.Entry(f1, bd=2, width=15, textvariable=self.label)
        self.e2 = Tix.Entry(f1, bd=2, width=15, textvariable=self.color)
        self.e3 = Tix.Entry(f1, bd=2, width=15, textvariable=self.group)

        self.e2.bind('<Return>', self.createHlist)

        self.l3.config(state=DISABLED)
        self.e3.config(state=DISABLED)

        self.b1 = Tix.OptionMenu(f1, options='menubutton.width 14')
        self.b1.menubutton.config(bd=2, relief=RAISED)
        self.b1.config(variable=self.type, command=self.getType)

        self.e1.grid(row=0, column=1, padx=5, pady=5, sticky=W)
        self.e2.grid(row=1, column=1, padx=5, pady=5, sticky=W)
        self.e3.grid(row=2, column=1, padx=5, pady=5, sticky=W)
        self.b1.grid(row=3, column=1, padx=0, pady=5, sticky=W)

        for key in self.typeList.keys():
            self.b1.add_command(self.typeList[key], label=self.typeList[key])

        box1 = Tix.ButtonBox(f1, orientation=VERTICAL, relief=FLAT)
        box1.add('create', text=t.CREATE, command=self.createHlist)
        box1.add('modify', text=t.MODIFY, command=self.editHlist)
        box1.add('erase',  text=t.ERASE,  command=self.cancelHlist)
        box1.grid(row=0, column=2, rowspan=4, padx=15, pady=2, sticky=W)

        # NoteBook Page 2
        #
        nb.page2.configure(bg=self.bg)

        f2 = Tix.Frame(nb.page2, relief=FLAT)
        f2.pack(side=TOP, fill=X)

        Tix.Label(f2, relief=FLAT, text=t.FIC_ENV).grid(row=0,column=0,padx=15,pady=15)

        self.img = Tix.PhotoImage(file=PIC_PATH+'search1.gif')
        env = Tix.Button(f2, image=self.img, command=self.searchListEnv)
        env.grid(row=0,column=1,padx=15,pady=15)


    def _initializeWidgets(self):
        """
        Extract resquested informations from XML document.
        This informations are used to initialize the widgets.
        For this page default values of all widgets are necessary
        included in the XML file.
        """
        if self.mdl.getCase() == "byReference":
            self.refSortOut()
        else:
            self.typeSortOut()


#-------------------------------------------------------------------------------
# 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.AUTO_TITLE    = "AUTOMATIQUE"
            self.BAD_FILE      = "Attention : le fichier sélectionné n'est pas correct.\n\n"\
                                 "Verifier votre sélection"
            self.CREATE        = "Créer"
            self.ERASE         = "Effacer"
            self.FACES_BORD    = "Attention : les références de faces de bord suivantes" \
                                 " ont déjà été déclarées :\n\n"
            self.FIC_ENV       = "Sélectionner le listing enveloppe"
            self.GROUP         = "Groupe"
            self.INFO          = "Informations"
            self.INFO_DELETE   = "Attention : la modification de la définition d'une"\
                                " condition limite entraîne la perte des informations"\
                                " associées à la précédente définition."
            self.INLET         = "entrée"
            self.LABEL         = "Étiquette"
            self.MANUAL_TITLE  = "MANUEL"
            self.MODIFY        = "Modifier"
            self.OUTLET        = "sortie"
            self.POPUP         = "Menu popup"
            self.REF           = "Référence"
            self.SELECT_ALL    = "Tout sélectionner"
            self.SORT_OUT      = "Trier par"
            self.SELECT_TYPE   = "Sélection par type"
            self.SYMMETRY      = "symétrie"
            self.TITLE         = "Définition des zones frontières"
            self.TYPE          = "Type"
##            self.UNDEFINED     = "indéfini"
            self.UNSELECT      = "Désélectionner"
            self.VISU_TITLE    = "VISUALISATION"
            self.WALL          = "paroi"
        else:
            self.AUTO_TITLE    = "AUTOMATIC"
            self.BAD_FILE      = "Warning : the selected file is not a correct file.\n\n"\
                                "Verify your selection"
            self.CREATE        = "Create"
            self.ERASE         = "Delete"
            self.FACES_BORD    = "Warning : the following faces de bord referencies " \
                                 "have been already created :\n\n"
            self.FIC_ENV       = "Select the envelop file"
            self.GROUP         = "Group"
            self.INFO          = "Informations"
            self.INFO_DELETE   = "Warning : the modification of a region boundary"\
                                " definition occurs the lost of data about the previous"\
                                " definition."
            self.INLET         = "inlet"
            self.LABEL         = "Label"
            self.MANUAL_TITLE  = "MANUAL"
            self.MODIFY        = "Modify"
            self.OUTLET        = "outlet"
            self.POPUP         = "Menu popup"
            self.REF           = "Reference"
            self.SELECT_ALL    = "Select all"
            self.SELECT_TYPE   = "Selection by type"
            self.SORT_OUT      = "Sort out by"
            self.SYMMETRY      = "symmetry"
            self.TITLE         = "Define Boundary regions"
            self.TYPE          = "Type"
##            self.UNDEFINED     = "undefined"
            self.UNSELECT      = "Unselect"
            self.VISU_TITLE    = "VISUALIZATION"
            self.WALL          = "wall"

        # 2) Messages
        #
        if Tool.GuiParam.lang == 'fr':
            self.MSG_HLIST   = "Cliquer le bouton droit pour "       +\
                               "le menu contextuel."
        else:
            self.MSG_HLIST   = "Click right button for popup menu."


#-------------------------------------------------------------------------------
# Turbulence test case
#-------------------------------------------------------------------------------


class DefBCTestCase(unittest.TestCase):
    """
    """
    def setUp(self):
        """
        This method is executed before all "check" methods.
        """
        from Base.XMLstuff import TkGuiModel
        self.case = TkGuiModel(None)


    def tearDown(self):
        """
        This method is executed after all "check" methods.
        """
        del self.case


    def checkDefBCModelInstantiation(self):
        """Check whether the DefBCModel class could be instantiated"""
        model = None
        model = DefBCModel(self.case)
        assert model != None, 'Could not instantiate DefBCModel'


    def checksetBoundaryDefandCond(self):
        """
        """
        model = DefBCModel(self.case)
        model.xmlSetBoundaryDefandCond('inlet', 'porte', '4', None)
        truc = model.node_bc.toString()
        
        doc = '<boundary_conditions>'\
                  '<boundary_definition>'\
                      '<inlet label="porte">'\
                          '<reference>4</reference>'\
                      '</inlet>'\
                  '</boundary_definition>'\
                  '<inlet label="porte">'\
                       '<velocity_pressure choice=""/>'\
                       '<turbulence choice=""/>'\
                  '</boundary_definition>'\
                  '<inlet label="porte">'\
                       '<velocity_pressure choice=""/>'\
                       '<turbulence choice=""/>'\
                       '<scalar choice="" label="temperature_celsius" type="thermal"/>'\
                       '<scalar choice="" label="scal1" type="user"/>'\
                  '</inlet>'\
              '</boundary_conditions>'

        assert doc == truc, 'Could not set the boundary reference number'

        model.xmlSetBoundaryDefandCond('inlet', 'porte', None, 'titi')
        truc = model.node_bc.toString()

        doc = '<boundary_conditions>'\
                  '<boundary_definition>'\
                      '<inlet label="porte">'\
                          '<reference>4</reference>'\
                          '<group>titi</group>'\
                      '</inlet>'\
                  '</boundary_definition>'\
                  '<inlet label="porte">'\
                       '<velocity_pressure choice=""/>'\
                       '<turbulence choice=""/>'\
                       '<scalar choice="" label="temperature_celsius" type="thermal"/>'\
                       '<scalar choice="" label="scal1" type="user"/>'\
                  '</inlet>'\
              '</boundary_conditions>'

        assert doc == truc, 'Could not set the boundary group string'



def suite():
    testSuite = unittest.makeSuite(DefBCTestCase, "check")
    return testSuite

    
def runTest():
    runner = unittest.TextTestRunner()
    runner.run(suite())


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


syntax highlighted by Code2HTML, v. 0.9.1