Salome HOME
pour elts de structure
[tools/eficas.git] / Editeur / widgets.py
index 0c02a3c880201ac91242a0d2c8f46bdc7c8c083a..0b39e7215e21f9d184c6c6ccb10f93fd95349638 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 #            CONFIGURATION MANAGEMENT OF EDF VERSION
 # ======================================================================
 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
@@ -22,6 +23,7 @@
 #          EFICAS
 # ----------------------------------------------------------
 
+import Tkinter
 from Tkinter import *
 import Pmw
 import os,sys,re,string
@@ -35,6 +37,19 @@ from utils import save_in_file
 from centerwindow import centerwindow
 
 from Noyau.N_utils import repr_float
+from Accas import AsException
+
+# Surcharge de la fonction askyesno qui retourne un resultat errone en Python 2.3 avec Tk 8.4
+# et Tkinter.wantobject==1
+import tkMessageBox
+def askyesno(title=None, message=None, **options):
+    "Ask a question; return true if the answer is yes"
+    s = tkMessageBox._show(title, message, tkMessageBox.QUESTION, tkMessageBox.YESNO, **options)
+    if s == tkMessageBox.YES:return 1
+    if s == tkMessageBox.NO:return 0
+    if s:return 1
+    return 0
+
     
 class Fenetre :
     """ Cette classe permet de créer une fenêtre Toplevel dans laquelle
@@ -42,6 +57,7 @@ class Fenetre :
     def __init__(self,appli,titre="",texte=""):
         self.appli=appli
         self.fenetre = Toplevel()
+        self.fenetre.withdraw()
         self.fenetre.configure(width = 800,height=500)
         self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
         self.fenetre.title("Visualisation du "+titre)
@@ -73,6 +89,7 @@ class Fenetre :
         # affichage du texte
         self.affiche_texte(self.texte)
         centerwindow(self.fenetre)
+        self.fenetre.deiconify()
 
     def page_up(self,event):
         event.widget.yview_scroll(-1, "page")
@@ -85,6 +102,7 @@ class Fenetre :
 
     def wait(self):
         self.fenetre.grab_set()
+        self.zone_texte.focus_set()
         self.fenetre.wait_window(self.fenetre)
 
     def quit(self):
@@ -110,204 +128,352 @@ class Fenetre :
         """ Permet de sauvegarder le texte dans un fichier dont on a demandé le nom
         à l'utilisateur """
         file = asksaveasfilename(defaultextension = '.comm',
-                               initialdir = self.appli.CONFIGURATION.rep_user,
+                               #initialdir = self.appli.CONFIGURATION.rep_user,
+                               initialdir = self.appli.CONFIGURATION.initialdir,
                                title="Sauvegarde du "+self.titre)
-        if file != '':
-            if not save_in_file(file,self.texte) :
+        if file :
+            if not save_in_file(file,self.texte,None) :
                 showerror("Sauvegarde impossible",
                        "Impossible de sauvegarder le texte dans le fichier spécifié\n"+
                           "Vérifiez les droits d'écriture")
             else:
                 showinfo("Sauvegarde effectuée","Sauvegarde effectuée dans le fichier %s" %file)
 
+    def destroy(self):
+        try :
+          self.fenetre.destroy()
+       except :
+          pass
+
+class FenetreYesNo(Fenetre):
+    def __init__(self,appli,titre="",texte="",yes="Yes",no="No"):
+        self.appli=appli
+        self.fenetre = Toplevel()
+        self.fenetre.configure(width = 800,height=500)
+        self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
+        self.fenetre.title(titre)
+        self.texte = string.replace(texte,'\r\n','\n')
+        self.titre = titre
+        fonte=fontes.standardcourier10
+        # définition des frames
+        self.frame_texte = Frame(self.fenetre)
+        self.frame_boutons = Frame(self.fenetre)
+        self.frame_boutons.place(relx=0,rely=0,    relwidth=1.,relheight=0.1)
+        self.frame_texte.place(  relx=0,rely=0.1,  relwidth=1, relheight=0.9)
+        # définition de la zone texte et du scrollbar
+        self.zone_texte = Text(self.frame_texte,font=fonte)
+        self.zone_texte.bind("<Key-Prior>", self.page_up)
+        self.zone_texte.bind("<Key-Next>", self.page_down)
+        self.zone_texte.bind("<Key-Up>", self.unit_up)
+        self.zone_texte.bind("<Key-Down>", self.unit_down)
+        self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
+        #self.scroll_h = Scrollbar (self.frame_texte,command = self.zone_texte.xview)
+        self.scroll_v.pack(side='right',fill ='y')
+        #self.scroll_h.pack(side='bottom',fill ='x')
+        self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
+        self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
+        # définition des boutons
+        self.but_yes = Button(self.frame_boutons,text = yes,command=self.yes)
+        self.but_no = Button(self.frame_boutons,text = no,command = self.no)
+        self.but_yes.place(relx=0.4,rely=0.5,anchor='center')
+        self.but_no.place(relx=0.6,rely=0.5,anchor='center')
+        # affichage du texte
+        self.affiche_texte(self.texte)
+        centerwindow(self.fenetre)
+
+    def yes(self):
+        self.result=1
+        self.quit()
+
+    def no(self):
+        self.result=0
+        self.quit()
+
 class FenetreDeSelection(Fenetre):
-    """ Classe dérivée de Fenêtre permettant la récupération d'une zone de texte sélectionnée.\r
-        Cette classe est utilisée pour affecter une liste de valeurs à un mot-clé.\r
-    """\r
-    def __init__(self,panel,item,appli,titre="",texte=""):\r
-        Fenetre.__init__(self,appli,titre=titre,texte=texte)\r
-        self.fenetre.configure(width = 320,height=400)\r
+    """ Classe dérivée de Fenêtre permettant la récupération d'une zone de texte sélectionnée.
+        Cette classe est utilisée pour affecter une liste de valeurs à un mot-clé.
+    """
+    def __init__(self,panel,item,appli,titre="",texte="",cardinal=1):
+        Fenetre.__init__(self,appli,titre=titre,texte=texte)
+       self.frame_boutons.place_forget()
+        self.frame_texte.place_forget()
+        self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.8)
+        self.frame_boutons.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
+
+        self.cardinal=cardinal
+        self.fenetre.configure(width = 320,height=400)
         centerwindow(self.fenetre)
         self.panel = panel
         self.item = item
         self.fenetre.title(titre)
-        self.but_save.configure(text="Ajouter",command=self.traite_selection)\r
-        # séparateur par défaut\r
-        self.separateur = ";"\r
-        # création de la zone de saisie du séparateur\r
-        l_separateurs_autorises = self.get_separateurs_autorises()\r
-        self.choix_sep = Pmw.ComboBox(self.frame_boutons,\r
-                                      label_text = "Séparateur :",\r
-                                      labelpos = 'w',\r
-                                      listheight = 100,\r
-                                      selectioncommand = self.choose_separateur,\r
-                                      scrolledlist_items = l_separateurs_autorises)\r
-        self.choix_sep.component('entry').configure(width=6)\r
-        self.choix_sep.place(relx=0.01,rely=0.5,anchor='w')\r
-        self.choix_sep.selectitem(self.separateur)\r
-        # Replacement\r
-        self.but_quit.place_forget()\r
-        self.but_save.place_forget()\r
-        self.but_save.place(relx=0.6,rely=0.5,anchor='center')\r
-        self.but_quit.place(relx=0.8,rely=0.5,anchor='center')\r
-\r
-    def get_separateurs_autorises(self):\r
-        """\r
-        Retourne la liste des séparateurs autorisés\r
-        """\r
-        return ['espace',';',',']\r
-\r
-    def choose_separateur(self,nom_sep):\r
-        """\r
-        Affecte à self.separateur le caractère séparateur correspondant à nom_sep\r
-        """\r
-        if nom_sep == 'espace' :\r
-            self.separateur = ' '\r
-        else:\r
-            self.separateur = nom_sep\r
-        \r
-    def traite_selection(self):\r
-        """ Cette méthode effectue tous les traitements nécessaires pour vérifier\r
-            et affecter la liste de valeurs à l'objet réprésenté par self.item\r
-        """\r
-        # Récupère la liste des chaines de caractères de la zone sélectionnée\r
-        message,liste = self.recupere_liste()\r
-        if self.test_probleme(message,"Sélectionnez des données") == 0:\r
-            return\r
-        # Vérifie que le nombre de données est dans les limites attendues\r
-        message = self.verif_liste(liste)\r
-        if self.test_probleme(message,"Vérifiez le nombre de données") == 0:\r
-            return\r
-        # Crée une liste de valeurs du type attendu\r
-        message,liste_valeurs = self.creation_liste_valeurs(liste)\r
-        if self.test_probleme(message,"Vérifiez le type des données") == 0:\r
-            return\r
-        # Vérifie que chaque valeur est dans le domaine exigé\r
-        message = self.verif_valeurs(liste_valeurs)\r
-        if self.test_probleme(message,"Vérifiez le domaine des valeurs") == 0:\r
-            return\r
-        # Ajoute les valeurs dans la liste de valeurs du mot-clé\r
-        self.ajouter_valeurs(liste_valeurs)\r
-        self.appli.affiche_infos("Liste de valeurs acceptée")\r
-\r
-    def test_probleme(self, message, message_eficas):\r
-        """ Cette méthode affiche un message d'erreur si message != ''\r
-            et retourne 0, sinon retourne 1 sans rien afficher.\r
-        """\r
-        if message != "":\r
-            showinfo("Problème",message)\r
-            self.fenetre.tkraise()\r
-            self.appli.affiche_infos(message_eficas)\r
-            return 0\r
-        else:\r
-            return 1\r
-\r
-    def recupere_liste(self):\r
-        """ Cette méthode récupère le texte de la zone sélectionnée, construit et\r
-            retourne une liste avec les chaines qui se trouvent entre les séparateurs.\r
-            S'il n'y a pas de données selectionnées, elle retourne un message d'erreur\r
-            et une liste vide.\r
-        """\r
-        message = ""\r
-        try:\r
-            selection=self.fenetre.selection_get()\r
-        except:\r
-            message = "Pas de donnée sélectionnée"\r
-            return message,None\r
-        # les retours chariots doivent être interprétés comme des séparateurs\r
-        selection = string.replace(selection,'\n',self.separateur)\r
-        # on splitte la sélection suivant le caractère séparateur\r
-        liste_chaines = string.split(selection,self.separateur)\r
-        l_chaines = []\r
-        for chaine in liste_chaines:\r
-            chaine = string.strip(chaine)\r
-            if chaine != '' : l_chaines.append(chaine)\r
-        return message,l_chaines\r
-\r
-    def verif_liste(self, liste):\r
-        """ Cette méthode effectue des tests sur le nombre d'éléments de la liste\r
-            et retourne 1 si la liste est correcte, sinon 0 et le message d'erreur\r
-            correspondant.\r
-        """\r
-        message = ""\r
-        # nombre d'éléments sélectionnés\r
-        nombre_elements = len(liste)\r
-        # nombre d'éléments déja dans la liste du panel\r
-        nombre_in_liste = len(self.panel.Liste_valeurs.get_liste())\r
-        multiplicite = self.item.GetMultiplicite()\r
-        if (nombre_elements % multiplicite) != 0:\r
-            message = "Vous devez sélectionner "+str(multiplicite)+" * n données"\r
-            return message\r
-        nombre_valeurs = nombre_elements / multiplicite\r
-        cardinalite = self.item.GetMinMax()\r
-        if nombre_valeurs < cardinalite[0]:\r
-            message = "Vous devez sélectionner au moins "+str(cardinalite[0])+" valeurs"\r
-            return message\r
-        if cardinalite[1] != "**" and nombre_valeurs > (long(cardinalite[1])-nombre_in_liste):\r
-            message = "La liste ne peut avoir plus de "+str(cardinalite[1])+" valeurs"\r
-            return message\r
-\r
-        return message\r
-\r
-    def creation_liste_valeurs(self, liste):\r
-        """ Cette méthode crée et retourne une liste de valeurs du type attendu\r
-            par le mot-clé. La liste de valeurs est créée à partir de la liste\r
-            de chaines de caractères transmise.\r
-        """\r
-        type_attendu = self.item.GetType()[0]\r
-        if type_attendu == 'R':\r
-            return self.convertir(liste, f_conversion= float)\r
-        elif type_attendu == 'I':\r
-            return self.convertir(liste, f_conversion= int)\r
-        elif type_attendu == 'TXM':\r
-            return self.convertir(liste)\r
-        else:\r
-            message = "Seuls les entiers, les réels et les chaines de caractères sont convertis"\r
-            return message,None\r
-\r
-    def convertir(self, liste, f_conversion=None):\r
-        """ Cette méthode essaie de convertir les éléments de la liste avec la\r
-            fonction f_conversion si elle existe, et retourne la liste des\r
-            éléments dans le type voulu en cas de succès, sinon retourne None.\r
-        """\r
-        liste_valeurs = []\r
-        message = ""\r
-        for chaine in liste:\r
-            if f_conversion:\r
-                try:\r
-                    liste_valeurs.append(f_conversion(chaine))\r
-                except:\r
-                    message = "Impossible de convertir "+chaine+" dans le type attendu"\r
-                    return message,None\r
-            else:\r
-                liste_valeurs.append(chaine)\r
-        return message,liste_valeurs\r
-\r
-    def verif_valeurs(self, liste_valeurs):\r
-        """ Cette méthode teste tous les éléments de la liste, et retourne 1 si chaque\r
-            élément est dans le domaine voulu.\r
-        """\r
-        message = ""\r
-        for valeur in liste_valeurs:\r
-            test = self.item.IsInIntervalle(valeur)\r
-            if test == 0:\r
-                intervalle = str(self.item.GetIntervalle()[0])+","+str(self.item.GetIntervalle()[1])\r
-                message = "La valeur "+str(valeur)+" n'est pas dans l'intervalle ["+intervalle+"]"\r
-                return message\r
-        return message\r
-\r
-    def ajouter_valeurs(self, liste_valeurs):\r
-        """ Cette méthode ajoute les nouvelles valeurs à la liste existante."""\r
-        liste = self.panel.Liste_valeurs.get_liste()\r
-        liste.extend(liste_valeurs)\r
+        self.but_save.configure(text="Ajouter",command=self.traite_selection)
+        # séparateur par défaut
+        self.separateur = ';'
+        # création de la zone de saisie du séparateur
+        l_separateurs_autorises = self.get_separateurs_autorises()
+        self.choix_sep = Pmw.ComboBox(self.frame_boutons,
+                                      label_text = "Séparateur :",
+                                      labelpos = 'w',
+                                      listheight = 100,
+                                      selectioncommand = self.choose_separateur,
+                                      scrolledlist_items = l_separateurs_autorises)
+        self.choix_sep.component('entry').configure(width=6)
+        self.choix_sep.place(relx=0.01,rely=0.5,anchor='w')
+        self.choix_sep.selectitem(self.separateur)
+        # Replacement
+        self.but_quit.place_forget()
+        self.but_save.place_forget()
+       self.but_all  = Button(self.frame_boutons,text = "Tout Sélectionner", command=self.tout)
+        self.but_save.place(relx=0.6,rely=0.6,anchor='center')
+        self.but_quit.place(relx=0.8,rely=0.6,anchor='center')
+        self.but_all.place(relx=0.7,rely=0.2,anchor='center')
+       self.choose_separateur('espace')
+     
+
+    def get_separateurs_autorises(self):
+        """
+        Retourne la liste des séparateurs autorisés
+        """
+        return ['espace',';',',']
+
+    def choose_separateur(self,nom_sep):
+        """
+        Affecte à self.separateur le caractère séparateur correspondant à nom_sep
+        """
+        if nom_sep == 'espace' :
+            self.separateur = ' '
+        else:
+            self.separateur = nom_sep
+        
+    def tout(self):
+        liste=[]
+       texte=self.texte.splitlines()
+       for l in texte :
+           for mot in string.split(l,self.separateur):
+              if mot != '' and mot != ' ' and mot != self.separateur :
+                 liste.append(mot)
+       self.traite_selection(liste)
+
+    def traite_selection(self,liste=None):
+        """ Cette méthode effectue tous les traitements nécessaires pour vérifier
+            et affecter la liste de valeurs à l'objet réprésenté par self.item
+        """
+        # Récupère la liste des chaines de caractères de la zone sélectionnée
+       message=""
+       if liste == None:
+           message,liste = self.recupere_liste()
+        if self.test_probleme(message,"Sélectionnez des données") == 0:
+            return
+        # Vérifie que le nombre de données est dans les limites attendues
+        message = self.verif_liste(liste)
+        if self.test_probleme(message,"Vérifiez le nombre de données") == 0:
+            return
+        # Crée une liste de valeurs du type attendu
+        message,liste_valeurs = self.creation_liste_valeurs(liste)
+        if self.test_probleme(message,"Vérifiez le type des données") == 0:
+            return
+        # Vérifie que chaque valeur est dans le domaine exigé
+        message = self.verif_valeurs(liste_valeurs)
+        if self.test_probleme(message,"Vérifiez le domaine des valeurs") == 0:
+            return
+        # Ajoute les valeurs dans la liste de valeurs du mot-clé
+        if self.cardinal != 1 :
+           nb=self.cardinal
+           l_valeurs=[]
+           # a ameliorer
+           if (len(liste_valeurs)%nb != 0):
+                message="La cardinalité n'est pas correcte"
+                self.test_probleme(message,"On attend des tuples")
+                return
+           for i in range(len(liste_valeurs)/nb) :
+               if (nb==2):
+                   t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1])
+               elif (nb ==3):
+                   t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1], liste_valeurs[i*nb+2])
+               else :
+                  print "probleme : prevenir la maintenance Eficas"
+                  return
+               l_valeurs.append(t)
+           liste_valeurs=l_valeurs
+        self.ajouter_valeurs(liste_valeurs)
+        self.appli.affiche_infos("Liste de valeurs acceptée")
+
+    def test_probleme(self, message, message_eficas):
+        """ Cette méthode affiche un message d'erreur si message != ''
+            et retourne 0, sinon retourne 1 sans rien afficher.
+        """
+        if message != "":
+            showinfo("Problème",message)
+            self.fenetre.tkraise()
+            self.appli.affiche_infos(message_eficas)
+            return 0
+        else:
+            return 1
+
+    def recupere_liste(self):
+        """ Cette méthode récupère le texte de la zone sélectionnée, construit et
+            retourne une liste avec les chaines qui se trouvent entre les séparateurs.
+            S'il n'y a pas de données selectionnées, elle retourne un message d'erreur
+            et une liste vide.
+        """
+        message = ""
+        try:
+            selection=self.fenetre.selection_get()
+        except:
+            message = "Pas de donnée sélectionnée"
+            return message,None
+        # les retours chariots doivent être interprétés comme des séparateurs
+        selection = string.replace(selection,'\n',self.separateur)
+        # on splitte la sélection suivant le caractère séparateur
+        liste_chaines = string.split(selection,self.separateur)
+        l_chaines = []
+        for chaine in liste_chaines:
+            chaine = string.strip(chaine)
+            if chaine != '' : l_chaines.append(chaine)
+        return message,l_chaines
+
+    def verif_liste(self, liste):
+        """ Cette méthode effectue des tests sur le nombre d'éléments de la liste
+            et retourne 1 si la liste est correcte, sinon 0 et le message d'erreur
+            correspondant.
+        """
+        message = ""
+        # nombre d'éléments sélectionnés
+        nombre_elements = len(liste)
+        # nombre d'éléments déja dans la liste du panel
+        nombre_in_liste = len(self.panel.Liste_valeurs.get_liste())
+        multiplicite = self.item.GetMultiplicite()
+        if (nombre_elements % multiplicite) != 0:
+            message = "Vous devez sélectionner "+str(multiplicite)+" * n données"
+            return message
+        nombre_valeurs = nombre_elements / multiplicite
+        cardinalite = self.item.GetMinMax()
+        if nombre_valeurs < cardinalite[0]:
+            message = "Vous devez sélectionner au moins "+str(cardinalite[0])+" valeurs"
+            return message
+        if cardinalite[1] != "**" and nombre_valeurs > (long(cardinalite[1])-nombre_in_liste):
+            message = "La liste ne peut avoir plus de "+str(cardinalite[1])+" valeurs"
+            return message
+
+        return message
+
+    def creation_liste_valeurs(self, liste):
+        """ Cette méthode crée et retourne une liste de valeurs du type attendu
+            par le mot-clé. La liste de valeurs est créée à partir de la liste
+            de chaines de caractères transmise.
+        """
+        type_attendu = self.item.GetType()[0]
+        if type_attendu == 'R':
+            return self.convertir(liste, f_conversion= float)
+        elif type_attendu == 'I':
+            return self.convertir(liste, f_conversion= int)
+        elif type_attendu == 'TXM':
+            return self.convertir(liste)
+        else:
+            message = "Seuls les entiers, les réels et les chaines de caractères sont convertis"
+            return message,None
+
+    def convertir(self, liste, f_conversion=None):
+        """ Cette méthode essaie de convertir les éléments de la liste avec la
+            fonction f_conversion si elle existe, et retourne la liste des
+            éléments dans le type voulu en cas de succès, sinon retourne None.
+        """
+        liste_valeurs = []
+       message = ""
+        for chaine in liste:
+            if f_conversion:
+                try:
+                    liste_valeurs.append(f_conversion(chaine))
+                except:
+                    message = "Impossible de convertir "+chaine+" dans le type attendu"
+                    return message,None
+            else:
+                liste_valeurs.append(chaine)
+        return message,liste_valeurs
+
+    def verif_valeurs(self, liste_valeurs):
+        """ Cette méthode teste tous les éléments de la liste, et retourne 1 si chaque
+            élément est dans le domaine voulu.
+        """
+        message = ""
+        for valeur in liste_valeurs:
+            test = self.item.IsInIntervalle(valeur)
+            if test == 0:
+                intervalle = str(self.item.GetIntervalle()[0])+","+str(self.item.GetIntervalle()[1])
+                message = "La valeur "+str(valeur)+" n'est pas dans l'intervalle ["+intervalle+"]"
+                return message
+        return message
+
+    def ajouter_valeurs(self, liste_valeurs):
+        """ Cette méthode ajoute les nouvelles valeurs à la liste existante."""
+        liste = self.panel.Liste_valeurs.get_liste()
+        liste.extend(liste_valeurs)
         self.panel.Liste_valeurs.put_liste(liste)
 
+class FenetreDeParametre(Fenetre) :
+    def __init__(self,parent,item,appli,texte):
+        self.parent=parent
+        self.appli=appli
+        self.fenetre = Toplevel()
+        self.fenetre.configure(width = 250,height=100)
+        self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
+        self.fenetre.title("Parametres")
+        self.titre = "Parametres"
+        self.texte = string.replace(texte,'\r\n','\n')
+        fonte=fontes.standardcourier10
+
+        # définition des frames
+        self.frame_texte = Frame(self.fenetre)
+        self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.7)
+        # définition de la zone texte et du scrollbar
+        self.zone_texte = Text(self.frame_texte,font=fonte)
+        self.zone_texte.bind("<Key-Prior>", self.page_up)
+        self.zone_texte.bind("<Key-Next>", self.page_down)
+        self.zone_texte.bind("<Key-Up>", self.unit_up)
+        self.zone_texte.bind("<Key-Down>", self.unit_down)
+        self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
+        self.scroll_v.pack(side='right',fill ='y')
+        self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
+        self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
+        # affichage du texte
+        self.affiche_texte(self.texte)
+        self.zone_texte.config(state="disabled")
+
+       # définition des boutons
+       self.frame_boutons = Frame(self.fenetre)
+       self.frame_boutons.place(relheight=0.3,relx=0,rely=0.65,relwidth=1.)
+       self.label1 = Label(self.frame_boutons,text="surligner la")
+       self.label2 = Label(self.frame_boutons,text="ligne entière")
+       self.label1.place(relx=0.1,rely=0)
+       self.label2.place(relx=0.1,rely=0.5)
+       self.but_quit = Button(self.frame_boutons,text = "Fermer",command=self.quit)
+       self.but_save = Button(self.frame_boutons,text = "Choisir",command = self.Choisir)
+       self.but_save.place(relx=0.6,rely=0,relheight=1)
+       self.but_quit.place(relx=0.8,rely=0,relheight=1)
+
+
+    def Choisir(self):
+        try:
+            selection=self.zone_texte.selection_get()
+        except:
+            showerror("Pas de donnée sélectionnée",
+                       "Selectionner un parametre")
+        l_param = ""
+        for param in selection.splitlines():
+           nomparam=param[0:param.find("=")-1]
+            if nomparam != '' : 
+               l_param=l_param+nomparam+','
+       self.parent.entry.delete(0,Tkinter.END)
+       self.parent.entry.insert(0,l_param[0:-1])
+       self.parent.valid_valeur()
+       self.quit()
+
 class Formulaire:
-    """\r
+    """
     Cette classe permet de créer une boîte Dialog dans laquelle
-    on affiche un formulaire à remplir par l'utilisateur\r
+    on affiche un formulaire à remplir par l'utilisateur
     """
-    def __init__(self,fen_pere,obj_pere=None,titre="",texte="",items=(),mode='query',commande=None):\r
+    def __init__(self,fen_pere,obj_pere=None,titre="",texte="",items=(),mode='query',commande=None):
         if items in ((),[]) : return
         self.items = items
         self.titre = titre
@@ -318,25 +484,25 @@ class Formulaire:
         self.command = commande
         self.display()
 
-    def display(self):\r
+    def display(self):
         self.init_validateurs()
         self.init_fenetre()
         self.init_texte()
         self.init_items_formulaire()
         self.fenetre.activate(geometry='centerscreenalways')
-\r
-    def init_validateurs(self):\r
-        """\r
-        Crée le dictionnaire des validateurs des objets reconnus par le formulaire\r
-        """\r
-        self.d_validateurs = {}\r
-        self.d_validateurs['rep']  = self.repvalidator\r
-        self.d_validateurs['file'] = self.filevalidator\r
-        self.d_validateurs['cata']= self.catavalidator\r
+
+    def init_validateurs(self):
+        """
+        Crée le dictionnaire des validateurs des objets reconnus par le formulaire
+        """
+        self.d_validateurs = {}
+        self.d_validateurs['rep']  = self.repvalidator
+        self.d_validateurs['file'] = self.filevalidator
+        self.d_validateurs['cata']= self.catavalidator
         
-    def init_fenetre(self):\r
-        """\r
-        Crée la fenêtre Dialog\r
+    def init_fenetre(self):
+        """
+        Crée la fenêtre Dialog
         """
         if self.mode == 'query':
             buttons=('Valider','Annuler')
@@ -352,118 +518,118 @@ class Formulaire:
                                   buttons=buttons,
                                   defaultbutton = defaultbutton,
                                   title = self.titre,
-                                  command = self.execute)\r
+                                  command = self.execute)
         self.fenetre.withdraw()
         
-    def init_texte(self):\r
-        """\r
-        Crée le label qui affiche le texte à l'intérieur du panneau\r
+    def init_texte(self):
+        """
+        Crée le label qui affiche le texte à l'intérieur du panneau
         """
-        fonte=fontes.standard\r
-        fr_texte = Frame(self.fenetre.interior(),height=60)\r
+        fonte=fontes.standard
+        fr_texte = Frame(self.fenetre.interior(),height=60)
         fr_texte.pack(side='top',fill='x',expand=1)
         Label(fr_texte,text = self.texte, font=fonte).place(relx=0.5,rely=0.5,anchor='center')
-\r
-    def init_items_formulaire(self):\r
-        """\r
-        Crée et affiche les items dans la boîte de dialogue\r
-        """\r
-        self.radiobut = 0\r
-        self.widgets = []\r
-        self.item_widgets = {}\r
-        length_maxi = 0\r
+
+    def init_items_formulaire(self):
+        """
+        Crée et affiche les items dans la boîte de dialogue
+        """
+        self.radiobut = 0
+        self.widgets = []
+        self.item_widgets = {}
+        length_maxi = 0
         for item in self.items:
-            if len(item[0])>length_maxi : length_maxi = len(item[0])\r
-        window = self.fenetre.interior()\r
-        for item in self.items :\r
-            label,nature,nom_var,defaut = item\r
-            # création de la frame\r
-            fr_item = Frame(window,height=40,width=700)\r
-            fr_item.pack(side='top',fill='x',expand=1)\r
-            # création du label\r
-            Label(fr_item,text = label).place(relx=0.05,rely=0.4)\r
+            if len(item[0])>length_maxi : length_maxi = len(item[0])
+        window = self.fenetre.interior()
+        for item in self.items :
+            label,nature,nom_var,defaut = item
+            # création de la frame
+            fr_item = Frame(window,height=40,width=700)
+            fr_item.pack(side='top',fill='x',expand=1)
+            # création du label
+            Label(fr_item,text = label).place(relx=0.05,rely=0.4)
             if nature in ('rep','file','cata'):
-                # création de l'entry\r
-                e_item = Entry(fr_item) \r
-                e_item.place(relx=0.5,rely=0.4,relwidth=0.45)\r
-                self.widgets.append(e_item)\r
-                self.item_widgets[item] = e_item\r
-                if defaut : e_item.insert(0,str(defaut))\r
-            elif nature == 'YesNo':\r
-                # création de la StringVar\r
-                var = StringVar()\r
-                setattr(self,'item_'+nom_var,var)\r
-                var.set(defaut)\r
-                # création du radiobouton\r
-                rb1 = Radiobutton(fr_item,text='OUI',variable=var,value='OUI')\r
-                rb2 = Radiobutton(fr_item,text='NON',variable=var,value='NON')\r
-                rb1.place(relx=0.65,rely=0.5,anchor='center')\r
-                rb2.place(relx=0.80,rely=0.5,anchor='center')\r
-                self.widgets.append((rb1,rb2))\r
-                self.item_widgets[item] = var\r
-        # détermination de la méthode à appliquer sur les boutons\r
-        if self.mode == 'query':\r
-            function = self.active\r
-        elif self.mode == 'display':\r
-            function = self.inactive\r
-        else:\r
-            return\r
-        # on applique la méthode sur les boutons (activation ou désactivation)    \r
-        for widget in self.widgets :\r
-            if type(widget) == types.TupleType:\r
-                for widg in widget :\r
-                    apply(function,(widg,),{})\r
-            else:\r
-                apply(function,(widget,),{})\r
-\r
-    def active(self,widget):\r
-        """\r
-        Active le widget passé en argument\r
-        """\r
-        widget.configure(state='normal',bg='white')\r
-\r
-    def inactive(self,widget):\r
-        """\r
-        Inactive le widget passé en argument\r
-        """\r
-        if not isinstance(widget,Radiobutton) :\r
-            widget.configure(state='disabled',bg='gray95')\r
-        else :\r
-            widget.configure(state='disabled')\r
-\r
-# --------------------------------------------------------------------------------\r
-#       Validateurs des noms de répertoire, de fichiers et de catalogues\r
-# --------------------------------------------------------------------------------\r
+                # création de l'entry
+                e_item = Entry(fr_item) 
+                e_item.place(relx=0.5,rely=0.4,relwidth=0.45)
+                self.widgets.append(e_item)
+                self.item_widgets[item] = e_item
+                if defaut : e_item.insert(0,str(defaut))
+            elif nature == 'YesNo':
+                # création de la StringVar
+                var = StringVar()
+                setattr(self,'item_'+nom_var,var)
+                var.set(defaut)
+                # création du radiobouton
+                rb1 = Radiobutton(fr_item,text='OUI',variable=var,value='OUI')
+                rb2 = Radiobutton(fr_item,text='NON',variable=var,value='NON')
+                rb1.place(relx=0.65,rely=0.5,anchor='center')
+                rb2.place(relx=0.80,rely=0.5,anchor='center')
+                self.widgets.append((rb1,rb2))
+                self.item_widgets[item] = var
+        # détermination de la méthode à appliquer sur les boutons
+        if self.mode == 'query':
+            function = self.active
+        elif self.mode == 'display':
+            function = self.inactive
+        else:
+            return
+        # on applique la méthode sur les boutons (activation ou désactivation)  
+        for widget in self.widgets :
+            if type(widget) == types.TupleType:
+                for widg in widget :
+                    apply(function,(widg,),{})
+            else:
+                apply(function,(widget,),{})
+
+    def active(self,widget):
+        """
+        Active le widget passé en argument
+        """
+        widget.configure(state='normal',bg='white')
+
+    def inactive(self,widget):
+        """
+        Inactive le widget passé en argument
+        """
+        if not isinstance(widget,Radiobutton) :
+            widget.configure(state='disabled',bg='gray95')
+        else :
+            widget.configure(state='disabled')
+
+# --------------------------------------------------------------------------------
+#       Validateurs des noms de répertoire, de fichiers et de catalogues
+# -------------------------------------------------------------------------------
 
     def repvalidator(self,text):
-        """\r
-        Teste si text peut faire référence à un répertoire ou non\r
-        Retourne 1 si valide, 0 sinon\r
-        """\r
+        """
+        Teste si text peut faire référence à un répertoire ou non
+        Retourne 1 si valide, 0 sinon
+        """
         return os.path.isdir(text),'Répertoire introuvable : %s' %text
 
     def filevalidator(self,text):
-        """\r
-        Teste si text peut faire référence à un fichier ou non\r
-        Retourne 1 si valide, 0 sinon\r
-        """\r
+        """
+        Teste si text peut faire référence à un fichier ou non
+        Retourne 1 si valide, 0 sinon
+        """
         return os.path.isfile(text),'Fichier introuvable : %s' %text
-\r
-    def catavalidator(self,text):\r
-        """\r
-        Teste si  text est un chemin d'accès valide à un catalogue\r
-        Retourne 1 si valide, 0 sinon\r
-        """\r
-        return os.path.isfile(text),"Catalogue introuvable : %s" %text\r
-\r
-# --------------------------------------------------------------------------------\r
-#       Méthodes callbacks des boutons et de fin\r
-# --------------------------------------------------------------------------------\r
+
+    def catavalidator(self,text):
+        """
+        Teste si  text est un chemin d'accès valide à un catalogue
+        Retourne 1 si valide, 0 sinon
+        """
+        return os.path.isfile(text),"Catalogue introuvable : %s" %text
+
+# --------------------------------------------------------------------------------
+#       Méthodes callbacks des boutons et de fin
+# --------------------------------------------------------------------------------
         
-    def execute(self,txt):\r
-        """\r
-        Cette commande est activée à chaque clic sur un bouton.\r
-        Redirige l'action sur la bonne méthode en fonction du bouton activé\r
+    def execute(self,txt):
+        """
+        Cette commande est activée à chaque clic sur un bouton.
+        Redirige l'action sur la bonne méthode en fonction du bouton activé
         """
         if txt == 'Valider':
             self.fini()
@@ -476,26 +642,26 @@ class Formulaire:
             print "Nom de bouton inconnu"
             self.quit()
 
-    def fini(self):\r
-        """\r
-        Commande qui termine le panneau et sauvegarde les nouvelles options\r
-        dans l'objet resultat (dictionnaire)\r
+    def fini(self):
+        """
+        Commande qui termine le panneau et sauvegarde les nouvelles options
+        dans l'objet resultat (dictionnaire)
         """
         dico={}
-        for item,widget in self.item_widgets.items():\r
-            nom_var = item[2]\r
+        for item,widget in self.item_widgets.items():
+            nom_var = item[2]
             type_var = item[1]
-            valeur = widget.get()\r
-            if self.d_validateurs.has_key(type_var):\r
-                test = self.d_validateurs[type_var](valeur)\r
-                if not test :\r
-                    # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode\r
-                    # sans tuer la fenêtre bien sûr\r
-                    widget.selection_range(0,END)\r
+            valeur = widget.get()
+            if self.d_validateurs.has_key(type_var):
+                test = self.d_validateurs[type_var](valeur)
+                if not test :
+                    # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode
+                    # sans tuer la fenêtre bien sûr
+                    widget.selection_range(0,END)
                     return
             dico[nom_var] = valeur
         self.fenetre.destroy()    
-        self.resultat=dico\r
+        self.resultat=dico
         
     def quit(self):
         self.fenetre.destroy()
@@ -504,7 +670,7 @@ class Formulaire:
 class ListeChoix :
     """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre
         en passant les commandes à lancer suivant différents bindings """
-    def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre=''):
+    def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre='',optionReturn=None):
         self.parent = parent
         self.page = page
         self.liste = liste
@@ -516,6 +682,7 @@ class ListeChoix :
         self.active = active
         self.titre = titre
         self.filtre = filtre
+        self.optionReturn = optionReturn
         self.init()
 
     def init(self):        
@@ -552,9 +719,10 @@ class ListeChoix :
         self.MCbox.pack(fill='y',expand=1,padx=2,pady=2)
         self.MCbox.configure(yscrollcommand=self.MCscroll.set)
 
+
     def affiche_liste(self):
         """ Affiche la liste dans la fenêtre"""
-        i=0
+        liste_labels=[]
         self.MCbox.config(state=NORMAL)
         self.MCbox.delete(1.0,END)
         for objet in self.liste :
@@ -566,37 +734,129 @@ class ListeChoix :
           elif type(objet) in (types.StringType,types.IntType):
               mot = objet
           elif type(objet) == types.FloatType :
-              mot = repr_float(objet)
+              mot = self.parent.get_valeur_texte(objet)
+              if mot == "" :
+                 mot = str(objet)
+          elif type(objet) == types.TupleType :
+              mot="("
+              premier=1
+              for val in objet:
+                if (not premier):
+                  mot=mot+"," 
+                 else:
+                   premier=0
+                 valtexte = self.parent.get_valeur_texte(val)
+                 if valtexte != "" :
+                    mot=mot+valtexte
+                 else:
+                    mot=mot+str(val)
+              mot=mot+")"
           else:
               mot=`objet`
           label = Label(self.MCbox,
                         text = mot,
                         fg = 'black',bg = 'gray95',justify = 'left')
           self.dico_labels[mot]=label
+          liste_labels.append(label)
           self.MCbox.window_create(END,
                                    window=label,
                                    stretch = 1)
           self.MCbox.insert(END,'\n')
+          if self.optionReturn != None :
+              label.bind("<Return>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
+              label.bind("<KP_Enter>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
+          label.bind("<Key-Right>",lambda e,s=self,x=objet,l=label : s.selectNextItem(x,l))
+          label.bind("<Key-Left>" ,lambda e,s=self,x=objet,l=label  : s.selectPrevItem(x,l))
           if self.active == 'oui':
               label.bind(self.liste_commandes[0][0],lambda e,s=self,c=self.liste_commandes[0][1],x=objet,l=label : s.selectitem(x,l,c))
               label.bind(self.liste_commandes[1][0],lambda e,s=self,c=self.liste_commandes[1][1],x=objet,l=label : s.deselectitem(l,x,c))
               label.bind(self.liste_commandes[2][0],lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitem(x,l,c))
-          try :
-              self.liste_marques.index(i)
-              self.markitem(label)
-          except:
+
+        for marque in self.liste_marques:
+           try:
+              self.markitem(liste_labels[marque])
+           except:
               pass
-          i=i+1
+
         self.MCbox.config(state=DISABLED)
         self.selection = None
 
+    def clear_marque(self):
+        try:
+          self.dico_labels[self.arg_selected].configure(bg='gray95',fg='black')
+          self.arg_selected = ''
+       except :
+         pass
+
+    def surligne(self,marque):
+        try :
+          self.highlightitem(self.dico_labels[marque])
+           self.arg_selected = marque
+       except:
+          pass
+
+    def chooseitemsurligne(self,mot,label,commande):
+        """ Active la méthode de choix passée en argument"""
+        try:
+           mot=self.arg_selected
+           commande(mot)
+        except AsException,e:
+           raison=str(e)
+           showerror(raison.split('\n')[0],raison)
+
     def chooseitem(self,mot,label,commande):
         """ Active la méthode de choix passée en argument"""
-        commande(mot)
+        try:
+           commande(mot)
+        except AsException,e:
+           raison=str(e)
+           showerror(raison.split('\n')[0],raison)
+        
+    def selectNextItem(self,mot,label):
+        try :
+           index=self.liste.index(mot)
+           indexsuivant=index+1
+          if indexsuivant > len(self.liste) -1:
+             indexsuivant=0
+           motsuivant=self.liste[indexsuivant]
+           labelsuivant=self.dico_labels[motsuivant]
+           self.clear_marque()
+           if self.selection != None :
+              self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
+              self.selection = (mot,label,self.selection[2])
+           index = self.MCbox.index(labelsuivant)
+           self.MCbox.see(index)
+           self.highlightitem(labelsuivant)
+           self.arg_selected=motsuivant
+           labelsuivant.focus_set()
+        # PN il faut faire quelque chose pour être dans la fenetre
+        except:
+           pass
+           
+    def selectPrevItem(self,mot,label):
+        try :
+           index=self.liste.index(mot)
+           indexprec=index-1
+           motprec=self.liste[indexprec]
+           labelprec=self.dico_labels[motprec]
+           self.clear_marque()
+           if self.selection != None :
+              self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
+              self.selection = (mot,label,self.selection[2])
+           index = self.MCbox.index(labelprec)
+           self.MCbox.see(index)
+           self.highlightitem(labelprec)
+           self.arg_selected=motprec
+           labelprec.focus_set()
+        # PN il faut faire quelque chose pour être dans la fenetre
+        except:
+           pass
+           
         
     def selectitem(self,mot,label,commande) :
         """ Met l'item sélectionné (représenté par son label) en surbrillance
             et lance la commande associée au double-clic"""
+       self.clear_marque()
         if self.selection != None :
             self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
         self.highlightitem(label)
@@ -606,6 +866,7 @@ class ListeChoix :
 
     def highlightitem(self,label) :
         """ Met l'item représenté par son label en surbrillance """
+        label.focus_set()
         label.configure(bg='#00008b',fg='white')
         
     def markitem(self,label):
@@ -618,6 +879,17 @@ class ListeChoix :
         self.arg_selected = ''
         if commande != None : commande(mot)
 
+    def cherche_selected_item(self):
+        index=self.MCbox.index(self.selection[1])
+        lign,col=map(int,string.split(index,'.'))
+        return lign
+
+    def remove_selected_item(self):
+        index=self.MCbox.index(self.selection[1])
+        lign,col=map(int,string.split(index,'.'))
+        del self.liste[lign-1]
+        self.affiche_liste()
+
     def entry_changed(self,event=None):
         """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
         de l'entry et frappe <Return>"""
@@ -630,25 +902,36 @@ class ListeChoix :
                 index = self.MCbox.index(self.dico_labels[arg])
                 self.MCbox.see(index)
                 self.arg_selected = arg
+                self.dico_labels[self.arg_selected].focus_set()
                 break
 
-    def get_liste_old(self):
+        #try :
+          #self.dico_labels[self.arg_selected].focus_set()
+        #except :
+          #pass
+
+    def get_liste_BAK(self):
+        raise "OBSOLETE"
         return self.liste
 
+    # PN attention à la gestion des paramétres
+    # cela retourne H = 1 , et ni H, ni 1
+    #            print repr(val)
+    #            print val.__class__.__name__
     def get_liste(self):
         l=[]
         for val in self.liste:
-            try:
-                val = eval(val)
-                l.append(val)
-            except:
+#            try:
+#                v = eval(val)
+#              l.append(v)
+#            except:
                 l.append(val)
         return l
     
     def put_liste(self,liste):
         self.liste = liste
         self.affiche_liste()
-        
+
 class Affichage :
   """ Cette classe permet d'afficher au lancement d'EFICAS le message
       d'attente et la barre de progression"""
@@ -702,9 +985,9 @@ class Affichage :
       self.progress.update()
 
 class Ask_Format_Fichier :
-    """\r
+    """
     Cette classe permet de créer une fenêtre Toplevel dans laquelle
-    on propose le choix du format de fichier de commandes à ouvrir\r
+    on propose le choix du format de fichier de commandes à ouvrir
     """
     def __init__(self,appli):
         self.fenetre = Toplevel()
@@ -818,3 +1101,202 @@ class BARRE_K2000(Toplevel):
         
     def quit(self):
         self.quit = 1        
+
+class ListeChoixParGroupes(ListeChoix) :
+    """ 
+        Cette classe est utilisée pour afficher une liste de commandes classées par
+        groupes. L'utilisateur peut réaliser des actions de selection
+        qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
+        Exemple de binding:
+           liste_commandes = (("<Enter>",self.selectCmd),
+                              ("<Leave>",self.deselectCmd),
+                              ("<Double-Button-1>",self.defCmd))
+        Il s'agit d'une liste de doublets dont le premier element est un evenement et le 
+        deuxieme un callback a appeler sur l'evenement en question.
+
+    """
+    def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
+                      active ='oui',filtre='non',titre='',optionReturn=None):
+        self.parent = parent
+        self.page = page
+        self.liste_groupes = liste_groupes
+        self.dict_groupes = dict_groupes
+        self.dico_labels={}
+        self.selection = None
+        self.liste_commandes = liste_commandes
+        self.liste_marques = liste_marques
+        self.arg_selected=''
+        self.active = active
+        self.titre = titre
+        self.filtre = filtre
+        self.optionReturn = optionReturn
+        self.init()
+
+    def affiche_liste(self):
+        """ Affiche la liste dans la fenêtre"""
+        liste_labels=[]
+        self.MCbox.config(state=NORMAL)
+        self.MCbox.delete(1.0,END)
+        for grp in self.liste_groupes:
+           # On itère sur les groupes
+           if grp == "CACHE":continue
+           liste_commandes=self.dict_groupes[grp]
+           text="GROUPE<<<<<<<< "+grp+" "
+           text=text+">"*max(0,30-len(text))
+           label = Label(self.MCbox,
+                        text = text,
+                        fg = 'black',bg = 'gray95',justify = 'left')
+           # On stocke la relation entre le nom de la commande et le label
+           self.dico_labels[grp]=label
+           liste_labels.append(label)
+           self.MCbox.window_create(END,
+                                   window=label,
+                                   stretch = 1)
+           self.MCbox.insert(END,'\n')
+           for cmd in liste_commandes:
+              label = Label(self.MCbox,
+                        text = cmd,
+                        fg = 'black',bg = 'gray95',justify = 'left')
+              # On stocke la relation entre le nom de la commande et le label
+              self.dico_labels[cmd]=label
+              self.MCbox.window_create(END,
+                                   window=label,
+                                   stretch = 1)
+              self.MCbox.insert(END,'\n')
+
+              def null(*tp,**args): return
+
+              if self.active == 'oui':
+                  # Traitement par defaut des evenements
+                  label.bind("<Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.selectitem(x,l,c))
+                  label.bind("<Leave>",lambda e,s=self,c=null,x=cmd,l=label: s.deselectitem(l,x,c))
+                  label.bind("<Double-Button-1>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
+                  label.bind("<Return>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
+                  label.bind("<KP_Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
+                  label.bind("<Key-Right>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
+                  label.bind("<Key-Down>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
+                  label.bind("<Key-Left>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
+                  label.bind("<Key-Up>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
+
+                  # Si des callbacks sont definis on les utilise
+                  for event,callback in self.liste_commandes:
+                      if event == "<Enter>":
+                         label.bind("<Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.selectitem(x,l,c))
+                      elif event == "<Leave>":
+                         label.bind("<Leave>",lambda e,s=self,c=callback,x=cmd,l=label: s.deselectitem(l,x,c))
+                      elif event == "<Double-Button-1>":
+                         label.bind("<Double-Button-1>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
+                      elif event == "<Return>":
+                         label.bind("<Return>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
+                      elif event == "<KP_Enter>":
+                         label.bind("<KP_Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
+                      elif event == "<Key-Right>":
+                         label.bind("<Key-Right>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
+                      elif event == "<Key-Down>":
+                         label.bind("<Key-Down>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
+                      elif event == "<Key-Left>":
+                         label.bind("<Key-Left>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
+                      elif event == "<Key-Up>":
+                         label.bind("<Key-Up>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
+                      else:
+                         label.bind(event,lambda e,s=self,c=callback,x=cmd,l=label: c())
+
+        for marque in self.liste_marques:
+           try:
+              self.markitem(liste_labels[marque])
+           except:
+              pass
+
+        self.MCbox.config(state=DISABLED)
+        self.selection = None
+
+    def selectPrevItem(self,mot,label,callback,group,cmd):
+        g=self.liste_groupes.index(group)
+        liste_commandes=self.dict_groupes[group]
+        c=liste_commandes.index(cmd)
+        if c > 0:
+           co=liste_commandes[c-1]
+        else:
+           # debut de liste. On passe au groupe precedent
+           if g > 0:
+              gr=self.liste_groupes[g-1]
+              co=self.dict_groupes[gr][-1]
+           else:
+              # debut des groupes. On ne fait rien
+              return
+
+        # On a trouve l'item precedent
+        self.clear_marque()
+        labelsuivant=self.dico_labels[co]
+        if self.selection != None :
+           self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
+           self.selection = (co,labelsuivant,self.selection[2])
+        index = self.MCbox.index(labelsuivant)
+        self.MCbox.see(index)
+        self.arg_selected=co
+        self.highlightitem(labelsuivant)
+        labelsuivant.focus_set()
+        callback(co)
+
+    def selectNextItem(self,mot,label,callback,group,cmd):
+        g=self.liste_groupes.index(group)
+        liste_commandes=self.dict_groupes[group]
+        c=liste_commandes.index(cmd)
+        try:
+           co=liste_commandes[c+1]
+        except:
+           # fin de liste. On passe au groupe suivant
+           try:
+              gr=self.liste_groupes[g+1]
+              co=self.dict_groupes[gr][0]
+           except:
+              # fin des groupes. On ne fait rien
+              return
+        # On a trouve l'item suivant
+        self.clear_marque()
+        labelsuivant=self.dico_labels[co]
+        if self.selection != None :
+           self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
+           self.selection = (co,labelsuivant,self.selection[2])
+        index = self.MCbox.index(labelsuivant)
+        self.MCbox.see(index)
+        self.arg_selected=co
+        self.highlightitem(labelsuivant)
+        labelsuivant.focus_set()
+        callback(co)
+
+    def entry_changed(self,event=None):
+        """ 
+            Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
+            de l'entry et frappe <Return>
+        """
+        if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
+
+        filtre = self.entry.get()+"*"
+        FILTRE = string.upper(filtre)
+        #
+        # On cherche d'abord dans les noms de groupe
+        # puis dans les noms de commande groupe par groupe
+        #
+        for grp in self.liste_groupes:
+            if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
+                self.highlightitem(self.dico_labels[grp])
+                index = self.MCbox.index(self.dico_labels[grp])
+                self.MCbox.see(index)
+                # On ne selectionne pas le groupe
+                #self.arg_selected = grp
+                self.dico_labels[grp].focus_set()
+                # On a trouve un groupe on arrete la recherche
+                return
+
+        for grp in self.liste_groupes:
+           for cmd in self.dict_groupes[grp] :
+              if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
+                 self.highlightitem(self.dico_labels[cmd])
+                 index = self.MCbox.index(self.dico_labels[cmd])
+                 self.MCbox.see(index)
+                 self.arg_selected = cmd
+                 self.dico_labels[self.arg_selected].focus_set()
+                 # On a trouve une commande  on arrete la recherche
+                 return
+