# -*- 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 contains the following classes and function:
- BodyForcesModel
- BodyForcesView
- PageText
- BodyForcesTestCase
"""


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


from math import sqrt
import sys, Tix, unittest
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


#-------------------------------------------------------------------------------
# Body Force model class
#-------------------------------------------------------------------------------


class BodyForcesModel:

    def __init__(self, case):

        """
        Constuctor.
        """
        self.case = case

        self.node_pp      = self.case.xmlGetNode('physical_properties')
        self.node_gravity = self.node_pp.xmlInitNode('gravity')
        self.node_hydpres = self.node_pp.xmlInitNode('hydrostatic_pressure', 'status')

        self.nodes = ['gravity_x', 'gravity_y', 'gravity_z']


    def getGravity(self, var):
        """
        """
        if var not in self.nodes:
            raise NameError, "gravity nodes names error"
        gravity = self.node_gravity.xmlGetDouble(var)
        if not gravity: gravity = 0.

        return gravity


    def setGravity(self, num, value):
        """
        """
        if num == 'x' or num == 'X':
            num = 0
        elif num == 'y' or num == 'Y':
            num = 1
        elif num == 'z' or num == 'Z':
            num = 2
        self.node_gravity.xmlSetData(self.nodes[num], value)


    def getHydrostaticPressure(self):
        """
        """
        if self.node_hydpres['status'] == 'on':
            return 1
        else:
            self.node_hydpres['status'] = 'off'
            return 0


    def setHydrostaticPressure(self, var):
        """
        """
        self.node_hydpres['status'] = var


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


class BodyForcesView(TkPage.Page):
    """
    Class to open the Body Forces (gravity) Page.
    """
    def _tkControlVariables(self):
        """
        Tkinter variables declaration.
        """
        self.gravity_x  = Tix.DoubleVar()
        self.gravity_y  = Tix.DoubleVar()
        self.gravity_z  = Tix.DoubleVar()
        self.hpr_yes_no = Tix.StringVar()


    def _pageControl(self):
        """
        Xml node declaration and supplementary default value settings.
        """
        self.bF = BodyForcesModel(self.case)


    def getGravity(self, num, gravity, event=None):
        """
        Input GX, GY, GZ
        """
        self.stbar.busy()

#        if self.check2.hasType(self.e[num].entry, gravity):
        if self.check2.hasType(self.e[num], gravity):
            self.bF.setGravity(num, gravity.get())

        self.stbar.idle()


    def getGravityNormalization(self, event=None):
        """
        Normalize the gravity direction to 9,81 m/s2
        """
        self.stbar.busy()

        try:
            gx = self.gravity_x.get()
            gy = self.gravity_y.get()
            gz = self.gravity_z.get()
            norm = sqrt( gx**2 + gy**2 + gz**2)

            if norm != 0:
                coeff = 9.81 / norm
                self.gravity_x.set( coeff * gx )
                self.gravity_y.set( coeff * gy )
                self.gravity_z.set( coeff * gz )
        except:
            pass

        self.stbar.idle()


    def getHydrostaticPressure(self, event=None):
        """
        Input IHYDPR.
        """
        self.stbar.busy()
        self.bF.setHydrostaticPressure(self.hpr_yes_no.get())
        self.stbar.idle()


    def _createWidgets(self):
        """
        Make widgets and the layout.
        """
        t = PageText()

        # FIRST PART : GRAVITY MANAGEMENT LAYOUT
        #
        lf1 = Tix.LabelFrame(self.myPage, bd=2, label=t.GRAVITY_TITLE, relief=FLAT)
        lf1.label.config(font=fT)
        lf1.pack(side=TOP, fill=X, padx=10, pady=10)

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

        self.e = [0]*3
#        for (i, var, tx1, tx2) in [(0, self.gravity_x, t.GRAVITY_X, "GX"),
#                                   (1, self.gravity_y, t.GRAVITY_Y, "GY"),
#                                   (2, self.gravity_z, t.GRAVITY_Z, "GZ")]:

#            self.e[i] = Tix.ComboBox(w1, label=tx1, editable=1,
#                                     bd=2, listwidth=30,
#                                     selectmode="", variable=var)
#            self.e[i].entry.config(width=8)
#            self.e[i].entry.event_add("<<Event>>", "<Return>", "<Leave>", "<FocusOut>")
#            self.e[i].entry.bind("<<Event>>", TkPage.Callback(self.getGravity,i,var))
#            self.e[i].slistbox.config(height=85, scrollbar="auto")
#            self.e[i].config(command=TkPage.Callback(self.getGravity,i,var))

#            self.balloon.bind_widget(self.e[i], balloonmsg=t.KEYWORD+tx2)
#            self.e[i].insert(END, '0.0')
#            self.e[i].insert(END, '9.81')
#            self.e[i].insert(END, '-9.81')
#            self.e[i].grid(row=i, column=0, padx=5, pady=10, sticky=W)

#            Tix.Label(w1, text=t.GRAVITY_UNIT).\
#                          grid(row=i, column=1, padx=2, pady=2, sticky=W)

        for (i, var, tx1, tx2) in [(0, self.gravity_x, t.GRAVITY_X, "GX"),
                                   (1, self.gravity_y, t.GRAVITY_Y, "GY"),
                                   (2, self.gravity_z, t.GRAVITY_Z, "GZ")]:

            Tix.Label(w1, text=tx1).grid(row=i, column=0, padx=2, pady=2, sticky=W)
            self.e[i] = Tix.Entry(w1, bd=2, width=8, textvariable=var)
            self.e[i].event_add("<<Event>>", "<Return>", "<Leave>", "<FocusOut>")
            self.e[i].bind("<<Event>>", TkPage.Callback(self.getGravity,i,var))

            self.balloon.bind_widget(self.e[i], balloonmsg=t.KEYWORD+tx2)
            self.e[i].grid(row=i, column=1, padx=5, pady=10, sticky=W)

            Tix.Label(w1, text=t.GRAVITY_UNIT).\
                          grid(row=i, column=2, padx=2, pady=2, sticky=W)
        # Separator
        #
        Tix.Frame(lf1.frame, height=2, bd=2, relief=SUNKEN).pack(side=TOP, fill=X)


        # Gravity Normalization
        #
        w2 = Tix.Frame(lf1.frame, relief=FLAT)
        w2.pack(side=TOP, padx=10)

        l1 = Tix.Label(w2, text=t.GRAVITY_NORM)
        l1.pack(side=LEFT, padx=5, pady=10)

        self.img = Tix.PhotoImage(file=PIC_PATH+'gravity.gif')
        self.b = Tix.Button(w2, image=self.img, command=self.getGravityNormalization)
        self.b.pack(side=LEFT, padx=5, pady=5)


        # SECOND PART : HYDROSTATIC PRESSURE MANAGEMENT LAYOUT
        #
        lf2 = Tix.LabelFrame(self.myPage, bd=2, label=t.HPRESSURE_TITLE, relief=FLAT)
        lf2.label.config(font=fT)
        lf2.pack(side=TOP, fill=X, padx=10, pady=10)

        # Left column
        #
        l2 = Tix.Label(lf2.frame, text=t.HPRESSURE)
        self.balloon.bind_widget(l2, balloonmsg=t.KEYWORD+"IPHYDR")
        l2.grid(row=0, column=0, columnspan=2, padx=5, pady=10)

        # Right column
        #
        self.b = [0]*2
        for (i, tx1, tx2) in [(0, t.YES,'on' ),
                              (1, t.NO, 'off')]:

            self.b[i] = Tix.Radiobutton(lf2.frame, text=tx1, value=tx2,
                                        variable=self.hpr_yes_no,
                                        command=self.getHydrostaticPressure)
            self.b[i].grid(row=1, column=i, pady=10)


    def _initializeWidgets(self):
        """
        Extract resquested informations from XML document.
        This informations are used to initialize the widgets.
        """
        #temp, gravity = 0., 0.
        gravity = 0., 0.
        if (self.bF.getHydrostaticPressure()):
            self.b[0].select()
        else:
            self.b[1].select()

        for (num, var) in [(0, self.gravity_x),
                           (1, self.gravity_y),
                           (2, self.gravity_z)]:
            gravity = self.bF.getGravity(self.bF.nodes[num])
        #    temp = temp + gravity
            var.set(gravity)

        # default initialization on Gz
        #if not temp: self.gravity_z.set(-9.81)


#-------------------------------------------------------------------------------
# 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.GRAVITY_NORM    = "Forcer la norme du vecteur gravité à 9,81 m/s2"
            self.GRAVITY_TITLE   = "Gravité"
            self.GRAVITY_UNIT    = "m/s2"
            self.GRAVITY_X       = "Gravité selon X"
            self.GRAVITY_Y       = "Gravité selon Y"
            self.GRAVITY_Z       = "Gravité selon Z"
            self.HPRESSURE       = "Interpolation de pression en écoulement stratifié :"
            self.HPRESSURE_TITLE = "Pression hydrostatique"
            self.KEYWORD         = "Mot clé Code_Saturne : "
            self.NO              = "standard"
            self.YES             = "améliorée"
        else:
            self.GRAVITY_NORM    = "Normalize the gravity vector to 9,81 m/s2"
            self.GRAVITY_TITLE   = "Gravity"
            self.GRAVITY_UNIT    = "m/s2"
            self.GRAVITY_X       = "Gravity on X"
            self.GRAVITY_Y       = "Gravity on Y"
            self.GRAVITY_Z       = "Gravity on Z"
            self.HPRESSURE       = "Pressure interpolation in stratified flow:"
            self.HPRESSURE_TITLE = "Hydrostatic pressure"
            self.KEYWORD         = "Code_Saturne key word: "
            self.NO              = "standard"
            self.YES             = "improved"

        # 2) Messages
        #


#-------------------------------------------------------------------------------
# BodyForce test case
#-------------------------------------------------------------------------------


class BodyForcesTestCase(unittest.TestCase):
    """
    """
    def setUp(self):
        """
        This method is executed before all "check" methods.
        """
        from Base.XMLengine import Case, XMLDocument
        from Base.XMLinitialize import XMLinit
        Tool.GuiParam.lang = 'en'
        self.case = Case(None)
        XMLinit(self.case)

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

    def checkBodyForcesInstantiation(self):
        """
        Check whether the BodyForcesModel class could be instantiated
        """
        model = None
        model = BodyForcesModel(self.case)

        assert model != None, 'Could not instantiate BodyForcesModel'

    def checkSetGravity(self):
        """
        Check whether the gravity terms could be set
        """
        mdl = BodyForcesModel(self.case)
        mdl.node_gravity.xmlRemoveChild('gravity')
        mdl.setGravity('x', 1)
        mdl.setGravity('Y', 2)
        mdl.setGravity(2, 3)

        truc = mdl.node_gravity.toString()
        doc = '<gravity>'\
                '<gravity_x>1</gravity_x>'\
                '<gravity_y>2</gravity_y>'\
                '<gravity_z>3</gravity_z>'\
              '</gravity>'
        assert doc == truc, 'Could not set gravity'


    def checkGetGravity(self):
        """
        Check whether the gravity terms could be get
        """
        mdl = BodyForcesModel(self.case)
        mdl.node_gravity.xmlRemoveChild('gravity')
        mdl.setGravity('x', 1)
        mdl.setGravity('Y', 2)
        mdl.setGravity(2, 3)

        list = []
        list.append(mdl.getGravity('gravity_x'))
        list.append(mdl.getGravity('gravity_y'))
        list.append(mdl.getGravity('gravity_z'))

        assert list == [1,2,3], 'Could not get gravity'


    def checkSetHydrostaticPressure(self):
        """
        Check whether the hydrostatic pressure could be set
        """
        mdl = BodyForcesModel(self.case)
        mdl.setHydrostaticPressure('on')

        truc = mdl.node_hydpres.toString()
        doc = '<hydrostatic_pressure status="on"/>'
        assert doc == truc, 'Could not set hydrostatic pressure'


    def checkSetHydrostaticPressure(self):
        """
        Check whether the hydrostatic pressure could be get
        """
        mdl = BodyForcesModel(self.case)
        mdl.setHydrostaticPressure('toto')

        assert mdl.getHydrostaticPressure() == 0,\
                    'Could not get hydrostatic pressure'


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


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


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


syntax highlighted by Code2HTML, v. 0.9.1