Salome HOME
bcdbdc3d1b4947988f357e378d9e5fe215614a28
[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.fenetre.wait_window(self.fenetre)
89
90     def quit(self):
91         self.fenetre.destroy()
92
93     def efface_scroll(self):
94         """ Efface le scroll lorsqu'il n'est pas nécessaire : ne marche pas"""
95         self.scroll_v.pack_forget()
96         #self.scroll_h.pack_forget()
97
98     def affiche_texte(self,texte):
99         """ Affiche le texte dans la fenêtre """
100         if texte != "" :
101             self.zone_texte.insert(END,texte)
102             try:
103                 self.fenetre.update_idletasks()
104                 x0,y0,x1,y1 = self.zone_texte.bbox(END)
105                 if (y1-y0) < 300 : self.efface_scroll()
106             except:
107                 pass
108
109     def save(self):
110         """ Permet de sauvegarder le texte dans un fichier dont on a demandé le nom
111         à l'utilisateur """
112         file = asksaveasfilename(defaultextension = '.comm',
113                                #initialdir = self.appli.CONFIGURATION.rep_user,
114                                initialdir = self.appli.CONFIGURATION.initialdir,
115                                title="Sauvegarde du "+self.titre)
116         if file != '':
117             if not save_in_file(file,self.texte) :
118                 showerror("Sauvegarde impossible",
119                        "Impossible de sauvegarder le texte dans le fichier spécifié\n"+
120                           "Vérifiez les droits d'écriture")
121             else:
122                 showinfo("Sauvegarde effectuée","Sauvegarde effectuée dans le fichier %s" %file)
123
124 class FenetreDeSelection(Fenetre):
125     """ Classe dérivée de Fenêtre permettant la récupération d'une zone de texte sélectionnée.\r
126         Cette classe est utilisée pour affecter une liste de valeurs à un mot-clé.\r
127     """\r
128     def __init__(self,panel,item,appli,titre="",texte=""):\r
129         Fenetre.__init__(self,appli,titre=titre,texte=texte)\r
130         self.fenetre.configure(width = 320,height=400)\r
131         centerwindow(self.fenetre)
132         self.panel = panel
133         self.item = item
134         self.fenetre.title(titre)
135         self.but_save.configure(text="Ajouter",command=self.traite_selection)\r
136         # séparateur par défaut\r
137         self.separateur = ";"\r
138         # création de la zone de saisie du séparateur\r
139         l_separateurs_autorises = self.get_separateurs_autorises()\r
140         self.choix_sep = Pmw.ComboBox(self.frame_boutons,\r
141                                       label_text = "Séparateur :",\r
142                                       labelpos = 'w',\r
143                                       listheight = 100,\r
144                                       selectioncommand = self.choose_separateur,\r
145                                       scrolledlist_items = l_separateurs_autorises)\r
146         self.choix_sep.component('entry').configure(width=6)\r
147         self.choix_sep.place(relx=0.01,rely=0.5,anchor='w')\r
148         self.choix_sep.selectitem(self.separateur)\r
149         # Replacement\r
150         self.but_quit.place_forget()\r
151         self.but_save.place_forget()\r
152         self.but_save.place(relx=0.6,rely=0.5,anchor='center')\r
153         self.but_quit.place(relx=0.8,rely=0.5,anchor='center')\r
154 \r
155     def get_separateurs_autorises(self):\r
156         """\r
157         Retourne la liste des séparateurs autorisés\r
158         """\r
159         return ['espace',';',',']\r
160 \r
161     def choose_separateur(self,nom_sep):\r
162         """\r
163         Affecte à self.separateur le caractère séparateur correspondant à nom_sep\r
164         """\r
165         if nom_sep == 'espace' :\r
166             self.separateur = ' '\r
167         else:\r
168             self.separateur = nom_sep\r
169         \r
170     def traite_selection(self):\r
171         """ Cette méthode effectue tous les traitements nécessaires pour vérifier\r
172             et affecter la liste de valeurs à l'objet réprésenté par self.item\r
173         """\r
174         # Récupère la liste des chaines de caractères de la zone sélectionnée\r
175         message,liste = self.recupere_liste()\r
176         if self.test_probleme(message,"Sélectionnez des données") == 0:\r
177             return\r
178         # Vérifie que le nombre de données est dans les limites attendues\r
179         message = self.verif_liste(liste)\r
180         if self.test_probleme(message,"Vérifiez le nombre de données") == 0:\r
181             return\r
182         # Crée une liste de valeurs du type attendu\r
183         message,liste_valeurs = self.creation_liste_valeurs(liste)\r
184         if self.test_probleme(message,"Vérifiez le type des données") == 0:\r
185             return\r
186         # Vérifie que chaque valeur est dans le domaine exigé\r
187         message = self.verif_valeurs(liste_valeurs)\r
188         if self.test_probleme(message,"Vérifiez le domaine des valeurs") == 0:\r
189             return\r
190         # Ajoute les valeurs dans la liste de valeurs du mot-clé\r
191         self.ajouter_valeurs(liste_valeurs)\r
192         self.appli.affiche_infos("Liste de valeurs acceptée")\r
193 \r
194     def test_probleme(self, message, message_eficas):\r
195         """ Cette méthode affiche un message d'erreur si message != ''\r
196             et retourne 0, sinon retourne 1 sans rien afficher.\r
197         """\r
198         if message != "":\r
199             showinfo("Problème",message)\r
200             self.fenetre.tkraise()\r
201             self.appli.affiche_infos(message_eficas)\r
202             return 0\r
203         else:\r
204             return 1\r
205 \r
206     def recupere_liste(self):\r
207         """ Cette méthode récupère le texte de la zone sélectionnée, construit et\r
208             retourne une liste avec les chaines qui se trouvent entre les séparateurs.\r
209             S'il n'y a pas de données selectionnées, elle retourne un message d'erreur\r
210             et une liste vide.\r
211         """\r
212         message = ""\r
213         try:\r
214             selection=self.fenetre.selection_get()\r
215         except:\r
216             message = "Pas de donnée sélectionnée"\r
217             return message,None\r
218         # les retours chariots doivent être interprétés comme des séparateurs\r
219         selection = string.replace(selection,'\n',self.separateur)\r
220         # on splitte la sélection suivant le caractère séparateur\r
221         liste_chaines = string.split(selection,self.separateur)\r
222         l_chaines = []\r
223         for chaine in liste_chaines:\r
224             chaine = string.strip(chaine)\r
225             if chaine != '' : l_chaines.append(chaine)\r
226         return message,l_chaines\r
227 \r
228     def verif_liste(self, liste):\r
229         """ Cette méthode effectue des tests sur le nombre d'éléments de la liste\r
230             et retourne 1 si la liste est correcte, sinon 0 et le message d'erreur\r
231             correspondant.\r
232         """\r
233         message = ""\r
234         # nombre d'éléments sélectionnés\r
235         nombre_elements = len(liste)\r
236         # nombre d'éléments déja dans la liste du panel\r
237         nombre_in_liste = len(self.panel.Liste_valeurs.get_liste())\r
238         multiplicite = self.item.GetMultiplicite()\r
239         if (nombre_elements % multiplicite) != 0:\r
240             message = "Vous devez sélectionner "+str(multiplicite)+" * n données"\r
241             return message\r
242         nombre_valeurs = nombre_elements / multiplicite\r
243         cardinalite = self.item.GetMinMax()\r
244         if nombre_valeurs < cardinalite[0]:\r
245             message = "Vous devez sélectionner au moins "+str(cardinalite[0])+" valeurs"\r
246             return message\r
247         if cardinalite[1] != "**" and nombre_valeurs > (long(cardinalite[1])-nombre_in_liste):\r
248             message = "La liste ne peut avoir plus de "+str(cardinalite[1])+" valeurs"\r
249             return message\r
250 \r
251         return message\r
252 \r
253     def creation_liste_valeurs(self, liste):\r
254         """ Cette méthode crée et retourne une liste de valeurs du type attendu\r
255             par le mot-clé. La liste de valeurs est créée à partir de la liste\r
256             de chaines de caractères transmise.\r
257         """\r
258         type_attendu = self.item.GetType()[0]\r
259         if type_attendu == 'R':\r
260             return self.convertir(liste, f_conversion= float)\r
261         elif type_attendu == 'I':\r
262             return self.convertir(liste, f_conversion= int)\r
263         elif type_attendu == 'TXM':\r
264             return self.convertir(liste)\r
265         else:\r
266             message = "Seuls les entiers, les réels et les chaines de caractères sont convertis"\r
267             return message,None\r
268 \r
269     def convertir(self, liste, f_conversion=None):\r
270         """ Cette méthode essaie de convertir les éléments de la liste avec la\r
271             fonction f_conversion si elle existe, et retourne la liste des\r
272             éléments dans le type voulu en cas de succès, sinon retourne None.\r
273         """\r
274         liste_valeurs = []\r
275         message = ""\r
276         for chaine in liste:\r
277             if f_conversion:\r
278                 try:\r
279                     liste_valeurs.append(f_conversion(chaine))\r
280                 except:\r
281                     message = "Impossible de convertir "+chaine+" dans le type attendu"\r
282                     return message,None\r
283             else:\r
284                 liste_valeurs.append(chaine)\r
285         return message,liste_valeurs\r
286 \r
287     def verif_valeurs(self, liste_valeurs):\r
288         """ Cette méthode teste tous les éléments de la liste, et retourne 1 si chaque\r
289             élément est dans le domaine voulu.\r
290         """\r
291         message = ""\r
292         for valeur in liste_valeurs:\r
293             test = self.item.IsInIntervalle(valeur)\r
294             if test == 0:\r
295                 intervalle = str(self.item.GetIntervalle()[0])+","+str(self.item.GetIntervalle()[1])\r
296                 message = "La valeur "+str(valeur)+" n'est pas dans l'intervalle ["+intervalle+"]"\r
297                 return message\r
298         return message\r
299 \r
300     def ajouter_valeurs(self, liste_valeurs):\r
301         """ Cette méthode ajoute les nouvelles valeurs à la liste existante."""\r
302         liste = self.panel.Liste_valeurs.get_liste()\r
303         liste.extend(liste_valeurs)\r
304         self.panel.Liste_valeurs.put_liste(liste)
305
306 class Formulaire:
307     """\r
308     Cette classe permet de créer une boîte Dialog dans laquelle
309     on affiche un formulaire à remplir par l'utilisateur\r
310     """
311     def __init__(self,fen_pere,obj_pere=None,titre="",texte="",items=(),mode='query',commande=None):\r
312         if items in ((),[]) : return
313         self.items = items
314         self.titre = titre
315         self.texte = texte
316         self.fen_pere = fen_pere
317         self.obj_pere = obj_pere
318         self.mode= mode
319         self.command = commande
320         self.display()
321
322     def display(self):\r
323         self.init_validateurs()
324         self.init_fenetre()
325         self.init_texte()
326         self.init_items_formulaire()
327         self.fenetre.activate(geometry='centerscreenalways')
328 \r
329     def init_validateurs(self):\r
330         """\r
331         Crée le dictionnaire des validateurs des objets reconnus par le formulaire\r
332         """\r
333         self.d_validateurs = {}\r
334         self.d_validateurs['rep']  = self.repvalidator\r
335         self.d_validateurs['file'] = self.filevalidator\r
336         self.d_validateurs['cata']= self.catavalidator\r
337         
338     def init_fenetre(self):\r
339         """\r
340         Crée la fenêtre Dialog\r
341         """
342         if self.mode == 'query':
343             buttons=('Valider','Annuler')
344             defaultbutton = 'Valider'
345         elif self.mode == 'display':
346             if self.command :
347                 buttons=(self.command[0],'OK')
348                 defaultbutton = 'OK'
349             else:
350                 buttons=('OK')
351                 defaultbutton = 'OK'
352         self.fenetre = Pmw.Dialog(self.fen_pere,
353                                   buttons=buttons,
354                                   defaultbutton = defaultbutton,
355                                   title = self.titre,
356                                   command = self.execute)\r
357         self.fenetre.withdraw()
358         
359     def init_texte(self):\r
360         """\r
361         Crée le label qui affiche le texte à l'intérieur du panneau\r
362         """
363         fonte=fontes.standard\r
364         fr_texte = Frame(self.fenetre.interior(),height=60)\r
365         fr_texte.pack(side='top',fill='x',expand=1)
366         Label(fr_texte,text = self.texte, font=fonte).place(relx=0.5,rely=0.5,anchor='center')
367 \r
368     def init_items_formulaire(self):\r
369         """\r
370         Crée et affiche les items dans la boîte de dialogue\r
371         """\r
372         self.radiobut = 0\r
373         self.widgets = []\r
374         self.item_widgets = {}\r
375         length_maxi = 0\r
376         for item in self.items:
377             if len(item[0])>length_maxi : length_maxi = len(item[0])\r
378         window = self.fenetre.interior()\r
379         for item in self.items :\r
380             label,nature,nom_var,defaut = item\r
381             # création de la frame\r
382             fr_item = Frame(window,height=40,width=700)\r
383             fr_item.pack(side='top',fill='x',expand=1)\r
384             # création du label\r
385             Label(fr_item,text = label).place(relx=0.05,rely=0.4)\r
386             if nature in ('rep','file','cata'):
387                 # création de l'entry\r
388                 e_item = Entry(fr_item) \r
389                 e_item.place(relx=0.5,rely=0.4,relwidth=0.45)\r
390                 self.widgets.append(e_item)\r
391                 self.item_widgets[item] = e_item\r
392                 if defaut : e_item.insert(0,str(defaut))\r
393             elif nature == 'YesNo':\r
394                 # création de la StringVar\r
395                 var = StringVar()\r
396                 setattr(self,'item_'+nom_var,var)\r
397                 var.set(defaut)\r
398                 # création du radiobouton\r
399                 rb1 = Radiobutton(fr_item,text='OUI',variable=var,value='OUI')\r
400                 rb2 = Radiobutton(fr_item,text='NON',variable=var,value='NON')\r
401                 rb1.place(relx=0.65,rely=0.5,anchor='center')\r
402                 rb2.place(relx=0.80,rely=0.5,anchor='center')\r
403                 self.widgets.append((rb1,rb2))\r
404                 self.item_widgets[item] = var\r
405         # détermination de la méthode à appliquer sur les boutons\r
406         if self.mode == 'query':\r
407             function = self.active\r
408         elif self.mode == 'display':\r
409             function = self.inactive\r
410         else:\r
411             return\r
412         # on applique la méthode sur les boutons (activation ou désactivation)    \r
413         for widget in self.widgets :\r
414             if type(widget) == types.TupleType:\r
415                 for widg in widget :\r
416                     apply(function,(widg,),{})\r
417             else:\r
418                 apply(function,(widget,),{})\r
419 \r
420     def active(self,widget):\r
421         """\r
422         Active le widget passé en argument\r
423         """\r
424         widget.configure(state='normal',bg='white')\r
425 \r
426     def inactive(self,widget):\r
427         """\r
428         Inactive le widget passé en argument\r
429         """\r
430         if not isinstance(widget,Radiobutton) :\r
431             widget.configure(state='disabled',bg='gray95')\r
432         else :\r
433             widget.configure(state='disabled')\r
434 \r
435 # --------------------------------------------------------------------------------\r
436 #       Validateurs des noms de répertoire, de fichiers et de catalogues\r
437 # --------------------------------------------------------------------------------\r
438
439     def repvalidator(self,text):
440         """\r
441         Teste si text peut faire référence à un répertoire ou non\r
442         Retourne 1 si valide, 0 sinon\r
443         """\r
444         return os.path.isdir(text),'Répertoire introuvable : %s' %text
445
446     def filevalidator(self,text):
447         """\r
448         Teste si text peut faire référence à un fichier ou non\r
449         Retourne 1 si valide, 0 sinon\r
450         """\r
451         return os.path.isfile(text),'Fichier introuvable : %s' %text
452 \r
453     def catavalidator(self,text):\r
454         """\r
455         Teste si  text est un chemin d'accès valide à un catalogue\r
456         Retourne 1 si valide, 0 sinon\r
457         """\r
458         return os.path.isfile(text),"Catalogue introuvable : %s" %text\r
459 \r
460 # --------------------------------------------------------------------------------\r
461 #       Méthodes callbacks des boutons et de fin\r
462 # --------------------------------------------------------------------------------\r
463         
464     def execute(self,txt):\r
465         """\r
466         Cette commande est activée à chaque clic sur un bouton.\r
467         Redirige l'action sur la bonne méthode en fonction du bouton activé\r
468         """
469         if txt == 'Valider':
470             self.fini()
471         elif txt in ('OK','Annuler'):
472             self.quit()
473         elif txt == 'Modifier':
474             self.resultat = apply(self.command[1],(),{})
475             self.fenetre.destroy()
476         else :
477             print "Nom de bouton inconnu"
478             self.quit()
479
480     def fini(self):\r
481         """\r
482         Commande qui termine le panneau et sauvegarde les nouvelles options\r
483         dans l'objet resultat (dictionnaire)\r
484         """
485         dico={}
486         for item,widget in self.item_widgets.items():\r
487             nom_var = item[2]\r
488             type_var = item[1]
489             valeur = widget.get()\r
490             if self.d_validateurs.has_key(type_var):\r
491                 test = self.d_validateurs[type_var](valeur)\r
492                 if not test :\r
493                     # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode\r
494                     # sans tuer la fenêtre bien sûr\r
495                     widget.selection_range(0,END)\r
496                     return
497             dico[nom_var] = valeur
498         self.fenetre.destroy()    
499         self.resultat=dico\r
500         
501     def quit(self):
502         self.fenetre.destroy()
503         self.resultat=None
504         
505 class ListeChoix :
506     """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre
507         en passant les commandes à lancer suivant différents bindings """
508     def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre=''):
509         self.parent = parent
510         self.page = page
511         self.liste = liste
512         self.dico_labels={}
513         self.selection = None
514         self.liste_commandes = liste_commandes
515         self.liste_marques = liste_marques
516         self.arg_selected=''
517         self.active = active
518         self.titre = titre
519         self.filtre = filtre
520         self.init()
521
522     def init(self):        
523         self.make_label_titre()
524         self.make_entry_filtre()
525         self.make_text_box()
526         try:
527             self.entry.component('entry').focus()
528         except:
529             pass
530
531     def make_label_titre(self):
532         """ Crée le label correspondant au titre """
533         if self.titre == '' : return
534         fonte_titre = fontes.standard_gras_souligne
535         self.label = Label(self.page,
536                            text = self.titre,
537                            font = fonte_titre)
538         self.label.pack(side='top',pady=2)
539         
540     def make_entry_filtre(self):
541         """ Crée l'entry permettant à l'utilisateur d'entrer un filtre de sélection dans la liste """
542         if self.filtre != 'oui' : return
543         self.entry = Pmw.EntryField(self.page,labelpos='w',
544                                     label_text="Filtre :",
545                                     command=self.entry_changed)
546         self.entry.pack(side='top',pady=2)
547         
548     def make_text_box(self):
549         """ Crée la fenêtre texte dans laquelle sera affichée la liste """
550         self.MCbox = Text (self.page,relief='sunken',bg='gray95',bd=2)
551         self.MCscroll = Scrollbar (self.page,command = self.MCbox.yview)
552         self.MCscroll.pack(side='right',fill ='y',pady=2)
553         self.MCbox.pack(fill='y',expand=1,padx=2,pady=2)
554         self.MCbox.configure(yscrollcommand=self.MCscroll.set)
555
556     def affiche_liste(self):
557         """ Affiche la liste dans la fenêtre"""
558         i=0
559         self.MCbox.config(state=NORMAL)
560         self.MCbox.delete(1.0,END)
561         for objet in self.liste :
562           if type(objet) == types.InstanceType:
563               try:
564                   mot = objet.nom
565               except:
566                   mot = str(objet)
567           elif type(objet) in (types.StringType,types.IntType):
568               mot = objet
569           elif type(objet) == types.FloatType :
570               mot = repr_float(objet)
571           else:
572               mot=`objet`
573           label = Label(self.MCbox,
574                         text = mot,
575                         fg = 'black',bg = 'gray95',justify = 'left')
576           self.dico_labels[mot]=label
577           self.MCbox.window_create(END,
578                                    window=label,
579                                    stretch = 1)
580           self.MCbox.insert(END,'\n')
581           if self.active == 'oui':
582               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))
583               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))
584               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))
585           try :
586               self.liste_marques.index(i)
587               self.markitem(label)
588           except:
589               pass
590           i=i+1
591         self.MCbox.config(state=DISABLED)
592         self.selection = None
593
594     def chooseitem(self,mot,label,commande):
595         """ Active la méthode de choix passée en argument"""
596         commande(mot)
597         
598     def selectitem(self,mot,label,commande) :
599         """ Met l'item sélectionné (représenté par son label) en surbrillance
600             et lance la commande associée au double-clic"""
601         if self.selection != None :
602             self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
603         self.highlightitem(label)
604         self.selection = (mot,label,commande)
605         self.arg_selected = mot
606         commande(mot)
607
608     def highlightitem(self,label) :
609         """ Met l'item représenté par son label en surbrillance """
610         label.configure(bg='#00008b',fg='white')
611         
612     def markitem(self,label):
613         """ Met l'item (représenté par son label) en rouge """
614         label.configure(bg='gray95',fg='red')
615         
616     def deselectitem(self,label,mot='',commande=None) :
617         """ Remet l'item (représenté par son label) en noir"""
618         label.configure(bg='gray95',fg='black')
619         self.arg_selected = ''
620         if commande != None : commande(mot)
621
622     def entry_changed(self,event=None):
623         """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
624         de l'entry et frappe <Return>"""
625         if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
626         filtre = self.entry.get()+"*"
627         FILTRE = string.upper(filtre)
628         for arg in self.liste :
629             if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
630                 self.highlightitem(self.dico_labels[arg])
631                 index = self.MCbox.index(self.dico_labels[arg])
632                 self.MCbox.see(index)
633                 self.arg_selected = arg
634                 break
635
636     def get_liste_old(self):
637         return self.liste
638
639     def get_liste(self):
640         l=[]
641         for val in self.liste:
642             try:
643                 val = eval(val)
644                 l.append(val)
645             except:
646                 l.append(val)
647         return l
648     
649     def put_liste(self,liste):
650         self.liste = liste
651         self.affiche_liste()
652         
653 class Affichage :
654   """ Cette classe permet d'afficher au lancement d'EFICAS le message
655       d'attente et la barre de progression"""
656   def __init__(self,master,message,barre ='oui'):
657       from Tools.foztools.foztools import Slider
658       fonte=fontes.standard12_gras
659       self.master=master
660       self.frame = Frame(self.master)
661       self.frame.pack(expand=1,fill='both')
662       self.mess = Label(self.frame,text=message,justify='center',
663                         bd=2,relief='groove',font=fonte)
664       self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
665       self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
666                              fillColor='#00008b',width=200,height=30,
667                              background='white',labelColor='red')
668       if barre == 'oui':
669           self.progress.frame.pack(in_=self.frame,side='top')
670       self.master.update()
671       if barre == 'oui':
672           self.progress.frame.after(1000,self.update)
673
674   def configure(self,**options):
675       if options.has_key('message'):
676           self.mess.configure(text=options['message'])
677       if options.has_key('barre'):
678           if options['barre'] == 'oui' :
679               self.progress.frame.pack(in_=self.frame,side='top')
680           elif options['barre'] == 'non' :
681               self.progress.frame.pack_forget()
682       self.master.update_idletasks()
683       
684   def quit(self):
685       self.frame.destroy()
686       self.master.update()
687
688   def update(self,event=None):
689       """ Permet de faire avancer la barre de progression """
690       try :
691           bar=self.progress
692           bar.value = bar.value+self.increment
693           bar.update()
694           self.master.after(100,self.update)
695       except:
696           pass
697
698   def configure_barre(self,nb):
699       """ Calcule l'incrément de progression de la barre en fonction
700           du nombre d'opérations à effectuer afin que le compteur
701           soit à 100% à la fin des opérations"""
702       self.increment = 100./nb
703       self.progress.update()
704
705 class Ask_Format_Fichier :
706     """\r
707     Cette classe permet de créer une fenêtre Toplevel dans laquelle
708     on propose le choix du format de fichier de commandes à ouvrir\r
709     """
710     def __init__(self,appli):
711         self.fenetre = Toplevel()
712         self.fenetre.configure(width = 250,height=150)
713         self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
714         self.fenetre.title("Choix du format du fichier de commandes")
715         # définition des frames
716         self.frame_texte = Frame(self.fenetre)
717         self.frame_radioboutons = Frame(self.fenetre)
718         self.frame_bouton_ok = Frame(self.fenetre)
719         self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
720         self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
721         self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
722         # définition de la zone texte et du scrollbar
723         zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
724         zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
725         # définition des radioboutons
726         Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
727                     variable=appli.format_fichier,value='Aster').pack(anchor='n')
728         Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
729                     variable=appli.format_fichier,value='Python').pack(anchor='n')
730         # création du bouton OK
731         Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
732         # centrage de la fenêtre
733         centerwindow(self.fenetre)
734
735     def quit(self):
736         self.fenetre.destroy()
737
738 class BARRE_K2000(Toplevel):
739     def __init__(self,master=None,text = ""):
740         Toplevel.__init__(self,master,relief='groove')
741         self.master.iconify()
742         self.geometry("250x100+0+0")
743         self.protocol("WM_DELETE_WINDOW",self.quit)
744         # frame principale dans self (= Toplevel)
745         self.frame = Frame(self)
746         self.frame.place(relwidth=1,relheight=1)
747         # frame contenant le texte à afficher 
748         self.frame_text = Frame(self.frame)
749         self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
750         # frame contenant le canvas de la barre
751         self.frame_canv = Frame(self.frame)
752         self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
753         # canvas dans lequel sera affichée la barre K2000
754         self.canvas = Canvas(self.frame_canv)
755         self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
756         # on affiche le texte et la barre
757         self.build_text(text)
758         self.build_batons()
759         #self.overrideredirect(1)
760         # on active la barre ...
761         self.master.after(1000,self.launch)
762         # on centre la fenêtre
763         centerwindow(self)
764         self.focus()
765
766     def build_text(self,text):
767         """
768         Affichage de text dans frame_text
769         """
770         self.texte_var = StringVar()
771         self.texte_var.set(text)
772         Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
773         
774     def build_batons(self):
775         """
776         Construit la suite de bâtons dans le canvas
777         """
778         self.l_batons=[]
779         self.black = -1
780         self.sens = 'D'
781         self.quit = 0
782         for i in range(0,40):
783             id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
784             self.l_batons.append(id)
785
786     def launch(self):
787         """
788         Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
789         """
790         if self.quit == 1 :
791             self.destroy()
792             self.master.deiconify()
793             return
794         if self.sens == 'D':
795             self.black = self.black+1
796             l_bat = self.l_batons[0:self.black+1]
797             l_bat.reverse()
798         elif self.sens == 'G':
799             self.black = self.black-1
800             l_bat = self.l_batons[self.black:]
801         i=0
802         for bat in l_bat :
803             num_color = 5+i*10
804             if num_color < 10 : color = 'black'
805             elif num_color > 90 : color = 'white'
806             else: color = 'gray'+`num_color`
807             self.canvas.itemconfigure(bat,fill=color)
808             i=i+1
809         if self.black == len(self.l_batons) :
810             self.sens = 'G'
811         if self.black == 0 and self.sens == 'G':self.sens = 'D'
812         self.after(80,self.launch)
813
814     def update_text(self,new_text):
815         """
816         Remplace le texte affiché par new_text
817         """
818         self.texte_var.set(new_text)
819         
820     def quit(self):
821         self.quit = 1