Salome HOME
CCAR: merge de la version 1.14 dans la branche principale
[tools/eficas.git] / InterfaceTK / 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 Editeur.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: V1_14 $"
43 __Id__="$Id: cataediteur.py,v 1.1.4.3.4.1 2008-10-10 13:47:11 pnoyret 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.parent.appli.get_docu(self.node)
115       if cle_doc == None : return
116       cle_doc = string.replace(cle_doc,'.','')
117       commande = self.parent.appli.CONFIGURATION.exec_acrobat
118       nom_fichier = cle_doc+".doc"
119       rep_fichier = cle_doc[0:2]
120       fichier = os.path.abspath(os.path.join(self.parent.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
121       print 'commande =',commande
122       print 'fichier =',fichier
123       print 'existe =',os.path.isfile(fichier)
124       if os.name == 'nt':
125           os.spawnv(os.P_NOWAIT,commande,(commande,fichier))
126       elif os.name == 'posix':
127           script ="#!/usr/bin/sh \n%s %s" %(commande,nom_fichier)
128           pid = os.system(script)
129       
130   def supprimer(self):
131       """ Suppression du noeud courant """
132       if self.parent.modified == 'n' : self.parent.init_modif()
133       pere = self.node.parent
134       self.node.delete()
135       pere.select()
136       
137   def affiche(self):
138       """ Force l'affichage des fenêtres en cours """
139       self.tkraise()
140
141   def selectMC(self,name):
142       """ On retrouve le mot-clé sous le curseur pour affichage du fr """
143       cmd=self.node.item.get_definition()
144       texte_infos = ''
145       for e in cmd.entites.keys() :
146           if e == name :
147               texte_infos=getattr(cmd.entites[e],'fr')
148               break
149       if texte_infos == '' : texte_infos="Pas d'infos disponibles"
150       self.parent.appli.affiche_infos(texte_infos)
151
152   def defMC(self,name):
153       """ On ajoute un mot-clé à la commande : subnode """
154       if name == SEPARATEUR:return
155       if self.parent.modified == 'n' : self.parent.init_modif()
156       if name != "COMMENTAIRE":
157           self.node.append_child(name)
158       else :
159           self.ajout_commentaire()    
160
161   def selectFilsCmd(self,name):
162       pass
163           
164   def defFilsCmd(self,name):
165       pass
166     
167   def defCmdFirst(self,name):
168       """ On ajoute une commande ou un commentaire au début du fichier de commandes """
169       if name == SEPARATEUR:return
170       if self.parent.modified == 'n' : self.parent.init_modif()
171       if name != "COMMENTAIRE":
172           new_node = self.node.append_child(name,'first')
173       else :
174           new_node = self.ajout_commentaire_first()
175
176   def add_commande_avant(self,event=None):
177     pass
178
179   def add_commande_apres(self,event=None):
180     pass          
181         
182 class OngletPanel(Panel) :
183   """ Cette classe est virtuelle et doit être dérivée
184       Elle contient les principales méthodes d'affichage des différents onglets"""
185
186   def raisecmd(self,page):
187       self.nb.page(page).focus_set()
188       if page == 'Concept': self._any.focus()
189
190   def affiche(self):
191       page=self.nb.getcurselection()
192       self.nb.page(page).focus_set()
193       if page == 'Concept':self._any.component('entry').focus_set()
194       self.tkraise()
195
196   def makeConceptPage(self,page):
197       """ Crée la page de saisie du nom du concept """
198       self.label = Label(page,text='Nom du concept :')
199       self.label.place(relx=0.1,rely=0.4)
200       self._any = Entry(page,relief='sunken')
201       self._any.place(relx=0.35,rely=0.4,relwidth=0.5)
202       self._any.bind("<Return>",lambda e,s=self:s.execConcept())
203       self._any.bind("<KP_Enter>",lambda e,s=self:s.execConcept())
204       self._any.insert(0,self.node.item.GetText())
205       type_sd = self.node.item.object.get_type_sd_prod()
206       if type_sd :
207           txt = "L'opérateur courant retourne un objet de type %s" %type_sd
208           self.label = Label(page, text = txt)
209           self.label.place(relx=0.5,rely=0.55,anchor='n')
210       self._any.focus()
211           
212   def makeCommandePage(self,page):
213       """ Affiche la page d'ajout d'une commande relativement à l'objet commande sélectionné """
214       titre = "Où voulez-vous insérer une commande par rapport à %s" %self.node.item.object.nom
215       Label(page,text=titre).place(relx=0.5,rely=0.2,anchor='w')
216       b_avant = Button(page,text='AVANT',
217                        command = self.node.item.add_commande_avant)
218       b_apres = Button(page,text='APRES',
219                        command = self.node.item.add_commande_apres)
220       b_avant.place(relx=0.35,rely=0.5,anchor='w')
221       b_apres.place(relx=0.65,rely=0.5,anchor='w')
222
223   def deselectMC(self,name):
224       self.parent.appli.affiche_infos('')
225     
226   def get_liste_cmd(self):
227       listeCmd = self.node.item.object.niveau.definition.get_liste_cmd()
228       return listeCmd
229
230   def get_liste_fils_cmd(self):
231       return ['Mot-clé simple','Mot-clé facteur','Bloc']
232
233   def makeMoclesPage(self,page):
234       frame1 = Frame(page,height = 20)
235       frame1.pack(side='top',fill='x')
236       label = Label(frame1,text ="Le mot-clé choisi sera ajouté à la fin du catalogue")
237       label.pack(side='top')
238       frame2 = Frame(page)
239       frame2.pack(side='top',fill='both',expand=1)
240       liste_cmd = self.get_liste_fils_cmd()
241       liste_commandes = (("<Enter>",self.selectFilsCmd),
242                          ("<Leave>",self.deselectFilsCmd),
243                          ("<Double-Button-1>",self.defFilsCmd))
244       Liste = ListeChoix(self,frame2,liste_cmd,liste_commandes = liste_commandes,titre = "Mots-clés")
245       Liste.affiche_liste()
246
247   def deselectFilsCmd(self,name):
248       pass
249     
250   def makeJDCPage(self,page):
251       liste_cmd = self.get_liste_cmd()
252       liste_commandes = (("<Enter>",self.selectCmd),
253                          ("<Leave>",self.deselectCmd),
254                          ("<Double-Button-1>",self.defCmdFirst))
255       Liste = ListeChoix(self,page,liste_cmd,liste_commandes = liste_commandes,filtre='oui',titre = "Commandes")
256       Liste.affiche_liste()
257
258   def makeReglesPage(self,page) :
259     regles = []
260     regles = self.node.item.get_regles()
261     dictionnaire = self.node.item.get_mc_presents()
262     texte_regles = []
263     l_regles_en_defaut=[]
264     if len(regles) > 0:
265       i = 0
266       for regle in regles :
267         texte_regles.append(regle.gettext())
268         texte,test = regle.verif(dictionnaire)
269         if test == 0 : l_regles_en_defaut.append(i)
270         i = i+1
271     Liste = ListeChoix(self,page,texte_regles,liste_marques=l_regles_en_defaut,active='non',titre="Règles")
272     Liste.affiche_liste()
273     #self.afficheListe(page,texte_regles,self.selectRegle,self.execRegle)
274
275   def execConcept(self):
276       """ Nomme le concept SD retourné par l'étape """
277       if self.parent.modified == 'n' : self.parent.init_modif()
278       nom = self._any.get()
279       # Pourquoi node.etape ???
280       #test,mess = self.node.etape.item.nomme_sd(nom)
281       test,mess = self.node.item.nomme_sd(nom)
282       self.parent.appli.affiche_infos(mess)
283       self.node.racine.update()
284   
285   def changed(self):
286       pass
287
288   def makeAttributsPage(self,page):
289     l_attributs=self.node.item.object.attributs
290     d_defauts = self.node.item.object.attributs_defauts
291     for attribut in l_attributs :
292       attr = self.node.item.object.entites_attributs.get(attribut,None)
293       if attr.valeur is d_defauts[attribut] :
294         texte = attribut+' = '+repr(attr.valeur)+' (defaut)'
295       else:
296         texte = attribut+' = '+repr(attr.valeur)
297       Label(page,text=texte).pack(side='top')
298
299   def makeSimpPage(self,page):
300     texte = "Où voulez-vous ajouter un mot-clé simple ?"
301     Label(page,text=texte).place(relx=0.5,rely=0.3,anchor='center')
302     b1 = Button(page,text='AVANT '+self.node.item.object.nom,command=self.add_simp_avant)
303     b2 = Button(page,text='APRES '+self.node.item.object.nom,command=self.add_simp_apres)
304     b1.place(relx=0.5,rely=0.5,anchor='center')
305     b2.place(relx=0.5,rely=0.6,anchor='center')
306
307   def add_simp_avant(self,event=None):
308     """
309     Ajoute un mot-clé simple avant celui courant
310     """
311     self.node.append_brother('new_simp','before')
312     self.node.update()
313
314   def add_simp_apres(self,event=None):
315     """
316     Ajoute un mot-clé simple après celui courant
317     """
318     self.node.append_brother('new_simp','after')
319     self.node.update()    
320     
321 class TYPEPanel(Frame):
322   def __init__(self,parent,panneau,node) :
323       self.parent=parent
324       self.panneau = panneau
325       self.node=node
326       Frame.__init__(self,self.panneau)
327       self.place(x=0,y=0,relheight=1,relwidth=1)
328       self.creer_texte()
329
330   def creer_texte(self):
331       texte = "Le noeud sélectionné correspond à un type\n"
332       self.label = Label(self,text=texte)
333       self.label.place(relx=0.5,rely=0.4,relwidth=0.8,anchor='center')
334
335 class OPERPanel(OngletPanel):
336   def init(self):
337     nb = Pmw.NoteBook(self,raisecommand=self.raisecmd)
338     
339     nb.pack(fill = 'both', expand = 1)
340     self.nb=nb
341     nb.add('Mocles', tab_text='Ajouter mots-clés')
342     nb.add('Commandes',tab_text='Ajouter une commande')
343     self.makeMoclesPage(nb.page("Mocles"))
344     self.makeCommandePage(nb.page("Commandes"))
345     nb.tab('Mocles').focus_set()
346     nb.setnaturalsize()
347     self.affiche()
348
349 class SIMPPanel(OngletPanel):
350   def init(self):
351     nb = Pmw.NoteBook(self,raisecommand=self.raisecmd)
352     nb.pack(fill = 'both', expand = 1)
353     self.nb=nb
354     nb.add('generaux', tab_text='Données générales')
355     nb.add('ihm',tab_text='Données IHM')
356     nb.add('mocle',tab_text='Ajouter un mot-cle simple')
357     self.makeAttributsGenerauxPage(nb.page("generaux"))
358     self.makeAttributsIHMPage(nb.page("ihm"))
359     self.makeSimpPage(nb.page('mocle'))
360     nb.tab('generaux').focus_set()
361     nb.setnaturalsize()
362     self.affiche()
363
364   def makeAttributsGenerauxPage(self,page):
365     fr1 = Frame(page,bd=1,relief='raised')
366     fr2 = Frame(page,bd=1,relief='raised')
367     fr3 = Frame(page,bd=1,relief='raised')
368     fr4 = Frame(page,bd=1,relief='raised')
369     fr5 = Frame(page,bd=1,relief='raised')
370     fr1.place(relheight=0.14,relwidth=1,rely=0)
371     fr2.place(relheight=0.14,relwidth=1,rely=0.14)
372     fr3.place(relheight=0.29,relwidth=1,rely=0.28)
373     fr4.place(relheight=0.14,relwidth=1,rely=0.57)
374     fr5.place(relheight=0.28,relwidth=1,rely=0.71)
375     # nom du mot-clé
376     Label(fr1,text = 'Nom :').place(relx=0.05,rely=0.3,anchor='w')
377     self.e_nom = Entry(fr1)
378     self.e_nom.place(relx=0.35,rely=0.3,relwidth=0.3,anchor='w')
379     self.e_nom.bind("<Return>",lambda e,s=self : s.set_valeur_attribut('nom',None))
380     self.e_nom.bind("<KP_Enter>",lambda e,s=self : s.set_valeur_attribut('nom',None))
381     self.e_nom.insert(0,self.get_valeur_attribut('nom'))
382     # Statut
383     Label(fr1,text='Statut : ').place(relx=0.05,rely=0.7,anchor='w')
384     self.statut=StringVar()
385     valeurs_statut=[('obligatoire','o'),
386                     ('facultatif','f'),
387                     ('caché','c')
388                     ]
389     self.statut.set(self.node.item.object.get_valeur_attribut('statut'))
390     i=0
391     for text,mode in valeurs_statut:
392       b=Radiobutton(fr1,text=text,variable=self.statut,value=mode,
393                     command = lambda s=self,m=mode : s.set_valeur_attribut('statut',m))
394       b.place(relx=0.25+i*0.25,rely=0.7,anchor='w')
395       i=i+1
396     # Type ...
397     Label(fr2,text='Type de la valeur : ').place(relx=0.05,rely=0.5,anchor='w')
398     self.e_type = Entry(fr2)
399     self.e_type.place(relx=0.35,rely=0.5,relwidth=0.5,anchor='w')
400     self.e_type.insert(0,self.node.item.object.get_valeur_attribut('type'))
401     # Domaine de validité
402     Label(fr3,text='Domaine de validité : ').place(relx=0.05,rely=0.2,anchor='w')
403     self.domaine = StringVar()
404     self.domaine.set(self.node.item.object.get_valeur_attribut('domaine_validité'))
405     b1=Radiobutton(fr3,text='continu',variable=self.domaine,value='continu',
406                    command=lambda s=self,f=fr3 :s.change_domaine(f))
407     b2=Radiobutton(fr3,text='discret',variable=self.domaine,value='discret',
408                    command=lambda s=self,f=fr3 :s.change_domaine(f))
409     b1.place(relx=0.35,rely=0.2,anchor='w')
410     b2.place(relx=0.65,rely=0.2,anchor='w')
411     self.change_domaine(fr3)
412     # Défaut ...
413     if self.domaine.get() == 'continu':
414       # le développeur peut donner la valeur qu'il souhaite, moyennant la vérification de type...
415       Label(fr4,text='Valeur par défaut : ').place(relx=0.05,rely=0.5,anchor='w')
416       self.e_defaut = Entry(fr4)
417       self.e_defaut.place(relx=0.35,rely=0.5,relwidth=0.5,anchor='w')
418       if self.node.item.object.get_valeur_attribut('defaut') :
419         self.e_defaut.insert(0,self.node.item.object.get_valeur_attribut('defaut'))
420       self.e_defaut.bind("<Return>",lambda e,s=self : s.set_valeur_attribut('defaut',None))
421       self.e_defaut.bind("<KP_Enter>",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.e_val_min.bind("<KP_Enter>",lambda e,s=self : s.set_valeur_attribut('val_min',None))
538       self.set_valeur_attribut('val_min',self.get_valeur_attribut('val_min'))
539       # val_max
540       self.l_val_max = Label(fr3,text='Valeur maximale : ')
541       self.l_val_max.place(relx=0.05,rely=0.8,anchor='w')
542       self.e_val_max = Entry(fr3)
543       self.e_val_max.place(relx=0.35,rely=0.8,relwidth=0.5,anchor='w')
544       self.e_val_max.bind("<Return>",lambda e,s=self : s.set_valeur_attribut('val_max',None))
545       self.e_val_max.bind("<KP_Enter>",lambda e,s=self : s.set_valeur_attribut('val_max',None))
546       self.set_valeur_attribut('val_max',self.get_valeur_attribut('val_max'))
547
548 # ------------------------------------------------------------------
549 # Méthodes de validation des entrées faites par l'utilisateur
550 # ------------------------------------------------------------------
551
552   def get_valeur_attribut(self,nom_attr):
553     """
554     Demande à l'item de retourner la valeur de l'attribut nom_attr
555     """
556     return self.node.item.get_valeur_attribut(nom_attr)
557   
558   def set_valeur_attribut(self,nom_attr,new_valeur):
559     """
560     Affecte la valeur new_valeur à l'attribut nom_attr
561     Vérifie si celle-ci est valide, sinon restaure l'ancienne
562     """
563     if new_valeur is None :
564       widget = getattr(self,'e_'+nom_attr)
565       if hasattr(widget,'getcurselection'):
566         new_valeur = widget.getcurselection()
567       else:
568         new_valeur = widget.get()
569     print "on affecte %s a %s" %(str(new_valeur),nom_attr)
570     self.node.item.set_valeur_attribut(nom_attr,new_valeur)
571     self.node.update()
572
573   def change_into(self):
574     """
575     Méthode activée par double clic sur la ListBox d'affichage des valeurs discrètes possibles :
576     permet de changer la liste de ces valeurs
577     """
578     showinfo("Fonction non encore disponible",
579              "Vous ne pouvez pas encore modifier la liste into par cette IHM")
580     
581 class OBJECTItem(TreeItem):
582   def __init__(self,appli,labeltext,object,setfunction=None,objet_cata_ordonne = None):
583     self.appli = appli
584     self.labeltext = labeltext
585     self.object=object
586     self.setfunction = setfunction
587     self.objet_cata_ordonne = objet_cata_ordonne
588     
589   def GetLabelText(self):
590     return self.labeltext,None,None
591
592   def get_fr(self):
593     return ''
594   
595   def isMCList(self):
596     return 0
597
598   def isactif(self):
599     return 1
600
601   def add_commande_avant(self):
602     pass
603
604   def add_commande_apres(self):
605     pass
606
607   def set_valeur_attribut(self,nom_attr,new_valeur):
608     """
609     Affecte la valeur new_valeur à l'attribut nom_attr
610     Vérifie si celle-ci est valide, sinon restaure l'ancienne
611     """
612     old_valeur = self.object.get_valeur_attribut(nom_attr)
613     self.object.set_valeur_attribut(nom_attr,new_valeur)
614     verificateur = 'verif_'+nom_attr
615     if hasattr(self.object,verificateur):
616       if not getattr(self.object,verificateur)():
617         # la nouvelle valeur de nom_attr n'est pas valide : on restaure l'ancienne (sans vérification)
618         self.object.set_valeur_attribut(nom_attr,old_valeur)
619         print 'changement de valeur refuse'
620         return
621     print 'changement de valeur accepte'
622     self.object.init_modif()
623
624   def get_valeur_attribut(self,nom_attr):
625     """
626     Retourne la valeur de l'attribut nom_attr
627     """
628     return self.object.get_valeur_attribut(nom_attr)
629         
630 class CATAItem(OBJECTItem):
631   def GetSubList(self):
632     sublist=[]
633     for fils in self.object.entites_fils:
634       item = make_objecttreeitem(self.appli,fils.objet.label + " : ",fils,objet_cata_ordonne=self.objet_cata_ordonne)
635       sublist.append(item)
636     return sublist
637   
638   def GetIconName(self):
639     if self.object.isvalid():
640       return 'ast-green-square'
641     else:
642       return 'ast-red-square'
643
644   def GetText(self):
645     return "Catalogue %s" %self.appli.code
646
647   def add_commande_avant(self):
648     pass
649
650   def add_commande_apres(self):
651     pass
652
653      
654 def transforme_liste_dico(liste):
655   d={}
656   for item in liste :
657     d[item.nom]=item
658   return d
659       
660 class OPERItem(OBJECTItem):
661   panel = OPERPanel
662   def GetSubList(self):
663     sublist=[]
664     # on classe les fils dans l'ordre du catalogue ...
665     l_cles_fils = self.get_liste_mc_ordonnee()
666     # on crée les items fils ...
667     dico_fils = transforme_liste_dico(self.object.entites_fils)
668     for k in l_cles_fils :
669       typ = TYPE_COMPLET(dico_fils[k])
670       if type(self.objet_cata_ordonne) == types.InstanceType :
671         objet_cata = self.objet_cata_ordonne.entites[k]
672       else :
673         objet_cata = self.objet_cata_ordonne.get(k,None)
674       item = make_objecttreeitem(self.appli,typ + " : ",dico_fils[k],objet_cata_ordonne = objet_cata)
675       sublist.append(item)
676     return sublist
677
678   def GetText(self):
679     #return self.object.nom
680     return self.object.get_valeur_attribut('nom')
681
682   def get_liste_mc_ordonnee(self):
683     return self.objet_cata_ordonne.ordre_mc
684
685   def GetIconName(self):
686     if self.object.isvalid():
687       return 'ast-green-square'
688     else:
689       return 'ast-red-square'
690
691   def additem(self,name,pos):
692       if isinstance(name,TreeItem) :
693           cmd=self.object.addentite(name.getObject(),pos)
694       else :
695           cmd = self.object.addentite(name,pos)
696       typ = TYPE_COMPLET(cmd)
697       item = make_objecttreeitem(self.appli,typ + " : ", cmd)
698       return item
699
700   def get_attribut(self,nom):
701     if nom == 'nature': return 'OPERATEUR'
702
703   def get_liste_mc_presents(self):
704     return []
705
706   def verif_condition_regles(self,liste):
707     return []
708   
709 class PROCItem(OPERItem):
710   panel = OPERPanel
711   
712 class MACROItem(OPERItem):
713   panel = OPERPanel
714     
715 class SIMPItem(OPERItem):
716   panel = SIMPPanel
717   
718   def GetIconName(self):
719     if self.object.isvalid():
720       return 'ast-green-ball'
721     else:
722       return 'ast-red-ball'
723
724   def IsExpandable(self):
725     return 0
726
727   def GetSubList(self):
728     return []
729   
730 class FACTItem(OPERItem):
731   def GetIconName(self):
732     if self.object.isvalid():
733       return 'ast-green-los'
734     else:
735       return 'ast-red-los'
736
737 class BLOCItem(FACTItem): pass
738
739 class TYPEItem(SIMPItem):
740   panel = TYPEPanel
741   def get_dico_attributs(self):
742     self.d_attributs = {}
743
744   def GetSubList(self):
745     return []
746
747   def IsExpandable(self):
748     return 0
749
750   def GetText(self):
751     return self.object.nom
752
753 class NIVEAUItem(OPERItem):
754   def IsExpandable(self):
755       return 1
756
757   def get_liste_mc_ordonnee(self):
758     l=[]
759     for fils in self.object.entites_fils:
760       l.append(fils.nom)
761     return l
762   
763   def GetSubList(self):
764     sublist=[]
765     # on classe les fils dans l'ordre du catalogue ...
766     l_cles_fils = self.get_liste_mc_ordonnee()
767     # on crꥠles items fils ...
768     dico_fils = transforme_liste_dico(self.object.entites_fils)
769     for k in l_cles_fils :
770       typ = TYPE_COMPLET(dico_fils[k])
771       if type(self.objet_cata_ordonne) == types.InstanceType :
772         objet_cata = self.objet_cata_ordonne.entites[k]
773       else :
774         objet_cata = self.objet_cata_ordonne.get(k,None)
775       item = make_objecttreeitem(self.appli,typ + " : ",dico_fils[k],objet_cata_ordonne = objet_cata)
776       sublist.append(item)
777     return sublist
778   
779   def GetLabelText(self):
780       """ Retourne 3 valeurs :
781         - le texte à afficher dans le noeud représentant l'item
782         - la fonte dans laquelle afficher ce texte
783         - la couleur du texte
784       """
785       return self.labeltext,Fonte_Niveau,'#00008b'
786     
787   def GetIconName(self):
788     if self.object.isvalid():
789       return "ast-green-text"
790     else:
791       return 'ast-red-text'
792
793   def additem(self,name,pos):
794       if isinstance(name,TreeItem) :
795           cmd=self.object.addentite(name.getObject(),pos)
796       else :
797           cmd = self.object.addentite(name,pos)
798       typ = TYPE_COMPLET(obj)
799       item = make_objecttreeitem(self.appli,typ+ " : ", cmd)
800       return item
801
802   def suppitem(self,item) :
803     # item = item de l'ETAPE à supprimer du JDC
804     # item.getObject() = ETAPE ou _C
805     # self.object = JDC
806     itemobject=item.getObject()
807     if self.object.suppentite(itemobject):
808        if isinstance(itemobject,_C):
809           message = "Commentaire supprimé"
810        else :
811           message = "Commande " + itemobject.nom + " supprimée"
812        self.appli.affiche_infos(message)
813        return 1
814     else:
815        self.appli.affiche_infos("Pb interne : impossible de supprimer cet objet")
816        return 0
817
818   def GetText(self):
819       return ''
820     
821 class ATTRIBUTItem(SIMPItem):
822   def get_dico_attributs(self):
823     self.d_attributs = {}
824
825   def GetSubList(self):
826     return []
827
828   def IsExpandable(self):
829     return 0
830
831   def GetText(self):
832     return self.object
833
834   def GetIconName(self):
835     return 'aucune' 
836
837 class CataEditeur:
838   def __init__(self,parent,appli,cata):
839     self.parent = parent
840     self.cata = definition_cata.CATALOGUE(cata)
841     self.appli = appli
842     self.top = Toplevel()
843     self.top.geometry("800x500")
844     self.top.title("Edition d'un catalogue")
845     self.init()
846
847   def close(self):
848     self.top.destroy()
849
850   def init(self):
851     self.nodes={}
852     self.creerbarremenus()
853     self.pane = Pmw.PanedWidget(self.top,
854                                 hull_width = 800,
855                                 hull_height = 500,
856                                 orient = 'horizontal')
857     self.pane.add('canvas',min = 0.4, max = 0.6, size = 0.45)
858     self.pane.add('panel',min = 0.4, max = 0.6, size = 0.55)
859     self.pane.pack(expand =1, fill = 'both')
860     self.scrolledcanvas = Pmw.ScrolledCanvas(self.pane.pane('canvas'),
861                                              hull_width=1.,
862                                              hull_height=1.,
863                                              borderframe=1)
864     Pmw.Color.changecolor(self.scrolledcanvas.component('canvas'),background='gray95')
865     self.scrolledcanvas.pack(padx=10,pady=10,expand=1, fill="both")
866     self.item = CATAItem(self.appli,"Catalogue",
867                            self.cata,
868                           objet_cata_ordonne = self.appli.readercata.cata_ordonne_dico)
869
870     self.tree = Tree(self.appli,self.item,self.scrolledcanvas,command = self.select_node)
871     self.tree.draw()
872     self.node = self.tree.node_selected
873
874   def creerbarremenus(self) :
875       self.menubar=Menu(self.top)
876       self.filemenu=Menu(self.menubar,tearoff=0)
877       self.filemenu.add_command(label='Quitter',command=self.quit)
878
879       self.editmenu=Menu(self.menubar,tearoff=0)
880       #self.editmenu.add_command(label='Copier',command=self.copy)
881       #self.editmenu.add_command(label='Couper',command=self.cut)
882       #self.editmenu.add_command(label='Coller',command=self.paste)
883
884       self.affichagemenu=Menu(self.menubar,tearoff=0)
885       self.affichagemenu.add_command(label='Rapport de validation',
886                                      command = self.visuCR)
887       self.affichagemenu.add_command(label='shell',command = self.shell)
888       #self.affichagemenu.add_command(label='Fichier ࡰlat',command=self.visu_a_plat)
889       #self.affichagemenu.add_command(label='Fichier .py',command =self.visuJDC_py)
890       #self.affichagemenu.add_command(label='Fichier source',command = self.visu_txt_brut_JDC)
891       #self.affichagemenu.add_command(label='Param鵲es Eficas',command=self.affichage_fichier_ini)
892       
893       #self.optionmenu=Menu(self.menubar,tearoff=0)
894       #self.optionmenu.add_command(label='Catalogue d귥loppeur',command=self.choix_cata_developpeur)
895
896       self.menubar.add_cascade(label='Fichier',menu=self.filemenu)
897       self.menubar.add_cascade(label='Edition',menu=self.editmenu)
898       self.menubar.add_cascade(label='Jeu de commandes',menu=self.affichagemenu)
899       #self.menubar.add_cascade(label='Browsers',menu=self.browsermenu)
900       #self.menubar.add_cascade(label='Catalogue',menu=self.cataloguemenu)
901       #self.menubar.add_cascade(label='Options',menu=self.optionmenu)
902       self.top.configure(menu=self.menubar)
903       self.top.protocol("WM_DELETE_WINDOW",self.quit)
904       self.top.minsize(900,500)
905       self.top.geometry("900x500")
906
907   def shell(self,event=None):
908       import Interp
909       d={'j':self.tree.item.getObject()}
910       Interp.InterpWindow(d,parent=self.parent)
911       
912   def visuCR(self,mode='Cata'):
913     txt = str(self.cata.report())
914     titre="Rapport de validation du catalogue"
915     Fenetre(self.appli,titre=titre,texte=txt)
916   
917   def select_node(self,node):
918     self.nodes[node]=self.create_panel(node)
919
920   def create_panel(self,node):
921     if hasattr(node.item,"panel"):
922       return getattr(node.item,"panel")(self,self.pane.pane('panel'),node)
923       
924   def quit(self) :
925     self.top.destroy()
926     
927   def settitle(self):
928     self.top.wm_title("Browser de catalogue " )
929     self.top.wm_iconname("CataBrowser")
930
931  
932 dispatch = {
933     'OPER'   : OPERItem,
934     'PROC'   : PROCItem,
935     'MACRO'  : MACROItem,
936     'SIMP'   : SIMPItem,
937     'FACT'   : FACTItem,
938     'BLOC'   : BLOCItem,
939     'TYPE'   : TYPEItem,
940     'NIVEAU' : NIVEAUItem
941 }
942
943 def TYPE(o):
944   if isinstance(o,definition_cata.OPER_CATA):return 'OPER'
945   elif isinstance(o,definition_cata.PROC_CATA):return 'PROC'
946   elif isinstance(o,definition_cata.MACRO_CATA):return 'MACRO'
947   elif isinstance(o,definition_cata.SIMP_CATA):return 'SIMP'
948   elif isinstance(o,definition_cata.FACT_CATA):return 'FACT'
949   elif isinstance(o,definition_cata.BLOC_CATA):return 'BLOC'
950   elif isinstance(o,definition_cata.TYPE_CATA):return 'TYPE'
951   elif isinstance(o,definition_cata.NIVEAU_CATA) : return 'NIVEAU'
952   else:return type(o)
953
954 def TYPE_COMPLET(o):
955   if isinstance(o,definition_cata.OPER_CATA):return "OPERATEUR"
956   elif isinstance(o,definition_cata.PROC_CATA):return "PROCEDURE"
957   elif isinstance(o,definition_cata.MACRO_CATA):return "MACRO"
958   elif isinstance(o,definition_cata.SIMP_CATA):return "Mot-clé SIMPLE"
959   elif isinstance(o,definition_cata.FACT_CATA):return "Mot-clé FACTEUR"
960   elif isinstance(o,definition_cata.BLOC_CATA):return "BLOC"
961   elif isinstance(o,definition_cata.TYPE_CATA):return "Type"
962   elif isinstance(o,definition_cata.NIVEAU_CATA):return "Niveau"
963   else: return "Inconnu ("+`type(o)`+")"
964   
965 def make_objecttreeitem(appli,labeltext, object, setfunction=None,objet_cata_ordonne=None):
966     t = TYPE(object)
967     if dispatch.has_key(t):
968       c = dispatch[t]
969     else:
970       print 'on a un objet de type :',type(object),'  ',object
971       c = ATTRIBUTItem
972     return c(appli,labeltext, object, setfunction = setfunction,objet_cata_ordonne=objet_cata_ordonne)
973
974
975