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