Salome HOME
ajout properties.py
[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               mot = str(objet)
572           else:
573               mot=`objet`
574           label = Label(self.MCbox,
575                         text = mot,
576                         fg = 'black',bg = 'gray95',justify = 'left')
577           self.dico_labels[mot]=label
578           self.MCbox.window_create(END,
579                                    window=label,
580                                    stretch = 1)
581           self.MCbox.insert(END,'\n')
582           if self.active == 'oui':
583               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))
584               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))
585               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))
586           try :
587               self.liste_marques.index(i)
588               self.markitem(label)
589           except:
590               pass
591           i=i+1
592         self.MCbox.config(state=DISABLED)
593         self.selection = None
594
595     def chooseitem(self,mot,label,commande):
596         """ Active la méthode de choix passée en argument"""
597         commande(mot)
598         
599     def selectitem(self,mot,label,commande) :
600         """ Met l'item sélectionné (représenté par son label) en surbrillance
601             et lance la commande associée au double-clic"""
602         if self.selection != None :
603             self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
604         self.highlightitem(label)
605         self.selection = (mot,label,commande)
606         self.arg_selected = mot
607         commande(mot)
608
609     def highlightitem(self,label) :
610         """ Met l'item représenté par son label en surbrillance """
611         label.configure(bg='#00008b',fg='white')
612         
613     def markitem(self,label):
614         """ Met l'item (représenté par son label) en rouge """
615         label.configure(bg='gray95',fg='red')
616         
617     def deselectitem(self,label,mot='',commande=None) :
618         """ Remet l'item (représenté par son label) en noir"""
619         label.configure(bg='gray95',fg='black')
620         self.arg_selected = ''
621         if commande != None : commande(mot)
622
623     def entry_changed(self,event=None):
624         """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
625         de l'entry et frappe <Return>"""
626         if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
627         filtre = self.entry.get()+"*"
628         FILTRE = string.upper(filtre)
629         for arg in self.liste :
630             if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
631                 self.highlightitem(self.dico_labels[arg])
632                 index = self.MCbox.index(self.dico_labels[arg])
633                 self.MCbox.see(index)
634                 self.arg_selected = arg
635                 break
636
637     def get_liste_old(self):
638         return self.liste
639
640     def get_liste(self):
641         l=[]
642         for val in self.liste:
643             try:
644                 val = eval(val)
645                 l.append(val)
646             except:
647                 l.append(val)
648         return l
649     
650     def put_liste(self,liste):
651         self.liste = liste
652         self.affiche_liste()
653         
654 class Affichage :
655   """ Cette classe permet d'afficher au lancement d'EFICAS le message
656       d'attente et la barre de progression"""
657   def __init__(self,master,message,barre ='oui'):
658       from Tools.foztools.foztools import Slider
659       fonte=fontes.standard12_gras
660       self.master=master
661       self.frame = Frame(self.master)
662       self.frame.pack(expand=1,fill='both')
663       self.mess = Label(self.frame,text=message,justify='center',
664                         bd=2,relief='groove',font=fonte)
665       self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
666       self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
667                              fillColor='#00008b',width=200,height=30,
668                              background='white',labelColor='red')
669       if barre == 'oui':
670           self.progress.frame.pack(in_=self.frame,side='top')
671       self.master.update()
672       if barre == 'oui':
673           self.progress.frame.after(1000,self.update)
674
675   def configure(self,**options):
676       if options.has_key('message'):
677           self.mess.configure(text=options['message'])
678       if options.has_key('barre'):
679           if options['barre'] == 'oui' :
680               self.progress.frame.pack(in_=self.frame,side='top')
681           elif options['barre'] == 'non' :
682               self.progress.frame.pack_forget()
683       self.master.update_idletasks()
684       
685   def quit(self):
686       self.frame.destroy()
687       self.master.update()
688
689   def update(self,event=None):
690       """ Permet de faire avancer la barre de progression """
691       try :
692           bar=self.progress
693           bar.value = bar.value+self.increment
694           bar.update()
695           self.master.after(100,self.update)
696       except:
697           pass
698
699   def configure_barre(self,nb):
700       """ Calcule l'incrément de progression de la barre en fonction
701           du nombre d'opérations à effectuer afin que le compteur
702           soit à 100% à la fin des opérations"""
703       self.increment = 100./nb
704       self.progress.update()
705
706 class Ask_Format_Fichier :
707     """\r
708     Cette classe permet de créer une fenêtre Toplevel dans laquelle
709     on propose le choix du format de fichier de commandes à ouvrir\r
710     """
711     def __init__(self,appli):
712         self.fenetre = Toplevel()
713         self.fenetre.configure(width = 250,height=150)
714         self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
715         self.fenetre.title("Choix du format du fichier de commandes")
716         # définition des frames
717         self.frame_texte = Frame(self.fenetre)
718         self.frame_radioboutons = Frame(self.fenetre)
719         self.frame_bouton_ok = Frame(self.fenetre)
720         self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
721         self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
722         self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
723         # définition de la zone texte et du scrollbar
724         zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
725         zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
726         # définition des radioboutons
727         Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
728                     variable=appli.format_fichier,value='Aster').pack(anchor='n')
729         Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
730                     variable=appli.format_fichier,value='Python').pack(anchor='n')
731         # création du bouton OK
732         Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
733         # centrage de la fenêtre
734         centerwindow(self.fenetre)
735
736     def quit(self):
737         self.fenetre.destroy()
738
739 class BARRE_K2000(Toplevel):
740     def __init__(self,master=None,text = ""):
741         Toplevel.__init__(self,master,relief='groove')
742         self.master.iconify()
743         self.geometry("250x100+0+0")
744         self.protocol("WM_DELETE_WINDOW",self.quit)
745         # frame principale dans self (= Toplevel)
746         self.frame = Frame(self)
747         self.frame.place(relwidth=1,relheight=1)
748         # frame contenant le texte à afficher 
749         self.frame_text = Frame(self.frame)
750         self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
751         # frame contenant le canvas de la barre
752         self.frame_canv = Frame(self.frame)
753         self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
754         # canvas dans lequel sera affichée la barre K2000
755         self.canvas = Canvas(self.frame_canv)
756         self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
757         # on affiche le texte et la barre
758         self.build_text(text)
759         self.build_batons()
760         #self.overrideredirect(1)
761         # on active la barre ...
762         self.master.after(1000,self.launch)
763         # on centre la fenêtre
764         centerwindow(self)
765         self.focus()
766
767     def build_text(self,text):
768         """
769         Affichage de text dans frame_text
770         """
771         self.texte_var = StringVar()
772         self.texte_var.set(text)
773         Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
774         
775     def build_batons(self):
776         """
777         Construit la suite de bâtons dans le canvas
778         """
779         self.l_batons=[]
780         self.black = -1
781         self.sens = 'D'
782         self.quit = 0
783         for i in range(0,40):
784             id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
785             self.l_batons.append(id)
786
787     def launch(self):
788         """
789         Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
790         """
791         if self.quit == 1 :
792             self.destroy()
793             self.master.deiconify()
794             return
795         if self.sens == 'D':
796             self.black = self.black+1
797             l_bat = self.l_batons[0:self.black+1]
798             l_bat.reverse()
799         elif self.sens == 'G':
800             self.black = self.black-1
801             l_bat = self.l_batons[self.black:]
802         i=0
803         for bat in l_bat :
804             num_color = 5+i*10
805             if num_color < 10 : color = 'black'
806             elif num_color > 90 : color = 'white'
807             else: color = 'gray'+`num_color`
808             self.canvas.itemconfigure(bat,fill=color)
809             i=i+1
810         if self.black == len(self.l_batons) :
811             self.sens = 'G'
812         if self.black == 0 and self.sens == 'G':self.sens = 'D'
813         self.after(80,self.launch)
814
815     def update_text(self,new_text):
816         """
817         Remplace le texte affiché par new_text
818         """
819         self.texte_var.set(new_text)
820         
821     def quit(self):
822         self.quit = 1        
823
824 class ListeChoixParGroupes(ListeChoix) :
825     """ 
826         Cette classe est utilisée pour afficher une liste de commandes classées par
827         groupes. L'utilisateur peut réaliser des actions de selection
828         qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
829     """
830     def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
831                       active ='oui',filtre='non',titre=''):
832         self.parent = parent
833         self.page = page
834         self.liste_groupes = liste_groupes
835         self.dict_groupes = dict_groupes
836         self.dico_labels={}
837         self.selection = None
838         self.liste_commandes = liste_commandes
839         self.liste_marques = liste_marques
840         self.arg_selected=''
841         self.active = active
842         self.titre = titre
843         self.filtre = filtre
844         self.init()
845
846     def affiche_liste(self):
847         """ Affiche la liste dans la fenêtre"""
848         i=0
849         self.MCbox.config(state=NORMAL)
850         self.MCbox.delete(1.0,END)
851         for grp in self.liste_groupes:
852            # On itère sur les groupes
853            if grp == "CACHE":continue
854            liste_commandes=self.dict_groupes[grp]
855            text="GROUPE<<<<<<<< "+grp+" "
856            text=text+">"*max(0,30-len(text))
857            label = Label(self.MCbox,
858                         text = text,
859                         fg = 'black',bg = 'gray95',justify = 'left')
860            # On stocke la relation entre le nom de la commande et le label
861            self.dico_labels[grp]=label
862            self.MCbox.window_create(END,
863                                    window=label,
864                                    stretch = 1)
865            self.MCbox.insert(END,'\n')
866            for cmd in liste_commandes:
867               label = Label(self.MCbox,
868                         text = cmd,
869                         fg = 'black',bg = 'gray95',justify = 'left')
870               # On stocke la relation entre le nom de la commande et le label
871               self.dico_labels[cmd]=label
872               self.MCbox.window_create(END,
873                                    window=label,
874                                    stretch = 1)
875               self.MCbox.insert(END,'\n')
876               if self.active == 'oui':
877                   label.bind(self.liste_commandes[0][0],
878                          lambda e,s=self,c=self.liste_commandes[0][1],x=cmd,l=label : s.selectitem(x,l,c))
879                   label.bind(self.liste_commandes[1][0],
880                          lambda e,s=self,c=self.liste_commandes[1][1],x=cmd,l=label : s.deselectitem(l,x,c))
881                   label.bind(self.liste_commandes[2][0],
882                          lambda e,s=self,c=self.liste_commandes[2][1],x=cmd,l=label : s.chooseitem(x,l,c))
883               # On marque les items specifies dans liste_marques
884               #if i in self.liste_marques : self.markitem(label)
885               i=i+1
886         self.MCbox.config(state=DISABLED)
887         self.selection = None
888
889     def entry_changed(self,event=None):
890         """ 
891             Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
892             de l'entry et frappe <Return>
893         """
894         if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
895         filtre = self.entry.get()+"*"
896         FILTRE = string.upper(filtre)
897         #
898         # On cherche d'abord dans les noms de groupe
899         # puis dans les noms de commande groupe par groupe
900         #
901         for grp in self.liste_groupes:
902             if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
903                 index = self.MCbox.index(self.dico_labels[grp])
904                 self.MCbox.see(index)
905                 # On ne selectionne pas le groupe
906                 #self.arg_selected = grp
907                 # On a trouve un groupe on arrete la recherche
908                 return
909
910         for grp in self.liste_groupes:
911            for cmd in self.dict_groupes[grp] :
912               if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
913                  self.highlightitem(self.dico_labels[cmd])
914                  index = self.MCbox.index(self.dico_labels[cmd])
915                  self.MCbox.see(index)
916                  self.arg_selected = cmd
917                  # On a trouve une commande  on arrete la recherche
918                  return
919