# -*- 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 window dialog classes for the Tk GUI.

This module defines the following classes:
- Dialog
- ShowInfo
- About
- Warning
- Error
- AskYesNo (to be used with the askyesno function)
- DirSelect (to be used with the dirselect function)
- DialogText
"""

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


import os
import Tix
from Tkconstants import *


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


from Common import *
import Toolbox
import TkPage


#-------------------------------------------------------------------------------
# Popup dialog Windows
#-------------------------------------------------------------------------------


class Dialog(Tix.Toplevel):
    """
    Class to open dialogs.
    This class is intended as a base class for custom dialogs.
    This class is a mix from SimpleDialog.py and Dialog.py (with little changes)
    """
    def __init__(self, parent=None, **options):
        """
        Initialize a dialog popup window.
        Arguments:
        parent             -- a parent window (the application window)
        options['parent']  -- idem
        options['title']   -- the dialog title
        options['default'] -- object which contains parameters
        options['stbar']   -- status bar for status message and balloon widget
        options['case']    -- object which contens the current case
        options['class_']  -- new widget class name
        """
        for key in options.keys():
            if key not in ('parent','title','default','stbar','case','class_'):
                raise TypeError, "__init__() got an unexpected keyword argument '%s'"%key

        if not parent and options.has_key('parent'):
            parent = options['parent']

        if not parent:
            raise TypeError, "__init__() takes at least 2 non-keyword argument (1 given)"

        if options.has_key('class_'):
            Tix.Toplevel.__init__(parent, class_=options['class_'])
        else:
            Tix.Toplevel.__init__(self, parent)

        if options.has_key('title'):
            self.title(options['title'])
            self.iconname(options['title'])

        self.parent = parent
        self.check2 = TkPage.DataValidator2()

        # Fonts.
        #
        Toolbox.setupFontDefault(self)

        # Look for the status bar and the balloon widget
        #
        if options.has_key('stbar'):
            self.stbar = options['stbar']
            self.balloon = Tix.Balloon(self, statusbar=self.stbar.label, bd=1, bg='black')
            self.balloon.message.config(bg=wm['background'])

        # Attribute for results storage
        #
        self.result = None

        # Attribute for Dialog Window configuration
        #
        if options.has_key('default'):
            self.default = options['default']

        # Current case
        #
        if options.has_key('case'):
            self.case = options['case']

        self.protocol('WM_DELETE_WINDOW', self.cancel)

        frame = Tix.Frame(self, relief=FLAT)
        frame.pack()
        self.initial_focus = self.body(frame)
        if not self.initial_focus:
            self.initial_focus = self

        self.sequence()

        self.buttonbox()

        # Call this function AFTER the layout of all children widgets
        #
        self._set_transient(parent)

        # Make sure that no mouse or keyboard events are sent to the wrong window
        #
        self.grab_set()

        # Move the keyboard focus to the dialog window
        #
        self.initial_focus.focus_set()

        # Start local event lopp, and resume execusion of parent window
        #
        self.wait_window(self)


    def _set_transient(self, parent, relx=0.5, rely=0.3):
        """
        Manage the display of new window.
        """
        # Remain invisible while we figure out the geometry
        #
        self.withdraw()

        # A transient window is allways drawn on top of its parent
        #
        self.transient(parent)

        # Actualize geometry information
        #
        self.update_idletasks()

        if parent.winfo_ismapped():
            m_width = parent.winfo_width()
            m_height = parent.winfo_height()
            m_x = parent.winfo_rootx()
            m_y = parent.winfo_rooty()
        else:
            m_width = parent.winfo_screenwidth()
            m_height = parent.winfo_screenheight()
            m_x = m_y = 0

        w_width = self.winfo_reqwidth()
        w_height = self.winfo_reqheight()
        x = m_x + (m_width - w_width) * relx
        y = m_y + (m_height - w_height) * rely
        if x+w_width > parent.winfo_screenwidth():
            x = parent.winfo_screenwidth() - w_width
        elif x < 0:
            x = 0
        if y+w_height > parent.winfo_screenheight():
            y = parent.winfo_screenheight() - w_height
        elif y < 0:
            y = 0
        self.geometry("+%d+%d" % (x, y))

        # Become visible at the desired location
        #
        self.deiconify()


    def destroy(self):
        """
        Destroy the window
        """
        self.initial_focus = None
        Tix.Toplevel.destroy(self)

    #
    # construction hooks

    def body(self, master):
        """
        Create dialog body.
        Return widget that should have initial focus.
        This method should be overridden, and is called
        by the __init__ method.
        """
        pass


    def sequence(self):
        """
        Bind the dialog window with 'Echap' and 'Return'
        Override if you don't want the standard binding
        (for example  ou have to bind the dialog window
        with only 'Echap' and delete sequence 'Return', 
        when there is any entries on the dialog window).

        """
        self.bind('<Return>', self.ok)
        self.bind('<Escape>', self.cancel)


    def buttonbox(self):
        """
        Add standard button box.
        Override if you don't want the standard buttons.
        """
        t = DialogText()

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

        # Button box
        #
        box = Tix.Frame(self, relief=FLAT)
        box.pack()

        b1 = Tix.Button(box, text=t.VALIDATE,
                        underline=0, width=10,
                        command=self.ok, default=ACTIVE)
        b1.grid(row=0, column=0, padx=5, pady=10)
        b1.bind('<Return>', self.ok)

        b2 = Tix.Button(box, text=t.CANCEL,
                        underline=0, width=10,
                        command=self.cancel)
        b2.grid(row=0, column=1, padx=5, pady=10)
        b2.bind('<Return>', self.cancel)

    #
    # standard button semantics

    def ok(self, event=None):
        """
        First hide the dialog window, then call the apply method, and
        finally destroy the dialog window.
        """
        if not self.validate():
            # put focus back
            #
            self.initial_focus.focus_set()
            return

        # Put invisible and actualize geometry information
        #
        self.withdraw()
        self.update_idletasks()

        self.apply()

        # put focus back to the parent window and close the dialog window.
        #
        self.parent.focus_set()
        self.destroy()


    def cancel(self, event=None):
        """
        Close the dialog window.
        You should override it if necessary.
        """
        self.result = self.default

        # put focus back to the parent window
        #
        self.parent.focus_set()
        self.destroy()
    #
    # command hooks

    def validate(self):
        """
        This method is called automatically to validate the data before the
        dialog is destroyed. By default, it always validates OK.
        You should override it if necessary.
        """
        return 1


    def apply(self):
        """
        Process the data.
        This method is called automatically to process the data, *after*
        the dialog is destroyed. By default, it does nothing.
        You should override it.
        """
        pass


    #
    # usefull methods


    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)


#-------------------------------------------------------------------------------
# ShowInfo popup window
#-------------------------------------------------------------------------------


class ShowInfo(Dialog):
    """
    This class is intended as a base class for Informations dialog window.
    It is usefull two for the About dialog window.
    """        
    def __init__(self, parent=None, **options):
        """
        Initialize a ShowInfo dialog popup window.
        Arguments:
        parent             -- a parent window (the application window)
        options['parent']  -- idem
        options['title']   -- the dialog title
        options['text']    -- object which contains the texte of the dialog popup window
        options['image']   -- the image to display in the left of the window
        options['justify'] -- text justification (CENTER, LEFT(default), RIGHT)
        options['length']  -- number max of characters in each line
        options['default'] -- object which contains parameters
        """
        # Check arguments, an options[key] set to 'None' is deleted in order to take
        # a default value.
        #
        for key in options.keys():
            if key not in ('parent','title','default','text','image','length','justify'):
                raise TypeError, "__init__() got an unexpected keyword argument '%s'"%key
            else:
                if options[key] == None: del options[key]

        # Set default values
        #
        if not parent and options.has_key('parent'):
            parent = options['parent']

        if not parent:
            raise TypeError, "__init__() takes at least 2 non-keyword arguments (1 given)"

        if options.has_key('text'):
            self.text = options['text']
        else:
            self.text = ""

        if options.has_key('image'):
            self.image = PIC_PATH + options['image']
        else:
            self.image = PIC_PATH + 'boussole.gif'

        if options.has_key('length'):
            self.lenght = options['length']
        else:
            self.lenght = LENGHT_WIDTH

        if options.has_key('justify'):
            self.justify = options['justify']
        else:
            self.justify = LEFT

        if not options.has_key('default'):
            options['default'] = "no"

        if not options.has_key('title'):
            options['title'] = ""

        Dialog.__init__(self, parent, title=options['title'], default=options['default'])


    def body(self, master):
        """
        Format selector layout
        """
        # Window dialog layout
        #
        self.img = Tix.PhotoImage(file=self.image)

        w, h = self.img.width(), self.img.height()

        Tix.Label(master, width=w,  height=h,
                  relief=SUNKEN, bd=1, image=self.img) \
                  .pack(side=LEFT, padx=15, pady=15, ipadx=5, ipady=5)

        Tix.Label(master, text=self.text,
                  relief=FLAT, wraplength=self.lenght, justify=self.justify) \
                  .pack(side=LEFT, padx=20, pady=20)


    def buttonbox(self):
        """
        Override standard button box.
        """
        t = DialogText()

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

        # Button box
        #
        box = Tix.Frame(self, relief=FLAT)
        box.pack()

        b = Tix.Button(box, text=t.CLOSE, underline=0, width=10,
                       command=self.cancel, default=ACTIVE)
        b.pack(side=TOP, padx=10, pady=10)


#-------------------------------------------------------------------------------
# About popup window
#-------------------------------------------------------------------------------


class About(ShowInfo):
    """
    Initialize an About dialog popup window.
    """        
    def __init__(self, parent,
                 title=None, text=None, image=None,
                 justify=None, length=None):
        """
        Arguments:
        parent  -- a parent window (the application window)
        title   -- the dialog title
        text    -- object which contains the texte of the dialog popup window
        image   -- the image to display in the left of the window
        justify -- text justification (CENTER (default), LEFT, RIGHT)
        length  -- number max of characters in each line
        """
        t = DialogText()

        if not title:
            title = t.ABOUT

        if not text:
            text = t.MSG_ABOUT

        if not image:
            image = 'telephone.gif'

        if not justify:
            justify = CENTER

        if not length:
            length = 250

        ShowInfo.__init__(self, parent, title=title, text=text,
                          image=image, justify=justify, length=length)


#-------------------------------------------------------------------------------
# Warning popup window
#-------------------------------------------------------------------------------


class Warning(ShowInfo):
    """
    Initialize a Warning dialog popup window.
    """        
    def __init__(self, parent,
                 title=None, text=None, image=None,
                 justify=None, length=None):
        """
        Arguments:
        parent  -- a parent window (the application window)
        title   -- the dialog title
        text    -- object which contains the texte of the dialog popup window
        image   -- the image to display in the left of the window
        justify -- text justification (CENTER, LEFT(default), RIGHT)
        length  -- number max of characters in each line
        """
        if not title:
            t = DialogText()
            title = t.WARNING

        if not image:
            image = 'danger.gif'

        ShowInfo.__init__(self, parent, title=title, text=text,
                          image=image, justify=justify, length=length)


#-------------------------------------------------------------------------------
# Error popup window
#-------------------------------------------------------------------------------


class Error(ShowInfo):
    """
    Initialize an Error dialog popup window.    
    """        
    def __init__(self, parent,
                 title=None, text=None, image=None,
                 justify=None, length=None):
        """
        Arguments:
        parent  -- a parent window (the application window)
        title   -- the dialog title
        text    -- object which contains the texte of the dialog popup window
        image   -- the image to display in the left of the window
        justify -- text justification (CENTER, LEFT(default), RIGHT)
        length  -- number max of characters in each line
        """
        if not title:
            t = DialogText()
            title = t.ERROR

        if not image:
            image = 'tete_de_mort.gif'

        ShowInfo.__init__(self, parent, title=title, text=text,
                          image=image, justify=justify, length=length)


#-------------------------------------------------------------------------------
# AskYesNo popup window
#-------------------------------------------------------------------------------


class AskYesNo(ShowInfo):
    """
    Initialize an AskYesNo dialog popup window.
    """        
    def __init__(self, parent,
                 title=None, text=None, image=None,
                 justify=None, length=None, default='no'):
        """
        Arguments:
        parent  -- a parent window (the application window)
        title   -- the dialog title
        text    -- object which contains the texte of the dialog popup window
        image   -- the image to display in the left of the window
        justify -- text justification (CENTER (default), LEFT, RIGHT)
        length  -- number max of characters in each line
        default -- object which contains parameters
        """
        if not title:
            t = DialogText()
            title = t.QUESTION

        if not image:
            image = 'question.gif'

        ShowInfo.__init__(self, parent, title=title, text=text, image=image,
                          justify=justify, length=length, default=default)


    def buttonbox(self):
        """
        Override standard button box.
        """
        t = DialogText()

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

        # Button box
        #
        box = Tix.Frame(self, relief=FLAT)
        box.pack()

        b1 = Tix.Button(box, text=t.YES,
                        underline=0, width=10,
                        command=self.ok, default=ACTIVE)
        b1.grid(row=0, column=0, padx=10, pady=10)
        b2 = Tix.Button(box, text=t.NO,
                        underline=0, width=10,
                        command=self.cancel)
        b2.grid(row=0, column=1, padx=10, pady=10)


    def apply(self):
        """
        What to do when user clicks on 'YES'.
        """
        self.result = 'yes'


def askyesno (parent, **options):
    """
    Ask a question, and return the answer
    """
    return AskYesNo(parent, **options).result


#-------------------------------------------------------------------------------
# DirSelect popup window
#-------------------------------------------------------------------------------


class DirSelect(Dialog):
    """
    Initialize a directory selector dialog popup window.
    """        
    def __init__(self, parent=None, **options):
        """
        Arguments:
        parent             -- a parent window (the application window)
        options['parent']  -- idem
        options['title']   -- the dialog title
        options['stbar']   -- status bar for status message and balloon widget
        options['image']   -- the image to display in the left of the window
        options['default'] -- object which contains parameters
        """
        # Check arguments, an options[key] set to 'None' is deleted in order to take
        # a default value.
        #
        for key in options.keys():
            if key not in ('parent','title','default','image', 'stbar'):
                raise TypeError, "__init__() got an unexpected keyword argument '%s'"%key
            else:
                if options[key] == None: del options[key]

        # Set default values
        #
        if not parent and options.has_key('parent'):
            parent = options['parent']

        if not parent:
            raise TypeError, "__init__() takes at least 2 non-keyword arguments (1 given)"

        if options.has_key('image'):
            self.image = PIC_PATH + options['image']
        else:
            self.image = PIC_PATH + 'file_cabinet.gif'

        if not options.has_key('default'):
            options['default'] = '/home'

        if not options.has_key('title'):
            t = DialogText()
            options['title'] = t.DIRECTORY

        Dialog.__init__(self, parent, title=options['title'],
                        default=options['default'], stbar=options['stbar'])



    def sequence(self):
        """
        Bind the dialog window only with 'Echap'.
        Override the generic sequence method because the ComboBox is binded
        with the <Return> event.
        """
        self.bind("<Escape>", self.cancel)


    def selectTreeDir(self, pathName):
        """
        When the user click (or bouble-click) on a folder, its name is put in the
        ComboBox entry.
        """
        try:
            if os.path.isdir(pathName):
                self.cbx_dir.set(pathName)
                self._scrollHandler(self.cbx.entry, "moveto", 1)
                self.tree.hlist.xview(pathName)
        except TypeError:
            pass


    def changeDirInTree(self, dir):
        """
        Update the Tree with a new directory.
        """
        self.tree.chdir(dir)

        # the following try/except syntaxe is used because of a Tix bug.
        # We have a trouble shooting when self.default=os.getcwd() .
        #
        try:
            self.tree.hlist.selection_clear()
            self.tree.hlist.selection_set(dir)
        except:
            pass


    def selectCbxDir(self, event=None):
        """
        - verify that the input directory exist
        - add the directory in the slistbox
        - update the DirTree with this new directory
        """
        try:
            dir = self.cbx_dir.get()
            if os.path.isdir(dir):
                self.cbx.add_history(dir)
                self.check2.begin(self.cbx.entry)
                self.changeDirInTree(dir)
            else:
                self.check2.error(self.cbx.entry)
                t = DialogText()

        except TypeError:
            self.check2.error(self.cbx.entry)

        # These 2 lines actually does not work
        #
        self.cbx.entry.selection_range(0,0)
        self._scrollHandler(self.cbx.entry, "moveto", 1)


    def showHiddenFolders(self, event=None):
        """
        Specifies whether hidden directories should be shown.
        """
        if self.hiddenFolders.get() == 'on':
            self.tree.config(showhidden="1")
        else:
            self.tree.config(showhidden="0")


    def body(self, master):
        """
        Format selector layout
        """
        t = DialogText()

        # Tkinter variables declaration
        #
        self.cbx_dir       = Tix.StringVar()
        self.hiddenFolders = Tix.StringVar()

        # Image layout
        #
        self.img = Tix.PhotoImage(file=self.image)

        w, h = self.img.width(), self.img.height()

        Tix.Label(master, width=w,  height=h,
                  relief=SUNKEN, bd=1, image=self.img) \
                  .pack(side=LEFT, padx=15, pady=15, ipadx=5, ipady=5)

        # Frame and title layout
        #
        top = Tix.Frame(master, relief=FLAT)
        top.pack(side=LEFT, padx=20, pady=20)

        frame1 = Tix.Frame(top, relief=FLAT)
        frame1.pack(side=TOP)

        Tix.Label(frame1, text= t.DIRECTORY, relief=FLAT).\
                          pack(side=TOP, anchor=W, padx=6, pady=2)

        # ComboBox layout
        #
        self.cbx = Tix.ComboBox(frame1,
                                editable=1,
                                history=0,
                                historylimit=20,
                                bd=2,
                                listwidth=210,
                                selectmode="",
                                variable=self.cbx_dir)

        self.cbx.entry.event_add("<<E>>", "<Return>", "<Leave>", "<FocusOut>")
        self.cbx.entry.bind("<<E>>", self.selectCbxDir)
        self.cbx.slistbox.config(height=100, scrollbar="auto")
        self.cbx.slistbox.vsb.config(width=10, bd=1)
        self.cbx.slistbox.hsb.config(width=10, bd=1)
        self.cbx.pack(side=TOP, anchor=W, fill=X)
        self.cbx.config(command=self.selectCbxDir)

        # Scrollbar layout
        #
        self.scrollcbx = Tix.Scrollbar(frame1, orient=HORIZONTAL, width=10, bd=1,
                                       command=TkPage.Callback(self._scrollHandler,\
                                                               self.cbx.entry))
        self.scrollcbx.pack(side=TOP, fill=X, anchor=W, padx=6, pady=0)
        self.cbx.entry['xscrollcommand'] = self.scrollcbx.set

        # DirTree layout
        #
        self.tree = Tix.DirTree(top, options=' hlist.wideSelection "1"     \
                                               hlist.wideSelection "1"     \
                                               hlist.selectmode "single" ' )

        self.tree.config(width=200, height=300, browsecmd=self.selectTreeDir)

        self.tree.hlist.config(background=wm['treebackground'],
                               selectbackground=wm['treeselectcolor'])
        self.tree.vsb.config(width=10, bd=1)
        self.tree.hsb.config(width=10, bd=1)
        self.tree.pack(side=TOP, expand=1, fill=BOTH, pady=10)

        # Show hidden folders
        #
        frame2 = Tix.Frame(top, relief=FLAT)
        frame2.pack(side=TOP)

        l = Tix.Label(frame2, text=t.HIDDEN_FOLDERS)
        l.grid(row=1, column=0, padx=5, pady=0, sticky=W)

        c = Tix.Checkbutton(frame2, onvalue='on', offvalue='off',
                            variable=self.hiddenFolders,
                            command=self.showHiddenFolders)
        c.grid(row=1, column=1, sticky=E)

        # Default Value
        #
        self.changeDirInTree(self.default)
        # the following try/except syntaxe is used because of a Tix bug.
        # We have a trouble shooting when self.default=os.getcwd() .
        #
        try:
            self.tree.hlist.yview(self.default)
        except:
            pass
        self.cbx_dir.set(self.default)
        self.cbx.append_history(self.default)
        self._scrollHandler(self.cbx.entry, "moveto", 1)
        c.deselect()

        # Must we change the returned default directory?
        #
        self.default = None


    def apply(self):
        """
        What to do when user clicks on 'YES'.
        """
        self.result = self.cbx_dir.get()


def dirselect (parent, **options):
    """
    Ask for a directory, and return its name
    """
    return DirSelect(parent, **options).result


#-------------------------------------------------------------------------------
# Texts for this module
#-------------------------------------------------------------------------------


class DialogText:
    """
    Storage of all texts and messages for this module.
    """
    def __init__(self):
        
        # 1) Texts
        #
        if Toolbox.GuiParam.lang == 'fr':
            self.ABOUT            = "À propos"
            self.CANCEL           = "Annuler"
            self.CLOSE            = "Fermer"
            self.DIRECTORY        = "Répertoire :"
            self.ERROR            = "Erreur"
            self.HIDDEN_FOLDERS   = "Afficher les répertoires cachés"
            self.QUESTION         = "Question"
            self.NO               = "Non"
            self.VALIDATE         = "Valider"
            self.WARNING          = "Attention"
            self.YES              = "Oui"
        else:
            self.ABOUT            = "About"
            self.CANCEL           = "Cancel"
            self.CLOSE            = "Close"
            self.DIRECTORY        = "Directory:"
            self.ERROR            = "Error"
            self.HIDDEN_FOLDERS   = "Show hidden directories"
            self.QUESTION         = "Question"
            self.NO               = "No"
            self.VALIDATE         = "Validate"
            self.WARNING          = "Warning"
            self.YES              = "Yes"

        # 2) Messages
        #
        if Toolbox.GuiParam.lang == 'fr':
            self.MSG_ABOUT     = "Interface Code_Saturne\n"                    +\
                                 "version " + VERSION + "\n\n"                 +\
                                 "Pour toutes informations à propos de cette " +\
                                 "application merci de contacter :\n\n"        +\
                                 "Alexandre Douce\n"                           +\
                                 "(0130877308 - Alexandre.Douce@edf.fr)\n\n"   +\
                                 "Nicole Picard\n"                             +\
                                 "(0130877824 - Nicole-N.Picard@edf.fr)\n\n"   +\
                                 "Jean-Luc Rousset\n"                          +\
                                 "(0130877943 - Jean-Luc.Rousset@edf.fr)"
        else:
            self.MSG_ABOUT     = "Code_Saturne Interface\n"                    +\
                                 "version " + VERSION + "\n\n"                 +\
                                 "For information about this application "     +\
                                 "please contact :\n\n"                        +\
                                 "Alexandre Douce\n"                           +\
                                 "(0130877308 - Alexandre.Douce@edf.fr)\n\n"   +\
                                 "Nicole Picard\n"                             +\
                                 "(0130877824 - Nicole-N.Picard@edf.fr)\n\n"   +\
                                 "Jean-Luc Rousset\n"                          +\
                                 "(0130877943 - Jean-Luc.Rousset@edf.fr)"


#-------------------------------------------------------------------------------
# End of Dialog
#-------------------------------------------------------------------------------


syntax highlighted by Code2HTML, v. 0.9.1