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