]> SALOME platform Git repositories - tools/eficas.git/blob - Editeur/widgets.py
Salome HOME
PN : pour déplacement dans l arbre
[tools/eficas.git] / Editeur / widgets.py
1 # -*- coding: utf-8 -*-
2 #            CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
9 #
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
14 #
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
18 #
19 #
20 # ======================================================================
21 # ----------------------------------------------------------
22 #   Cette classe sert à définir les widgets utilisés par
23 #          EFICAS
24 # ----------------------------------------------------------
25
26 import Tkinter
27 from Tkinter import *
28 import Pmw
29 import os,sys,re,string
30 import types,fnmatch
31 import traceback
32 from tkFileDialog import *
33 from tkMessageBox import showinfo,askyesno,showerror,askretrycancel
34
35 import fontes
36 import prefs
37 from utils import save_in_file
38 from centerwindow import centerwindow
39
40 from Noyau.N_utils import repr_float
41 from Accas import AsException
42
43 # Surcharge de la fonction askyesno qui retourne un resultat errone en Python 2.3 avec Tk 8.4
44 # et Tkinter.wantobject==1
45 import tkMessageBox
46 def askyesno(title=None, message=None, **options):
47     "Ask a question; return true if the answer is yes"
48     s = tkMessageBox._show(title, message, tkMessageBox.QUESTION, tkMessageBox.YESNO, **options)
49     if s == tkMessageBox.YES:return 1
50     if s == tkMessageBox.NO:return 0
51     if s:return 1
52     return 0
53
54     
55 class Fenetre :
56     """ Cette classe permet de créer une fenêtre Toplevel dans laquelle
57         on peut afficher un texte et qui permet de le sauver"""
58     def __init__(self,appli,titre="",texte=""):
59         self.appli=appli
60         self.fenetre = Toplevel()
61         self.fenetre.withdraw()
62         self.fenetre.configure(width = 800,height=500)
63         self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
64         self.fenetre.title("Visualisation du "+titre)
65         self.texte = string.replace(texte,'\r\n','\n')
66         self.titre = titre
67         fonte=fontes.standardcourier10
68         # définition des frames
69         self.frame_texte = Frame(self.fenetre)
70         self.frame_boutons = Frame(self.fenetre)
71         self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.9)
72         self.frame_boutons.place(relheight=0.1,relx=0,rely=0.9,relwidth=1.)
73         # définition de la zone texte et du scrollbar
74         self.zone_texte = Text(self.frame_texte,font=fonte)
75         self.zone_texte.bind("<Key-Prior>", self.page_up)
76         self.zone_texte.bind("<Key-Next>", self.page_down)
77         self.zone_texte.bind("<Key-Up>", self.unit_up)
78         self.zone_texte.bind("<Key-Down>", self.unit_down)
79         self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
80         #self.scroll_h = Scrollbar (self.frame_texte,command = self.zone_texte.xview)
81         self.scroll_v.pack(side='right',fill ='y')
82         #self.scroll_h.pack(side='bottom',fill ='x')
83         self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
84         self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
85         # définition des boutons
86         self.but_quit = Button(self.frame_boutons,text = "Fermer",command=self.quit)
87         self.but_save = Button(self.frame_boutons,text = "sauver",command = self.save)
88         self.but_quit.place(relx=0.4,rely=0.5,anchor='center')
89         self.but_save.place(relx=0.6,rely=0.5,anchor='center')
90         # affichage du texte
91         self.affiche_texte(self.texte)
92         centerwindow(self.fenetre)
93         self.fenetre.deiconify()
94
95     def page_up(self,event):
96         event.widget.yview_scroll(-1, "page")
97     def page_down(self,event):
98         event.widget.yview_scroll(1, "page")
99     def unit_up(self,event):
100         event.widget.yview_scroll(-1, "unit")
101     def unit_down(self,event):
102         event.widget.yview_scroll(1, "unit")
103
104     def wait(self):
105         self.fenetre.grab_set()
106         self.zone_texte.focus_set()
107         self.fenetre.wait_window(self.fenetre)
108
109     def quit(self):
110         self.fenetre.destroy()
111
112     def efface_scroll(self):
113         """ Efface le scroll lorsqu'il n'est pas nécessaire : ne marche pas"""
114         self.scroll_v.pack_forget()
115         #self.scroll_h.pack_forget()
116
117     def affiche_texte(self,texte):
118         """ Affiche le texte dans la fenêtre """
119         if texte != "" :
120             self.zone_texte.insert(END,texte)
121             try:
122                 self.fenetre.update_idletasks()
123                 x0,y0,x1,y1 = self.zone_texte.bbox(END)
124                 if (y1-y0) < 300 : self.efface_scroll()
125             except:
126                 pass
127
128     def save(self):
129         """ Permet de sauvegarder le texte dans un fichier dont on a demandé le nom
130         à l'utilisateur """
131         file = asksaveasfilename(defaultextension = '.comm',
132                                #initialdir = self.appli.CONFIGURATION.rep_user,
133                                initialdir = self.appli.CONFIGURATION.initialdir,
134                                title="Sauvegarde du "+self.titre)
135         if file :
136             if not save_in_file(file,self.texte,None) :
137                 showerror("Sauvegarde impossible",
138                        "Impossible de sauvegarder le texte dans le fichier spécifié\n"+
139                           "Vérifiez les droits d'écriture")
140             else:
141                 showinfo("Sauvegarde effectuée","Sauvegarde effectuée dans le fichier %s" %file)
142
143     def destroy(self):
144         try :
145            self.fenetre.destroy()
146         except :
147            pass
148
149 class FenetreYesNo(Fenetre):
150     def __init__(self,appli,titre="",texte="",yes="Yes",no="No"):
151         self.appli=appli
152         self.fenetre = Toplevel()
153         self.fenetre.configure(width = 800,height=500)
154         self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
155         self.fenetre.title(titre)
156         self.texte = string.replace(texte,'\r\n','\n')
157         self.titre = titre
158         fonte=fontes.standardcourier10
159         # définition des frames
160         self.frame_texte = Frame(self.fenetre)
161         self.frame_boutons = Frame(self.fenetre)
162         self.frame_boutons.place(relx=0,rely=0,    relwidth=1.,relheight=0.1)
163         self.frame_texte.place(  relx=0,rely=0.1,  relwidth=1, relheight=0.9)
164         # définition de la zone texte et du scrollbar
165         self.zone_texte = Text(self.frame_texte,font=fonte)
166         self.zone_texte.bind("<Key-Prior>", self.page_up)
167         self.zone_texte.bind("<Key-Next>", self.page_down)
168         self.zone_texte.bind("<Key-Up>", self.unit_up)
169         self.zone_texte.bind("<Key-Down>", self.unit_down)
170         self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
171         #self.scroll_h = Scrollbar (self.frame_texte,command = self.zone_texte.xview)
172         self.scroll_v.pack(side='right',fill ='y')
173         #self.scroll_h.pack(side='bottom',fill ='x')
174         self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
175         self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
176         # définition des boutons
177         self.but_yes = Button(self.frame_boutons,text = yes,command=self.yes)
178         self.but_no = Button(self.frame_boutons,text = no,command = self.no)
179         self.but_yes.place(relx=0.4,rely=0.5,anchor='center')
180         self.but_no.place(relx=0.6,rely=0.5,anchor='center')
181         # affichage du texte
182         self.affiche_texte(self.texte)
183         centerwindow(self.fenetre)
184
185     def yes(self):
186         self.result=1
187         self.quit()
188
189     def no(self):
190         self.result=0
191         self.quit()
192
193 class FenetreDeSelection(Fenetre):
194     """ Classe dérivée de Fenêtre permettant la récupération d'une zone de texte sélectionnée.
195         Cette classe est utilisée pour affecter une liste de valeurs à un mot-clé.
196     """
197     def __init__(self,panel,item,appli,titre="",texte="",cardinal=1):
198         Fenetre.__init__(self,appli,titre=titre,texte=texte)
199         self.frame_boutons.place_forget()
200         self.frame_texte.place_forget()
201         self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.8)
202         self.frame_boutons.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
203
204         self.cardinal=cardinal
205         self.fenetre.configure(width = 320,height=400)
206         centerwindow(self.fenetre)
207         self.panel = panel
208         self.item = item
209         self.fenetre.title(titre)
210         self.but_save.configure(text="Ajouter",command=self.traite_selection)
211         # séparateur par défaut
212         self.separateur = ';'
213         # création de la zone de saisie du séparateur
214         l_separateurs_autorises = self.get_separateurs_autorises()
215         self.choix_sep = Pmw.ComboBox(self.frame_boutons,
216                                       label_text = "Séparateur :",
217                                       labelpos = 'w',
218                                       listheight = 100,
219                                       selectioncommand = self.choose_separateur,
220                                       scrolledlist_items = l_separateurs_autorises)
221         self.choix_sep.component('entry').configure(width=6)
222         self.choix_sep.place(relx=0.01,rely=0.5,anchor='w')
223         self.choix_sep.selectitem(self.separateur)
224         # Replacement
225         self.but_quit.place_forget()
226         self.but_save.place_forget()
227         self.but_all  = Button(self.frame_boutons,text = "Tout Sélectionner", command=self.tout)
228         self.but_save.place(relx=0.6,rely=0.6,anchor='center')
229         self.but_quit.place(relx=0.8,rely=0.6,anchor='center')
230         self.but_all.place(relx=0.7,rely=0.2,anchor='center')
231         self.choose_separateur('espace')
232      
233
234     def get_separateurs_autorises(self):
235         """
236         Retourne la liste des séparateurs autorisés
237         """
238         return ['espace',';',',']
239
240     def choose_separateur(self,nom_sep):
241         """
242         Affecte à self.separateur le caractère séparateur correspondant à nom_sep
243         """
244         if nom_sep == 'espace' :
245             self.separateur = ' '
246         else:
247             self.separateur = nom_sep
248         
249     def tout(self):
250         liste=[]
251         texte=self.texte.splitlines()
252         for l in texte :
253             for mot in string.split(l,self.separateur):
254                if mot != '' and mot != ' ' and mot != self.separateur :
255                   liste.append(mot)
256         self.traite_selection(liste)
257
258     def traite_selection(self,liste=None):
259         """ Cette méthode effectue tous les traitements nécessaires pour vérifier
260             et affecter la liste de valeurs à l'objet réprésenté par self.item
261         """
262         # Récupère la liste des chaines de caractères de la zone sélectionnée
263         message=""
264         if liste == None:
265            message,liste = self.recupere_liste()
266         if self.test_probleme(message,"Sélectionnez des données") == 0:
267             return
268         # Vérifie que le nombre de données est dans les limites attendues
269         message = self.verif_liste(liste)
270         if self.test_probleme(message,"Vérifiez le nombre de données") == 0:
271             return
272         # Crée une liste de valeurs du type attendu
273         message,liste_valeurs = self.creation_liste_valeurs(liste)
274         if self.test_probleme(message,"Vérifiez le type des données") == 0:
275             return
276         # Vérifie que chaque valeur est dans le domaine exigé
277         message = self.verif_valeurs(liste_valeurs)
278         if self.test_probleme(message,"Vérifiez le domaine des valeurs") == 0:
279             return
280         # Ajoute les valeurs dans la liste de valeurs du mot-clé
281         if self.cardinal != 1 :
282            nb=self.cardinal
283            l_valeurs=[]
284            # a ameliorer
285            if (len(liste_valeurs)%nb != 0):
286                 message="La cardinalité n'est pas correcte"
287                 self.test_probleme(message,"On attend des tuples")
288                 return
289            for i in range(len(liste_valeurs)/nb) :
290                if (nb==2):
291                    t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1])
292                elif (nb ==3):
293                    t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1], liste_valeurs[i*nb+2])
294                else :
295                   print "probleme : prevenir la maintenance Eficas"
296                   return
297                l_valeurs.append(t)
298            liste_valeurs=l_valeurs
299         self.ajouter_valeurs(liste_valeurs)
300         self.appli.affiche_infos("Liste de valeurs acceptée")
301
302     def test_probleme(self, message, message_eficas):
303         """ Cette méthode affiche un message d'erreur si message != ''
304             et retourne 0, sinon retourne 1 sans rien afficher.
305         """
306         if message != "":
307             showinfo("Problème",message)
308             self.fenetre.tkraise()
309             self.appli.affiche_infos(message_eficas)
310             return 0
311         else:
312             return 1
313
314     def recupere_liste(self):
315         """ Cette méthode récupère le texte de la zone sélectionnée, construit et
316             retourne une liste avec les chaines qui se trouvent entre les séparateurs.
317             S'il n'y a pas de données selectionnées, elle retourne un message d'erreur
318             et une liste vide.
319         """
320         message = ""
321         try:
322             selection=self.fenetre.selection_get()
323         except:
324             message = "Pas de donnée sélectionnée"
325             return message,None
326         # les retours chariots doivent être interprétés comme des séparateurs
327         selection = string.replace(selection,'\n',self.separateur)
328         # on splitte la sélection suivant le caractère séparateur
329         liste_chaines = string.split(selection,self.separateur)
330         l_chaines = []
331         for chaine in liste_chaines:
332             chaine = string.strip(chaine)
333             if chaine != '' : l_chaines.append(chaine)
334         return message,l_chaines
335
336     def verif_liste(self, liste):
337         """ Cette méthode effectue des tests sur le nombre d'éléments de la liste
338             et retourne 1 si la liste est correcte, sinon 0 et le message d'erreur
339             correspondant.
340         """
341         message = ""
342         # nombre d'éléments sélectionnés
343         nombre_elements = len(liste)
344         # nombre d'éléments déja dans la liste du panel
345         nombre_in_liste = len(self.panel.Liste_valeurs.get_liste())
346         multiplicite = self.item.GetMultiplicite()
347         if (nombre_elements % multiplicite) != 0:
348             message = "Vous devez sélectionner "+str(multiplicite)+" * n données"
349             return message
350         nombre_valeurs = nombre_elements / multiplicite
351         cardinalite = self.item.GetMinMax()
352         if nombre_valeurs < cardinalite[0]:
353             message = "Vous devez sélectionner au moins "+str(cardinalite[0])+" valeurs"
354             return message
355         if cardinalite[1] != "**" and nombre_valeurs > (long(cardinalite[1])-nombre_in_liste):
356             message = "La liste ne peut avoir plus de "+str(cardinalite[1])+" valeurs"
357             return message
358
359         return message
360
361     def creation_liste_valeurs(self, liste):
362         """ Cette méthode crée et retourne une liste de valeurs du type attendu
363             par le mot-clé. La liste de valeurs est créée à partir de la liste
364             de chaines de caractères transmise.
365         """
366         type_attendu = self.item.GetType()[0]
367         if type_attendu == 'R':
368             return self.convertir(liste, f_conversion= float)
369         elif type_attendu == 'I':
370             return self.convertir(liste, f_conversion= int)
371         elif type_attendu == 'TXM':
372             return self.convertir(liste)
373         else:
374             message = "Seuls les entiers, les réels et les chaines de caractères sont convertis"
375             return message,None
376
377     def convertir(self, liste, f_conversion=None):
378         """ Cette méthode essaie de convertir les éléments de la liste avec la
379             fonction f_conversion si elle existe, et retourne la liste des
380             éléments dans le type voulu en cas de succès, sinon retourne None.
381         """
382         liste_valeurs = []
383         message = ""
384         for chaine in liste:
385             if f_conversion:
386                 try:
387                     liste_valeurs.append(f_conversion(chaine))
388                 except:
389                     message = "Impossible de convertir "+chaine+" dans le type attendu"
390                     return message,None
391             else:
392                 liste_valeurs.append(chaine)
393         return message,liste_valeurs
394
395     def verif_valeurs(self, liste_valeurs):
396         """ Cette méthode teste tous les éléments de la liste, et retourne 1 si chaque
397             élément est dans le domaine voulu.
398         """
399         message = ""
400         for valeur in liste_valeurs:
401             test = self.item.IsInIntervalle(valeur)
402             if test == 0:
403                 intervalle = str(self.item.GetIntervalle()[0])+","+str(self.item.GetIntervalle()[1])
404                 message = "La valeur "+str(valeur)+" n'est pas dans l'intervalle ["+intervalle+"]"
405                 return message
406         return message
407
408     def ajouter_valeurs(self, liste_valeurs):
409         """ Cette méthode ajoute les nouvelles valeurs à la liste existante."""
410         liste = self.panel.Liste_valeurs.get_liste()
411         liste.extend(liste_valeurs)
412         self.panel.Liste_valeurs.put_liste(liste)
413
414 class FenetreDeParametre(Fenetre) :
415     def __init__(self,parent,item,appli,texte):
416         self.parent=parent
417         self.appli=appli
418         self.fenetre = Toplevel()
419         self.fenetre.configure(width = 250,height=100)
420         self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
421         self.fenetre.title("Parametres")
422         self.titre = "Parametres"
423         self.texte = string.replace(texte,'\r\n','\n')
424         fonte=fontes.standardcourier10
425
426         # définition des frames
427         self.frame_texte = Frame(self.fenetre)
428         self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.7)
429         # définition de la zone texte et du scrollbar
430         self.zone_texte = Text(self.frame_texte,font=fonte)
431         self.zone_texte.bind("<Key-Prior>", self.page_up)
432         self.zone_texte.bind("<Key-Next>", self.page_down)
433         self.zone_texte.bind("<Key-Up>", self.unit_up)
434         self.zone_texte.bind("<Key-Down>", self.unit_down)
435         self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
436         self.scroll_v.pack(side='right',fill ='y')
437         self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
438         self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
439         # affichage du texte
440         self.affiche_texte(self.texte)
441         self.zone_texte.config(state="disabled")
442
443         # définition des boutons
444         self.frame_boutons = Frame(self.fenetre)
445         self.frame_boutons.place(relheight=0.3,relx=0,rely=0.65,relwidth=1.)
446         self.label1 = Label(self.frame_boutons,text="surligner la")
447         self.label2 = Label(self.frame_boutons,text="ligne entière")
448         self.label1.place(relx=0.1,rely=0)
449         self.label2.place(relx=0.1,rely=0.5)
450         self.but_quit = Button(self.frame_boutons,text = "Fermer",command=self.quit)
451         self.but_save = Button(self.frame_boutons,text = "Choisir",command = self.Choisir)
452         self.but_save.place(relx=0.6,rely=0,relheight=1)
453         self.but_quit.place(relx=0.8,rely=0,relheight=1)
454
455
456     def Choisir(self):
457         try:
458             selection=self.zone_texte.selection_get()
459         except:
460             showerror("Pas de donnée sélectionnée",
461                        "Selectionner un parametre")
462         l_param = ""
463         for param in selection.splitlines():
464             nomparam=param[0:param.find("=")-1]
465             if nomparam != '' : 
466                 l_param=l_param+nomparam+','
467         self.parent.entry.delete(0,Tkinter.END)
468         self.parent.entry.insert(0,l_param[0:-1])
469         self.parent.valid_valeur()
470         self.quit()
471
472 class Formulaire:
473     """
474     Cette classe permet de créer une boîte Dialog dans laquelle
475     on affiche un formulaire à remplir par l'utilisateur
476     """
477     def __init__(self,fen_pere,obj_pere=None,titre="",texte="",items=(),mode='query',commande=None):
478         if items in ((),[]) : return
479         self.items = items
480         self.titre = titre
481         self.texte = texte
482         self.fen_pere = fen_pere
483         self.obj_pere = obj_pere
484         self.mode= mode
485         self.command = commande
486         self.display()
487
488     def display(self):
489         self.init_validateurs()
490         self.init_fenetre()
491         self.init_texte()
492         self.init_items_formulaire()
493         self.fenetre.activate(geometry='centerscreenalways')
494
495     def init_validateurs(self):
496         """
497         Crée le dictionnaire des validateurs des objets reconnus par le formulaire
498         """
499         self.d_validateurs = {}
500         self.d_validateurs['rep']  = self.repvalidator
501         self.d_validateurs['file'] = self.filevalidator
502         self.d_validateurs['cata']= self.catavalidator
503         
504     def init_fenetre(self):
505         """
506         Crée la fenêtre Dialog
507         """
508         if self.mode == 'query':
509             buttons=('Valider','Annuler')
510             defaultbutton = 'Valider'
511         elif self.mode == 'display':
512             if self.command :
513                 buttons=(self.command[0],'OK')
514                 defaultbutton = 'OK'
515             else:
516                 buttons=('OK')
517                 defaultbutton = 'OK'
518         self.fenetre = Pmw.Dialog(self.fen_pere,
519                                   buttons=buttons,
520                                   defaultbutton = defaultbutton,
521                                   title = self.titre,
522                                   command = self.execute)
523         self.fenetre.withdraw()
524         
525     def init_texte(self):
526         """
527         Crée le label qui affiche le texte à l'intérieur du panneau
528         """
529         fonte=fontes.standard
530         fr_texte = Frame(self.fenetre.interior(),height=60)
531         fr_texte.pack(side='top',fill='x',expand=1)
532         Label(fr_texte,text = self.texte, font=fonte).place(relx=0.5,rely=0.5,anchor='center')
533
534     def init_items_formulaire(self):
535         """
536         Crée et affiche les items dans la boîte de dialogue
537         """
538         self.radiobut = 0
539         self.widgets = []
540         self.item_widgets = {}
541         length_maxi = 0
542         for item in self.items:
543             if len(item[0])>length_maxi : length_maxi = len(item[0])
544         window = self.fenetre.interior()
545         for item in self.items :
546             if len(item) == 4 :
547                label,nature,nom_var,defaut = item
548                chaine="Yes" 
549                chaine2="No"
550             else :
551                label,nature,nom_var,defaut,chaine,chaine2 = item
552             # création de la frame
553             fr_item = Frame(window,height=40,width=700)
554             fr_item.pack(side='top',fill='x',expand=1)
555             # création du label
556             Label(fr_item,text = label).place(relx=0.05,rely=0.4)
557             if nature in ('rep','file','cata'):
558                 # création de l'entry
559                 e_item = Entry(fr_item) 
560                 e_item.place(relx=0.5,rely=0.4,relwidth=0.45)
561                 self.widgets.append(e_item)
562                 self.item_widgets[item] = e_item
563                 if defaut : e_item.insert(0,str(defaut))
564             elif nature == 'YesNo':
565                 # création de la StringVar
566                 var = StringVar()
567                 setattr(self,'item_'+nom_var,var)
568                 var.set(defaut)
569                 # création du radiobouton
570                 rb1 = Radiobutton(fr_item,text=chaine,variable=var,value='OUI')
571                 rb2 = Radiobutton(fr_item,text=chaine2,variable=var,value='NON')
572                 rb1.place(relx=0.65,rely=0.5,anchor='center')
573                 rb2.place(relx=0.80,rely=0.5,anchor='center')
574                 self.widgets.append((rb1,rb2))
575                 self.item_widgets[item] = var
576         # détermination de la méthode à appliquer sur les boutons
577         if self.mode == 'query':
578             function = self.active
579         elif self.mode == 'display':
580             function = self.inactive
581         else:
582             return
583         # on applique la méthode sur les boutons (activation ou désactivation)  
584         for widget in self.widgets :
585             if type(widget) == types.TupleType:
586                 for widg in widget :
587                     apply(function,(widg,),{})
588             else:
589                 apply(function,(widget,),{})
590
591     def active(self,widget):
592         """
593         Active le widget passé en argument
594         """
595         widget.configure(state='normal',bg='white')
596
597     def inactive(self,widget):
598         """
599         Inactive le widget passé en argument
600         """
601         if not isinstance(widget,Radiobutton) :
602             widget.configure(state='disabled',bg='gray95')
603         else :
604             widget.configure(state='disabled')
605
606 # --------------------------------------------------------------------------------
607 #       Validateurs des noms de répertoire, de fichiers et de catalogues
608 # -------------------------------------------------------------------------------
609
610     def repvalidator(self,text):
611         """
612         Teste si text peut faire référence à un répertoire ou non
613         Retourne 1 si valide, 0 sinon
614         """
615         return os.path.isdir(text),'Répertoire introuvable : %s' %text
616
617     def filevalidator(self,text):
618         """
619         Teste si text peut faire référence à un fichier ou non
620         Retourne 1 si valide, 0 sinon
621         """
622         return os.path.isfile(text),'Fichier introuvable : %s' %text
623
624     def catavalidator(self,text):
625         """
626         Teste si  text est un chemin d'accès valide à un catalogue
627         Retourne 1 si valide, 0 sinon
628         """
629         return os.path.isfile(text),"Catalogue introuvable : %s" %text
630
631 # --------------------------------------------------------------------------------
632 #       Méthodes callbacks des boutons et de fin
633 # --------------------------------------------------------------------------------
634         
635     def execute(self,txt):
636         """
637         Cette commande est activée à chaque clic sur un bouton.
638         Redirige l'action sur la bonne méthode en fonction du bouton activé
639         """
640         if txt == 'Valider':
641             self.fini()
642         elif txt in ('OK','Annuler'):
643             self.quit()
644         elif txt == 'Modifier':
645             self.resultat = apply(self.command[1],(),{})
646             self.fenetre.destroy()
647         else :
648             print "Nom de bouton inconnu"
649             self.quit()
650
651     def fini(self):
652         """
653         Commande qui termine le panneau et sauvegarde les nouvelles options
654         dans l'objet resultat (dictionnaire)
655         """
656         dico={}
657         for item,widget in self.item_widgets.items():
658             nom_var = item[2]
659             type_var = item[1]
660             valeur = widget.get()
661             if self.d_validateurs.has_key(type_var):
662                 test = self.d_validateurs[type_var](valeur)
663                 if not test :
664                     # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode
665                     # sans tuer la fenêtre bien sûr
666                     widget.selection_range(0,END)
667                     return
668             dico[nom_var] = valeur
669         self.fenetre.destroy()    
670         self.resultat=dico
671         
672     def quit(self):
673         self.fenetre.destroy()
674         self.resultat=None
675         
676 class ListeChoix :
677     """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre
678         en passant les commandes à lancer suivant différents bindings """
679     def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre='',
680                  optionReturn=None, fonte_titre=fontes.standard_gras_souligne):
681         self.parent = parent
682         self.page = page
683         self.liste = liste
684         self.dico_labels={}
685         self.selection = None
686         self.liste_commandes = liste_commandes
687         self.liste_marques = liste_marques
688         self.arg_selected=''
689         self.active = active
690         self.titre = titre
691         self.filtre = filtre
692         self.optionReturn = optionReturn
693         self.fonte_titre=fonte_titre
694         self.init()
695
696     def init(self):        
697         self.make_label_titre()
698         self.make_entry_filtre()
699         self.make_text_box()
700         try:
701             self.entry.component('entry').focus()
702         except:
703             pass
704
705     def make_label_titre(self):
706         """ Crée le label correspondant au titre """
707         if self.titre == '' : return
708         self.label = Label(self.page,
709                            text = self.titre,
710                            font = self.fonte_titre)
711         self.label.pack(side='top',pady=2)
712         
713     def make_entry_filtre(self):
714         """ Crée l'entry permettant à l'utilisateur d'entrer un filtre de sélection dans la liste """
715         if self.filtre != 'oui' : return
716         self.entry = Pmw.EntryField(self.page,labelpos='w',
717                                     label_text="Filtre :",
718                                     command=self.entry_changed)
719         self.entry.pack(side='top',pady=2)
720         
721     def make_text_box(self):
722         """ Crée la fenêtre texte dans laquelle sera affichée la liste """
723         self.MCbox = Text (self.page,relief='sunken',bg='gray95',bd=2)
724         self.MCscroll = Scrollbar (self.page,command = self.MCbox.yview)
725         self.MCscroll.pack(side='right',fill ='y',pady=2)
726         self.MCbox.pack(fill='y',expand=1,padx=2,pady=2)
727         self.MCbox.configure(yscrollcommand=self.MCscroll.set)
728
729
730     def affiche_liste(self):
731         """ Affiche la liste dans la fenêtre"""
732         liste_labels=[]
733         self.MCbox.config(state=NORMAL)
734         self.MCbox.delete(1.0,END)
735         for objet in self.liste :
736           if type(objet) == types.InstanceType:
737               try:
738                   mot = objet.nom
739               except:
740                   mot = str(objet)
741           elif type(objet) in (types.StringType,types.IntType):
742               mot = objet
743           elif type(objet) == types.FloatType :
744               mot = self.parent.get_valeur_texte(objet)
745               if mot == "" :
746                  mot = str(objet)
747           elif type(objet) == types.TupleType :
748               mot="("
749               premier=1
750               for val in objet:
751                  if (not premier):
752                    mot=mot+"," 
753                  else:
754                    premier=0
755                  valtexte = self.parent.get_valeur_texte(val)
756                  if valtexte != "" :
757                     mot=mot+valtexte
758                  else:
759                     mot=mot+str(val)
760               mot=mot+")"
761           else:
762               mot=`objet`
763           label = Label(self.MCbox,
764                         text = mot,
765                         fg = 'black',bg = 'gray95',justify = 'left')
766           self.dico_labels[mot]=label
767           liste_labels.append(label)
768           self.MCbox.window_create(END,
769                                    window=label,
770                                    stretch = 1)
771           self.MCbox.insert(END,'\n')
772           if self.optionReturn != None :
773               label.bind("<Return>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
774               label.bind("<KP_Enter>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
775           label.bind("<Key-Right>",lambda e,s=self,x=objet,l=label : s.selectNextItem(x,l))
776           label.bind("<Key-Down>",lambda e, s=self,x=objet,l=label : s.selectNextItem(x,l))
777           label.bind("<Key-Left>" ,lambda e,s=self,x=objet,l=label  : s.selectPrevItem(x,l))
778           label.bind("<Key-Up>" ,lambda e,s=self,x=objet,l=label  : s.selectPrevItem(x,l))
779           if self.active == 'oui':
780               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))
781               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))
782               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))
783
784         for marque in self.liste_marques:
785            try:
786               self.markitem(liste_labels[marque])
787            except:
788               pass
789
790         self.MCbox.config(state=DISABLED)
791         self.selection = None
792         for event,callback in self.liste_commandes:
793             if event == "<Enter>":
794                self.selection=None,None,callback
795                break
796
797     def clear_marque(self):
798         try:
799           self.dico_labels[self.arg_selected].configure(bg='gray95',fg='black')
800           self.arg_selected = ''
801         except :
802           pass
803
804     def surligne(self,marque):
805         try :
806            self.highlightitem(self.dico_labels[marque])
807            self.arg_selected = marque
808         except:
809            pass
810
811     def chooseitemsurligne(self,mot,label,commande):
812         """ Active la méthode de choix passée en argument"""
813         try:
814            mot=self.arg_selected
815            commande(mot)
816         except AsException,e:
817            raison=str(e)
818            showerror(raison.split('\n')[0],raison)
819
820     def chooseitem(self,mot,label,commande):
821         """ Active la méthode de choix passée en argument"""
822         try:
823            commande(mot)
824         except AsException,e:
825            raison=str(e)
826            showerror(raison.split('\n')[0],raison)
827
828     def selectNextItem(self,mot,label):
829         index=self.liste.index(mot)
830         indexsuivant=index+1
831         if indexsuivant > len(self.liste) -1:
832            indexsuivant=0
833         motsuivant=self.liste[indexsuivant]
834         labelsuivant=self.dico_labels[motsuivant]
835         index = self.MCbox.index(labelsuivant)
836         self.MCbox.see(index)
837         self.selectitem(motsuivant,labelsuivant,self.selection[2],)
838            
839     def selectPrevItem(self,mot,label):
840         index=self.liste.index(mot)
841         indexprec=index-1
842         motprec=self.liste[indexprec]
843         labelprec=self.dico_labels[motprec]
844         index = self.MCbox.index(labelprec)
845         self.MCbox.see(index)
846         self.selectitem(motprec,labelprec,self.selection[2],)
847         
848     def selectitem(self,mot,label,commande) :
849         """ Met l'item sélectionné (représenté par son label) en surbrillance
850             et lance la commande associée au double-clic"""
851         self.clear_marque()
852         if self.selection != None :
853             self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
854         self.highlightitem(label)
855         self.selection = (mot,label,commande)
856         self.arg_selected = mot
857         if commande : commande(mot)
858
859     def highlightitem(self,label) :
860         """ Met l'item représenté par son label en surbrillance """
861         label.focus_set()
862         label.configure(bg='#00008b',fg='white')
863         
864     def markitem(self,label):
865         """ Met l'item (représenté par son label) en rouge """
866         label.configure(bg='gray95',fg='red')
867         
868     def deselectitem(self,label,mot='',commande=None) :
869         """ Remet l'item (représenté par son label) en noir"""
870         if label:label.configure(bg='gray95',fg='black')
871         self.arg_selected = ''
872         if commande and mot : commande(mot)
873
874     def cherche_selected_item(self):
875         index=self.MCbox.index(self.selection[1])
876         lign,col=map(int,string.split(index,'.'))
877         return lign
878
879     def remove_selected_item(self):
880         index=self.MCbox.index(self.selection[1])
881         lign,col=map(int,string.split(index,'.'))
882         del self.liste[lign-1]
883         self.affiche_liste()
884
885     def entry_changed(self,event=None):
886         """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
887         de l'entry et frappe <Return>"""
888         if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
889         filtre = self.entry.get()+"*"
890         FILTRE = string.upper(filtre)
891         for arg in self.liste :
892             if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
893                 label=self.dico_labels[arg]
894                 index = self.MCbox.index(label)
895                 self.MCbox.see(index)
896                 self.selectitem(arg,label,self.selection[2])
897                 break
898
899         #try :
900           #self.dico_labels[self.arg_selected].focus_set()
901         #except :
902           #pass
903
904
905     # PN attention à la gestion des paramétres
906     # cela retourne H = 1 , et ni H, ni 1
907     #            print repr(val)
908     #            print val.__class__.__name__
909     def get_liste(self):
910         l=[]
911         for val in self.liste:
912 #            try:
913 #                v = eval(val)
914 #               l.append(v)
915 #            except:
916                 l.append(val)
917         return l
918     
919     def put_liste(self,liste):
920         self.liste = liste
921         self.affiche_liste()
922
923 class Affichage :
924   """ Cette classe permet d'afficher au lancement d'EFICAS le message
925       d'attente et la barre de progression"""
926   def __init__(self,master,message,barre ='oui'):
927       from Tools.foztools.foztools import Slider
928       fonte=fontes.standard12_gras
929       self.master=master
930       self.frame = Frame(self.master)
931       self.frame.pack(expand=1,fill='both')
932       self.mess = Label(self.frame,text=message,justify='center',
933                         bd=2,relief='groove',font=fonte)
934       self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
935       self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
936                              fillColor='#00008b',width=200,height=30,
937                              background='white',labelColor='red')
938       if barre == 'oui':
939           self.progress.frame.pack(in_=self.frame,side='top')
940       self.master.update()
941       if barre == 'oui':
942           self.progress.frame.after(1000,self.update)
943
944   def configure(self,**options):
945       if options.has_key('message'):
946           self.mess.configure(text=options['message'])
947       if options.has_key('barre'):
948           if options['barre'] == 'oui' :
949               self.progress.frame.pack(in_=self.frame,side='top')
950           elif options['barre'] == 'non' :
951               self.progress.frame.pack_forget()
952       self.master.update_idletasks()
953       
954   def quit(self):
955       self.frame.destroy()
956       self.master.update()
957
958   def update(self,event=None):
959       """ Permet de faire avancer la barre de progression """
960       try :
961           bar=self.progress
962           bar.value = bar.value+self.increment
963           bar.update()
964           self.master.after(100,self.update)
965       except:
966           pass
967
968   def configure_barre(self,nb):
969       """ Calcule l'incrément de progression de la barre en fonction
970           du nombre d'opérations à effectuer afin que le compteur
971           soit à 100% à la fin des opérations"""
972       self.increment = 100./nb
973       self.progress.update()
974
975 class Ask_Format_Fichier :
976     """
977     Cette classe permet de créer une fenêtre Toplevel dans laquelle
978     on propose le choix du format de fichier de commandes à ouvrir
979     """
980     def __init__(self,appli):
981         self.fenetre = Toplevel()
982         self.fenetre.configure(width = 250,height=150)
983         self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
984         self.fenetre.title("Choix du format du fichier de commandes")
985         # définition des frames
986         self.frame_texte = Frame(self.fenetre)
987         self.frame_radioboutons = Frame(self.fenetre)
988         self.frame_bouton_ok = Frame(self.fenetre)
989         self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
990         self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
991         self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
992         # définition de la zone texte et du scrollbar
993         zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
994         zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
995         # définition des radioboutons
996         Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
997                     variable=appli.format_fichier,value='Aster').pack(anchor='n')
998         Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
999                     variable=appli.format_fichier,value='Python').pack(anchor='n')
1000         # création du bouton OK
1001         Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
1002         # centrage de la fenêtre
1003         centerwindow(self.fenetre)
1004
1005     def quit(self):
1006         self.fenetre.destroy()
1007
1008 class BARRE_K2000(Toplevel):
1009     def __init__(self,master=None,text = ""):
1010         Toplevel.__init__(self,master,relief='groove')
1011         self.master.iconify()
1012         self.geometry("250x100+0+0")
1013         self.protocol("WM_DELETE_WINDOW",self.quit)
1014         # frame principale dans self (= Toplevel)
1015         self.frame = Frame(self)
1016         self.frame.place(relwidth=1,relheight=1)
1017         # frame contenant le texte à afficher 
1018         self.frame_text = Frame(self.frame)
1019         self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
1020         # frame contenant le canvas de la barre
1021         self.frame_canv = Frame(self.frame)
1022         self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
1023         # canvas dans lequel sera affichée la barre K2000
1024         self.canvas = Canvas(self.frame_canv)
1025         self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
1026         # on affiche le texte et la barre
1027         self.build_text(text)
1028         self.build_batons()
1029         #self.overrideredirect(1)
1030         # on active la barre ...
1031         self.master.after(1000,self.launch)
1032         # on centre la fenêtre
1033         centerwindow(self)
1034         self.focus()
1035
1036     def build_text(self,text):
1037         """
1038         Affichage de text dans frame_text
1039         """
1040         self.texte_var = StringVar()
1041         self.texte_var.set(text)
1042         Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
1043         
1044     def build_batons(self):
1045         """
1046         Construit la suite de bâtons dans le canvas
1047         """
1048         self.l_batons=[]
1049         self.black = -1
1050         self.sens = 'D'
1051         self.quit = 0
1052         for i in range(0,40):
1053             id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
1054             self.l_batons.append(id)
1055
1056     def launch(self):
1057         """
1058         Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
1059         """
1060         if self.quit == 1 :
1061             self.destroy()
1062             self.master.deiconify()
1063             return
1064         if self.sens == 'D':
1065             self.black = self.black+1
1066             l_bat = self.l_batons[0:self.black+1]
1067             l_bat.reverse()
1068         elif self.sens == 'G':
1069             self.black = self.black-1
1070             l_bat = self.l_batons[self.black:]
1071         i=0
1072         for bat in l_bat :
1073             num_color = 5+i*10
1074             if num_color < 10 : color = 'black'
1075             elif num_color > 90 : color = 'white'
1076             else: color = 'gray'+`num_color`
1077             self.canvas.itemconfigure(bat,fill=color)
1078             i=i+1
1079         if self.black == len(self.l_batons) :
1080             self.sens = 'G'
1081         if self.black == 0 and self.sens == 'G':self.sens = 'D'
1082         self.after(80,self.launch)
1083
1084     def update_text(self,new_text):
1085         """
1086         Remplace le texte affiché par new_text
1087         """
1088         self.texte_var.set(new_text)
1089         
1090     def quit(self):
1091         self.quit = 1        
1092
1093 class ListeChoixParGroupes(ListeChoix) :
1094     """ 
1095         Cette classe est utilisée pour afficher une liste de commandes classées par
1096         groupes. L'utilisateur peut réaliser des actions de selection
1097         qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
1098         Exemple de binding:
1099            liste_commandes = (("<Enter>",self.selectCmd),
1100                               ("<Leave>",self.deselectCmd),
1101                               ("<Double-Button-1>",self.defCmd))
1102         Il s'agit d'une liste de doublets dont le premier element est un evenement et le 
1103         deuxieme un callback a appeler sur l'evenement en question.
1104
1105     """
1106     def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
1107                       active ='oui',filtre='non',titre='',optionReturn=None,fonte_titre=fontes.standard_gras_souligne):
1108         self.parent = parent
1109         self.page = page
1110         self.liste_groupes = liste_groupes
1111         self.dict_groupes = dict_groupes
1112         self.dico_labels={}
1113         self.selection = None
1114         self.liste_commandes = liste_commandes
1115         self.liste_marques = liste_marques
1116         self.arg_selected=''
1117         self.active = active
1118         self.titre = titre
1119         self.filtre = filtre
1120         self.optionReturn = optionReturn
1121         self.fonte_titre=fonte_titre
1122         self.init()
1123
1124     def affiche_liste(self):
1125         """ Affiche la liste dans la fenêtre"""
1126         liste_labels=[]
1127         self.MCbox.config(state=NORMAL)
1128         self.MCbox.delete(1.0,END)
1129         for grp in self.liste_groupes:
1130            # On itère sur les groupes
1131            if grp == "CACHE":continue
1132            liste_commandes=self.dict_groupes[grp]
1133            text="GROUPE<<<<<<<< "+grp+" "
1134            text=text+">"*max(0,30-len(text))
1135            label = Label(self.MCbox,
1136                         text = text,
1137                         fg = 'black',bg = 'gray95',justify = 'left')
1138            # On stocke la relation entre le nom de la commande et le label
1139            self.dico_labels[grp]=label
1140            liste_labels.append(label)
1141            self.MCbox.window_create(END,
1142                                    window=label,
1143                                    stretch = 1)
1144            self.MCbox.insert(END,'\n')
1145            for cmd in liste_commandes:
1146               label = Label(self.MCbox,
1147                         text = cmd,
1148                         fg = 'black',bg = 'gray95',justify = 'left')
1149               # On stocke la relation entre le nom de la commande et le label
1150               self.dico_labels[cmd]=label
1151               self.MCbox.window_create(END,
1152                                    window=label,
1153                                    stretch = 1)
1154               self.MCbox.insert(END,'\n')
1155
1156               def null(*tp,**args): return
1157
1158               if self.active == 'oui':
1159                   # Traitement par defaut des evenements
1160                   label.bind("<Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.selectitem(x,l,c))
1161                   label.bind("<Leave>",lambda e,s=self,c=null,x=cmd,l=label: s.deselectitem(l,x,c))
1162                   label.bind("<Double-Button-1>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1163                   label.bind("<Return>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1164                   label.bind("<KP_Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1165                   label.bind("<Key-Right>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1166                   label.bind("<Key-Down>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1167                   label.bind("<Key-Left>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1168                   label.bind("<Key-Up>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1169
1170                   # Si des callbacks sont definis on les utilise
1171                   for event,callback in self.liste_commandes:
1172                       if event == "<Enter>":
1173                          label.bind("<Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.selectitem(x,l,c))
1174                       elif event == "<Leave>":
1175                          label.bind("<Leave>",lambda e,s=self,c=callback,x=cmd,l=label: s.deselectitem(l,x,c))
1176                       elif event == "<Double-Button-1>":
1177                          label.bind("<Double-Button-1>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1178                       elif event == "<Return>":
1179                          label.bind("<Return>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1180                       elif event == "<KP_Enter>":
1181                          label.bind("<KP_Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1182                       elif event == "<Key-Right>":
1183                          label.bind("<Key-Right>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1184                       elif event == "<Key-Down>":
1185                          label.bind("<Key-Down>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1186                       elif event == "<Key-Left>":
1187                          label.bind("<Key-Left>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1188                       elif event == "<Key-Up>":
1189                          label.bind("<Key-Up>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1190                       else:
1191                          label.bind(event,lambda e,s=self,c=callback,x=cmd,l=label: c())
1192
1193         for marque in self.liste_marques:
1194            try:
1195               self.markitem(liste_labels[marque])
1196            except:
1197               pass
1198
1199         self.MCbox.config(state=DISABLED)
1200         self.selection = None
1201         for event,callback in self.liste_commandes:
1202             if event == "<Enter>":
1203                self.selection=None,None,callback
1204                break
1205
1206     def selectPrevItem(self,mot,label,callback,group,cmd):
1207         g=self.liste_groupes.index(group)
1208         liste_commandes=self.dict_groupes[group]
1209         c=liste_commandes.index(cmd)
1210         if c > 0:
1211            co=liste_commandes[c-1]
1212         else:
1213            # debut de liste. On passe au groupe precedent
1214            if g > 0:
1215               gr=self.liste_groupes[g-1]
1216               co=self.dict_groupes[gr][-1]
1217            else:
1218               # debut des groupes. On ne fait rien
1219               return
1220         # On a trouve l'item precedent
1221         labelsuivant=self.dico_labels[co]
1222         index = self.MCbox.index(labelsuivant)
1223         self.MCbox.see(index)
1224         self.selectitem(co,labelsuivant,self.selection[2],)
1225
1226     def selectNextItem(self,mot,label,callback,group,cmd):
1227         g=self.liste_groupes.index(group)
1228         liste_commandes=self.dict_groupes[group]
1229         c=liste_commandes.index(cmd)
1230         try:
1231            co=liste_commandes[c+1]
1232         except:
1233            # fin de liste. On passe au groupe suivant
1234            try:
1235               gr=self.liste_groupes[g+1]
1236               co=self.dict_groupes[gr][0]
1237            except:
1238               # fin des groupes. On ne fait rien
1239               return
1240         # On a trouve l'item suivant
1241         labelsuivant=self.dico_labels[co]
1242         index = self.MCbox.index(labelsuivant)
1243         self.MCbox.see(index)
1244         self.selectitem(co,labelsuivant,self.selection[2],)
1245
1246     def entry_changed(self,event=None):
1247         """ 
1248             Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
1249             de l'entry et frappe <Return>
1250         """
1251         if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
1252
1253         filtre = self.entry.get()+"*"
1254         FILTRE = string.upper(filtre)
1255         #
1256         # On cherche d'abord dans les noms de groupe
1257         # puis dans les noms de commande groupe par groupe
1258         #
1259         for grp in self.liste_groupes:
1260             if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
1261                 cmd=self.dict_groupes[grp][0]
1262                 label=self.dico_labels[cmd]
1263                 index = self.MCbox.index(label)
1264                 self.MCbox.see(index)
1265                 self.selectitem(cmd,label,self.selection[2])
1266                 # On a trouve un groupe on arrete la recherche
1267                 return
1268
1269         for grp in self.liste_groupes:
1270            for cmd in self.dict_groupes[grp] :
1271               if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
1272                  label=self.dico_labels[cmd]
1273                  index = self.MCbox.index(label)
1274                  self.MCbox.see(index)
1275                  self.selectitem(cmd,label,self.selection[2])
1276                  # On a trouve une commande  on arrete la recherche
1277                  return
1278