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