]> SALOME platform Git repositories - tools/eficas.git/blob - Editeur/widgets.py
Salome HOME
correction navigation dans liste commandes
[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         self.dontselect=0
793         for event,callback in self.liste_commandes:
794             if event == "<Enter>":
795                self.selection=None,None,callback
796                break
797
798     def clear_marque(self):
799         try:
800           self.dico_labels[self.arg_selected].configure(bg='gray95',fg='black')
801           self.arg_selected = ''
802         except :
803           pass
804
805     def surligne(self,marque):
806         try :
807            self.highlightitem(self.dico_labels[marque])
808            self.arg_selected = marque
809         except:
810            pass
811
812     def chooseitemsurligne(self,mot,label,commande):
813         """ Active la méthode de choix passée en argument"""
814         try:
815            mot=self.arg_selected
816            commande(mot)
817         except AsException,e:
818            raison=str(e)
819            showerror(raison.split('\n')[0],raison)
820
821     def chooseitem(self,mot,label,commande):
822         """ Active la méthode de choix passée en argument"""
823         try:
824            commande(mot)
825         except AsException,e:
826            raison=str(e)
827            showerror(raison.split('\n')[0],raison)
828
829     def selectNextItem(self,mot,label):
830         index=self.liste.index(mot)
831         indexsuivant=index+1
832         if indexsuivant > len(self.liste) -1:
833            indexsuivant=0
834         motsuivant=self.liste[indexsuivant]
835         labelsuivant=self.dico_labels[motsuivant]
836         index = self.MCbox.index(labelsuivant)
837         self.MCbox.see(index)
838         self.selectthis(motsuivant,labelsuivant,self.selection[2],)
839         self.dontselect=1
840            
841     def selectPrevItem(self,mot,label):
842         index=self.liste.index(mot)
843         indexprec=index-1
844         motprec=self.liste[indexprec]
845         labelprec=self.dico_labels[motprec]
846         index = self.MCbox.index(labelprec)
847         self.MCbox.see(index)
848         self.selectthis(motprec,labelprec,self.selection[2],)
849         self.dontselect=1
850         
851     def selectthis(self,mot,label,commande) :
852         self.clear_marque()
853         if self.selection != None :
854             self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
855         self.highlightitem(label)
856         self.selection = (mot,label,commande)
857         self.arg_selected = mot
858         if commande : commande(mot)
859
860     def selectitem(self,mot,label,commande) :
861         """ Met l'item sélectionné (représenté par son label) en surbrillance
862             et lance la commande associée au double-clic"""
863         if self.dontselect:
864            self.dontselect=0
865            return
866         self.selectthis(mot,label,commande)
867
868     def highlightitem(self,label) :
869         """ Met l'item représenté par son label en surbrillance """
870         label.focus_set()
871         label.configure(bg='#00008b',fg='white')
872         
873     def markitem(self,label):
874         """ Met l'item (représenté par son label) en rouge """
875         label.configure(bg='gray95',fg='red')
876         
877     def deselectitem(self,label,mot='',commande=None) :
878         """ Remet l'item (représenté par son label) en noir"""
879         if label:label.configure(bg='gray95',fg='black')
880         self.arg_selected = ''
881         if commande and mot : commande(mot)
882
883     def cherche_selected_item(self):
884         index=self.MCbox.index(self.selection[1])
885         lign,col=map(int,string.split(index,'.'))
886         return lign
887
888     def remove_selected_item(self):
889         index=self.MCbox.index(self.selection[1])
890         lign,col=map(int,string.split(index,'.'))
891         del self.liste[lign-1]
892         self.affiche_liste()
893
894     def entry_changed(self,event=None):
895         """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
896         de l'entry et frappe <Return>"""
897         if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
898         filtre = self.entry.get()+"*"
899         FILTRE = string.upper(filtre)
900         for arg in self.liste :
901             if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
902                 label=self.dico_labels[arg]
903                 index = self.MCbox.index(label)
904                 self.MCbox.see(index)
905                 self.selectitem(arg,label,self.selection[2])
906                 break
907
908         #try :
909           #self.dico_labels[self.arg_selected].focus_set()
910         #except :
911           #pass
912
913
914     # PN attention à la gestion des paramétres
915     # cela retourne H = 1 , et ni H, ni 1
916     #            print repr(val)
917     #            print val.__class__.__name__
918     def get_liste(self):
919         l=[]
920         for val in self.liste:
921 #            try:
922 #                v = eval(val)
923 #               l.append(v)
924 #            except:
925                 l.append(val)
926         return l
927     
928     def put_liste(self,liste):
929         self.liste = liste
930         self.affiche_liste()
931
932 class Affichage :
933   """ Cette classe permet d'afficher au lancement d'EFICAS le message
934       d'attente et la barre de progression"""
935   def __init__(self,master,message,barre ='oui'):
936       from Tools.foztools.foztools import Slider
937       fonte=fontes.standard12_gras
938       self.master=master
939       self.frame = Frame(self.master)
940       self.frame.pack(expand=1,fill='both')
941       self.mess = Label(self.frame,text=message,justify='center',
942                         bd=2,relief='groove',font=fonte)
943       self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
944       self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
945                              fillColor='#00008b',width=200,height=30,
946                              background='white',labelColor='red')
947       if barre == 'oui':
948           self.progress.frame.pack(in_=self.frame,side='top')
949       self.master.update()
950       if barre == 'oui':
951           self.progress.frame.after(1000,self.update)
952
953   def configure(self,**options):
954       if options.has_key('message'):
955           self.mess.configure(text=options['message'])
956       if options.has_key('barre'):
957           if options['barre'] == 'oui' :
958               self.progress.frame.pack(in_=self.frame,side='top')
959           elif options['barre'] == 'non' :
960               self.progress.frame.pack_forget()
961       self.master.update_idletasks()
962       
963   def quit(self):
964       self.frame.destroy()
965       self.master.update()
966
967   def update(self,event=None):
968       """ Permet de faire avancer la barre de progression """
969       try :
970           bar=self.progress
971           bar.value = bar.value+self.increment
972           bar.update()
973           self.master.after(100,self.update)
974       except:
975           pass
976
977   def configure_barre(self,nb):
978       """ Calcule l'incrément de progression de la barre en fonction
979           du nombre d'opérations à effectuer afin que le compteur
980           soit à 100% à la fin des opérations"""
981       self.increment = 100./nb
982       self.progress.update()
983
984 class Ask_Format_Fichier :
985     """
986     Cette classe permet de créer une fenêtre Toplevel dans laquelle
987     on propose le choix du format de fichier de commandes à ouvrir
988     """
989     def __init__(self,appli):
990         self.fenetre = Toplevel()
991         self.fenetre.configure(width = 250,height=150)
992         self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
993         self.fenetre.title("Choix du format du fichier de commandes")
994         # définition des frames
995         self.frame_texte = Frame(self.fenetre)
996         self.frame_radioboutons = Frame(self.fenetre)
997         self.frame_bouton_ok = Frame(self.fenetre)
998         self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
999         self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
1000         self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
1001         # définition de la zone texte et du scrollbar
1002         zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
1003         zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
1004         # définition des radioboutons
1005         Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
1006                     variable=appli.format_fichier,value='Aster').pack(anchor='n')
1007         Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
1008                     variable=appli.format_fichier,value='Python').pack(anchor='n')
1009         # création du bouton OK
1010         Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
1011         # centrage de la fenêtre
1012         centerwindow(self.fenetre)
1013
1014     def quit(self):
1015         self.fenetre.destroy()
1016
1017 class BARRE_K2000(Toplevel):
1018     def __init__(self,master=None,text = ""):
1019         Toplevel.__init__(self,master,relief='groove')
1020         self.master.iconify()
1021         self.geometry("250x100+0+0")
1022         self.protocol("WM_DELETE_WINDOW",self.quit)
1023         # frame principale dans self (= Toplevel)
1024         self.frame = Frame(self)
1025         self.frame.place(relwidth=1,relheight=1)
1026         # frame contenant le texte à afficher 
1027         self.frame_text = Frame(self.frame)
1028         self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
1029         # frame contenant le canvas de la barre
1030         self.frame_canv = Frame(self.frame)
1031         self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
1032         # canvas dans lequel sera affichée la barre K2000
1033         self.canvas = Canvas(self.frame_canv)
1034         self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
1035         # on affiche le texte et la barre
1036         self.build_text(text)
1037         self.build_batons()
1038         #self.overrideredirect(1)
1039         # on active la barre ...
1040         self.master.after(1000,self.launch)
1041         # on centre la fenêtre
1042         centerwindow(self)
1043         self.focus()
1044
1045     def build_text(self,text):
1046         """
1047         Affichage de text dans frame_text
1048         """
1049         self.texte_var = StringVar()
1050         self.texte_var.set(text)
1051         Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
1052         
1053     def build_batons(self):
1054         """
1055         Construit la suite de bâtons dans le canvas
1056         """
1057         self.l_batons=[]
1058         self.black = -1
1059         self.sens = 'D'
1060         self.quit = 0
1061         for i in range(0,40):
1062             id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
1063             self.l_batons.append(id)
1064
1065     def launch(self):
1066         """
1067         Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
1068         """
1069         if self.quit == 1 :
1070             self.destroy()
1071             self.master.deiconify()
1072             return
1073         if self.sens == 'D':
1074             self.black = self.black+1
1075             l_bat = self.l_batons[0:self.black+1]
1076             l_bat.reverse()
1077         elif self.sens == 'G':
1078             self.black = self.black-1
1079             l_bat = self.l_batons[self.black:]
1080         i=0
1081         for bat in l_bat :
1082             num_color = 5+i*10
1083             if num_color < 10 : color = 'black'
1084             elif num_color > 90 : color = 'white'
1085             else: color = 'gray'+`num_color`
1086             self.canvas.itemconfigure(bat,fill=color)
1087             i=i+1
1088         if self.black == len(self.l_batons) :
1089             self.sens = 'G'
1090         if self.black == 0 and self.sens == 'G':self.sens = 'D'
1091         self.after(80,self.launch)
1092
1093     def update_text(self,new_text):
1094         """
1095         Remplace le texte affiché par new_text
1096         """
1097         self.texte_var.set(new_text)
1098         
1099     def quit(self):
1100         self.quit = 1        
1101
1102 class ListeChoixParGroupes(ListeChoix) :
1103     """ 
1104         Cette classe est utilisée pour afficher une liste de commandes classées par
1105         groupes. L'utilisateur peut réaliser des actions de selection
1106         qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
1107         Exemple de binding:
1108            liste_commandes = (("<Enter>",self.selectCmd),
1109                               ("<Leave>",self.deselectCmd),
1110                               ("<Double-Button-1>",self.defCmd))
1111         Il s'agit d'une liste de doublets dont le premier element est un evenement et le 
1112         deuxieme un callback a appeler sur l'evenement en question.
1113
1114     """
1115     def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
1116                       active ='oui',filtre='non',titre='',optionReturn=None,fonte_titre=fontes.standard_gras_souligne):
1117         self.parent = parent
1118         self.page = page
1119         self.liste_groupes = liste_groupes
1120         self.dict_groupes = dict_groupes
1121         self.dico_labels={}
1122         self.selection = None
1123         self.liste_commandes = liste_commandes
1124         self.liste_marques = liste_marques
1125         self.arg_selected=''
1126         self.active = active
1127         self.titre = titre
1128         self.filtre = filtre
1129         self.optionReturn = optionReturn
1130         self.fonte_titre=fonte_titre
1131         self.init()
1132
1133     def affiche_liste(self):
1134         """ Affiche la liste dans la fenêtre"""
1135         liste_labels=[]
1136         self.MCbox.config(state=NORMAL)
1137         self.MCbox.delete(1.0,END)
1138         for grp in self.liste_groupes:
1139            # On itère sur les groupes
1140            if grp == "CACHE":continue
1141            liste_commandes=self.dict_groupes[grp]
1142            text="GROUPE<<<<<<<< "+grp+" "
1143            text=text+">"*max(0,30-len(text))
1144            label = Label(self.MCbox,
1145                         text = text,
1146                         fg = 'black',bg = 'gray95',justify = 'left')
1147            # On stocke la relation entre le nom de la commande et le label
1148            self.dico_labels[grp]=label
1149            liste_labels.append(label)
1150            self.MCbox.window_create(END,
1151                                    window=label,
1152                                    stretch = 1)
1153            self.MCbox.insert(END,'\n')
1154            for cmd in liste_commandes:
1155               label = Label(self.MCbox,
1156                         text = cmd,
1157                         fg = 'black',bg = 'gray95',justify = 'left')
1158               # On stocke la relation entre le nom de la commande et le label
1159               self.dico_labels[cmd]=label
1160               self.MCbox.window_create(END,
1161                                    window=label,
1162                                    stretch = 1)
1163               self.MCbox.insert(END,'\n')
1164
1165               def null(*tp,**args): return
1166
1167               if self.active == 'oui':
1168                   # Traitement par defaut des evenements
1169                   label.bind("<Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.selectitem(x,l,c))
1170                   label.bind("<Leave>",lambda e,s=self,c=null,x=cmd,l=label: s.deselectitem(l,x,c))
1171                   label.bind("<Double-Button-1>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1172                   label.bind("<Return>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1173                   label.bind("<KP_Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1174                   label.bind("<Key-Right>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1175                   label.bind("<Key-Down>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1176                   label.bind("<Key-Left>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1177                   label.bind("<Key-Up>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1178
1179                   # Si des callbacks sont definis on les utilise
1180                   for event,callback in self.liste_commandes:
1181                       if event == "<Enter>":
1182                          label.bind("<Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.selectitem(x,l,c))
1183                       elif event == "<Leave>":
1184                          label.bind("<Leave>",lambda e,s=self,c=callback,x=cmd,l=label: s.deselectitem(l,x,c))
1185                       elif event == "<Double-Button-1>":
1186                          label.bind("<Double-Button-1>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1187                       elif event == "<Return>":
1188                          label.bind("<Return>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1189                       elif event == "<KP_Enter>":
1190                          label.bind("<KP_Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1191                       elif event == "<Key-Right>":
1192                          label.bind("<Key-Right>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1193                       elif event == "<Key-Down>":
1194                          label.bind("<Key-Down>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1195                       elif event == "<Key-Left>":
1196                          label.bind("<Key-Left>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1197                       elif event == "<Key-Up>":
1198                          label.bind("<Key-Up>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1199                       else:
1200                          label.bind(event,lambda e,s=self,c=callback,x=cmd,l=label: c())
1201
1202         for marque in self.liste_marques:
1203            try:
1204               self.markitem(liste_labels[marque])
1205            except:
1206               pass
1207
1208         self.MCbox.config(state=DISABLED)
1209         self.selection = None
1210         self.dontselect=0
1211         for event,callback in self.liste_commandes:
1212             if event == "<Enter>":
1213                self.selection=None,None,callback
1214                break
1215
1216     def selectPrevItem(self,mot,label,callback,group,cmd):
1217         g=self.liste_groupes.index(group)
1218         liste_commandes=self.dict_groupes[group]
1219         c=liste_commandes.index(cmd)
1220         if c > 0:
1221            co=liste_commandes[c-1]
1222         else:
1223            # debut de liste. On passe au groupe precedent
1224            if g > 0:
1225               gr=self.liste_groupes[g-1]
1226               co=self.dict_groupes[gr][-1]
1227            else:
1228               # debut des groupes. On ne fait rien
1229               return
1230         # On a trouve l'item precedent
1231         labelsuivant=self.dico_labels[co]
1232         index = self.MCbox.index(labelsuivant)
1233         self.MCbox.see(index)
1234         self.selectthis(co,labelsuivant,self.selection[2],)
1235         self.dontselect=1
1236
1237     def selectNextItem(self,mot,label,callback,group,cmd):
1238         g=self.liste_groupes.index(group)
1239         liste_commandes=self.dict_groupes[group]
1240         c=liste_commandes.index(cmd)
1241         try:
1242            co=liste_commandes[c+1]
1243         except:
1244            # fin de liste. On passe au groupe suivant
1245            try:
1246               gr=self.liste_groupes[g+1]
1247               co=self.dict_groupes[gr][0]
1248            except:
1249               # fin des groupes. On ne fait rien
1250               return
1251         # On a trouve l'item suivant
1252         labelsuivant=self.dico_labels[co]
1253         index = self.MCbox.index(labelsuivant)
1254         self.MCbox.see(index)
1255         self.selectthis(co,labelsuivant,self.selection[2],)
1256         self.dontselect=1
1257
1258     def entry_changed(self,event=None):
1259         """ 
1260             Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
1261             de l'entry et frappe <Return>
1262         """
1263         if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
1264
1265         filtre = self.entry.get()+"*"
1266         FILTRE = string.upper(filtre)
1267         #
1268         # On cherche d'abord dans les noms de groupe
1269         # puis dans les noms de commande groupe par groupe
1270         #
1271         for grp in self.liste_groupes:
1272             if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
1273                 cmd=self.dict_groupes[grp][0]
1274                 label=self.dico_labels[cmd]
1275                 index = self.MCbox.index(label)
1276                 self.MCbox.see(index)
1277                 self.selectitem(cmd,label,self.selection[2])
1278                 # On a trouve un groupe on arrete la recherche
1279                 return
1280
1281         for grp in self.liste_groupes:
1282            for cmd in self.dict_groupes[grp] :
1283               if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
1284                  label=self.dico_labels[cmd]
1285                  index = self.MCbox.index(label)
1286                  self.MCbox.see(index)
1287                  self.selectitem(cmd,label,self.selection[2])
1288                  # On a trouve une commande  on arrete la recherche
1289                  return
1290