Salome HOME
PN : pour afficher correctement les arguments de la formule nouvelle.
[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.5 2004/09/10 15:51:48 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.getObject(),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.getObject(),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.getObject() = ETAPE ou _C
803     # self.object = JDC
804     itemobject=item.getObject()
805     if self.object.suppentite(itemobject):
806        if isinstance(itemobject,_C):
807           message = "Commentaire supprimé"
808        else :
809           message = "Commande " + itemobject.nom + " supprimée"
810        self.appli.affiche_infos(message)
811        return 1
812     else:
813        self.appli.affiche_infos("Pb interne : impossible de supprimer cet objet")
814        return 0
815
816   def GetText(self):
817       return ''
818     
819 class ATTRIBUTItem(SIMPItem):
820   def get_dico_attributs(self):
821     self.d_attributs = {}
822
823   def GetSubList(self):
824     return []
825
826   def IsExpandable(self):
827     return 0
828
829   def GetText(self):
830     return self.object
831
832   def GetIconName(self):
833     return 'aucune' 
834
835 class CataEditeur:
836   def __init__(self,parent,appli,cata):
837     self.parent = parent
838     self.cata = definition_cata.CATALOGUE(cata)
839     self.appli = appli
840     self.top = Toplevel()
841     self.top.geometry("800x500")
842     self.top.title("Edition d'un catalogue")
843     self.init()
844
845   def close(self):
846     self.top.destroy()
847
848   def init(self):
849     self.nodes={}
850     self.creerbarremenus()
851     self.pane = Pmw.PanedWidget(self.top,
852                                 hull_width = 800,
853                                 hull_height = 500,
854                                 orient = 'horizontal')
855     self.pane.add('canvas',min = 0.4, max = 0.6, size = 0.5)
856     self.pane.add('panel',min = 0.4, max = 0.6, size = 0.5)
857     self.pane.pack(expand =1, fill = 'both')
858     self.scrolledcanvas = Pmw.ScrolledCanvas(self.pane.pane('canvas'),
859                                              hull_width=1.,
860                                              hull_height=1.,
861                                              borderframe=1)
862     Pmw.Color.changecolor(self.scrolledcanvas.component('canvas'),background='gray95')
863     self.scrolledcanvas.pack(padx=10,pady=10,expand=1, fill="both")
864     self.item = CATAItem(self.appli,"Catalogue",
865                            self.cata,
866                           objet_cata_ordonne = self.appli.readercata.cata_ordonne_dico)
867
868     self.tree = Tree(self.appli,self.item,self.scrolledcanvas,command = self.select_node)
869     self.tree.draw()
870     self.node = self.tree.node_selected
871
872   def creerbarremenus(self) :
873       self.menubar=Menu(self.top)
874       self.filemenu=Menu(self.menubar,tearoff=0)
875       self.filemenu.add_command(label='Quitter',command=self.quit)
876
877       self.editmenu=Menu(self.menubar,tearoff=0)
878       #self.editmenu.add_command(label='Copier',command=self.copy)
879       #self.editmenu.add_command(label='Couper',command=self.cut)
880       #self.editmenu.add_command(label='Coller',command=self.paste)
881
882       self.affichagemenu=Menu(self.menubar,tearoff=0)
883       self.affichagemenu.add_command(label='Rapport de validation',
884                                      command = self.visuCR)
885       self.affichagemenu.add_command(label='shell',command = self.shell)
886       #self.affichagemenu.add_command(label='Fichier ࡰlat',command=self.visu_a_plat)
887       #self.affichagemenu.add_command(label='Fichier .py',command =self.visuJDC_py)
888       #self.affichagemenu.add_command(label='Fichier source',command = self.visu_txt_brut_JDC)
889       #self.affichagemenu.add_command(label='Param鵲es Eficas',command=self.affichage_fichier_ini)
890       
891       #self.optionmenu=Menu(self.menubar,tearoff=0)
892       #self.optionmenu.add_command(label='Catalogue d귥loppeur',command=self.choix_cata_developpeur)
893
894       self.menubar.add_cascade(label='Fichier',menu=self.filemenu)
895       self.menubar.add_cascade(label='Edition',menu=self.editmenu)
896       self.menubar.add_cascade(label='Jeu de commandes',menu=self.affichagemenu)
897       #self.menubar.add_cascade(label='Browsers',menu=self.browsermenu)
898       #self.menubar.add_cascade(label='Catalogue',menu=self.cataloguemenu)
899       #self.menubar.add_cascade(label='Options',menu=self.optionmenu)
900       self.top.configure(menu=self.menubar)
901       self.top.protocol("WM_DELETE_WINDOW",self.quit)
902       self.top.minsize(900,500)
903       self.top.geometry("900x500")
904
905   def shell(self,event=None):
906       import Interp
907       d={'j':self.tree.item.getObject()}
908       Interp.InterpWindow(d,parent=self.parent)
909       
910   def visuCR(self,mode='Cata'):
911     txt = str(self.cata.report())
912     titre="Rapport de validation du catalogue"
913     Fenetre(self.appli,titre=titre,texte=txt)
914   
915   def select_node(self,node):
916     self.nodes[node]=self.create_panel(node)
917
918   def create_panel(self,node):
919     if hasattr(node.item,"panel"):
920       return getattr(node.item,"panel")(self,self.pane.pane('panel'),node)
921       
922   def quit(self) :
923     self.top.destroy()
924     
925   def settitle(self):
926     self.top.wm_title("Browser de catalogue " )
927     self.top.wm_iconname("CataBrowser")
928
929  
930 dispatch = {
931     'OPER'   : OPERItem,
932     'PROC'   : PROCItem,
933     'MACRO'  : MACROItem,
934     'SIMP'   : SIMPItem,
935     'FACT'   : FACTItem,
936     'BLOC'   : BLOCItem,
937     'TYPE'   : TYPEItem,
938     'NIVEAU' : NIVEAUItem
939 }
940
941 def TYPE(o):
942   if isinstance(o,definition_cata.OPER_CATA):return 'OPER'
943   elif isinstance(o,definition_cata.PROC_CATA):return 'PROC'
944   elif isinstance(o,definition_cata.MACRO_CATA):return 'MACRO'
945   elif isinstance(o,definition_cata.SIMP_CATA):return 'SIMP'
946   elif isinstance(o,definition_cata.FACT_CATA):return 'FACT'
947   elif isinstance(o,definition_cata.BLOC_CATA):return 'BLOC'
948   elif isinstance(o,definition_cata.TYPE_CATA):return 'TYPE'
949   elif isinstance(o,definition_cata.NIVEAU_CATA) : return 'NIVEAU'
950   else:return type(o)
951
952 def TYPE_COMPLET(o):
953   if isinstance(o,definition_cata.OPER_CATA):return "OPERATEUR"
954   elif isinstance(o,definition_cata.PROC_CATA):return "PROCEDURE"
955   elif isinstance(o,definition_cata.MACRO_CATA):return "MACRO"
956   elif isinstance(o,definition_cata.SIMP_CATA):return "Mot-clé SIMPLE"
957   elif isinstance(o,definition_cata.FACT_CATA):return "Mot-clé FACTEUR"
958   elif isinstance(o,definition_cata.BLOC_CATA):return "BLOC"
959   elif isinstance(o,definition_cata.TYPE_CATA):return "Type"
960   elif isinstance(o,definition_cata.NIVEAU_CATA):return "Niveau"
961   else: return "Inconnu ("+`type(o)`+")"
962   
963 def make_objecttreeitem(appli,labeltext, object, setfunction=None,objet_cata_ordonne=None):
964     t = TYPE(object)
965     if dispatch.has_key(t):
966       c = dispatch[t]
967     else:
968       print 'on a un objet de type :',type(object),'  ',object
969       c = ATTRIBUTItem
970     return c(appli,labeltext, object, setfunction = setfunction,objet_cata_ordonne=objet_cata_ordonne)
971
972
973