Salome HOME
ajout pour accepter les accents sous python 2.3
[tools/eficas.git] / Editeur / cataediteur.py
1 # -*- coding: utf-8 -*-
2 #            CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
9 #
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
14 #
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
18 #
19 #
20 # ======================================================================
21 # Modules Python
22 import os
23 import sys
24 import types
25 import string
26 import Pmw
27 from widgets import showinfo
28 from Tkinter import *
29
30 # Modules Eficas
31 import fontes
32 from widgets import *
33 from treewidget import Tree
34 from Objecttreeitem import TreeItem
35 from Accas import AsException
36 from Noyau.N_CR import justify_text
37
38 from Accas import ASSD,GEOM
39 import definition_cata
40
41 #
42 __version__="$Name:  $"
43 __Id__="$Id: cataediteur.py,v 1.4 2004/03/11 09:59:00 eficas Exp $"
44 #
45
46 Fonte_Niveau = fontes.canvas_gras_italique
47
48 class Panel(Frame) :
49   """ Classe servant de classe mère à toutes celles représentant les
50       panneaux à afficher en fonction de la nature de l'objet en cours
51       Elle est toujours dérivée."""
52   def __init__(self,parent,panneau,node) :
53       self.parent=parent
54       self.panneau = panneau
55       self.node=node
56       Frame.__init__(self,self.panneau)
57       self.place(x=0,y=0,relheight=1,relwidth=1)
58       #self.creer_boutons()
59       self.init()
60
61   def creer_boutons(self):
62       """ Méthode créant les boutons se trouvant dans la partie contextuelle d'EFICAS
63       (à droite sous les onglets ) """
64       self.fr_but = Frame(self,height=30)
65       self.fr_but.pack(side='bottom',fill='x')
66       self.bouton_com = Button(self.fr_but,
67                                text = 'Commentaire',
68                                command = self.ajout_commentaire,
69                                width=14)
70       self.bouton_sup = Button(self.fr_but,
71                                text = "Supprimer",
72                                command=self.supprimer,
73                                width=14)
74       self.bouton_doc = Button(self.fr_but,
75                                text="Documentation",
76                                command=self.visu_doc,
77                                width=14)
78       self.bouton_cata = Button(self.fr_but,
79                                 text = "Catalogue",
80                                 command = self.show_catalogue,
81                                 width=14)
82       if self.parent.appli.CONFIGURATION.isdeveloppeur == 'OUI':
83           self.bouton_sup.place(relx=0.25,rely = 0.5,relheight = 0.8,anchor='w')
84           self.bouton_cata.place(relx=0.5,rely = 0.5,relheight = 0.8,anchor='w')
85           self.bouton_doc.place(relx=0.75,rely = 0.5,relheight = 0.8,anchor='w')
86       else:
87           self.bouton_sup.place(relx=0.3,rely = 0.5,relheight = 0.8,anchor='w')
88           self.bouton_doc.place(relx=0.7,rely = 0.5,relheight = 0.8,anchor='w')
89
90   def show_catalogue(self):
91       try:
92           genea = self.node.item.get_genealogie()
93           self.parent.appli.browser_catalogue_objet(genea)
94       except Exception,e:
95           traceback.print_exc()
96       
97   def efface(self):
98       self.node.efface()
99       
100   def ajout_commentaire(self,ind='after'):
101       """ Ajoute un commentaire à l'intérieur du JDC, par défaut après le noeud en cours"""
102       if self.parent.modified == 'n' : self.parent.init_modif()
103       return self.node.append_brother("COMMENTAIRE",ind)
104     
105   def ajout_commentaire_first(self):
106       """ Ajoute un commentaire en début de JDC"""
107       if self.parent.modified == 'n' : self.parent.init_modif()
108       return self.node.append_child("COMMENTAIRE",'first')
109         
110   def visu_doc(self):
111       """ Permet d'ouvrir le fichier doc U de la commande au format pdf avec Acrobat Reader
112         - Ne fonctionne pas sous UNIX (chemin d'accès Acrobat Reader)
113         - indication du chemin d'accès aux fichiers pdf à revoir : trop statique"""
114       #cle_doc = self.node.item.get_docu()
115       cle_doc = self.parent.appli.get_docu(self.node)
116       if cle_doc == None : return
117       cle_doc = string.replace(cle_doc,'.','')
118       #cle_doc = string.upper(cle_doc)
119       commande = self.parent.appli.CONFIGURATION.exec_acrobat
120       #nom_fichier = cle_doc+".pdf"
121       nom_fichier = cle_doc+".doc"
122       rep_fichier = cle_doc[0:2]
123       fichier = os.path.abspath(os.path.join(self.parent.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
124       print 'commande =',commande
125       print 'fichier =',fichier
126       print 'existe =',os.path.isfile(fichier)
127       if os.name == 'nt':
128           os.spawnv(os.P_NOWAIT,commande,(commande,fichier))
129       elif os.name == 'posix':
130           script ="#!/usr/bin/sh \n%s %s" %(commande,nom_fichier)
131           pid = os.system(script)
132       
133   def supprimer(self):
134       """ Suppression du noeud courant """
135       if self.parent.modified == 'n' : self.parent.init_modif()
136       pere = self.node.parent
137       self.node.delete()
138       pere.select()
139       
140   def affiche(self):
141       """ Force l'affichage des fenêtres en cours """
142       self.tkraise()
143
144   def selectMC(self,name):
145       """ On retrouve le mot-clé sous le curseur pour affichage du fr """
146       cmd=self.node.item.get_definition()
147       texte_infos = ''
148       for e in cmd.entites.keys() :
149           if e == name :
150               texte_infos=getattr(cmd.entites[e],'fr')
151               break
152       if texte_infos == '' : texte_infos="Pas d'infos disponibles"
153       self.parent.appli.affiche_infos(texte_infos)
154
155   def defMC(self,name):
156       """ On ajoute un mot-clé à la commande : subnode """
157       if name == SEPARATEUR:return
158       if self.parent.modified == 'n' : self.parent.init_modif()
159       if name != "COMMENTAIRE":
160           self.node.append_child(name)
161       else :
162           self.ajout_commentaire()    
163
164   def selectFilsCmd(self,name):
165       pass
166           
167   def defFilsCmd(self,name):
168       pass
169     
170   def defCmdFirst(self,name):
171       """ On ajoute une commande ou un commentaire au début du fichier de commandes """
172       if name == SEPARATEUR:return
173       if self.parent.modified == 'n' : self.parent.init_modif()
174       if name != "COMMENTAIRE":
175           new_node = self.node.append_child(name,'first')
176       else :
177           new_node = self.ajout_commentaire_first()
178
179   def add_commande_avant(self,event=None):
180     pass
181
182   def add_commande_apres(self,event=None):
183     pass          
184         
185 class OngletPanel(Panel) :
186   """ Cette classe est virtuelle et doit être dérivée
187       Elle contient les principales méthodes d'affichage des différents onglets"""
188
189   def raisecmd(self,page):
190       self.nb.page(page).focus_set()
191       if page == 'Concept': self._any.focus()
192
193   def affiche(self):
194       page=self.nb.getcurselection()
195       self.nb.page(page).focus_set()
196       if page == 'Concept':self._any.component('entry').focus_set()
197       self.tkraise()
198
199   def makeConceptPage(self,page):
200       """ Crée la page de saisie du nom du concept """
201       self.label = Label(page,text='Nom du concept :')
202       self.label.place(relx=0.1,rely=0.4)
203       self._any = Entry(page,relief='sunken')
204       self._any.place(relx=0.35,rely=0.4,relwidth=0.5)
205       self._any.bind("<Return>",lambda e,s=self:s.execConcept())
206       self._any.insert(0,self.node.item.GetText())
207       type_sd = self.node.item.object.get_type_sd_prod()
208       if type_sd :
209           txt = "L'opérateur courant retourne un objet de type %s" %type_sd
210           self.label = Label(page, text = txt)
211           self.label.place(relx=0.5,rely=0.55,anchor='n')
212       self._any.focus()
213           
214   def makeCommandePage(self,page):
215       """ Affiche la page d'ajout d'une commande relativement à l'objet commande sélectionné """
216       titre = "Où voulez-vous insérer une commande par rapport à %s" %self.node.item.object.nom
217       Label(page,text=titre).place(relx=0.5,rely=0.2,anchor='w')
218       b_avant = Button(page,text='AVANT',
219                        command = self.node.item.add_commande_avant)
220       b_apres = Button(page,text='APRES',
221                        command = self.node.item.add_commande_apres)
222       b_avant.place(relx=0.35,rely=0.5,anchor='w')
223       b_apres.place(relx=0.65,rely=0.5,anchor='w')
224
225   def deselectMC(self,name):
226       self.parent.appli.affiche_infos('')
227     
228   def get_liste_cmd(self):
229       listeCmd = self.node.item.object.niveau.definition.get_liste_cmd()
230       return listeCmd
231
232   def get_liste_fils_cmd(self):
233       return ['Mot-clé simple','Mot-clé facteur','Bloc']
234
235   def makeMoclesPage(self,page):
236       frame1 = Frame(page,height = 20)
237       frame1.pack(side='top',fill='x')
238       label = Label(frame1,text ="Le mot-clé choisi sera ajouté à la fin du catalogue")
239       label.pack(side='top')
240       frame2 = Frame(page)
241       frame2.pack(side='top',fill='both',expand=1)
242       liste_cmd = self.get_liste_fils_cmd()
243       liste_commandes = (("<Enter>",self.selectFilsCmd),
244                          ("<Leave>",self.deselectFilsCmd),
245                          ("<Double-Button-1>",self.defFilsCmd))
246       Liste = ListeChoix(self,frame2,liste_cmd,liste_commandes = liste_commandes,titre = "Mots-clés")
247       Liste.affiche_liste()
248
249   def deselectFilsCmd(self,name):
250       pass
251     
252   def makeJDCPage(self,page):
253       liste_cmd = self.get_liste_cmd()
254       liste_commandes = (("<Enter>",self.selectCmd),
255                          ("<Leave>",self.deselectCmd),
256                          ("<Double-Button-1>",self.defCmdFirst))
257       Liste = ListeChoix(self,page,liste_cmd,liste_commandes = liste_commandes,filtre='oui',titre = "Commandes")
258       Liste.affiche_liste()
259
260   def makeReglesPage(self,page) :
261     regles = []
262     regles = self.node.item.get_regles()
263     dictionnaire = self.node.item.get_mc_presents()
264     texte_regles = []
265     l_regles_en_defaut=[]
266     if len(regles) > 0:
267       i = 0
268       for regle in regles :
269         texte_regles.append(regle.gettext())
270         texte,test = regle.verif(dictionnaire)
271         if test == 0 : l_regles_en_defaut.append(i)
272         i = i+1
273     Liste = ListeChoix(self,page,texte_regles,liste_marques=l_regles_en_defaut,active='non',titre="Règles")
274     Liste.affiche_liste()
275     #self.afficheListe(page,texte_regles,self.selectRegle,self.execRegle)
276
277   def execConcept(self):
278       """ Nomme le concept SD retourné par l'étape """
279       if self.parent.modified == 'n' : self.parent.init_modif()
280       nom = self._any.get()
281       # Pourquoi node.etape ???
282       #test,mess = self.node.etape.item.nomme_sd(nom)
283       test,mess = self.node.item.nomme_sd(nom)
284       self.parent.appli.affiche_infos(mess)
285       self.node.racine.update()
286   
287   def changed(self):
288       pass
289
290   def makeAttributsPage(self,page):
291     l_attributs=self.node.item.object.attributs
292     d_defauts = self.node.item.object.attributs_defauts
293     for attribut in l_attributs :
294       attr = self.node.item.object.entites_attributs.get(attribut,None)
295       if attr.valeur is d_defauts[attribut] :
296         texte = attribut+' = '+repr(attr.valeur)+' (defaut)'
297       else:
298         texte = attribut+' = '+repr(attr.valeur)
299       Label(page,text=texte).pack(side='top')
300
301   def makeSimpPage(self,page):
302     texte = "Où voulez-vous ajouter un mot-clé simple ?"
303     Label(page,text=texte).place(relx=0.5,rely=0.3,anchor='center')
304     b1 = Button(page,text='AVANT '+self.node.item.object.nom,command=self.add_simp_avant)
305     b2 = Button(page,text='APRES '+self.node.item.object.nom,command=self.add_simp_apres)
306     b1.place(relx=0.5,rely=0.5,anchor='center')
307     b2.place(relx=0.5,rely=0.6,anchor='center')
308
309   def add_simp_avant(self,event=None):
310     """
311     Ajoute un mot-clé simple avant celui courant
312     """
313     self.node.append_brother('new_simp','before')
314     self.node.update()
315
316   def add_simp_apres(self,event=None):
317     """
318     Ajoute un mot-clé simple après celui courant
319     """
320     self.node.append_brother('new_simp','after')
321     self.node.update()    
322     
323 class TYPEPanel(Frame):
324   def __init__(self,parent,panneau,node) :
325       self.parent=parent
326       self.panneau = panneau
327       self.node=node
328       Frame.__init__(self,self.panneau)
329       self.place(x=0,y=0,relheight=1,relwidth=1)
330       self.creer_texte()
331
332   def creer_texte(self):
333       texte = "Le noeud sélectionné correspond à un type\n"
334       self.label = Label(self,text=texte)
335       self.label.place(relx=0.5,rely=0.4,relwidth=0.8,anchor='center')
336
337 class OPERPanel(OngletPanel):
338   def init(self):
339     nb = Pmw.NoteBook(self,raisecommand=self.raisecmd)
340     
341     nb.pack(fill = 'both', expand = 1)
342     self.nb=nb
343     nb.add('Mocles', tab_text='Ajouter mots-clés')
344     nb.add('Commandes',tab_text='Ajouter une commande')
345     self.makeMoclesPage(nb.page("Mocles"))
346     self.makeCommandePage(nb.page("Commandes"))
347     nb.tab('Mocles').focus_set()
348     nb.setnaturalsize()
349     self.affiche()
350    
351 class SIMPPanel(OngletPanel):
352   def init(self):
353     nb = Pmw.NoteBook(self,raisecommand=self.raisecmd)
354     nb.pack(fill = 'both', expand = 1)
355     self.nb=nb
356     nb.add('generaux', tab_text='Données générales')
357     nb.add('ihm',tab_text='Données IHM')
358     nb.add('mocle',tab_text='Ajouter un mot-cle simple')
359     self.makeAttributsGenerauxPage(nb.page("generaux"))
360     self.makeAttributsIHMPage(nb.page("ihm"))
361     self.makeSimpPage(nb.page('mocle'))
362     nb.tab('generaux').focus_set()
363     nb.setnaturalsize()
364     self.affiche()
365
366   def makeAttributsGenerauxPage(self,page):
367     fr1 = Frame(page,bd=1,relief='raised')
368     fr2 = Frame(page,bd=1,relief='raised')
369     fr3 = Frame(page,bd=1,relief='raised')
370     fr4 = Frame(page,bd=1,relief='raised')
371     fr5 = Frame(page,bd=1,relief='raised')
372     fr1.place(relheight=0.14,relwidth=1,rely=0)
373     fr2.place(relheight=0.14,relwidth=1,rely=0.14)
374     fr3.place(relheight=0.29,relwidth=1,rely=0.28)
375     fr4.place(relheight=0.14,relwidth=1,rely=0.57)
376     fr5.place(relheight=0.28,relwidth=1,rely=0.71)
377     # nom du mot-clé
378     Label(fr1,text = 'Nom :').place(relx=0.05,rely=0.3,anchor='w')
379     self.e_nom = Entry(fr1)
380     self.e_nom.place(relx=0.35,rely=0.3,relwidth=0.3,anchor='w')
381     self.e_nom.bind("<Return>",lambda e,s=self : s.set_valeur_attribut('nom',None))
382     self.e_nom.insert(0,self.get_valeur_attribut('nom'))
383     # Statut
384     Label(fr1,text='Statut : ').place(relx=0.05,rely=0.7,anchor='w')
385     self.statut=StringVar()
386     valeurs_statut=[('obligatoire','o'),
387                     ('facultatif','f'),
388                     ('caché','c')
389                     ]
390     self.statut.set(self.node.item.object.get_valeur_attribut('statut'))
391     i=0
392     for text,mode in valeurs_statut:
393       b=Radiobutton(fr1,text=text,variable=self.statut,value=mode,
394                     command = lambda s=self,m=mode : s.set_valeur_attribut('statut',m))
395       b.place(relx=0.25+i*0.25,rely=0.7,anchor='w')
396       i=i+1
397     # Type ...
398     Label(fr2,text='Type de la valeur : ').place(relx=0.05,rely=0.5,anchor='w')
399     self.e_type = Entry(fr2)
400     self.e_type.place(relx=0.35,rely=0.5,relwidth=0.5,anchor='w')
401     self.e_type.insert(0,self.node.item.object.get_valeur_attribut('type'))
402     # Domaine de validité
403     Label(fr3,text='Domaine de validité : ').place(relx=0.05,rely=0.2,anchor='w')
404     self.domaine = StringVar()
405     self.domaine.set(self.node.item.object.get_valeur_attribut('domaine_validité'))
406     b1=Radiobutton(fr3,text='continu',variable=self.domaine,value='continu',
407                    command=lambda s=self,f=fr3 :s.change_domaine(f))
408     b2=Radiobutton(fr3,text='discret',variable=self.domaine,value='discret',
409                    command=lambda s=self,f=fr3 :s.change_domaine(f))
410     b1.place(relx=0.35,rely=0.2,anchor='w')
411     b2.place(relx=0.65,rely=0.2,anchor='w')
412     self.change_domaine(fr3)
413     # Défaut ...
414     if self.domaine.get() == 'continu':
415       # le développeur peut donner la valeur qu'il souhaite, moyennant la vérification de type...
416       Label(fr4,text='Valeur par défaut : ').place(relx=0.05,rely=0.5,anchor='w')
417       self.e_defaut = Entry(fr4)
418       self.e_defaut.place(relx=0.35,rely=0.5,relwidth=0.5,anchor='w')
419       if self.node.item.object.get_valeur_attribut('defaut') :
420         self.e_defaut.insert(0,self.node.item.object.get_valeur_attribut('defaut'))
421       self.e_defaut.bind("<Return>",lambda e,s=self : s.set_valeur_attribut('defaut',None))
422     else :
423       # dans le cas discret, la valeur par défaut doit être dans l'ensemble des valeurs possibles (into)
424       liste = self.node.item.object.get_valeur_attribut('into')
425       if self.node.item.object.get_valeur_attribut('defaut') :
426         self.set_valeur_attribut('defaut',self.node.item.object.get_valeur_attribut('defaut'))
427       if liste == None : liste = []
428       self.e_defaut = Pmw.OptionMenu(fr4,labelpos='w',label_text = "Valeur par défaut : ",
429                                      items = self.node.item.object.get_valeur_attribut('into'),
430                                      menubutton_width=30)
431       self.e_defaut.configure(command = lambda e,s=self : s.set_valeur_attribut('defaut',None))
432       self.e_defaut.place(relx=0.05,rely=0.5,anchor='w')
433     # Liste de valeurs ?
434     Label(fr5,text='Liste de valeurs : ').place(relx=0.05,rely=0.2,anchor='w')
435     self.liste_valeurs = BooleanVar()
436     liste_valeurs = [('OUI',1),('NON',0)]
437     self.liste_valeurs.set(0)
438     i=0
439     for text,mode in liste_valeurs:
440       b=Radiobutton(fr5,text=text,variable=self.liste_valeurs,value=mode,
441                     command=lambda s=self,f=fr5 :s.change_liste_valeurs(f))
442       b.place(relx=0.35+i*0.2,rely=0.2,anchor='w')
443       i=i+1
444     self.change_liste_valeurs(fr5)
445
446   def makeAttributsIHMPage(self,page):
447     fr1 = Frame(page,height=100,bd=1,relief='raised')
448     fr2 = Frame(page,height=50,bd=1,relief='raised')
449     fr1.pack(side='top',fill='x')
450     fr2.pack(side='top',fill='x')
451     # Champ fr ...
452     Label(fr1,text='Champ fr : ').place(relx=0.05,rely=0.35,anchor='w')
453     self.e_fr = Entry(fr1)
454     self.e_fr.place(relx=0.35,rely=0.35,relwidth=0.6,anchor='w')
455     self.e_fr.insert(0,self.node.item.object.get_valeur_attribut('fr'))
456     # Champ ang ...
457     Label(fr1,text='Champ ang : ').place(relx=0.05,rely=0.70,anchor='w')
458     self.e_ang = Entry(fr1)
459     self.e_ang.place(relx=0.35,rely=0.70,relwidth=0.6,anchor='w')
460     self.e_ang.insert(0,self.node.item.object.get_valeur_attribut('ang'))
461     # Clé documentaire ...
462     Label(fr2,text='Clé documentaire : ').place(relx=0.05,rely=0.50,anchor='w')
463     self.e_docu = Entry(fr2)
464     self.e_docu.place(relx=0.35,rely=0.50,relwidth=0.6,anchor='w')
465     self.e_docu.insert(0,self.node.item.object.get_valeur_attribut('docu'))
466     
467   def detruit_widgets(self,l_widgets):
468     for nom_widg in l_widgets :
469       try:
470         widg = getattr(self,nom_widg)
471         widg.place_forget()
472         delattr(self,nom_widg)
473       except:
474         pass
475
476   def change_liste_valeurs(self,fr5):
477     valeur = self.liste_valeurs.get()
478     if valeur == 0 :
479       # pas de liste de valeurs
480       l_widgets=['l_homo','b1_homo','b2_homo','l_min','e_min','l_max','e_max']
481       self.detruit_widgets(l_widgets)
482     elif valeur == 1:
483       # pas de widgets à détruire ...
484       if hasattr(self,'l_homo') :
485         # on est déjà en mode 'liste' --> rien à faire
486         return 
487       # homo
488       self.l_homo = Label(fr5,text='Liste homogène : ')
489       self.l_homo.place(relx=0.05,rely=0.4,anchor='w')
490       self.homo = BooleanVar()
491       self.homo.set(self.node.item.object.get_valeur_attribut('homo'))
492       self.b1_homo=Radiobutton(fr5,text='OUI',variable=self.homo,value=1)
493       self.b2_homo=Radiobutton(fr5,text='NON',variable=self.homo,value=0)
494       self.b1_homo.place(relx=0.35,rely=0.4,anchor='w')
495       self.b2_homo.place(relx=0.65,rely=0.4,anchor='w')
496       # min ...
497       self.l_min = Label(fr5,text='Longueur minimale : ')
498       self.l_min.place(relx=0.05,rely=0.6,anchor='w')
499       self.e_min = Entry(fr5)
500       self.e_min.place(relx=0.4,rely=0.6,relwidth=0.3,anchor='w')
501       self.e_min.insert(0,self.node.item.object.get_valeur_attribut('min'))
502       # max ...
503       self.l_max = Label(fr5,text='Longueur maximale : ')
504       self.l_max.place(relx=0.05,rely=0.8,anchor='w')
505       self.e_max = Entry(fr5)
506       self.e_max.place(relx=0.4,rely=0.8,relwidth=0.3,anchor='w')
507       self.e_max.insert(0,self.node.item.object.get_valeur_attribut('max'))
508       
509   def change_domaine(self,fr3):
510     valeur = self.domaine.get()
511     if valeur == 'discret' :
512       l_widgets = ['l_val_min','l_val_max','e_val_min','e_val_max']
513       self.detruit_widgets(l_widgets)
514       # into
515       #self.l_into = Label(fr3,text='Ensemble de valeurs : ')
516       #self.l_into.place(relx=0.2,rely=0.5,anchor='w')
517       self.e_into = Pmw.ScrolledListBox(fr3,
518                                         items=self.node.item.object.get_valeur_attribut('into'),
519                                         labelpos='w',
520                                         label_text= 'Ensemble de valeurs : ',
521                                         listbox_height = 3,
522                                         dblclickcommand = self.change_into)
523       self.e_into.place(relx=0.05,rely=0.6,relwidth=0.9,anchor='w')
524       #self.e_into.insert(0,self.node.item.object.get_valeur_attribut('into'))
525     elif valeur == 'continu':
526       l_widgets = ['l_into','e_into']
527       self.detruit_widgets(l_widgets)
528       if hasattr(self,'l_val_min'):
529         # on est déjà en mode 'continu' --> rien à faire
530         return
531       # val_min
532       self.l_val_min = Label(fr3,text='Valeur minimale : ')
533       self.l_val_min.place(relx=0.05,rely=0.5,anchor='w')
534       self.e_val_min = Entry(fr3)
535       self.e_val_min.place(relx=0.35,rely=0.5,relwidth=0.5,anchor='w')
536       self.e_val_min.bind("<Return>",lambda e,s=self : s.set_valeur_attribut('val_min',None))
537       self.set_valeur_attribut('val_min',self.get_valeur_attribut('val_min'))
538       # val_max
539       self.l_val_max = Label(fr3,text='Valeur maximale : ')
540       self.l_val_max.place(relx=0.05,rely=0.8,anchor='w')
541       self.e_val_max = Entry(fr3)
542       self.e_val_max.place(relx=0.35,rely=0.8,relwidth=0.5,anchor='w')
543       self.e_val_max.bind("<Return>",lambda e,s=self : s.set_valeur_attribut('val_max',None))
544       self.set_valeur_attribut('val_max',self.get_valeur_attribut('val_max'))
545
546 # ------------------------------------------------------------------
547 # Méthodes de validation des entrées faites par l'utilisateur
548 # ------------------------------------------------------------------
549
550   def get_valeur_attribut(self,nom_attr):
551     """
552     Demande à l'item de retourner la valeur de l'attribut nom_attr
553     """
554     return self.node.item.get_valeur_attribut(nom_attr)
555   
556   def set_valeur_attribut(self,nom_attr,new_valeur):
557     """
558     Affecte la valeur new_valeur à l'attribut nom_attr
559     Vérifie si celle-ci est valide, sinon restaure l'ancienne
560     """
561     if new_valeur is None :
562       widget = getattr(self,'e_'+nom_attr)
563       if hasattr(widget,'getcurselection'):
564         new_valeur = widget.getcurselection()
565       else:
566         new_valeur = widget.get()
567     print "on affecte %s a %s" %(str(new_valeur),nom_attr)
568     self.node.item.set_valeur_attribut(nom_attr,new_valeur)
569     self.node.update()
570
571   def change_into(self):
572     """
573     Méthode activée par double clic sur la ListBox d'affichage des valeurs discrètes possibles :
574     permet de changer la liste de ces valeurs
575     """
576     showinfo("Fonction non encore disponible",
577              "Vous ne pouvez pas encore modifier la liste into par cette IHM")
578     
579 class OBJECTItem(TreeItem):
580   def __init__(self,appli,labeltext,object,setfunction=None,objet_cata_ordonne = None):
581     self.appli = appli
582     self.labeltext = labeltext
583     self.object=object
584     self.setfunction = setfunction
585     self.objet_cata_ordonne = objet_cata_ordonne
586     
587   def GetLabelText(self):
588     return self.labeltext,None,None
589
590   def get_fr(self):
591     return ''
592   
593   def isMCList(self):
594     return 0
595
596   def isactif(self):
597     return 1
598
599   def add_commande_avant(self):
600     pass
601
602   def add_commande_apres(self):
603     pass
604
605   def set_valeur_attribut(self,nom_attr,new_valeur):
606     """
607     Affecte la valeur new_valeur à l'attribut nom_attr
608     Vérifie si celle-ci est valide, sinon restaure l'ancienne
609     """
610     old_valeur = self.object.get_valeur_attribut(nom_attr)
611     self.object.set_valeur_attribut(nom_attr,new_valeur)
612     verificateur = 'verif_'+nom_attr
613     if hasattr(self.object,verificateur):
614       if not getattr(self.object,verificateur)():
615         # la nouvelle valeur de nom_attr n'est pas valide : on restaure l'ancienne (sans vérification)
616         self.object.set_valeur_attribut(nom_attr,old_valeur)
617         print 'changement de valeur refuse'
618         return
619     print 'changement de valeur accepte'
620     self.object.init_modif()
621
622   def get_valeur_attribut(self,nom_attr):
623     """
624     Retourne la valeur de l'attribut nom_attr
625     """
626     return self.object.get_valeur_attribut(nom_attr)
627         
628 class CATAItem(OBJECTItem):
629   def GetSubList(self):
630     sublist=[]
631     for fils in self.object.entites_fils:
632       item = make_objecttreeitem(self.appli,fils.objet.label + " : ",fils,objet_cata_ordonne=self.objet_cata_ordonne)
633       sublist.append(item)
634     return sublist
635   
636   def GetIconName(self):
637     if self.object.isvalid():
638       return 'ast-green-square'
639     else:
640       return 'ast-red-square'
641
642   def GetText(self):
643     return "Catalogue %s" %self.appli.code
644
645   def add_commande_avant(self):
646     pass
647
648   def add_commande_apres(self):
649     pass
650
651      
652 def transforme_liste_dico(liste):
653   d={}
654   for item in liste :
655     d[item.nom]=item
656   return d
657       
658 class OPERItem(OBJECTItem):
659   panel = OPERPanel
660   def GetSubList(self):
661     sublist=[]
662     # on classe les fils dans l'ordre du catalogue ...
663     l_cles_fils = self.get_liste_mc_ordonnee()
664     # on crée les items fils ...
665     dico_fils = transforme_liste_dico(self.object.entites_fils)
666     for k in l_cles_fils :
667       typ = TYPE_COMPLET(dico_fils[k])
668       if type(self.objet_cata_ordonne) == types.InstanceType :
669         objet_cata = self.objet_cata_ordonne.entites[k]
670       else :
671         objet_cata = self.objet_cata_ordonne.get(k,None)
672       item = make_objecttreeitem(self.appli,typ + " : ",dico_fils[k],objet_cata_ordonne = objet_cata)
673       sublist.append(item)
674     return sublist
675
676   def GetText(self):
677     #return self.object.nom
678     return self.object.get_valeur_attribut('nom')
679
680   def get_liste_mc_ordonnee(self):
681     return self.objet_cata_ordonne.ordre_mc
682
683   def GetIconName(self):
684     if self.object.isvalid():
685       return 'ast-green-square'
686     else:
687       return 'ast-red-square'
688
689   def additem(self,name,pos):
690       if isinstance(name,TreeItem) :
691           cmd=self.object.addentite(name.object,pos)
692       else :
693           cmd = self.object.addentite(name,pos)
694       typ = TYPE_COMPLET(cmd)
695       item = make_objecttreeitem(self.appli,typ + " : ", cmd)
696       return item
697
698   def get_attribut(self,nom):
699     if nom == 'nature': return 'OPERATEUR'
700
701   def get_liste_mc_presents(self):
702     return []
703
704   def verif_condition_regles(self,liste):
705     return []
706   
707 class PROCItem(OPERItem):
708   panel = OPERPanel
709   
710 class MACROItem(OPERItem):
711   panel = OPERPanel
712     
713 class SIMPItem(OPERItem):
714   panel = SIMPPanel
715   
716   def GetIconName(self):
717     if self.object.isvalid():
718       return 'ast-green-ball'
719     else:
720       return 'ast-red-ball'
721
722   def IsExpandable(self):
723     return 0
724
725   def GetSubList(self):
726     return []
727   
728 class FACTItem(OPERItem):
729   def GetIconName(self):
730     if self.object.isvalid():
731       return 'ast-green-los'
732     else:
733       return 'ast-red-los'
734
735 class BLOCItem(FACTItem): pass
736
737 class TYPEItem(SIMPItem):
738   panel = TYPEPanel
739   def get_dico_attributs(self):
740     self.d_attributs = {}
741
742   def GetSubList(self):
743     return []
744
745   def IsExpandable(self):
746     return 0
747
748   def GetText(self):
749     return self.object.nom
750
751 class NIVEAUItem(OPERItem):
752   def IsExpandable(self):
753       return 1
754
755   def get_liste_mc_ordonnee(self):
756     l=[]
757     for fils in self.object.entites_fils:
758       l.append(fils.nom)
759     return l
760   
761   def GetSubList(self):
762     sublist=[]
763     # on classe les fils dans l'ordre du catalogue ...
764     l_cles_fils = self.get_liste_mc_ordonnee()
765     # on crꥠles items fils ...
766     dico_fils = transforme_liste_dico(self.object.entites_fils)
767     for k in l_cles_fils :
768       typ = TYPE_COMPLET(dico_fils[k])
769       if type(self.objet_cata_ordonne) == types.InstanceType :
770         objet_cata = self.objet_cata_ordonne.entites[k]
771       else :
772         objet_cata = self.objet_cata_ordonne.get(k,None)
773       item = make_objecttreeitem(self.appli,typ + " : ",dico_fils[k],objet_cata_ordonne = objet_cata)
774       sublist.append(item)
775     return sublist
776   
777   def GetLabelText(self):
778       """ Retourne 3 valeurs :
779         - le texte à afficher dans le noeud représentant l'item
780         - la fonte dans laquelle afficher ce texte
781         - la couleur du texte
782       """
783       return self.labeltext,Fonte_Niveau,'#00008b'
784     
785   def GetIconName(self):
786     if self.object.isvalid():
787       return "ast-green-text"
788     else:
789       return 'ast-red-text'
790
791   def additem(self,name,pos):
792       if isinstance(name,TreeItem) :
793           cmd=self.object.addentite(name.object,pos)
794       else :
795           cmd = self.object.addentite(name,pos)
796       typ = TYPE_COMPLET(obj)
797       item = make_objecttreeitem(self.appli,typ+ " : ", cmd)
798       return item
799
800   def suppitem(self,item) :
801     # item = item de l'ETAPE à supprimer du JDC
802     # item.object = ETAPE ou _C
803     # self.object = JDC
804     self.object.suppentite(item.object)
805     if isinstance(item.object,_C):
806         message = "Commentaire supprimé"
807         self.appli.affiche_infos(message)
808     else :
809         message = "Commande " + item.object.nom + " supprimée"
810         self.appli.affiche_infos(message)
811     return 1
812
813   def GetText(self):
814       return ''
815     
816 class ATTRIBUTItem(SIMPItem):
817   def get_dico_attributs(self):
818     self.d_attributs = {}
819
820   def GetSubList(self):
821     return []
822
823   def IsExpandable(self):
824     return 0
825
826   def GetText(self):
827     return self.object
828
829   def GetIconName(self):
830     return 'aucune' 
831
832 class CataEditeur:
833   def __init__(self,parent,appli,cata):
834     self.parent = parent
835     self.cata = definition_cata.CATALOGUE(cata)
836     self.appli = appli
837     self.top = Toplevel()
838     self.top.geometry("800x500")
839     self.top.title("Edition d'un catalogue")
840     self.init()
841
842   def close(self):
843     self.top.destroy()
844
845   def init(self):
846     self.nodes={}
847     self.creerbarremenus()
848     self.pane = Pmw.PanedWidget(self.top,
849                                 hull_width = 800,
850                                 hull_height = 500,
851                                 orient = 'horizontal')
852     self.pane.add('canvas',min = 0.4, max = 0.6, size = 0.5)
853     self.pane.add('panel',min = 0.4, max = 0.6, size = 0.5)
854     self.pane.pack(expand =1, fill = 'both')
855     self.scrolledcanvas = Pmw.ScrolledCanvas(self.pane.pane('canvas'),
856                                              hull_width=1.,
857                                              hull_height=1.,
858                                              borderframe=1)
859     Pmw.Color.changecolor(self.scrolledcanvas.component('canvas'),background='gray95')
860     self.scrolledcanvas.pack(padx=10,pady=10,expand=1, fill="both")
861     self.item = CATAItem(self.appli,"Catalogue",
862                            self.cata,
863                           objet_cata_ordonne = self.appli.readercata.cata_ordonne_dico)
864
865     self.tree = Tree(self.appli,self.item,self.scrolledcanvas,command = self.select_node)
866     self.tree.draw()
867     self.node = self.tree.node_selected
868
869   def creerbarremenus(self) :
870       self.menubar=Menu(self.top)
871       self.filemenu=Menu(self.menubar,tearoff=0)
872       self.filemenu.add_command(label='Quitter',command=self.quit)
873
874       self.editmenu=Menu(self.menubar,tearoff=0)
875       #self.editmenu.add_command(label='Copier',command=self.copy)
876       #self.editmenu.add_command(label='Couper',command=self.cut)
877       #self.editmenu.add_command(label='Coller',command=self.paste)
878
879       self.affichagemenu=Menu(self.menubar,tearoff=0)
880       self.affichagemenu.add_command(label='Rapport de validation',
881                                      command = self.visuCR)
882       self.affichagemenu.add_command(label='shell',command = self.shell)
883       #self.affichagemenu.add_command(label='Fichier ࡰlat',command=self.visu_a_plat)
884       #self.affichagemenu.add_command(label='Fichier .py',command =self.visuJDC_py)
885       #self.affichagemenu.add_command(label='Fichier source',command = self.visu_txt_brut_JDC)
886       #self.affichagemenu.add_command(label='Param鵲es Eficas',command=self.affichage_fichier_ini)
887       
888       #self.optionmenu=Menu(self.menubar,tearoff=0)
889       #self.optionmenu.add_command(label='Catalogue d귥loppeur',command=self.choix_cata_developpeur)
890
891       self.menubar.add_cascade(label='Fichier',menu=self.filemenu)
892       self.menubar.add_cascade(label='Edition',menu=self.editmenu)
893       self.menubar.add_cascade(label='Jeu de commandes',menu=self.affichagemenu)
894       #self.menubar.add_cascade(label='Browsers',menu=self.browsermenu)
895       #self.menubar.add_cascade(label='Catalogue',menu=self.cataloguemenu)
896       #self.menubar.add_cascade(label='Options',menu=self.optionmenu)
897       self.top.configure(menu=self.menubar)
898       self.top.protocol("WM_DELETE_WINDOW",self.quit)
899       self.top.minsize(900,500)
900       self.top.geometry("900x500")
901
902   def shell(self,event=None):
903       import Interp
904       d={'j':self.tree.item.object}
905       Interp.InterpWindow(d,parent=self.parent)
906       
907   def visuCR(self,mode='Cata'):
908     txt = str(self.cata.report())
909     titre="Rapport de validation du catalogue"
910     Fenetre(self.appli,titre=titre,texte=txt)
911   
912   def select_node(self,node):
913     self.nodes[node]=self.create_panel(node)
914
915   def create_panel(self,node):
916     if hasattr(node.item,"panel"):
917       return getattr(node.item,"panel")(self,self.pane.pane('panel'),node)
918       
919   def quit(self) :
920     self.top.destroy()
921     
922   def settitle(self):
923     self.top.wm_title("Browser de catalogue " )
924     self.top.wm_iconname("CataBrowser")
925
926  
927 dispatch = {
928     'OPER'   : OPERItem,
929     'PROC'   : PROCItem,
930     'MACRO'  : MACROItem,
931     'SIMP'   : SIMPItem,
932     'FACT'   : FACTItem,
933     'BLOC'   : BLOCItem,
934     'TYPE'   : TYPEItem,
935     'NIVEAU' : NIVEAUItem
936 }
937
938 def TYPE(o):
939   if isinstance(o,definition_cata.OPER_CATA):return 'OPER'
940   elif isinstance(o,definition_cata.PROC_CATA):return 'PROC'
941   elif isinstance(o,definition_cata.MACRO_CATA):return 'MACRO'
942   elif isinstance(o,definition_cata.SIMP_CATA):return 'SIMP'
943   elif isinstance(o,definition_cata.FACT_CATA):return 'FACT'
944   elif isinstance(o,definition_cata.BLOC_CATA):return 'BLOC'
945   elif isinstance(o,definition_cata.TYPE_CATA):return 'TYPE'
946   elif isinstance(o,definition_cata.NIVEAU_CATA) : return 'NIVEAU'
947   else:return type(o)
948
949 def TYPE_COMPLET(o):
950   if isinstance(o,definition_cata.OPER_CATA):return "OPERATEUR"
951   elif isinstance(o,definition_cata.PROC_CATA):return "PROCEDURE"
952   elif isinstance(o,definition_cata.MACRO_CATA):return "MACRO"
953   elif isinstance(o,definition_cata.SIMP_CATA):return "Mot-clé SIMPLE"
954   elif isinstance(o,definition_cata.FACT_CATA):return "Mot-clé FACTEUR"
955   elif isinstance(o,definition_cata.BLOC_CATA):return "BLOC"
956   elif isinstance(o,definition_cata.TYPE_CATA):return "Type"
957   elif isinstance(o,definition_cata.NIVEAU_CATA):return "Niveau"
958   else: return "Inconnu ("+`type(o)`+")"
959   
960 def make_objecttreeitem(appli,labeltext, object, setfunction=None,objet_cata_ordonne=None):
961     t = TYPE(object)
962     if dispatch.has_key(t):
963       c = dispatch[t]
964     else:
965       print 'on a un objet de type :',type(object),'  ',object
966       c = ATTRIBUTItem
967     return c(appli,labeltext, object, setfunction = setfunction,objet_cata_ordonne=objet_cata_ordonne)
968
969
970