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