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