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