]> SALOME platform Git repositories - tools/eficas.git/blob - Editeur/widgets.py
Salome HOME
ajout pour accepter les accents sous python 2.3
[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 class FenetreYesNo(Fenetre):
141     def __init__(self,appli,titre="",texte="",yes="Yes",no="No"):
142         self.appli=appli
143         self.fenetre = Toplevel()
144         self.fenetre.configure(width = 800,height=500)
145         self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
146         self.fenetre.title(titre)
147         self.texte = string.replace(texte,'\r\n','\n')
148         self.titre = titre
149         fonte=fontes.standardcourier10
150         # définition des frames
151         self.frame_texte = Frame(self.fenetre)
152         self.frame_boutons = Frame(self.fenetre)
153         self.frame_boutons.place(relx=0,rely=0,    relwidth=1.,relheight=0.1)
154         self.frame_texte.place(  relx=0,rely=0.1,  relwidth=1, relheight=0.9)
155         # définition de la zone texte et du scrollbar
156         self.zone_texte = Text(self.frame_texte,font=fonte)
157         self.zone_texte.bind("<Key-Prior>", self.page_up)
158         self.zone_texte.bind("<Key-Next>", self.page_down)
159         self.zone_texte.bind("<Key-Up>", self.unit_up)
160         self.zone_texte.bind("<Key-Down>", self.unit_down)
161         self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
162         #self.scroll_h = Scrollbar (self.frame_texte,command = self.zone_texte.xview)
163         self.scroll_v.pack(side='right',fill ='y')
164         #self.scroll_h.pack(side='bottom',fill ='x')
165         self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
166         self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
167         # définition des boutons
168         self.but_yes = Button(self.frame_boutons,text = yes,command=self.yes)
169         self.but_no = Button(self.frame_boutons,text = no,command = self.no)
170         self.but_yes.place(relx=0.4,rely=0.5,anchor='center')
171         self.but_no.place(relx=0.6,rely=0.5,anchor='center')
172         # affichage du texte
173         self.affiche_texte(self.texte)
174         centerwindow(self.fenetre)
175
176     def yes(self):
177         self.result=1
178         self.quit()
179
180     def no(self):
181         self.result=0
182         self.quit()
183
184 class FenetreDeSelection(Fenetre):
185     """ Classe dérivée de Fenêtre permettant la récupération d'une zone de texte sélectionnée.
186         Cette classe est utilisée pour affecter une liste de valeurs à un mot-clé.
187     """
188     def __init__(self,panel,item,appli,titre="",texte=""):
189         Fenetre.__init__(self,appli,titre=titre,texte=texte)
190         self.fenetre.configure(width = 320,height=400)
191         centerwindow(self.fenetre)
192         self.panel = panel
193         self.item = item
194         self.fenetre.title(titre)
195         self.but_save.configure(text="Ajouter",command=self.traite_selection)
196         # séparateur par défaut
197         self.separateur = ";"
198         # création de la zone de saisie du séparateur
199         l_separateurs_autorises = self.get_separateurs_autorises()
200         self.choix_sep = Pmw.ComboBox(self.frame_boutons,
201                                       label_text = "Séparateur :",
202                                       labelpos = 'w',
203                                       listheight = 100,
204                                       selectioncommand = self.choose_separateur,
205                                       scrolledlist_items = l_separateurs_autorises)
206         self.choix_sep.component('entry').configure(width=6)
207         self.choix_sep.place(relx=0.01,rely=0.5,anchor='w')
208         self.choix_sep.selectitem(self.separateur)
209         # Replacement
210         self.but_quit.place_forget()
211         self.but_save.place_forget()
212         self.but_save.place(relx=0.6,rely=0.5,anchor='center')
213         self.but_quit.place(relx=0.8,rely=0.5,anchor='center')
214
215     def get_separateurs_autorises(self):
216         """
217         Retourne la liste des séparateurs autorisés
218         """
219         return ['espace',';',',']
220
221     def choose_separateur(self,nom_sep):
222         """
223         Affecte à self.separateur le caractère séparateur correspondant à nom_sep
224         """
225         if nom_sep == 'espace' :
226             self.separateur = ' '
227         else:
228             self.separateur = nom_sep
229         
230     def traite_selection(self):
231         """ Cette méthode effectue tous les traitements nécessaires pour vérifier
232             et affecter la liste de valeurs à l'objet réprésenté par self.item
233         """
234         # Récupère la liste des chaines de caractères de la zone sélectionnée
235         message,liste = self.recupere_liste()
236         if self.test_probleme(message,"Sélectionnez des données") == 0:
237             return
238         # Vérifie que le nombre de données est dans les limites attendues
239         message = self.verif_liste(liste)
240         if self.test_probleme(message,"Vérifiez le nombre de données") == 0:
241             return
242         # Crée une liste de valeurs du type attendu
243         message,liste_valeurs = self.creation_liste_valeurs(liste)
244         if self.test_probleme(message,"Vérifiez le type des données") == 0:
245             return
246         # Vérifie que chaque valeur est dans le domaine exigé
247         message = self.verif_valeurs(liste_valeurs)
248         if self.test_probleme(message,"Vérifiez le domaine des valeurs") == 0:
249             return
250         # Ajoute les valeurs dans la liste de valeurs du mot-clé
251         self.ajouter_valeurs(liste_valeurs)
252         self.appli.affiche_infos("Liste de valeurs acceptée")
253
254     def test_probleme(self, message, message_eficas):
255         """ Cette méthode affiche un message d'erreur si message != ''
256             et retourne 0, sinon retourne 1 sans rien afficher.
257         """
258         if message != "":
259             showinfo("Problème",message)
260             self.fenetre.tkraise()
261             self.appli.affiche_infos(message_eficas)
262             return 0
263         else:
264             return 1
265
266     def recupere_liste(self):
267         """ Cette méthode récupère le texte de la zone sélectionnée, construit et
268             retourne une liste avec les chaines qui se trouvent entre les séparateurs.
269             S'il n'y a pas de données selectionnées, elle retourne un message d'erreur
270             et une liste vide.
271         """
272         message = ""
273         try:
274             selection=self.fenetre.selection_get()
275         except:
276             message = "Pas de donnée sélectionnée"
277             return message,None
278         # les retours chariots doivent être interprétés comme des séparateurs
279         selection = string.replace(selection,'\n',self.separateur)
280         # on splitte la sélection suivant le caractère séparateur
281         liste_chaines = string.split(selection,self.separateur)
282         l_chaines = []
283         for chaine in liste_chaines:
284             chaine = string.strip(chaine)
285             if chaine != '' : l_chaines.append(chaine)
286         return message,l_chaines
287
288     def verif_liste(self, liste):
289         """ Cette méthode effectue des tests sur le nombre d'éléments de la liste
290             et retourne 1 si la liste est correcte, sinon 0 et le message d'erreur
291             correspondant.
292         """
293         message = ""
294         # nombre d'éléments sélectionnés
295         nombre_elements = len(liste)
296         # nombre d'éléments déja dans la liste du panel
297         nombre_in_liste = len(self.panel.Liste_valeurs.get_liste())
298         multiplicite = self.item.GetMultiplicite()
299         if (nombre_elements % multiplicite) != 0:
300             message = "Vous devez sélectionner "+str(multiplicite)+" * n données"
301             return message
302         nombre_valeurs = nombre_elements / multiplicite
303         cardinalite = self.item.GetMinMax()
304         if nombre_valeurs < cardinalite[0]:
305             message = "Vous devez sélectionner au moins "+str(cardinalite[0])+" valeurs"
306             return message
307         if cardinalite[1] != "**" and nombre_valeurs > (long(cardinalite[1])-nombre_in_liste):
308             message = "La liste ne peut avoir plus de "+str(cardinalite[1])+" valeurs"
309             return message
310
311         return message
312
313     def creation_liste_valeurs(self, liste):
314         """ Cette méthode crée et retourne une liste de valeurs du type attendu
315             par le mot-clé. La liste de valeurs est créée à partir de la liste
316             de chaines de caractères transmise.
317         """
318         type_attendu = self.item.GetType()[0]
319         if type_attendu == 'R':
320             return self.convertir(liste, f_conversion= float)
321         elif type_attendu == 'I':
322             return self.convertir(liste, f_conversion= int)
323         elif type_attendu == 'TXM':
324             return self.convertir(liste)
325         else:
326             message = "Seuls les entiers, les réels et les chaines de caractères sont convertis"
327             return message,None
328
329     def convertir(self, liste, f_conversion=None):
330         """ Cette méthode essaie de convertir les éléments de la liste avec la
331             fonction f_conversion si elle existe, et retourne la liste des
332             éléments dans le type voulu en cas de succès, sinon retourne None.
333         """
334         liste_valeurs = []
335         message = ""
336         for chaine in liste:
337             if f_conversion:
338                 try:
339                     liste_valeurs.append(f_conversion(chaine))
340                 except:
341                     message = "Impossible de convertir "+chaine+" dans le type attendu"
342                     return message,None
343             else:
344                 liste_valeurs.append(chaine)
345         return message,liste_valeurs
346
347     def verif_valeurs(self, liste_valeurs):
348         """ Cette méthode teste tous les éléments de la liste, et retourne 1 si chaque
349             élément est dans le domaine voulu.
350         """
351         message = ""
352         for valeur in liste_valeurs:
353             test = self.item.IsInIntervalle(valeur)
354             if test == 0:
355                 intervalle = str(self.item.GetIntervalle()[0])+","+str(self.item.GetIntervalle()[1])
356                 message = "La valeur "+str(valeur)+" n'est pas dans l'intervalle ["+intervalle+"]"
357                 return message
358         return message
359
360     def ajouter_valeurs(self, liste_valeurs):
361         """ Cette méthode ajoute les nouvelles valeurs à la liste existante."""
362         liste = self.panel.Liste_valeurs.get_liste()
363         liste.extend(liste_valeurs)
364         self.panel.Liste_valeurs.put_liste(liste)
365
366 class Formulaire:
367     """
368     Cette classe permet de créer une boîte Dialog dans laquelle
369     on affiche un formulaire à remplir par l'utilisateur
370     """
371     def __init__(self,fen_pere,obj_pere=None,titre="",texte="",items=(),mode='query',commande=None):
372         if items in ((),[]) : return
373         self.items = items
374         self.titre = titre
375         self.texte = texte
376         self.fen_pere = fen_pere
377         self.obj_pere = obj_pere
378         self.mode= mode
379         self.command = commande
380         self.display()
381
382     def display(self):
383         self.init_validateurs()
384         self.init_fenetre()
385         self.init_texte()
386         self.init_items_formulaire()
387         self.fenetre.activate(geometry='centerscreenalways')
388
389     def init_validateurs(self):
390         """
391         Crée le dictionnaire des validateurs des objets reconnus par le formulaire
392         """
393         self.d_validateurs = {}
394         self.d_validateurs['rep']  = self.repvalidator
395         self.d_validateurs['file'] = self.filevalidator
396         self.d_validateurs['cata']= self.catavalidator
397         
398     def init_fenetre(self):
399         """
400         Crée la fenêtre Dialog
401         """
402         if self.mode == 'query':
403             buttons=('Valider','Annuler')
404             defaultbutton = 'Valider'
405         elif self.mode == 'display':
406             if self.command :
407                 buttons=(self.command[0],'OK')
408                 defaultbutton = 'OK'
409             else:
410                 buttons=('OK')
411                 defaultbutton = 'OK'
412         self.fenetre = Pmw.Dialog(self.fen_pere,
413                                   buttons=buttons,
414                                   defaultbutton = defaultbutton,
415                                   title = self.titre,
416                                   command = self.execute)
417         self.fenetre.withdraw()
418         
419     def init_texte(self):
420         """
421         Crée le label qui affiche le texte à l'intérieur du panneau
422         """
423         fonte=fontes.standard
424         fr_texte = Frame(self.fenetre.interior(),height=60)
425         fr_texte.pack(side='top',fill='x',expand=1)
426         Label(fr_texte,text = self.texte, font=fonte).place(relx=0.5,rely=0.5,anchor='center')
427
428     def init_items_formulaire(self):
429         """
430         Crée et affiche les items dans la boîte de dialogue
431         """
432         self.radiobut = 0
433         self.widgets = []
434         self.item_widgets = {}
435         length_maxi = 0
436         for item in self.items:
437             if len(item[0])>length_maxi : length_maxi = len(item[0])
438         window = self.fenetre.interior()
439         for item in self.items :
440             label,nature,nom_var,defaut = item
441             # création de la frame
442             fr_item = Frame(window,height=40,width=700)
443             fr_item.pack(side='top',fill='x',expand=1)
444             # création du label
445             Label(fr_item,text = label).place(relx=0.05,rely=0.4)
446             if nature in ('rep','file','cata'):
447                 # création de l'entry
448                 e_item = Entry(fr_item) 
449                 e_item.place(relx=0.5,rely=0.4,relwidth=0.45)
450                 self.widgets.append(e_item)
451                 self.item_widgets[item] = e_item
452                 if defaut : e_item.insert(0,str(defaut))
453             elif nature == 'YesNo':
454                 # création de la StringVar
455                 var = StringVar()
456                 setattr(self,'item_'+nom_var,var)
457                 var.set(defaut)
458                 # création du radiobouton
459                 rb1 = Radiobutton(fr_item,text='OUI',variable=var,value='OUI')
460                 rb2 = Radiobutton(fr_item,text='NON',variable=var,value='NON')
461                 rb1.place(relx=0.65,rely=0.5,anchor='center')
462                 rb2.place(relx=0.80,rely=0.5,anchor='center')
463                 self.widgets.append((rb1,rb2))
464                 self.item_widgets[item] = var
465         # détermination de la méthode à appliquer sur les boutons
466         if self.mode == 'query':
467             function = self.active
468         elif self.mode == 'display':
469             function = self.inactive
470         else:
471             return
472         # on applique la méthode sur les boutons (activation ou désactivation)  
473         for widget in self.widgets :
474             if type(widget) == types.TupleType:
475                 for widg in widget :
476                     apply(function,(widg,),{})
477             else:
478                 apply(function,(widget,),{})
479
480     def active(self,widget):
481         """
482         Active le widget passé en argument
483         """
484         widget.configure(state='normal',bg='white')
485
486     def inactive(self,widget):
487         """
488         Inactive le widget passé en argument
489         """
490         if not isinstance(widget,Radiobutton) :
491             widget.configure(state='disabled',bg='gray95')
492         else :
493             widget.configure(state='disabled')
494
495 # --------------------------------------------------------------------------------
496 #       Validateurs des noms de répertoire, de fichiers et de catalogues
497 # -------------------------------------------------------------------------------
498
499     def repvalidator(self,text):
500         """
501         Teste si text peut faire référence à un répertoire ou non
502         Retourne 1 si valide, 0 sinon
503         """
504         return os.path.isdir(text),'Répertoire introuvable : %s' %text
505
506     def filevalidator(self,text):
507         """
508         Teste si text peut faire référence à un fichier ou non
509         Retourne 1 si valide, 0 sinon
510         """
511         return os.path.isfile(text),'Fichier introuvable : %s' %text
512
513     def catavalidator(self,text):
514         """
515         Teste si  text est un chemin d'accès valide à un catalogue
516         Retourne 1 si valide, 0 sinon
517         """
518         return os.path.isfile(text),"Catalogue introuvable : %s" %text
519
520 # --------------------------------------------------------------------------------
521 #       Méthodes callbacks des boutons et de fin
522 # --------------------------------------------------------------------------------
523         
524     def execute(self,txt):
525         """
526         Cette commande est activée à chaque clic sur un bouton.
527         Redirige l'action sur la bonne méthode en fonction du bouton activé
528         """
529         if txt == 'Valider':
530             self.fini()
531         elif txt in ('OK','Annuler'):
532             self.quit()
533         elif txt == 'Modifier':
534             self.resultat = apply(self.command[1],(),{})
535             self.fenetre.destroy()
536         else :
537             print "Nom de bouton inconnu"
538             self.quit()
539
540     def fini(self):
541         """
542         Commande qui termine le panneau et sauvegarde les nouvelles options
543         dans l'objet resultat (dictionnaire)
544         """
545         dico={}
546         for item,widget in self.item_widgets.items():
547             nom_var = item[2]
548             type_var = item[1]
549             valeur = widget.get()
550             if self.d_validateurs.has_key(type_var):
551                 test = self.d_validateurs[type_var](valeur)
552                 if not test :
553                     # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode
554                     # sans tuer la fenêtre bien sûr
555                     widget.selection_range(0,END)
556                     return
557             dico[nom_var] = valeur
558         self.fenetre.destroy()    
559         self.resultat=dico
560         
561     def quit(self):
562         self.fenetre.destroy()
563         self.resultat=None
564         
565 class ListeChoix :
566     """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre
567         en passant les commandes à lancer suivant différents bindings """
568     def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre=''):
569         self.parent = parent
570         self.page = page
571         self.liste = liste
572         self.dico_labels={}
573         self.selection = None
574         self.liste_commandes = liste_commandes
575         self.liste_marques = liste_marques
576         self.arg_selected=''
577         self.active = active
578         self.titre = titre
579         self.filtre = filtre
580         self.init()
581
582     def init(self):        
583         self.make_label_titre()
584         self.make_entry_filtre()
585         self.make_text_box()
586         try:
587             self.entry.component('entry').focus()
588         except:
589             pass
590
591     def make_label_titre(self):
592         """ Crée le label correspondant au titre """
593         if self.titre == '' : return
594         fonte_titre = fontes.standard_gras_souligne
595         self.label = Label(self.page,
596                            text = self.titre,
597                            font = fonte_titre)
598         self.label.pack(side='top',pady=2)
599         
600     def make_entry_filtre(self):
601         """ Crée l'entry permettant à l'utilisateur d'entrer un filtre de sélection dans la liste """
602         if self.filtre != 'oui' : return
603         self.entry = Pmw.EntryField(self.page,labelpos='w',
604                                     label_text="Filtre :",
605                                     command=self.entry_changed)
606         self.entry.pack(side='top',pady=2)
607         
608     def make_text_box(self):
609         """ Crée la fenêtre texte dans laquelle sera affichée la liste """
610         self.MCbox = Text (self.page,relief='sunken',bg='gray95',bd=2)
611         self.MCscroll = Scrollbar (self.page,command = self.MCbox.yview)
612         self.MCscroll.pack(side='right',fill ='y',pady=2)
613         self.MCbox.pack(fill='y',expand=1,padx=2,pady=2)
614         self.MCbox.configure(yscrollcommand=self.MCscroll.set)
615
616     def affiche_liste(self):
617         """ Affiche la liste dans la fenêtre"""
618         liste_labels=[]
619         self.MCbox.config(state=NORMAL)
620         self.MCbox.delete(1.0,END)
621         for objet in self.liste :
622           if type(objet) == types.InstanceType:
623               try:
624                   mot = objet.nom
625               except:
626                   mot = str(objet)
627           elif type(objet) in (types.StringType,types.IntType):
628               mot = objet
629           elif type(objet) == types.FloatType :
630               #mot = repr_float(objet)
631               mot = str(objet)
632           elif type(objet) == types.TupleType :
633               mot="("
634               premier=1
635               for val in objet:
636                   if (not premier):
637                      mot=mot+"," 
638                   else:
639                      premier=0
640                   mot=mot+str(val)
641               mot=mot+")"
642           else:
643               mot=`objet`
644           label = Label(self.MCbox,
645                         text = mot,
646                         fg = 'black',bg = 'gray95',justify = 'left')
647           self.dico_labels[mot]=label
648           liste_labels.append(label)
649           self.MCbox.window_create(END,
650                                    window=label,
651                                    stretch = 1)
652           self.MCbox.insert(END,'\n')
653           if self.active == 'oui':
654               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))
655               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))
656               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))
657
658         for marque in self.liste_marques:
659            try:
660               self.markitem(liste_labels[marque])
661            except:
662               pass
663
664         self.MCbox.config(state=DISABLED)
665         self.selection = None
666
667     def chooseitem(self,mot,label,commande):
668         """ Active la méthode de choix passée en argument"""
669         try:
670            commande(mot)
671         except AsException,e:
672            raison=str(e)
673            showerror(raison.split('\n')[0],raison)
674         
675     def selectitem(self,mot,label,commande) :
676         """ Met l'item sélectionné (représenté par son label) en surbrillance
677             et lance la commande associée au double-clic"""
678         if self.selection != None :
679             self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
680         self.highlightitem(label)
681         self.selection = (mot,label,commande)
682         self.arg_selected = mot
683         commande(mot)
684
685     def highlightitem(self,label) :
686         """ Met l'item représenté par son label en surbrillance """
687         label.configure(bg='#00008b',fg='white')
688         
689     def markitem(self,label):
690         """ Met l'item (représenté par son label) en rouge """
691         label.configure(bg='gray95',fg='red')
692         
693     def deselectitem(self,label,mot='',commande=None) :
694         """ Remet l'item (représenté par son label) en noir"""
695         label.configure(bg='gray95',fg='black')
696         self.arg_selected = ''
697         if commande != None : commande(mot)
698
699     def cherche_selected_item(self):
700         index=self.MCbox.index(self.selection[1])
701         lign,col=map(int,string.split(index,'.'))
702         return lign
703
704     def remove_selected_item(self):
705         index=self.MCbox.index(self.selection[1])
706         lign,col=map(int,string.split(index,'.'))
707         del self.liste[lign-1]
708         self.affiche_liste()
709
710     def entry_changed(self,event=None):
711         """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
712         de l'entry et frappe <Return>"""
713         if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
714         filtre = self.entry.get()+"*"
715         FILTRE = string.upper(filtre)
716         for arg in self.liste :
717             if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
718                 self.highlightitem(self.dico_labels[arg])
719                 index = self.MCbox.index(self.dico_labels[arg])
720                 self.MCbox.see(index)
721                 self.arg_selected = arg
722                 break
723
724     def get_liste_old(self):
725         return self.liste
726
727     # PN attention à la gestion des paramétres
728     # cela retourne H = 1 , et ni H, ni 1
729     #            print repr(val)
730     #            print val.__class__.__name__
731     def get_liste(self):
732         l=[]
733         for val in self.liste:
734 #            try:
735 #                v = eval(val)
736 #               l.append(v)
737 #            except:
738                 l.append(val)
739         return l
740     
741     def put_liste(self,liste):
742         self.liste = liste
743         self.affiche_liste()
744         
745 class Affichage :
746   """ Cette classe permet d'afficher au lancement d'EFICAS le message
747       d'attente et la barre de progression"""
748   def __init__(self,master,message,barre ='oui'):
749       from Tools.foztools.foztools import Slider
750       fonte=fontes.standard12_gras
751       self.master=master
752       self.frame = Frame(self.master)
753       self.frame.pack(expand=1,fill='both')
754       self.mess = Label(self.frame,text=message,justify='center',
755                         bd=2,relief='groove',font=fonte)
756       self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
757       self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
758                              fillColor='#00008b',width=200,height=30,
759                              background='white',labelColor='red')
760       if barre == 'oui':
761           self.progress.frame.pack(in_=self.frame,side='top')
762       self.master.update()
763       if barre == 'oui':
764           self.progress.frame.after(1000,self.update)
765
766   def configure(self,**options):
767       if options.has_key('message'):
768           self.mess.configure(text=options['message'])
769       if options.has_key('barre'):
770           if options['barre'] == 'oui' :
771               self.progress.frame.pack(in_=self.frame,side='top')
772           elif options['barre'] == 'non' :
773               self.progress.frame.pack_forget()
774       self.master.update_idletasks()
775       
776   def quit(self):
777       self.frame.destroy()
778       self.master.update()
779
780   def update(self,event=None):
781       """ Permet de faire avancer la barre de progression """
782       try :
783           bar=self.progress
784           bar.value = bar.value+self.increment
785           bar.update()
786           self.master.after(100,self.update)
787       except:
788           pass
789
790   def configure_barre(self,nb):
791       """ Calcule l'incrément de progression de la barre en fonction
792           du nombre d'opérations à effectuer afin que le compteur
793           soit à 100% à la fin des opérations"""
794       self.increment = 100./nb
795       self.progress.update()
796
797 class Ask_Format_Fichier :
798     """
799     Cette classe permet de créer une fenêtre Toplevel dans laquelle
800     on propose le choix du format de fichier de commandes à ouvrir
801     """
802     def __init__(self,appli):
803         self.fenetre = Toplevel()
804         self.fenetre.configure(width = 250,height=150)
805         self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
806         self.fenetre.title("Choix du format du fichier de commandes")
807         # définition des frames
808         self.frame_texte = Frame(self.fenetre)
809         self.frame_radioboutons = Frame(self.fenetre)
810         self.frame_bouton_ok = Frame(self.fenetre)
811         self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
812         self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
813         self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
814         # définition de la zone texte et du scrollbar
815         zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
816         zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
817         # définition des radioboutons
818         Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
819                     variable=appli.format_fichier,value='Aster').pack(anchor='n')
820         Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
821                     variable=appli.format_fichier,value='Python').pack(anchor='n')
822         # création du bouton OK
823         Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
824         # centrage de la fenêtre
825         centerwindow(self.fenetre)
826
827     def quit(self):
828         self.fenetre.destroy()
829
830 class BARRE_K2000(Toplevel):
831     def __init__(self,master=None,text = ""):
832         Toplevel.__init__(self,master,relief='groove')
833         self.master.iconify()
834         self.geometry("250x100+0+0")
835         self.protocol("WM_DELETE_WINDOW",self.quit)
836         # frame principale dans self (= Toplevel)
837         self.frame = Frame(self)
838         self.frame.place(relwidth=1,relheight=1)
839         # frame contenant le texte à afficher 
840         self.frame_text = Frame(self.frame)
841         self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
842         # frame contenant le canvas de la barre
843         self.frame_canv = Frame(self.frame)
844         self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
845         # canvas dans lequel sera affichée la barre K2000
846         self.canvas = Canvas(self.frame_canv)
847         self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
848         # on affiche le texte et la barre
849         self.build_text(text)
850         self.build_batons()
851         #self.overrideredirect(1)
852         # on active la barre ...
853         self.master.after(1000,self.launch)
854         # on centre la fenêtre
855         centerwindow(self)
856         self.focus()
857
858     def build_text(self,text):
859         """
860         Affichage de text dans frame_text
861         """
862         self.texte_var = StringVar()
863         self.texte_var.set(text)
864         Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
865         
866     def build_batons(self):
867         """
868         Construit la suite de bâtons dans le canvas
869         """
870         self.l_batons=[]
871         self.black = -1
872         self.sens = 'D'
873         self.quit = 0
874         for i in range(0,40):
875             id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
876             self.l_batons.append(id)
877
878     def launch(self):
879         """
880         Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
881         """
882         if self.quit == 1 :
883             self.destroy()
884             self.master.deiconify()
885             return
886         if self.sens == 'D':
887             self.black = self.black+1
888             l_bat = self.l_batons[0:self.black+1]
889             l_bat.reverse()
890         elif self.sens == 'G':
891             self.black = self.black-1
892             l_bat = self.l_batons[self.black:]
893         i=0
894         for bat in l_bat :
895             num_color = 5+i*10
896             if num_color < 10 : color = 'black'
897             elif num_color > 90 : color = 'white'
898             else: color = 'gray'+`num_color`
899             self.canvas.itemconfigure(bat,fill=color)
900             i=i+1
901         if self.black == len(self.l_batons) :
902             self.sens = 'G'
903         if self.black == 0 and self.sens == 'G':self.sens = 'D'
904         self.after(80,self.launch)
905
906     def update_text(self,new_text):
907         """
908         Remplace le texte affiché par new_text
909         """
910         self.texte_var.set(new_text)
911         
912     def quit(self):
913         self.quit = 1        
914
915 class ListeChoixParGroupes(ListeChoix) :
916     """ 
917         Cette classe est utilisée pour afficher une liste de commandes classées par
918         groupes. L'utilisateur peut réaliser des actions de selection
919         qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
920     """
921     def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
922                       active ='oui',filtre='non',titre=''):
923         self.parent = parent
924         self.page = page
925         self.liste_groupes = liste_groupes
926         self.dict_groupes = dict_groupes
927         self.dico_labels={}
928         self.selection = None
929         self.liste_commandes = liste_commandes
930         self.liste_marques = liste_marques
931         self.arg_selected=''
932         self.active = active
933         self.titre = titre
934         self.filtre = filtre
935         self.init()
936
937     def affiche_liste(self):
938         """ Affiche la liste dans la fenêtre"""
939         liste_labels=[]
940         self.MCbox.config(state=NORMAL)
941         self.MCbox.delete(1.0,END)
942         for grp in self.liste_groupes:
943            # On itère sur les groupes
944            if grp == "CACHE":continue
945            liste_commandes=self.dict_groupes[grp]
946            text="GROUPE<<<<<<<< "+grp+" "
947            text=text+">"*max(0,30-len(text))
948            label = Label(self.MCbox,
949                         text = text,
950                         fg = 'black',bg = 'gray95',justify = 'left')
951            # On stocke la relation entre le nom de la commande et le label
952            self.dico_labels[grp]=label
953            liste_labels.append(label)
954            self.MCbox.window_create(END,
955                                    window=label,
956                                    stretch = 1)
957            self.MCbox.insert(END,'\n')
958            for cmd in liste_commandes:
959               label = Label(self.MCbox,
960                         text = cmd,
961                         fg = 'black',bg = 'gray95',justify = 'left')
962               # On stocke la relation entre le nom de la commande et le label
963               self.dico_labels[cmd]=label
964               self.MCbox.window_create(END,
965                                    window=label,
966                                    stretch = 1)
967               self.MCbox.insert(END,'\n')
968               if self.active == 'oui':
969                   label.bind(self.liste_commandes[0][0],
970                          lambda e,s=self,c=self.liste_commandes[0][1],x=cmd,l=label : s.selectitem(x,l,c))
971                   label.bind(self.liste_commandes[1][0],
972                          lambda e,s=self,c=self.liste_commandes[1][1],x=cmd,l=label : s.deselectitem(l,x,c))
973                   label.bind(self.liste_commandes[2][0],
974                          lambda e,s=self,c=self.liste_commandes[2][1],x=cmd,l=label : s.chooseitem(x,l,c))
975
976         for marque in self.liste_marques:
977            try:
978               self.markitem(liste_labels[marque])
979            except:
980               pass
981
982         self.MCbox.config(state=DISABLED)
983         self.selection = None
984
985     def entry_changed(self,event=None):
986         """ 
987             Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
988             de l'entry et frappe <Return>
989         """
990         if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
991         filtre = self.entry.get()+"*"
992         FILTRE = string.upper(filtre)
993         #
994         # On cherche d'abord dans les noms de groupe
995         # puis dans les noms de commande groupe par groupe
996         #
997         for grp in self.liste_groupes:
998             if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
999                 index = self.MCbox.index(self.dico_labels[grp])
1000                 self.MCbox.see(index)
1001                 # On ne selectionne pas le groupe
1002                 #self.arg_selected = grp
1003                 # On a trouve un groupe on arrete la recherche
1004                 return
1005
1006         for grp in self.liste_groupes:
1007            for cmd in self.dict_groupes[grp] :
1008               if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
1009                  self.highlightitem(self.dico_labels[cmd])
1010                  index = self.MCbox.index(self.dico_labels[cmd])
1011                  self.MCbox.see(index)
1012                  self.arg_selected = cmd
1013                  # On a trouve une commande  on arrete la recherche
1014                  return
1015