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