Salome HOME
correction pour acception de concept liste
[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.6 2004/09/20 09:24:13 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.bind("<KP_Enter>",lambda e,s=self:s.execConcept())
207       self._any.insert(0,self.node.item.GetText())
208       type_sd = self.node.item.object.get_type_sd_prod()
209       if type_sd :
210           txt = "L'opérateur courant retourne un objet de type %s" %type_sd
211           self.label = Label(page, text = txt)
212           self.label.place(relx=0.5,rely=0.55,anchor='n')
213       self._any.focus()
214           
215   def makeCommandePage(self,page):
216       """ Affiche la page d'ajout d'une commande relativement à l'objet commande sélectionné """
217       titre = "Où voulez-vous insérer une commande par rapport à %s" %self.node.item.object.nom
218       Label(page,text=titre).place(relx=0.5,rely=0.2,anchor='w')
219       b_avant = Button(page,text='AVANT',
220                        command = self.node.item.add_commande_avant)
221       b_apres = Button(page,text='APRES',
222                        command = self.node.item.add_commande_apres)
223       b_avant.place(relx=0.35,rely=0.5,anchor='w')
224       b_apres.place(relx=0.65,rely=0.5,anchor='w')
225
226   def deselectMC(self,name):
227       self.parent.appli.affiche_infos('')
228     
229   def get_liste_cmd(self):
230       listeCmd = self.node.item.object.niveau.definition.get_liste_cmd()
231       return listeCmd
232
233   def get_liste_fils_cmd(self):
234       return ['Mot-clé simple','Mot-clé facteur','Bloc']
235
236   def makeMoclesPage(self,page):
237       frame1 = Frame(page,height = 20)
238       frame1.pack(side='top',fill='x')
239       label = Label(frame1,text ="Le mot-clé choisi sera ajouté à la fin du catalogue")
240       label.pack(side='top')
241       frame2 = Frame(page)
242       frame2.pack(side='top',fill='both',expand=1)
243       liste_cmd = self.get_liste_fils_cmd()
244       liste_commandes = (("<Enter>",self.selectFilsCmd),
245                          ("<Leave>",self.deselectFilsCmd),
246                          ("<Double-Button-1>",self.defFilsCmd))
247       Liste = ListeChoix(self,frame2,liste_cmd,liste_commandes = liste_commandes,titre = "Mots-clés")
248       Liste.affiche_liste()
249
250   def deselectFilsCmd(self,name):
251       pass
252     
253   def makeJDCPage(self,page):
254       liste_cmd = self.get_liste_cmd()
255       liste_commandes = (("<Enter>",self.selectCmd),
256                          ("<Leave>",self.deselectCmd),
257                          ("<Double-Button-1>",self.defCmdFirst))
258       Liste = ListeChoix(self,page,liste_cmd,liste_commandes = liste_commandes,filtre='oui',titre = "Commandes")
259       Liste.affiche_liste()
260
261   def makeReglesPage(self,page) :
262     regles = []
263     regles = self.node.item.get_regles()
264     dictionnaire = self.node.item.get_mc_presents()
265     texte_regles = []
266     l_regles_en_defaut=[]
267     if len(regles) > 0:
268       i = 0
269       for regle in regles :
270         texte_regles.append(regle.gettext())
271         texte,test = regle.verif(dictionnaire)
272         if test == 0 : l_regles_en_defaut.append(i)
273         i = i+1
274     Liste = ListeChoix(self,page,texte_regles,liste_marques=l_regles_en_defaut,active='non',titre="Règles")
275     Liste.affiche_liste()
276     #self.afficheListe(page,texte_regles,self.selectRegle,self.execRegle)
277
278   def execConcept(self):
279       """ Nomme le concept SD retourné par l'étape """
280       if self.parent.modified == 'n' : self.parent.init_modif()
281       nom = self._any.get()
282       # Pourquoi node.etape ???
283       #test,mess = self.node.etape.item.nomme_sd(nom)
284       test,mess = self.node.item.nomme_sd(nom)
285       self.parent.appli.affiche_infos(mess)
286       self.node.racine.update()
287   
288   def changed(self):
289       pass
290
291   def makeAttributsPage(self,page):
292     l_attributs=self.node.item.object.attributs
293     d_defauts = self.node.item.object.attributs_defauts
294     for attribut in l_attributs :
295       attr = self.node.item.object.entites_attributs.get(attribut,None)
296       if attr.valeur is d_defauts[attribut] :
297         texte = attribut+' = '+repr(attr.valeur)+' (defaut)'
298       else:
299         texte = attribut+' = '+repr(attr.valeur)
300       Label(page,text=texte).pack(side='top')
301
302   def makeSimpPage(self,page):
303     texte = "Où voulez-vous ajouter un mot-clé simple ?"
304     Label(page,text=texte).place(relx=0.5,rely=0.3,anchor='center')
305     b1 = Button(page,text='AVANT '+self.node.item.object.nom,command=self.add_simp_avant)
306     b2 = Button(page,text='APRES '+self.node.item.object.nom,command=self.add_simp_apres)
307     b1.place(relx=0.5,rely=0.5,anchor='center')
308     b2.place(relx=0.5,rely=0.6,anchor='center')
309
310   def add_simp_avant(self,event=None):
311     """
312     Ajoute un mot-clé simple avant celui courant
313     """
314     self.node.append_brother('new_simp','before')
315     self.node.update()
316
317   def add_simp_apres(self,event=None):
318     """
319     Ajoute un mot-clé simple après celui courant
320     """
321     self.node.append_brother('new_simp','after')
322     self.node.update()    
323     
324 class TYPEPanel(Frame):
325   def __init__(self,parent,panneau,node) :
326       self.parent=parent
327       self.panneau = panneau
328       self.node=node
329       Frame.__init__(self,self.panneau)
330       self.place(x=0,y=0,relheight=1,relwidth=1)
331       self.creer_texte()
332
333   def creer_texte(self):
334       texte = "Le noeud sélectionné correspond à un type\n"
335       self.label = Label(self,text=texte)
336       self.label.place(relx=0.5,rely=0.4,relwidth=0.8,anchor='center')
337
338 class OPERPanel(OngletPanel):
339   def init(self):
340     nb = Pmw.NoteBook(self,raisecommand=self.raisecmd)
341     
342     nb.pack(fill = 'both', expand = 1)
343     self.nb=nb
344     nb.add('Mocles', tab_text='Ajouter mots-clés')
345     nb.add('Commandes',tab_text='Ajouter une commande')
346     self.makeMoclesPage(nb.page("Mocles"))
347     self.makeCommandePage(nb.page("Commandes"))
348     nb.tab('Mocles').focus_set()
349     nb.setnaturalsize()
350     self.affiche()
351    
352 class SIMPPanel(OngletPanel):
353   def init(self):
354     nb = Pmw.NoteBook(self,raisecommand=self.raisecmd)
355     nb.pack(fill = 'both', expand = 1)
356     self.nb=nb
357     nb.add('generaux', tab_text='Données générales')
358     nb.add('ihm',tab_text='Données IHM')
359     nb.add('mocle',tab_text='Ajouter un mot-cle simple')
360     self.makeAttributsGenerauxPage(nb.page("generaux"))
361     self.makeAttributsIHMPage(nb.page("ihm"))
362     self.makeSimpPage(nb.page('mocle'))
363     nb.tab('generaux').focus_set()
364     nb.setnaturalsize()
365     self.affiche()
366
367   def makeAttributsGenerauxPage(self,page):
368     fr1 = Frame(page,bd=1,relief='raised')
369     fr2 = Frame(page,bd=1,relief='raised')
370     fr3 = Frame(page,bd=1,relief='raised')
371     fr4 = Frame(page,bd=1,relief='raised')
372     fr5 = Frame(page,bd=1,relief='raised')
373     fr1.place(relheight=0.14,relwidth=1,rely=0)
374     fr2.place(relheight=0.14,relwidth=1,rely=0.14)
375     fr3.place(relheight=0.29,relwidth=1,rely=0.28)
376     fr4.place(relheight=0.14,relwidth=1,rely=0.57)
377     fr5.place(relheight=0.28,relwidth=1,rely=0.71)
378     # nom du mot-clé
379     Label(fr1,text = 'Nom :').place(relx=0.05,rely=0.3,anchor='w')
380     self.e_nom = Entry(fr1)
381     self.e_nom.place(relx=0.35,rely=0.3,relwidth=0.3,anchor='w')
382     self.e_nom.bind("<Return>",lambda e,s=self : s.set_valeur_attribut('nom',None))
383     self.e_nom.bind("<KP_Enter>",lambda e,s=self : s.set_valeur_attribut('nom',None))
384     self.e_nom.insert(0,self.get_valeur_attribut('nom'))
385     # Statut
386     Label(fr1,text='Statut : ').place(relx=0.05,rely=0.7,anchor='w')
387     self.statut=StringVar()
388     valeurs_statut=[('obligatoire','o'),
389                     ('facultatif','f'),
390                     ('caché','c')
391                     ]
392     self.statut.set(self.node.item.object.get_valeur_attribut('statut'))
393     i=0
394     for text,mode in valeurs_statut:
395       b=Radiobutton(fr1,text=text,variable=self.statut,value=mode,
396                     command = lambda s=self,m=mode : s.set_valeur_attribut('statut',m))
397       b.place(relx=0.25+i*0.25,rely=0.7,anchor='w')
398       i=i+1
399     # Type ...
400     Label(fr2,text='Type de la valeur : ').place(relx=0.05,rely=0.5,anchor='w')
401     self.e_type = Entry(fr2)
402     self.e_type.place(relx=0.35,rely=0.5,relwidth=0.5,anchor='w')
403     self.e_type.insert(0,self.node.item.object.get_valeur_attribut('type'))
404     # Domaine de validité
405     Label(fr3,text='Domaine de validité : ').place(relx=0.05,rely=0.2,anchor='w')
406     self.domaine = StringVar()
407     self.domaine.set(self.node.item.object.get_valeur_attribut('domaine_validité'))
408     b1=Radiobutton(fr3,text='continu',variable=self.domaine,value='continu',
409                    command=lambda s=self,f=fr3 :s.change_domaine(f))
410     b2=Radiobutton(fr3,text='discret',variable=self.domaine,value='discret',
411                    command=lambda s=self,f=fr3 :s.change_domaine(f))
412     b1.place(relx=0.35,rely=0.2,anchor='w')
413     b2.place(relx=0.65,rely=0.2,anchor='w')
414     self.change_domaine(fr3)
415     # Défaut ...
416     if self.domaine.get() == 'continu':
417       # le développeur peut donner la valeur qu'il souhaite, moyennant la vérification de type...
418       Label(fr4,text='Valeur par défaut : ').place(relx=0.05,rely=0.5,anchor='w')
419       self.e_defaut = Entry(fr4)
420       self.e_defaut.place(relx=0.35,rely=0.5,relwidth=0.5,anchor='w')
421       if self.node.item.object.get_valeur_attribut('defaut') :
422         self.e_defaut.insert(0,self.node.item.object.get_valeur_attribut('defaut'))
423       self.e_defaut.bind("<Return>",lambda e,s=self : s.set_valeur_attribut('defaut',None))
424       self.e_defaut.bind("<KP_Enter>",lambda e,s=self : s.set_valeur_attribut('defaut',None))
425     else :
426       # dans le cas discret, la valeur par défaut doit être dans l'ensemble des valeurs possibles (into)
427       liste = self.node.item.object.get_valeur_attribut('into')
428       if self.node.item.object.get_valeur_attribut('defaut') :
429         self.set_valeur_attribut('defaut',self.node.item.object.get_valeur_attribut('defaut'))
430       if liste == None : liste = []
431       self.e_defaut = Pmw.OptionMenu(fr4,labelpos='w',label_text = "Valeur par défaut : ",
432                                      items = self.node.item.object.get_valeur_attribut('into'),
433                                      menubutton_width=30)
434       self.e_defaut.configure(command = lambda e,s=self : s.set_valeur_attribut('defaut',None))
435       self.e_defaut.place(relx=0.05,rely=0.5,anchor='w')
436     # Liste de valeurs ?
437     Label(fr5,text='Liste de valeurs : ').place(relx=0.05,rely=0.2,anchor='w')
438     self.liste_valeurs = BooleanVar()
439     liste_valeurs = [('OUI',1),('NON',0)]
440     self.liste_valeurs.set(0)
441     i=0
442     for text,mode in liste_valeurs:
443       b=Radiobutton(fr5,text=text,variable=self.liste_valeurs,value=mode,
444                     command=lambda s=self,f=fr5 :s.change_liste_valeurs(f))
445       b.place(relx=0.35+i*0.2,rely=0.2,anchor='w')
446       i=i+1
447     self.change_liste_valeurs(fr5)
448
449   def makeAttributsIHMPage(self,page):
450     fr1 = Frame(page,height=100,bd=1,relief='raised')
451     fr2 = Frame(page,height=50,bd=1,relief='raised')
452     fr1.pack(side='top',fill='x')
453     fr2.pack(side='top',fill='x')
454     # Champ fr ...
455     Label(fr1,text='Champ fr : ').place(relx=0.05,rely=0.35,anchor='w')
456     self.e_fr = Entry(fr1)
457     self.e_fr.place(relx=0.35,rely=0.35,relwidth=0.6,anchor='w')
458     self.e_fr.insert(0,self.node.item.object.get_valeur_attribut('fr'))
459     # Champ ang ...
460     Label(fr1,text='Champ ang : ').place(relx=0.05,rely=0.70,anchor='w')
461     self.e_ang = Entry(fr1)
462     self.e_ang.place(relx=0.35,rely=0.70,relwidth=0.6,anchor='w')
463     self.e_ang.insert(0,self.node.item.object.get_valeur_attribut('ang'))
464     # Clé documentaire ...
465     Label(fr2,text='Clé documentaire : ').place(relx=0.05,rely=0.50,anchor='w')
466     self.e_docu = Entry(fr2)
467     self.e_docu.place(relx=0.35,rely=0.50,relwidth=0.6,anchor='w')
468     self.e_docu.insert(0,self.node.item.object.get_valeur_attribut('docu'))
469     
470   def detruit_widgets(self,l_widgets):
471     for nom_widg in l_widgets :
472       try:
473         widg = getattr(self,nom_widg)
474         widg.place_forget()
475         delattr(self,nom_widg)
476       except:
477         pass
478
479   def change_liste_valeurs(self,fr5):
480     valeur = self.liste_valeurs.get()
481     if valeur == 0 :
482       # pas de liste de valeurs
483       l_widgets=['l_homo','b1_homo','b2_homo','l_min','e_min','l_max','e_max']
484       self.detruit_widgets(l_widgets)
485     elif valeur == 1:
486       # pas de widgets à détruire ...
487       if hasattr(self,'l_homo') :
488         # on est déjà en mode 'liste' --> rien à faire
489         return 
490       # homo
491       self.l_homo = Label(fr5,text='Liste homogène : ')
492       self.l_homo.place(relx=0.05,rely=0.4,anchor='w')
493       self.homo = BooleanVar()
494       self.homo.set(self.node.item.object.get_valeur_attribut('homo'))
495       self.b1_homo=Radiobutton(fr5,text='OUI',variable=self.homo,value=1)
496       self.b2_homo=Radiobutton(fr5,text='NON',variable=self.homo,value=0)
497       self.b1_homo.place(relx=0.35,rely=0.4,anchor='w')
498       self.b2_homo.place(relx=0.65,rely=0.4,anchor='w')
499       # min ...
500       self.l_min = Label(fr5,text='Longueur minimale : ')
501       self.l_min.place(relx=0.05,rely=0.6,anchor='w')
502       self.e_min = Entry(fr5)
503       self.e_min.place(relx=0.4,rely=0.6,relwidth=0.3,anchor='w')
504       self.e_min.insert(0,self.node.item.object.get_valeur_attribut('min'))
505       # max ...
506       self.l_max = Label(fr5,text='Longueur maximale : ')
507       self.l_max.place(relx=0.05,rely=0.8,anchor='w')
508       self.e_max = Entry(fr5)
509       self.e_max.place(relx=0.4,rely=0.8,relwidth=0.3,anchor='w')
510       self.e_max.insert(0,self.node.item.object.get_valeur_attribut('max'))
511       
512   def change_domaine(self,fr3):
513     valeur = self.domaine.get()
514     if valeur == 'discret' :
515       l_widgets = ['l_val_min','l_val_max','e_val_min','e_val_max']
516       self.detruit_widgets(l_widgets)
517       # into
518       #self.l_into = Label(fr3,text='Ensemble de valeurs : ')
519       #self.l_into.place(relx=0.2,rely=0.5,anchor='w')
520       self.e_into = Pmw.ScrolledListBox(fr3,
521                                         items=self.node.item.object.get_valeur_attribut('into'),
522                                         labelpos='w',
523                                         label_text= 'Ensemble de valeurs : ',
524                                         listbox_height = 3,
525                                         dblclickcommand = self.change_into)
526       self.e_into.place(relx=0.05,rely=0.6,relwidth=0.9,anchor='w')
527       #self.e_into.insert(0,self.node.item.object.get_valeur_attribut('into'))
528     elif valeur == 'continu':
529       l_widgets = ['l_into','e_into']
530       self.detruit_widgets(l_widgets)
531       if hasattr(self,'l_val_min'):
532         # on est déjà en mode 'continu' --> rien à faire
533         return
534       # val_min
535       self.l_val_min = Label(fr3,text='Valeur minimale : ')
536       self.l_val_min.place(relx=0.05,rely=0.5,anchor='w')
537       self.e_val_min = Entry(fr3)
538       self.e_val_min.place(relx=0.35,rely=0.5,relwidth=0.5,anchor='w')
539       self.e_val_min.bind("<Return>",lambda e,s=self : s.set_valeur_attribut('val_min',None))
540       self.e_val_min.bind("<KP_Enter>",lambda e,s=self : s.set_valeur_attribut('val_min',None))
541       self.set_valeur_attribut('val_min',self.get_valeur_attribut('val_min'))
542       # val_max
543       self.l_val_max = Label(fr3,text='Valeur maximale : ')
544       self.l_val_max.place(relx=0.05,rely=0.8,anchor='w')
545       self.e_val_max = Entry(fr3)
546       self.e_val_max.place(relx=0.35,rely=0.8,relwidth=0.5,anchor='w')
547       self.e_val_max.bind("<Return>",lambda e,s=self : s.set_valeur_attribut('val_max',None))
548       self.e_val_max.bind("<KP_Enter>",lambda e,s=self : s.set_valeur_attribut('val_max',None))
549       self.set_valeur_attribut('val_max',self.get_valeur_attribut('val_max'))
550
551 # ------------------------------------------------------------------
552 # Méthodes de validation des entrées faites par l'utilisateur
553 # ------------------------------------------------------------------
554
555   def get_valeur_attribut(self,nom_attr):
556     """
557     Demande à l'item de retourner la valeur de l'attribut nom_attr
558     """
559     return self.node.item.get_valeur_attribut(nom_attr)
560   
561   def set_valeur_attribut(self,nom_attr,new_valeur):
562     """
563     Affecte la valeur new_valeur à l'attribut nom_attr
564     Vérifie si celle-ci est valide, sinon restaure l'ancienne
565     """
566     if new_valeur is None :
567       widget = getattr(self,'e_'+nom_attr)
568       if hasattr(widget,'getcurselection'):
569         new_valeur = widget.getcurselection()
570       else:
571         new_valeur = widget.get()
572     print "on affecte %s a %s" %(str(new_valeur),nom_attr)
573     self.node.item.set_valeur_attribut(nom_attr,new_valeur)
574     self.node.update()
575
576   def change_into(self):
577     """
578     Méthode activée par double clic sur la ListBox d'affichage des valeurs discrètes possibles :
579     permet de changer la liste de ces valeurs
580     """
581     showinfo("Fonction non encore disponible",
582              "Vous ne pouvez pas encore modifier la liste into par cette IHM")
583     
584 class OBJECTItem(TreeItem):
585   def __init__(self,appli,labeltext,object,setfunction=None,objet_cata_ordonne = None):
586     self.appli = appli
587     self.labeltext = labeltext
588     self.object=object
589     self.setfunction = setfunction
590     self.objet_cata_ordonne = objet_cata_ordonne
591     
592   def GetLabelText(self):
593     return self.labeltext,None,None
594
595   def get_fr(self):
596     return ''
597   
598   def isMCList(self):
599     return 0
600
601   def isactif(self):
602     return 1
603
604   def add_commande_avant(self):
605     pass
606
607   def add_commande_apres(self):
608     pass
609
610   def set_valeur_attribut(self,nom_attr,new_valeur):
611     """
612     Affecte la valeur new_valeur à l'attribut nom_attr
613     Vérifie si celle-ci est valide, sinon restaure l'ancienne
614     """
615     old_valeur = self.object.get_valeur_attribut(nom_attr)
616     self.object.set_valeur_attribut(nom_attr,new_valeur)
617     verificateur = 'verif_'+nom_attr
618     if hasattr(self.object,verificateur):
619       if not getattr(self.object,verificateur)():
620         # la nouvelle valeur de nom_attr n'est pas valide : on restaure l'ancienne (sans vérification)
621         self.object.set_valeur_attribut(nom_attr,old_valeur)
622         print 'changement de valeur refuse'
623         return
624     print 'changement de valeur accepte'
625     self.object.init_modif()
626
627   def get_valeur_attribut(self,nom_attr):
628     """
629     Retourne la valeur de l'attribut nom_attr
630     """
631     return self.object.get_valeur_attribut(nom_attr)
632         
633 class CATAItem(OBJECTItem):
634   def GetSubList(self):
635     sublist=[]
636     for fils in self.object.entites_fils:
637       item = make_objecttreeitem(self.appli,fils.objet.label + " : ",fils,objet_cata_ordonne=self.objet_cata_ordonne)
638       sublist.append(item)
639     return sublist
640   
641   def GetIconName(self):
642     if self.object.isvalid():
643       return 'ast-green-square'
644     else:
645       return 'ast-red-square'
646
647   def GetText(self):
648     return "Catalogue %s" %self.appli.code
649
650   def add_commande_avant(self):
651     pass
652
653   def add_commande_apres(self):
654     pass
655
656      
657 def transforme_liste_dico(liste):
658   d={}
659   for item in liste :
660     d[item.nom]=item
661   return d
662       
663 class OPERItem(OBJECTItem):
664   panel = OPERPanel
665   def GetSubList(self):
666     sublist=[]
667     # on classe les fils dans l'ordre du catalogue ...
668     l_cles_fils = self.get_liste_mc_ordonnee()
669     # on crée les items fils ...
670     dico_fils = transforme_liste_dico(self.object.entites_fils)
671     for k in l_cles_fils :
672       typ = TYPE_COMPLET(dico_fils[k])
673       if type(self.objet_cata_ordonne) == types.InstanceType :
674         objet_cata = self.objet_cata_ordonne.entites[k]
675       else :
676         objet_cata = self.objet_cata_ordonne.get(k,None)
677       item = make_objecttreeitem(self.appli,typ + " : ",dico_fils[k],objet_cata_ordonne = objet_cata)
678       sublist.append(item)
679     return sublist
680
681   def GetText(self):
682     #return self.object.nom
683     return self.object.get_valeur_attribut('nom')
684
685   def get_liste_mc_ordonnee(self):
686     return self.objet_cata_ordonne.ordre_mc
687
688   def GetIconName(self):
689     if self.object.isvalid():
690       return 'ast-green-square'
691     else:
692       return 'ast-red-square'
693
694   def additem(self,name,pos):
695       if isinstance(name,TreeItem) :
696           cmd=self.object.addentite(name.getObject(),pos)
697       else :
698           cmd = self.object.addentite(name,pos)
699       typ = TYPE_COMPLET(cmd)
700       item = make_objecttreeitem(self.appli,typ + " : ", cmd)
701       return item
702
703   def get_attribut(self,nom):
704     if nom == 'nature': return 'OPERATEUR'
705
706   def get_liste_mc_presents(self):
707     return []
708
709   def verif_condition_regles(self,liste):
710     return []
711   
712 class PROCItem(OPERItem):
713   panel = OPERPanel
714   
715 class MACROItem(OPERItem):
716   panel = OPERPanel
717     
718 class SIMPItem(OPERItem):
719   panel = SIMPPanel
720   
721   def GetIconName(self):
722     if self.object.isvalid():
723       return 'ast-green-ball'
724     else:
725       return 'ast-red-ball'
726
727   def IsExpandable(self):
728     return 0
729
730   def GetSubList(self):
731     return []
732   
733 class FACTItem(OPERItem):
734   def GetIconName(self):
735     if self.object.isvalid():
736       return 'ast-green-los'
737     else:
738       return 'ast-red-los'
739
740 class BLOCItem(FACTItem): pass
741
742 class TYPEItem(SIMPItem):
743   panel = TYPEPanel
744   def get_dico_attributs(self):
745     self.d_attributs = {}
746
747   def GetSubList(self):
748     return []
749
750   def IsExpandable(self):
751     return 0
752
753   def GetText(self):
754     return self.object.nom
755
756 class NIVEAUItem(OPERItem):
757   def IsExpandable(self):
758       return 1
759
760   def get_liste_mc_ordonnee(self):
761     l=[]
762     for fils in self.object.entites_fils:
763       l.append(fils.nom)
764     return l
765   
766   def GetSubList(self):
767     sublist=[]
768     # on classe les fils dans l'ordre du catalogue ...
769     l_cles_fils = self.get_liste_mc_ordonnee()
770     # on crꥠles items fils ...
771     dico_fils = transforme_liste_dico(self.object.entites_fils)
772     for k in l_cles_fils :
773       typ = TYPE_COMPLET(dico_fils[k])
774       if type(self.objet_cata_ordonne) == types.InstanceType :
775         objet_cata = self.objet_cata_ordonne.entites[k]
776       else :
777         objet_cata = self.objet_cata_ordonne.get(k,None)
778       item = make_objecttreeitem(self.appli,typ + " : ",dico_fils[k],objet_cata_ordonne = objet_cata)
779       sublist.append(item)
780     return sublist
781   
782   def GetLabelText(self):
783       """ Retourne 3 valeurs :
784         - le texte à afficher dans le noeud représentant l'item
785         - la fonte dans laquelle afficher ce texte
786         - la couleur du texte
787       """
788       return self.labeltext,Fonte_Niveau,'#00008b'
789     
790   def GetIconName(self):
791     if self.object.isvalid():
792       return "ast-green-text"
793     else:
794       return 'ast-red-text'
795
796   def additem(self,name,pos):
797       if isinstance(name,TreeItem) :
798           cmd=self.object.addentite(name.getObject(),pos)
799       else :
800           cmd = self.object.addentite(name,pos)
801       typ = TYPE_COMPLET(obj)
802       item = make_objecttreeitem(self.appli,typ+ " : ", cmd)
803       return item
804
805   def suppitem(self,item) :
806     # item = item de l'ETAPE à supprimer du JDC
807     # item.getObject() = ETAPE ou _C
808     # self.object = JDC
809     itemobject=item.getObject()
810     if self.object.suppentite(itemobject):
811        if isinstance(itemobject,_C):
812           message = "Commentaire supprimé"
813        else :
814           message = "Commande " + itemobject.nom + " supprimée"
815        self.appli.affiche_infos(message)
816        return 1
817     else:
818        self.appli.affiche_infos("Pb interne : impossible de supprimer cet objet")
819        return 0
820
821   def GetText(self):
822       return ''
823     
824 class ATTRIBUTItem(SIMPItem):
825   def get_dico_attributs(self):
826     self.d_attributs = {}
827
828   def GetSubList(self):
829     return []
830
831   def IsExpandable(self):
832     return 0
833
834   def GetText(self):
835     return self.object
836
837   def GetIconName(self):
838     return 'aucune' 
839
840 class CataEditeur:
841   def __init__(self,parent,appli,cata):
842     self.parent = parent
843     self.cata = definition_cata.CATALOGUE(cata)
844     self.appli = appli
845     self.top = Toplevel()
846     self.top.geometry("800x500")
847     self.top.title("Edition d'un catalogue")
848     self.init()
849
850   def close(self):
851     self.top.destroy()
852
853   def init(self):
854     self.nodes={}
855     self.creerbarremenus()
856     self.pane = Pmw.PanedWidget(self.top,
857                                 hull_width = 800,
858                                 hull_height = 500,
859                                 orient = 'horizontal')
860     self.pane.add('canvas',min = 0.4, max = 0.6, size = 0.5)
861     self.pane.add('panel',min = 0.4, max = 0.6, size = 0.5)
862     self.pane.pack(expand =1, fill = 'both')
863     self.scrolledcanvas = Pmw.ScrolledCanvas(self.pane.pane('canvas'),
864                                              hull_width=1.,
865                                              hull_height=1.,
866                                              borderframe=1)
867     Pmw.Color.changecolor(self.scrolledcanvas.component('canvas'),background='gray95')
868     self.scrolledcanvas.pack(padx=10,pady=10,expand=1, fill="both")
869     self.item = CATAItem(self.appli,"Catalogue",
870                            self.cata,
871                           objet_cata_ordonne = self.appli.readercata.cata_ordonne_dico)
872
873     self.tree = Tree(self.appli,self.item,self.scrolledcanvas,command = self.select_node)
874     self.tree.draw()
875     self.node = self.tree.node_selected
876
877   def creerbarremenus(self) :
878       self.menubar=Menu(self.top)
879       self.filemenu=Menu(self.menubar,tearoff=0)
880       self.filemenu.add_command(label='Quitter',command=self.quit)
881
882       self.editmenu=Menu(self.menubar,tearoff=0)
883       #self.editmenu.add_command(label='Copier',command=self.copy)
884       #self.editmenu.add_command(label='Couper',command=self.cut)
885       #self.editmenu.add_command(label='Coller',command=self.paste)
886
887       self.affichagemenu=Menu(self.menubar,tearoff=0)
888       self.affichagemenu.add_command(label='Rapport de validation',
889                                      command = self.visuCR)
890       self.affichagemenu.add_command(label='shell',command = self.shell)
891       #self.affichagemenu.add_command(label='Fichier ࡰlat',command=self.visu_a_plat)
892       #self.affichagemenu.add_command(label='Fichier .py',command =self.visuJDC_py)
893       #self.affichagemenu.add_command(label='Fichier source',command = self.visu_txt_brut_JDC)
894       #self.affichagemenu.add_command(label='Param鵲es Eficas',command=self.affichage_fichier_ini)
895       
896       #self.optionmenu=Menu(self.menubar,tearoff=0)
897       #self.optionmenu.add_command(label='Catalogue d귥loppeur',command=self.choix_cata_developpeur)
898
899       self.menubar.add_cascade(label='Fichier',menu=self.filemenu)
900       self.menubar.add_cascade(label='Edition',menu=self.editmenu)
901       self.menubar.add_cascade(label='Jeu de commandes',menu=self.affichagemenu)
902       #self.menubar.add_cascade(label='Browsers',menu=self.browsermenu)
903       #self.menubar.add_cascade(label='Catalogue',menu=self.cataloguemenu)
904       #self.menubar.add_cascade(label='Options',menu=self.optionmenu)
905       self.top.configure(menu=self.menubar)
906       self.top.protocol("WM_DELETE_WINDOW",self.quit)
907       self.top.minsize(900,500)
908       self.top.geometry("900x500")
909
910   def shell(self,event=None):
911       import Interp
912       d={'j':self.tree.item.getObject()}
913       Interp.InterpWindow(d,parent=self.parent)
914       
915   def visuCR(self,mode='Cata'):
916     txt = str(self.cata.report())
917     titre="Rapport de validation du catalogue"
918     Fenetre(self.appli,titre=titre,texte=txt)
919   
920   def select_node(self,node):
921     self.nodes[node]=self.create_panel(node)
922
923   def create_panel(self,node):
924     if hasattr(node.item,"panel"):
925       return getattr(node.item,"panel")(self,self.pane.pane('panel'),node)
926       
927   def quit(self) :
928     self.top.destroy()
929     
930   def settitle(self):
931     self.top.wm_title("Browser de catalogue " )
932     self.top.wm_iconname("CataBrowser")
933
934  
935 dispatch = {
936     'OPER'   : OPERItem,
937     'PROC'   : PROCItem,
938     'MACRO'  : MACROItem,
939     'SIMP'   : SIMPItem,
940     'FACT'   : FACTItem,
941     'BLOC'   : BLOCItem,
942     'TYPE'   : TYPEItem,
943     'NIVEAU' : NIVEAUItem
944 }
945
946 def TYPE(o):
947   if isinstance(o,definition_cata.OPER_CATA):return 'OPER'
948   elif isinstance(o,definition_cata.PROC_CATA):return 'PROC'
949   elif isinstance(o,definition_cata.MACRO_CATA):return 'MACRO'
950   elif isinstance(o,definition_cata.SIMP_CATA):return 'SIMP'
951   elif isinstance(o,definition_cata.FACT_CATA):return 'FACT'
952   elif isinstance(o,definition_cata.BLOC_CATA):return 'BLOC'
953   elif isinstance(o,definition_cata.TYPE_CATA):return 'TYPE'
954   elif isinstance(o,definition_cata.NIVEAU_CATA) : return 'NIVEAU'
955   else:return type(o)
956
957 def TYPE_COMPLET(o):
958   if isinstance(o,definition_cata.OPER_CATA):return "OPERATEUR"
959   elif isinstance(o,definition_cata.PROC_CATA):return "PROCEDURE"
960   elif isinstance(o,definition_cata.MACRO_CATA):return "MACRO"
961   elif isinstance(o,definition_cata.SIMP_CATA):return "Mot-clé SIMPLE"
962   elif isinstance(o,definition_cata.FACT_CATA):return "Mot-clé FACTEUR"
963   elif isinstance(o,definition_cata.BLOC_CATA):return "BLOC"
964   elif isinstance(o,definition_cata.TYPE_CATA):return "Type"
965   elif isinstance(o,definition_cata.NIVEAU_CATA):return "Niveau"
966   else: return "Inconnu ("+`type(o)`+")"
967   
968 def make_objecttreeitem(appli,labeltext, object, setfunction=None,objet_cata_ordonne=None):
969     t = TYPE(object)
970     if dispatch.has_key(t):
971       c = dispatch[t]
972     else:
973       print 'on a un objet de type :',type(object),'  ',object
974       c = ATTRIBUTItem
975     return c(appli,labeltext, object, setfunction = setfunction,objet_cata_ordonne=objet_cata_ordonne)
976
977
978