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