]> SALOME platform Git repositories - tools/eficas.git/blob - Editeur/widgets.py
Salome HOME
CCAR: - correction divers problemes avec les blocs conditionnels et les mots
[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             label,nature,nom_var,defaut = item
547             # création de la frame
548             fr_item = Frame(window,height=40,width=700)
549             fr_item.pack(side='top',fill='x',expand=1)
550             # création du label
551             Label(fr_item,text = label).place(relx=0.05,rely=0.4)
552             if nature in ('rep','file','cata'):
553                 # création de l'entry
554                 e_item = Entry(fr_item) 
555                 e_item.place(relx=0.5,rely=0.4,relwidth=0.45)
556                 self.widgets.append(e_item)
557                 self.item_widgets[item] = e_item
558                 if defaut : e_item.insert(0,str(defaut))
559             elif nature == 'YesNo':
560                 # création de la StringVar
561                 var = StringVar()
562                 setattr(self,'item_'+nom_var,var)
563                 var.set(defaut)
564                 # création du radiobouton
565                 rb1 = Radiobutton(fr_item,text='OUI',variable=var,value='OUI')
566                 rb2 = Radiobutton(fr_item,text='NON',variable=var,value='NON')
567                 rb1.place(relx=0.65,rely=0.5,anchor='center')
568                 rb2.place(relx=0.80,rely=0.5,anchor='center')
569                 self.widgets.append((rb1,rb2))
570                 self.item_widgets[item] = var
571         # détermination de la méthode à appliquer sur les boutons
572         if self.mode == 'query':
573             function = self.active
574         elif self.mode == 'display':
575             function = self.inactive
576         else:
577             return
578         # on applique la méthode sur les boutons (activation ou désactivation)  
579         for widget in self.widgets :
580             if type(widget) == types.TupleType:
581                 for widg in widget :
582                     apply(function,(widg,),{})
583             else:
584                 apply(function,(widget,),{})
585
586     def active(self,widget):
587         """
588         Active le widget passé en argument
589         """
590         widget.configure(state='normal',bg='white')
591
592     def inactive(self,widget):
593         """
594         Inactive le widget passé en argument
595         """
596         if not isinstance(widget,Radiobutton) :
597             widget.configure(state='disabled',bg='gray95')
598         else :
599             widget.configure(state='disabled')
600
601 # --------------------------------------------------------------------------------
602 #       Validateurs des noms de répertoire, de fichiers et de catalogues
603 # -------------------------------------------------------------------------------
604
605     def repvalidator(self,text):
606         """
607         Teste si text peut faire référence à un répertoire ou non
608         Retourne 1 si valide, 0 sinon
609         """
610         return os.path.isdir(text),'Répertoire introuvable : %s' %text
611
612     def filevalidator(self,text):
613         """
614         Teste si text peut faire référence à un fichier ou non
615         Retourne 1 si valide, 0 sinon
616         """
617         return os.path.isfile(text),'Fichier introuvable : %s' %text
618
619     def catavalidator(self,text):
620         """
621         Teste si  text est un chemin d'accès valide à un catalogue
622         Retourne 1 si valide, 0 sinon
623         """
624         return os.path.isfile(text),"Catalogue introuvable : %s" %text
625
626 # --------------------------------------------------------------------------------
627 #       Méthodes callbacks des boutons et de fin
628 # --------------------------------------------------------------------------------
629         
630     def execute(self,txt):
631         """
632         Cette commande est activée à chaque clic sur un bouton.
633         Redirige l'action sur la bonne méthode en fonction du bouton activé
634         """
635         if txt == 'Valider':
636             self.fini()
637         elif txt in ('OK','Annuler'):
638             self.quit()
639         elif txt == 'Modifier':
640             self.resultat = apply(self.command[1],(),{})
641             self.fenetre.destroy()
642         else :
643             print "Nom de bouton inconnu"
644             self.quit()
645
646     def fini(self):
647         """
648         Commande qui termine le panneau et sauvegarde les nouvelles options
649         dans l'objet resultat (dictionnaire)
650         """
651         dico={}
652         for item,widget in self.item_widgets.items():
653             nom_var = item[2]
654             type_var = item[1]
655             valeur = widget.get()
656             if self.d_validateurs.has_key(type_var):
657                 test = self.d_validateurs[type_var](valeur)
658                 if not test :
659                     # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode
660                     # sans tuer la fenêtre bien sûr
661                     widget.selection_range(0,END)
662                     return
663             dico[nom_var] = valeur
664         self.fenetre.destroy()    
665         self.resultat=dico
666         
667     def quit(self):
668         self.fenetre.destroy()
669         self.resultat=None
670         
671 class ListeChoix :
672     """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre
673         en passant les commandes à lancer suivant différents bindings """
674     def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre='',
675                  optionReturn=None, fonte_titre=fontes.standard_gras_souligne):
676         self.parent = parent
677         self.page = page
678         self.liste = liste
679         self.dico_labels={}
680         self.selection = None
681         self.liste_commandes = liste_commandes
682         self.liste_marques = liste_marques
683         self.arg_selected=''
684         self.active = active
685         self.titre = titre
686         self.filtre = filtre
687         self.optionReturn = optionReturn
688         self.fonte_titre=fonte_titre
689         self.init()
690
691     def init(self):        
692         self.make_label_titre()
693         self.make_entry_filtre()
694         self.make_text_box()
695         try:
696             self.entry.component('entry').focus()
697         except:
698             pass
699
700     def make_label_titre(self):
701         """ Crée le label correspondant au titre """
702         if self.titre == '' : return
703         self.label = Label(self.page,
704                            text = self.titre,
705                            font = self.fonte_titre)
706         self.label.pack(side='top',pady=2)
707         
708     def make_entry_filtre(self):
709         """ Crée l'entry permettant à l'utilisateur d'entrer un filtre de sélection dans la liste """
710         if self.filtre != 'oui' : return
711         self.entry = Pmw.EntryField(self.page,labelpos='w',
712                                     label_text="Filtre :",
713                                     command=self.entry_changed)
714         self.entry.pack(side='top',pady=2)
715         
716     def make_text_box(self):
717         """ Crée la fenêtre texte dans laquelle sera affichée la liste """
718         self.MCbox = Text (self.page,relief='sunken',bg='gray95',bd=2)
719         self.MCscroll = Scrollbar (self.page,command = self.MCbox.yview)
720         self.MCscroll.pack(side='right',fill ='y',pady=2)
721         self.MCbox.pack(fill='y',expand=1,padx=2,pady=2)
722         self.MCbox.configure(yscrollcommand=self.MCscroll.set)
723
724
725     def affiche_liste(self):
726         """ Affiche la liste dans la fenêtre"""
727         liste_labels=[]
728         self.MCbox.config(state=NORMAL)
729         self.MCbox.delete(1.0,END)
730         for objet in self.liste :
731           if type(objet) == types.InstanceType:
732               try:
733                   mot = objet.nom
734               except:
735                   mot = str(objet)
736           elif type(objet) in (types.StringType,types.IntType):
737               mot = objet
738           elif type(objet) == types.FloatType :
739               mot = self.parent.get_valeur_texte(objet)
740               if mot == "" :
741                  mot = str(objet)
742           elif type(objet) == types.TupleType :
743               mot="("
744               premier=1
745               for val in objet:
746                  if (not premier):
747                    mot=mot+"," 
748                  else:
749                    premier=0
750                  valtexte = self.parent.get_valeur_texte(val)
751                  if valtexte != "" :
752                     mot=mot+valtexte
753                  else:
754                     mot=mot+str(val)
755               mot=mot+")"
756           else:
757               mot=`objet`
758           label = Label(self.MCbox,
759                         text = mot,
760                         fg = 'black',bg = 'gray95',justify = 'left')
761           self.dico_labels[mot]=label
762           liste_labels.append(label)
763           self.MCbox.window_create(END,
764                                    window=label,
765                                    stretch = 1)
766           self.MCbox.insert(END,'\n')
767           if self.optionReturn != None :
768               label.bind("<Return>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
769               label.bind("<KP_Enter>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
770           label.bind("<Key-Right>",lambda e,s=self,x=objet,l=label : s.selectNextItem(x,l))
771           label.bind("<Key-Left>" ,lambda e,s=self,x=objet,l=label  : s.selectPrevItem(x,l))
772           if self.active == 'oui':
773               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))
774               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))
775               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))
776
777         for marque in self.liste_marques:
778            try:
779               self.markitem(liste_labels[marque])
780            except:
781               pass
782
783         self.MCbox.config(state=DISABLED)
784         self.selection = None
785         for event,callback in self.liste_commandes:
786             if event == "<Enter>":
787                self.selection=None,None,callback
788                break
789
790     def clear_marque(self):
791         try:
792           self.dico_labels[self.arg_selected].configure(bg='gray95',fg='black')
793           self.arg_selected = ''
794         except :
795           pass
796
797     def surligne(self,marque):
798         try :
799            self.highlightitem(self.dico_labels[marque])
800            self.arg_selected = marque
801         except:
802            pass
803
804     def chooseitemsurligne(self,mot,label,commande):
805         """ Active la méthode de choix passée en argument"""
806         try:
807            mot=self.arg_selected
808            commande(mot)
809         except AsException,e:
810            raison=str(e)
811            showerror(raison.split('\n')[0],raison)
812
813     def chooseitem(self,mot,label,commande):
814         """ Active la méthode de choix passée en argument"""
815         try:
816            commande(mot)
817         except AsException,e:
818            raison=str(e)
819            showerror(raison.split('\n')[0],raison)
820         
821     def selectNextItem(self,mot,label):
822         index=self.liste.index(mot)
823         indexsuivant=index+1
824         if indexsuivant > len(self.liste) -1:
825            indexsuivant=0
826         motsuivant=self.liste[indexsuivant]
827         labelsuivant=self.dico_labels[motsuivant]
828         index = self.MCbox.index(labelsuivant)
829         self.MCbox.see(index)
830         self.selectitem(motsuivant,labelsuivant,self.selection[2],)
831            
832     def selectPrevItem(self,mot,label):
833         index=self.liste.index(mot)
834         indexprec=index-1
835         motprec=self.liste[indexprec]
836         labelprec=self.dico_labels[motprec]
837         index = self.MCbox.index(labelprec)
838         self.MCbox.see(index)
839         self.selectitem(motprec,labelprec,self.selection[2],)
840         
841     def selectitem(self,mot,label,commande) :
842         """ Met l'item sélectionné (représenté par son label) en surbrillance
843             et lance la commande associée au double-clic"""
844         self.clear_marque()
845         if self.selection != None :
846             self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
847         self.highlightitem(label)
848         self.selection = (mot,label,commande)
849         self.arg_selected = mot
850         if commande : commande(mot)
851
852     def highlightitem(self,label) :
853         """ Met l'item représenté par son label en surbrillance """
854         label.focus_set()
855         label.configure(bg='#00008b',fg='white')
856         
857     def markitem(self,label):
858         """ Met l'item (représenté par son label) en rouge """
859         label.configure(bg='gray95',fg='red')
860         
861     def deselectitem(self,label,mot='',commande=None) :
862         """ Remet l'item (représenté par son label) en noir"""
863         if label:label.configure(bg='gray95',fg='black')
864         self.arg_selected = ''
865         if commande and mot : commande(mot)
866
867     def cherche_selected_item(self):
868         index=self.MCbox.index(self.selection[1])
869         lign,col=map(int,string.split(index,'.'))
870         return lign
871
872     def remove_selected_item(self):
873         index=self.MCbox.index(self.selection[1])
874         lign,col=map(int,string.split(index,'.'))
875         del self.liste[lign-1]
876         self.affiche_liste()
877
878     def entry_changed(self,event=None):
879         """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
880         de l'entry et frappe <Return>"""
881         if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
882         filtre = self.entry.get()+"*"
883         FILTRE = string.upper(filtre)
884         for arg in self.liste :
885             if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
886                 label=self.dico_labels[arg]
887                 index = self.MCbox.index(label)
888                 self.MCbox.see(index)
889                 self.selectitem(arg,label,self.selection[2])
890                 break
891
892         #try :
893           #self.dico_labels[self.arg_selected].focus_set()
894         #except :
895           #pass
896
897
898     # PN attention à la gestion des paramétres
899     # cela retourne H = 1 , et ni H, ni 1
900     #            print repr(val)
901     #            print val.__class__.__name__
902     def get_liste(self):
903         l=[]
904         for val in self.liste:
905 #            try:
906 #                v = eval(val)
907 #               l.append(v)
908 #            except:
909                 l.append(val)
910         return l
911     
912     def put_liste(self,liste):
913         self.liste = liste
914         self.affiche_liste()
915
916 class Affichage :
917   """ Cette classe permet d'afficher au lancement d'EFICAS le message
918       d'attente et la barre de progression"""
919   def __init__(self,master,message,barre ='oui'):
920       from Tools.foztools.foztools import Slider
921       fonte=fontes.standard12_gras
922       self.master=master
923       self.frame = Frame(self.master)
924       self.frame.pack(expand=1,fill='both')
925       self.mess = Label(self.frame,text=message,justify='center',
926                         bd=2,relief='groove',font=fonte)
927       self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
928       self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
929                              fillColor='#00008b',width=200,height=30,
930                              background='white',labelColor='red')
931       if barre == 'oui':
932           self.progress.frame.pack(in_=self.frame,side='top')
933       self.master.update()
934       if barre == 'oui':
935           self.progress.frame.after(1000,self.update)
936
937   def configure(self,**options):
938       if options.has_key('message'):
939           self.mess.configure(text=options['message'])
940       if options.has_key('barre'):
941           if options['barre'] == 'oui' :
942               self.progress.frame.pack(in_=self.frame,side='top')
943           elif options['barre'] == 'non' :
944               self.progress.frame.pack_forget()
945       self.master.update_idletasks()
946       
947   def quit(self):
948       self.frame.destroy()
949       self.master.update()
950
951   def update(self,event=None):
952       """ Permet de faire avancer la barre de progression """
953       try :
954           bar=self.progress
955           bar.value = bar.value+self.increment
956           bar.update()
957           self.master.after(100,self.update)
958       except:
959           pass
960
961   def configure_barre(self,nb):
962       """ Calcule l'incrément de progression de la barre en fonction
963           du nombre d'opérations à effectuer afin que le compteur
964           soit à 100% à la fin des opérations"""
965       self.increment = 100./nb
966       self.progress.update()
967
968 class Ask_Format_Fichier :
969     """
970     Cette classe permet de créer une fenêtre Toplevel dans laquelle
971     on propose le choix du format de fichier de commandes à ouvrir
972     """
973     def __init__(self,appli):
974         self.fenetre = Toplevel()
975         self.fenetre.configure(width = 250,height=150)
976         self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
977         self.fenetre.title("Choix du format du fichier de commandes")
978         # définition des frames
979         self.frame_texte = Frame(self.fenetre)
980         self.frame_radioboutons = Frame(self.fenetre)
981         self.frame_bouton_ok = Frame(self.fenetre)
982         self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
983         self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
984         self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
985         # définition de la zone texte et du scrollbar
986         zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
987         zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
988         # définition des radioboutons
989         Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
990                     variable=appli.format_fichier,value='Aster').pack(anchor='n')
991         Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
992                     variable=appli.format_fichier,value='Python').pack(anchor='n')
993         # création du bouton OK
994         Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
995         # centrage de la fenêtre
996         centerwindow(self.fenetre)
997
998     def quit(self):
999         self.fenetre.destroy()
1000
1001 class BARRE_K2000(Toplevel):
1002     def __init__(self,master=None,text = ""):
1003         Toplevel.__init__(self,master,relief='groove')
1004         self.master.iconify()
1005         self.geometry("250x100+0+0")
1006         self.protocol("WM_DELETE_WINDOW",self.quit)
1007         # frame principale dans self (= Toplevel)
1008         self.frame = Frame(self)
1009         self.frame.place(relwidth=1,relheight=1)
1010         # frame contenant le texte à afficher 
1011         self.frame_text = Frame(self.frame)
1012         self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
1013         # frame contenant le canvas de la barre
1014         self.frame_canv = Frame(self.frame)
1015         self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
1016         # canvas dans lequel sera affichée la barre K2000
1017         self.canvas = Canvas(self.frame_canv)
1018         self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
1019         # on affiche le texte et la barre
1020         self.build_text(text)
1021         self.build_batons()
1022         #self.overrideredirect(1)
1023         # on active la barre ...
1024         self.master.after(1000,self.launch)
1025         # on centre la fenêtre
1026         centerwindow(self)
1027         self.focus()
1028
1029     def build_text(self,text):
1030         """
1031         Affichage de text dans frame_text
1032         """
1033         self.texte_var = StringVar()
1034         self.texte_var.set(text)
1035         Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
1036         
1037     def build_batons(self):
1038         """
1039         Construit la suite de bâtons dans le canvas
1040         """
1041         self.l_batons=[]
1042         self.black = -1
1043         self.sens = 'D'
1044         self.quit = 0
1045         for i in range(0,40):
1046             id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
1047             self.l_batons.append(id)
1048
1049     def launch(self):
1050         """
1051         Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
1052         """
1053         if self.quit == 1 :
1054             self.destroy()
1055             self.master.deiconify()
1056             return
1057         if self.sens == 'D':
1058             self.black = self.black+1
1059             l_bat = self.l_batons[0:self.black+1]
1060             l_bat.reverse()
1061         elif self.sens == 'G':
1062             self.black = self.black-1
1063             l_bat = self.l_batons[self.black:]
1064         i=0
1065         for bat in l_bat :
1066             num_color = 5+i*10
1067             if num_color < 10 : color = 'black'
1068             elif num_color > 90 : color = 'white'
1069             else: color = 'gray'+`num_color`
1070             self.canvas.itemconfigure(bat,fill=color)
1071             i=i+1
1072         if self.black == len(self.l_batons) :
1073             self.sens = 'G'
1074         if self.black == 0 and self.sens == 'G':self.sens = 'D'
1075         self.after(80,self.launch)
1076
1077     def update_text(self,new_text):
1078         """
1079         Remplace le texte affiché par new_text
1080         """
1081         self.texte_var.set(new_text)
1082         
1083     def quit(self):
1084         self.quit = 1        
1085
1086 class ListeChoixParGroupes(ListeChoix) :
1087     """ 
1088         Cette classe est utilisée pour afficher une liste de commandes classées par
1089         groupes. L'utilisateur peut réaliser des actions de selection
1090         qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
1091         Exemple de binding:
1092            liste_commandes = (("<Enter>",self.selectCmd),
1093                               ("<Leave>",self.deselectCmd),
1094                               ("<Double-Button-1>",self.defCmd))
1095         Il s'agit d'une liste de doublets dont le premier element est un evenement et le 
1096         deuxieme un callback a appeler sur l'evenement en question.
1097
1098     """
1099     def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
1100                       active ='oui',filtre='non',titre='',optionReturn=None,fonte_titre=fontes.standard_gras_souligne):
1101         self.parent = parent
1102         self.page = page
1103         self.liste_groupes = liste_groupes
1104         self.dict_groupes = dict_groupes
1105         self.dico_labels={}
1106         self.selection = None
1107         self.liste_commandes = liste_commandes
1108         self.liste_marques = liste_marques
1109         self.arg_selected=''
1110         self.active = active
1111         self.titre = titre
1112         self.filtre = filtre
1113         self.optionReturn = optionReturn
1114         self.fonte_titre=fonte_titre
1115         self.init()
1116
1117     def affiche_liste(self):
1118         """ Affiche la liste dans la fenêtre"""
1119         liste_labels=[]
1120         self.MCbox.config(state=NORMAL)
1121         self.MCbox.delete(1.0,END)
1122         for grp in self.liste_groupes:
1123            # On itère sur les groupes
1124            if grp == "CACHE":continue
1125            liste_commandes=self.dict_groupes[grp]
1126            text="GROUPE<<<<<<<< "+grp+" "
1127            text=text+">"*max(0,30-len(text))
1128            label = Label(self.MCbox,
1129                         text = text,
1130                         fg = 'black',bg = 'gray95',justify = 'left')
1131            # On stocke la relation entre le nom de la commande et le label
1132            self.dico_labels[grp]=label
1133            liste_labels.append(label)
1134            self.MCbox.window_create(END,
1135                                    window=label,
1136                                    stretch = 1)
1137            self.MCbox.insert(END,'\n')
1138            for cmd in liste_commandes:
1139               label = Label(self.MCbox,
1140                         text = cmd,
1141                         fg = 'black',bg = 'gray95',justify = 'left')
1142               # On stocke la relation entre le nom de la commande et le label
1143               self.dico_labels[cmd]=label
1144               self.MCbox.window_create(END,
1145                                    window=label,
1146                                    stretch = 1)
1147               self.MCbox.insert(END,'\n')
1148
1149               def null(*tp,**args): return
1150
1151               if self.active == 'oui':
1152                   # Traitement par defaut des evenements
1153                   label.bind("<Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.selectitem(x,l,c))
1154                   label.bind("<Leave>",lambda e,s=self,c=null,x=cmd,l=label: s.deselectitem(l,x,c))
1155                   label.bind("<Double-Button-1>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1156                   label.bind("<Return>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1157                   label.bind("<KP_Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1158                   label.bind("<Key-Right>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1159                   label.bind("<Key-Down>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1160                   label.bind("<Key-Left>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1161                   label.bind("<Key-Up>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1162
1163                   # Si des callbacks sont definis on les utilise
1164                   for event,callback in self.liste_commandes:
1165                       if event == "<Enter>":
1166                          label.bind("<Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.selectitem(x,l,c))
1167                       elif event == "<Leave>":
1168                          label.bind("<Leave>",lambda e,s=self,c=callback,x=cmd,l=label: s.deselectitem(l,x,c))
1169                       elif event == "<Double-Button-1>":
1170                          label.bind("<Double-Button-1>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1171                       elif event == "<Return>":
1172                          label.bind("<Return>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1173                       elif event == "<KP_Enter>":
1174                          label.bind("<KP_Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1175                       elif event == "<Key-Right>":
1176                          label.bind("<Key-Right>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1177                       elif event == "<Key-Down>":
1178                          label.bind("<Key-Down>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1179                       elif event == "<Key-Left>":
1180                          label.bind("<Key-Left>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1181                       elif event == "<Key-Up>":
1182                          label.bind("<Key-Up>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1183                       else:
1184                          label.bind(event,lambda e,s=self,c=callback,x=cmd,l=label: c())
1185
1186         for marque in self.liste_marques:
1187            try:
1188               self.markitem(liste_labels[marque])
1189            except:
1190               pass
1191
1192         self.MCbox.config(state=DISABLED)
1193         self.selection = None
1194         for event,callback in self.liste_commandes:
1195             if event == "<Enter>":
1196                self.selection=None,None,callback
1197                break
1198
1199     def selectPrevItem(self,mot,label,callback,group,cmd):
1200         g=self.liste_groupes.index(group)
1201         liste_commandes=self.dict_groupes[group]
1202         c=liste_commandes.index(cmd)
1203         if c > 0:
1204            co=liste_commandes[c-1]
1205         else:
1206            # debut de liste. On passe au groupe precedent
1207            if g > 0:
1208               gr=self.liste_groupes[g-1]
1209               co=self.dict_groupes[gr][-1]
1210            else:
1211               # debut des groupes. On ne fait rien
1212               return
1213         # On a trouve l'item precedent
1214         labelsuivant=self.dico_labels[co]
1215         index = self.MCbox.index(labelsuivant)
1216         self.MCbox.see(index)
1217         self.selectitem(co,labelsuivant,self.selection[2],)
1218
1219     def selectNextItem(self,mot,label,callback,group,cmd):
1220         g=self.liste_groupes.index(group)
1221         liste_commandes=self.dict_groupes[group]
1222         c=liste_commandes.index(cmd)
1223         try:
1224            co=liste_commandes[c+1]
1225         except:
1226            # fin de liste. On passe au groupe suivant
1227            try:
1228               gr=self.liste_groupes[g+1]
1229               co=self.dict_groupes[gr][0]
1230            except:
1231               # fin des groupes. On ne fait rien
1232               return
1233         # On a trouve l'item suivant
1234         labelsuivant=self.dico_labels[co]
1235         index = self.MCbox.index(labelsuivant)
1236         self.MCbox.see(index)
1237         self.selectitem(co,labelsuivant,self.selection[2],)
1238
1239     def entry_changed(self,event=None):
1240         """ 
1241             Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
1242             de l'entry et frappe <Return>
1243         """
1244         if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
1245
1246         filtre = self.entry.get()+"*"
1247         FILTRE = string.upper(filtre)
1248         #
1249         # On cherche d'abord dans les noms de groupe
1250         # puis dans les noms de commande groupe par groupe
1251         #
1252         for grp in self.liste_groupes:
1253             if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
1254                 cmd=self.dict_groupes[grp][0]
1255                 label=self.dico_labels[cmd]
1256                 index = self.MCbox.index(label)
1257                 self.MCbox.see(index)
1258                 self.selectitem(cmd,label,self.selection[2])
1259                 # On a trouve un groupe on arrete la recherche
1260                 return
1261
1262         for grp in self.liste_groupes:
1263            for cmd in self.dict_groupes[grp] :
1264               if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
1265                  label=self.dico_labels[cmd]
1266                  index = self.MCbox.index(label)
1267                  self.MCbox.see(index)
1268                  self.selectitem(cmd,label,self.selection[2])
1269                  # On a trouve une commande  on arrete la recherche
1270                  return
1271