]> SALOME platform Git repositories - tools/eficas.git/blob - Editeur/composimp.py
Salome HOME
This commit was generated by cvs2git to track changes on a CVS vendor
[tools/eficas.git] / Editeur / composimp.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 string,types,os
22 from Tkinter import *
23 import Pmw
24 from tkFileDialog import *
25 from tkMessageBox import showinfo
26 from copy import copy,deepcopy
27 import traceback
28
29 # Modules Eficas
30 import Objecttreeitem
31 import prefs
32 import panels
33 import images
34 from widgets import ListeChoix
35 from widgets import FenetreDeSelection
36
37 from Noyau.N_CR import justify_text
38 from utils import substract_list
39
40
41 class newSIMPPanel(panels.OngletPanel):
42   """
43   Classe virtuelle servant de classe mère à toutes les classes Panel
44   servant à afficher et récupérer la valeur d'un mot-clé simple.
45   Le panel est différent suivant le type de la valeur attendu
46   """
47   def init(self):
48       """
49       Méthode appelée par le constructeur de OngletPanel :
50       construit le notebook à 2 onglets utilisé par tous les panels de
51       tous les mots-clés simples
52       """
53       nb = Pmw.NoteBook(self,raisecommand=self.raisecmd)
54       nb.pack(fill = 'both', expand = 1)
55       self.nb=nb
56       nb.add('Valeur', tab_text='Saisir valeur')
57       #nb.add('Commentaire',tab_text='Insérer commentaire')
58       self.makeValeurPage(nb.page('Valeur'))
59       #self.makeCommentairePage(nb.page("Commentaire"))
60       nb.setnaturalsize()
61       
62 # ----------------------------------------------------------------------------------------
63 #   Méthodes utilisées pour l'affectation de la valeur donnée par l'utilisateur
64 #    au mot-clé courant
65 # ----------------------------------------------------------------------------------------
66
67   def record_valeur(self,name=None,mess='Valeur du mot-clé enregistrée'):
68       """
69           Enregistre  val comme valeur de self.node.item.object SANS 
70           faire de test de validité
71       """
72       if self.parent.modified == 'n' : self.parent.init_modif()
73       if name != None:
74           valeur =name
75       else :
76           #XXX Pourquoi proceder ainsi ? Il n'est pas possible de mettre
77           # None comme valeur du mot cle. 
78           # Probablement que ce debranchement permet de mettre record_valeur
79           # en call back, il faut donc aller chercher la valeur dans l'entry
80           valeur= self.entry.get()
81           self.entry.delete(0,END)
82           #XXX Pour permettre la mise a None du mot cle, on remet None si valeur == ''
83           if valeur == '':valeur=None
84       self.node.item.set_valeur(valeur,evaluation='non')
85       self.parent.appli.affiche_infos(mess)
86       if self.node.item.get_position()=='global':
87           self.node.etape.verif_all()
88       elif self.node.item.get_position()=='global_jdc':
89           self.node.racine.verif_all()
90       else :
91           self.node.parent.verif()
92       self.node.update()
93       if self.node.item.isvalid():
94           self.node.parent.select()
95
96 # ----------------------------------------------------------------------------------------
97 #   Méthodes utilisées pour la manipulation des items dans les listes de choix
98 # ----------------------------------------------------------------------------------------
99   def selectValeur(self,name):
100       self.selected_valeur = name
101
102   def deselectValeur(self,name):
103       self.selectValeur = None
104
105   def sup_valeur(self,name=None):
106       """
107       Supprime la valeur selectionnée de la liste des valeurs et la rajoute
108       à la liste des choix possibles
109       """
110       liste_valeurs = self.Liste_valeurs.get_liste()
111       liste_valeurs.remove(self.selected_valeur)
112       liste_choix = self.node.item.get_definition().into
113       liste_choix = substract_list(liste_choix,liste_valeurs)
114       self.Liste_valeurs.put_liste(liste_valeurs)
115       self.Liste_choix.put_liste(liste_choix)
116       self.selected_valeur = None
117
118   def add_choix(self,name=None):
119       """
120       Ajoute le choix selectionné à la liste des valeurs et le retire
121       de la liste des choix possibles
122       """
123       min,max = self.node.item.GetMinMax()
124       liste_valeurs = self.Liste_valeurs.get_liste()
125       if len(liste_valeurs) >= max :
126           self.parent.appli.affiche_infos("La liste ne peut pas avoir plus de %d éléments" %max)
127           return
128       liste_valeurs.append(self.selected_choix)
129       liste_choix = self.Liste_choix.get_liste()
130       # PN en attendant mieux
131       if "TYPE_ANCRAGE" not in self.node.item.get_genealogie():
132          liste_choix.remove(self.selected_choix)
133       self.Liste_valeurs.put_liste(liste_valeurs)
134       self.Liste_choix.put_liste(liste_choix)
135       self.selected_choix = None
136
137   def selectChoix(self,name):
138       self.selected_choix = name
139
140   def deselectChoix(self,name):
141       self.selectChoix = None
142       
143   def raisecmd(self,page):
144       try:
145          self.entry.focus()
146       except:
147          pass
148
149 class SHELLPanel(newSIMPPanel):
150   """
151   Classe Panel utilisé pour les mots-clés simples qui attendent un shell pour valeur
152   """
153
154   def makeValeurPage(self,page):
155       """ 
156       Affiche la page concernant l'objet pointé par self qui attend un shell
157       """
158       objet_mc = self.node.item.get_definition()
159       aide = self.gen_aide()
160       aide = justify_text(texte=aide)
161       self.frame = Frame(page)
162       self.frame.place(relx=0,rely=0,relwidth=1,relheight=1)
163       label_aide = Label(self.frame,text = aide)
164       label_aide.place(relx=0.5,rely=0.1,anchor='center')
165       self.text = Text(self.frame,bg='gray95')
166       self.text.place(relx=0.2,rely=0.2,relwidth=0.6,relheight=0.6)
167       but_val = Button(self.frame,text='Valider',command = self.valide_shell)
168       but_ann = Button(self.frame,text='Annuler',command = self.annule_shell)
169       but_val.place(relx=0.35,rely=0.9,anchor='center')
170       but_ann.place(relx=0.65,rely=0.9,anchor='center')
171       self.display_valeur()
172
173   def gen_aide(self):
174       """
175       Retourne une chaîne de caractères d'aide sur la valeur qu'attend l'objet
176       pointé par self
177       """
178       return "Un shell est attendu"
179     
180   def valide_shell(self,event=None):
181       """
182       Récupère la valeur saisie par l'utilisateur dans self.text
183       et la stocke dans l'objet MCSIMP courant
184       """
185       texte = self.text.get(1.0,END)
186       self.record_valeur(texte)
187
188   def annule_shell(self,event=None):
189       """
190       Annule toute saisie dans self.text
191       """
192       self.text.delete(0,END)
193
194   def display_valeur(self,val=None):
195       """
196       Affiche la valeur de l'objet pointé par self
197       """
198       if val != None :
199           valeur = val
200       else:
201           valeur = self.node.item.get_valeur()
202       if valeur == None : return
203       self.text.insert(END,valeur)
204
205 class PLUSIEURS_Panel(newSIMPPanel):
206   """
207   Classe virtuelle servant de classe mère à toutes celles définissant
208   un panneau pour un mot-clé simple qui attend une liste de valeurs
209   """
210   def accepte_modifs_valeur(self,min,max):
211       """
212       Méthode qui récupère la liste des valeurs donnée par l'utilisateur
213       et l'affecte au mot-clé courant.
214       """
215       l1_valeurs = self.Liste_valeurs.get_liste()
216       # PN : remplacement des paramétres par leur nom (cf get_liste)
217       #      
218       l_valeurs=[]
219       for  val in l1_valeurs :
220            if val.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'):
221                 v=val.nom
222            else:
223                 v=val
224            l_valeurs.append(v)
225     
226       print "l_valeurs = ", l_valeurs
227       longueur = len(l_valeurs)
228       if longueur < min or longueur > max :
229           self.parent.appli.affiche_infos("Valeur refusée : nombre d'éléments incorrect dans la liste")
230           return
231       if longueur > 1:
232          valeur = tuple(l_valeurs)
233       elif longueur == 1:
234          valeur = l_valeurs[0]
235       else:
236          valeur = None
237       self.parent.appli.affiche_infos("Valeur acceptée")
238       print "valeur = " ,valeur
239       self.record_valeur(valeur)
240       if self.node.item.isvalid():
241           self.node.parent.select()
242       # fermeture de la fenêtre de sélection
243       if self.ajout_valeurs:
244           self.ajout_valeurs.quit()
245           
246   def annule_modifs_valeur(self):
247       """
248       RAZ de la liste des valeurs (annule toutes les valeurs saisies par l'utilisateur)
249       """
250       self.node.select()
251       # fermeture de la fenêtre de sélection
252       if self.ajout_valeurs:
253           self.ajout_valeurs.quit()
254           
255   def traite_reel(self,valeur):
256       """
257       Cette fonction a pour but de rajouter le '.' en fin de chaîne pour un réel
258       ou de détecter si on fait référence à un concept produit par DEFI_VALEUR
259       ou un EVAL ...
260       """
261       valeur = string.strip(valeur)
262       liste_reels = self.node.item.get_sd_avant_du_bon_type()
263       if valeur in liste_reels:
264           return valeur
265       if len(valeur) >= 3 :
266           if valeur[0:4] == 'EVAL' :
267               # on a trouvé un EVAL --> on retourne directement la valeur
268               return valeur
269       if string.find(valeur,'.') == -1 :
270           # aucun '.' n'a été trouvé dans valeur --> on en rajoute un à la fin
271           return valeur+'.'
272       else:
273           return valeur
274         
275   def add_valeur_sans_into(self,name=None):
276       """
277       Lit ce que l'utilisateur a saisi dans self.entry et cherche à
278       l'évaluer :
279       - si la valeur est acceptable, elle est ajoutée dans la liste des valeurs
280       - sinon elle est refusée
281       """
282       min,max = self.node.item.GetMinMax()
283       if name != None :
284           valeur = name
285       else:
286           valeur = self.get_valeur()
287       if self.node.item.wait_reel():
288           valeur = self.traite_reel(valeur)
289       if self.node.item.wait_geom():
290           val,test1 = valeur,1
291       else:
292           val,test1 = self.node.item.object.eval_valeur(valeur)
293       if test1 :
294           test2 = self.node.item.object.verif_type(val)
295           if test2 :
296               liste_valeurs = self.Liste_valeurs.get_liste()
297               if len(liste_valeurs) >= max :
298                   self.parent.appli.affiche_infos("La liste a déjà atteint le nombre maximum d'éléments, ajout refusé")
299                   self.erase_valeur()
300                   return
301               liste_valeurs.append(val)
302               self.Liste_valeurs.put_liste(liste_valeurs)
303               self.erase_valeur()
304               self.parent.appli.affiche_infos("Nouvelle valeur acceptée")
305           else:
306               self.parent.appli.affiche_infos("Valeur incorrecte : ajout à la liste refusé")
307       else:
308           print "impossible d'évaluer %s" %val
309           self.parent.appli.affiche_infos("Valeur incorrecte : ajout à la liste refusé")
310       #if self.node.item.isvalid():
311       #    self.node.parent.select()
312
313   def sup_valeur_sans_into(self,name=None):
314       """
315       Méthode qui sert à retirer de la liste des valeurs la valeur sélectionnée
316       """
317       liste_valeurs = self.Liste_valeurs.get_liste()
318       try:
319           liste_valeurs.remove(self.selected_valeur)
320       except:
321           # la valeur sélectionnée n'est pas dans la liste
322           return
323       self.Liste_valeurs.put_liste(liste_valeurs)
324       #self.display_valeur('')
325       self.display_valeur(self.selected_valeur)
326       self.selected_valeur = None      
327
328   def display_valeur(self,val=None):
329       """
330       Affiche la valeur passée en argument dans l'entry de saisie.
331       Par défaut affiche la valeur du mot-clé simple
332       """
333       if not val :
334           valeur = self.node.item.getval()
335       else:
336           valeur = val
337       self.entry.delete(0,END)
338       if not valeur : return
339       self.entry.insert(0,str(valeur))
340       
341             
342 class PLUSIEURS_INTO_Panel(PLUSIEURS_Panel):
343   """
344   Classe servant à définir le panneau permettant d'afficher et de saisir une
345   liste de valeurs à choisir parmi une liste discrètes de valeurs possibles
346   """
347   def makeValeurPage(self,page):
348       """
349       Génère la page de saisie de plusieurs valeurs parmi un ensemble discret
350       de possibles
351       """
352       self.ajout_valeurs = None
353       # On récupère la bulle d'aide du panneau, l'objet, min et max (cardinalité de la liste),
354       # la liste des choix et la liste des valeurs
355       aide = self.get_aide()
356       aide = justify_text(texte=aide)
357       bulle_aide=self.get_bulle_aide()
358       objet_mc = self.node.item.get_definition()
359       min,max = self.node.item.GetMinMax()
360       l_choix=list(objet_mc.into)
361       l_choix.sort()
362       l_valeurs = self.node.item.GetListeValeurs()
363       # remplissage du panneau
364       self.frame_valeurs = Frame(page)
365       self.frame_valeurs.place(relx=0.05,rely=0.05,relwidth=0.35,relheight=0.7)
366       self.frame_boutons_fleches = Frame(page)
367       self.frame_boutons_fleches.place(relx=0.4,rely=0.,relwidth=0.2,relheight=0.7)
368       self.frame_choix = Frame(page)
369       self.frame_choix.place(relx=0.6,rely=0.05,relwidth=0.35,relheight=0.7)
370       self.frame_boutons = Frame(page)
371       self.frame_boutons.place(relx=0.35,rely=0.87,relwidth=0.3,relheight=0.1)
372       self.frame_aide = Frame(page)
373       self.frame_aide.place(relx=0.1,rely=0.75,relwidth=0.9,relheight=0.1)
374       liste_commandes_valeurs = (("<Button-1>",self.selectValeur),
375                                  ("<Button-3>",self.deselectValeur),
376                                  ("<Double-Button-1>",self.sup_valeur))
377       liste_commandes_choix = (("<Button-1>",self.selectChoix),
378                                ("<Button-3>",self.deselectChoix),
379                                ("<Double-Button-1>",self.add_choix))
380       self.Liste_valeurs = ListeChoix(self,self.frame_valeurs,l_valeurs,liste_commandes = liste_commandes_valeurs,
381                                       titre="Valeur(s) actuelle(s)")
382       self.Liste_choix = ListeChoix(self,self.frame_choix,l_choix,liste_commandes = liste_commandes_choix,
383                                     titre= "Valeurs possibles")
384       bouton_add = Button(self.frame_boutons_fleches,
385                           #text="<--",
386                           image = images.get_image('arrow_left'),
387                           command = self.add_choix)
388       bouton_sup = Button(self.frame_boutons_fleches,
389                           #text="-->",
390                           image = images.get_image('arrow_right'),
391                           command = self.sup_valeur)
392       bouton_accepter = Button(self.frame_boutons,
393                                text='Valider',
394                                command = lambda s=self,m=min,M=max : s.accepte_modifs_valeur(m,M))
395       bouton_annuler = Button(self.frame_boutons,
396                               text = 'Annuler',
397                               command = self.annule_modifs_valeur)
398       bouton_add.place(relx=0.3,rely=0.35)
399       bouton_sup.place(relx=0.3,rely=0.65)
400       for but in (bouton_accepter,bouton_annuler):
401           but.pack(side='left',padx=5)
402       self.Liste_valeurs.affiche_liste()
403       self.Liste_choix.affiche_liste()
404       for fram in (self.frame_valeurs,self.frame_boutons_fleches,self.frame_choix,self.frame_boutons):
405           fram.bind("<Button-3>",lambda e,s=self,a=bulle_aide : s.parent.appli.affiche_aide(e,a))
406           fram.bind("<ButtonRelease-3>",self.parent.appli.efface_aide)
407       self.frame_aide.update()
408       self.aide = Label(self.frame_aide,
409                         text = aide,
410                         justify='center',
411                         anchor='center',
412                         wraplength=int(self.frame_aide.winfo_width()*0.8))
413       self.aide.place(relx=0.5,rely=0.5,anchor='center',relwidth=1)
414
415   def get_aide(self):
416       """
417       Retourne la phrase d'aide indiquant de quel type de base doivent être les valeurs
418       que saisit l'utilisateur
419       """
420       mc = self.node.item.get_definition()
421       d_aides = { 'TXM' : 'chaînes de caractères',
422                   'R'   : 'réels',
423                   'I'   : 'entiers',
424                   'C'   : 'complexes'}
425       type = mc.type[0]
426       if not d_aides.has_key(type) : 
427          if mc.min == mc.max:
428             return str(mc.min)+" valeur(s) est(sont) attendue(s)"
429          else :
430             return "entrez entre "+str(mc.min)+" et "+str(mc.max)+" valeurs"
431       if mc.min == mc.max:
432           return "Une liste de "+str(mc.min)+" "+d_aides[type]+" est attendue"
433       else :
434           return "Entre "+str(mc.min)+" et "+str(mc.max)+" valeurs de type  "+d_aides[type]+" sont attendues"
435       return "  "
436
437   def get_bulle_aide(self):
438       """
439       Retourne la bulle d'aide du panneau (affichée par clic droit)
440       """
441       return """Un clic sur une valeur des deux listes la sélectionne.
442       - Un clic sur la flèche gauche stocke la valeur possible sélectionnée
443       dans la liste des valeurs que vous voulez affecter au mot-clé simple
444       - Un clic sur la flèche droite déstocke la valeur du mot-clé simple
445       sélectionnée (elle apparaît alors à nouveau comme choix possible
446       dans la liste des choix à droite)
447       - Cliquez sur 'Valider' pour affecter la liste des valeurs sélectionnées
448       au mot-clé simple courant
449       - Cliquez sur 'Annuler' pour restaurer la valeur du mot-clé simple
450       avant toute modification depuis le dernier 'Valider'"""
451
452 class PLUSIEURS_BASE_Panel(PLUSIEURS_Panel):
453   """
454   Classe définissant le panel associé aux mots-clés qui demandent
455   à l'utilisateur de donner une liste de valeurs qui ne sont pas
456   à choisir dans une liste discrètes et qui sont de type de base :
457   entier, réel, string,...
458   """
459   def makeValeurPage(self,page):
460       """
461       Crée la page de saisie d'une liste de valeurs à priori quelconques,
462       cad qui ne sont  pas à choisir dans une liste prédéfinie
463       """
464       # On récupère la bulle d'aide du panneau, l'objet, l'aide,min et max (cardinalité de la liste),
465       # et la liste des valeurs déjà affectées à l'objet courant
466       bulle_aide=self.get_bulle_aide()
467       objet_mc = self.node.item.get_definition()
468       aide = self.get_aide()
469       aide = justify_text(texte=aide)
470       min,max = self.node.item.GetMinMax()
471       l_valeurs = self.node.item.GetListeValeurs()
472       # création des frames globales
473       self.frame1 = Frame(page,relief='groove',bd=2)
474       self.frame2 = Frame(page)
475       self.frame1.place(relx=0.,rely=0.,relwidth=1.,relheight=0.85)
476       self.frame2.place(relx=0.,rely=0.85,relwidth=1,relheight=0.15)
477       self.frame_right = Frame(self.frame1)
478       self.frame_right.place(relx=0.35,rely=0.,relwidth=0.65,relheight=1.)
479       # création des frames internes
480       self.frame_valeurs = Frame(self.frame1)
481       self.frame_valeurs.place(relx=0.02,rely=0.05,relwidth=0.35,relheight=0.95)
482       self.frame_boutons_fleches = Frame(self.frame_right)
483       self.frame_boutons_fleches.place(relx=0.,rely=0.2,relwidth=0.2,relheight=0.5)
484       self.frame_choix = Frame(self.frame_right)
485       self.frame_choix.place(relx=0.2,rely=0.2,relwidth=0.7,relheight=0.5)
486       self.frame_aide = Frame(self.frame_right)
487       self.frame_aide.place(relx=0.1,rely=0.7,relwidth=0.8,relheight=0.3)
488       self.frame_boutons = Frame(self.frame2)
489       self.frame_boutons.place(relx=0.35,rely=0.,relwidth=0.3,relheight=1.)
490       for fram in (self.frame1,self.frame2,self.frame_right,self.frame_valeurs,
491                  self.frame_boutons_fleches,self.frame_choix,self.frame_aide,self.frame_boutons):
492           fram.bind("<Button-3>",lambda e,s=self,a=bulle_aide : s.parent.appli.affiche_aide(e,a))
493           fram.bind("<ButtonRelease-3>",self.parent.appli.efface_aide)
494       # création des objets dans les frames
495       liste_commandes_valeurs = (("<Button-1>",self.selectValeur),
496                                  ("<Button-3>",self.deselectValeur),
497                                  ("<Double-Button-1>",self.sup_valeur_sans_into))
498       self.Liste_valeurs = ListeChoix(self,self.frame_valeurs,l_valeurs,liste_commandes = liste_commandes_valeurs,
499                                       titre="Valeur(s) actuelle(s)")
500       # Création de l'entry ou de la liste des SD
501       self.label = Label(self.frame_choix,text="Valeur :")
502       self.make_entry(frame = self.frame_choix,command = self.add_valeur_sans_into)
503       self.label.place(relx=0.05,rely=0.5)
504       # Création d'un bouton "Importer ..." sur le panel.
505       bouton_valeurs_fichier = Button(self.frame_choix,
506                                       text="Importer ...",
507                                       command=self.select_in_file)
508       bouton_valeurs_fichier.place(relx=0.28,rely=0.7,relwidth=0.6)
509       self.ajout_valeurs = None
510       # boutons Ajouter et Supprimer
511       bouton_add = Button(self.frame_boutons_fleches,
512                           image = images.get_image('arrow_left'),
513                           command = self.add_valeur_sans_into)
514       bouton_sup = Button(self.frame_boutons_fleches,
515                           image = images.get_image('arrow_right'),
516                           command = self.sup_valeur_sans_into)
517       bouton_add.place(relx=0.3,rely=0.35)
518       bouton_sup.place(relx=0.3,rely=0.65)
519       # affichage de l'aide
520       self.frame_aide.update()
521       self.aide = Label(self.frame_aide,
522                         text = aide,
523                         justify='center',
524                         anchor='center',
525                         wraplength=int(self.frame_aide.winfo_width()*0.8))
526       self.aide.place(relx=0.5,rely=0.5,anchor='center',relwidth=1)
527       self.Liste_valeurs.affiche_liste()
528       # boutons Accepter et Annuler
529       bouton_accepter = Button(self.frame_boutons,
530                                text='Valider',
531                                command = lambda s=self,m=min,M=max : s.accepte_modifs_valeur(m,M))
532       bouton_annuler = Button(self.frame_boutons,
533                               text = 'Annuler',
534                               command = self.annule_modifs_valeur)
535       for but in (bouton_accepter,bouton_annuler):
536           but.pack(side='left',padx=5)
537
538   def select_in_file(self):
539       """ Permet d'ouvrir un fichier choisi par l'utilisateur. """
540       nom_fichier = askopenfilename(title="Choix fichier :")
541       if nom_fichier == "":
542           return
543       try:
544           f = open(nom_fichier, "rb")
545           selection_texte = f.read()
546           f.close()
547           self.ajout_valeurs = FenetreDeSelection(self, 
548                                                   self.node.item,
549                                                   self.parent.appli,
550                                                   titre="Sélection de valeurs",
551                                                   texte=selection_texte)
552       except:
553           traceback.print_exc()
554           showinfo("Erreur de fichier","impossible d'ouvir le fichier "+nom_fichier)
555           
556   def get_bulle_aide(self):
557       """
558       Retourne l'aide associée au panneau courant
559       """
560       return """Taper dans la boîte de saisie de droite la valeur que
561       vous voulez affecter au mot-clé simple.
562       - Cliquez sur la flèche gauche ou pressez <Return> pour la faire glisser
563       dans la liste des valeurs que vous voulez affecter au mot-clé simple
564       - Un clic sur une valeur de la liste la sélectionne
565       - Un clic sur la flèche droite ou un double-clic retire la valeur
566       sélectionnée de la liste
567       - Cliquez sur 'Valider' pour que la nouvelle valeur désirée soit affectée
568       au mot-clé simple
569       - Cliquez sur 'Annuler' pour annuler toutes les modifications faites
570       depuis le dernier clic sur 'Valider'"""
571
572   def get_aide(self):
573       """
574       Retourne la phrase d'aide indiquant de quel type de base doivent être les valeurs
575       que saisit l'utilisateur
576       """
577       mc = self.node.item.get_definition()
578       d_aides = { 'TXM' : 'chaînes de caractères',
579                   'R'   : 'réels',
580                   'I'   : 'entiers',
581                   'C'   : 'complexes'}
582       type = mc.type[0]
583       if not d_aides.has_key(type) : return 'Type de base inconnu'
584       if mc.min == mc.max:
585           return "Une liste de "+d_aides[type]+" chaînes de caractères est attendue"
586       else :
587           return "Une liste de "+d_aides[type]+" est attendue (min="+`mc.min`+",max="+`mc.max`+')'
588
589   def make_entry(self,frame,command):
590       """
591       Crée l'entry de saisie de la valeur souhaitée : distingue le
592       cas d'un complexe attendu, d'une autre valeur quelconque
593       """
594       if self.node.item.wait_complex():
595           self.typ_cplx=StringVar()
596           self.typ_cplx.set('RI')
597           rb1 = Radiobutton(frame, text='RI',variable=self.typ_cplx,value='RI')
598           rb2 = Radiobutton(frame, text='MP',variable=self.typ_cplx,value='MP')
599           self.entry1 = Pmw.EntryField(frame,validate='real')
600           self.entry2 = Pmw.EntryField(frame,validate='real')
601           rb1.place(relx=0.05,rely = 0.4)
602           rb2.place(relx=0.05,rely = 0.6)
603           self.entry1.component('entry').bind("<Return>",lambda e,s=self:s.entry2.component('entry').focus)
604           self.entry2.component('entry').bind("<Return>",lambda e,c=command:c())
605           self.entry1.place(relx=0.27,rely = 0.5,relwidth=0.35)
606           self.entry2.place(relx=0.65,rely = 0.5,relwidth=0.35)
607           self.entry1.focus()
608       else:
609           self.entry = Entry(frame,relief='sunken')
610           self.entry.place(relx=0.28,rely=0.5,relwidth=0.6)
611           self.entry.bind("<Return>",lambda e,c=command:c())
612           self.entry.focus()
613
614   def get_valeur(self):
615       """
616       Retourne la valeur saisie par l'utilisateur dans self.entry
617       """
618       return self.entry.get()
619
620   def erase_valeur(self):
621       """
622       Efface la valeur donnée par l'utilisateur dans l'entry
623       """
624       self.entry.delete(0,END)
625         
626 class PLUSIEURS_ASSD_Panel(PLUSIEURS_Panel):
627   """
628   Classe définissant le panel associé aux mots-clés qui demandent
629   à l'utilisateur de donner une liste de valeurs qui ne sont pas
630   à choisir dans une liste discrètes et qui sont de type dérivé d'ASSD
631   """
632   def makeValeurPage(self,page):
633       """
634       Génère la page de saisie de plusieurs noms de SD parmi un ensemble discret
635       de SD possibles, cad d'un type cohérent avec les types attendus par le mot-clé simple
636       """
637       # On récupère la bulle d'aide du panneau, l'objet, l'aide, min et max (cardinalité de la liste),
638       # la liste des valeurs déjà affectées à l'objet courant et la liste des SD du bon type
639       bulle_aide=self.get_bulle_aide()
640       self.ajout_valeurs=None
641       objet_mc = self.node.item.get_definition()
642       aide = self.get_aide()
643       aide = justify_text(texte=aide)
644       min,max = self.node.item.GetMinMax()
645       l_valeurs = self.node.item.GetListeValeurs()
646       l_choix=self.node.item.get_sd_avant_du_bon_type()
647       l_choix.sort()
648       # remplissage du panneau
649       self.frame_valeurs = Frame(page)
650       self.frame_valeurs.place(relx=0.05,rely=0.05,relwidth=0.35,relheight=0.7)
651       self.frame_boutons_fleches = Frame(page)
652       self.frame_boutons_fleches.place(relx=0.4,rely=0.,relwidth=0.2,relheight=0.7)
653       self.frame_choix = Frame(page)
654       self.frame_choix.place(relx=0.6,rely=0.05,relwidth=0.35,relheight=0.7)
655       self.frame_boutons = Frame(page)
656       self.frame_boutons.place(relx=0.35,rely=0.87,relwidth=0.3,relheight=0.1)
657       liste_commandes_valeurs = (("<Button-1>",self.selectValeur),
658                                  ("<Button-3>",self.deselectValeur),
659                                  ("<Double-Button-1>",self.sup_valeur_sans_into))
660       liste_commandes_choix = (("<Button-1>",self.selectChoix),
661                                ("<Button-3>",self.deselectChoix),
662                                ("<Double-Button-1>",self.add_valeur_sans_into))
663       self.Liste_valeurs = ListeChoix(self,self.frame_valeurs,l_valeurs,liste_commandes = liste_commandes_valeurs,
664                                       titre="Valeur(s) actuelle(s)")
665       self.Liste_choix = ListeChoix(self,self.frame_choix,l_choix,liste_commandes = liste_commandes_choix,
666                                     titre= "Valeurs possibles")
667       bouton_add = Button(self.frame_boutons_fleches,
668                           #text="<--",
669                           image = images.get_image('arrow_left'),
670                           command = self.add_valeur_sans_into)
671       bouton_sup = Button(self.frame_boutons_fleches,
672                           #text="-->",
673                           image = images.get_image('arrow_right'),
674                           command = self.sup_valeur_sans_into)
675       bouton_accepter = Button(self.frame_boutons,
676                                text='Valider',
677                                command = lambda s=self,m=min,M=max : s.accepte_modifs_valeur(m,M))
678       bouton_annuler = Button(self.frame_boutons,
679                               text = 'Annuler',
680                               command = self.annule_modifs_valeur)
681       bouton_add.place(relx=0.3,rely=0.35)
682       bouton_sup.place(relx=0.3,rely=0.65)
683       for but in (bouton_accepter,bouton_annuler):
684           but.pack(side='left',padx=5)
685       self.Liste_valeurs.affiche_liste()
686       self.Liste_choix.affiche_liste()
687       for fram in (self.frame_valeurs,self.frame_boutons_fleches,self.frame_choix,self.frame_boutons):
688           fram.bind("<Button-3>",lambda e,s=self,a=bulle_aide : s.parent.appli.affiche_aide(e,a))
689           fram.bind("<ButtonRelease-3>",self.parent.appli.efface_aide)
690
691   def get_bulle_aide(self):
692       """
693       Retourne la bulle d'aide associée au panneau
694       """
695       return """Un clic sur une valeur des deux listes la sélectionne.
696       - Un clic sur la flèche gauche stocke la valeur possible sélectionnée
697       dans la liste des valeurs que vous voulez affecter au mot-clé simple
698       - Un clic sur la flèche droite déstocke la valeur du mot-clé simple
699       sélectionnée (elle apparaît alors à nouveau comme choix possible
700       dans la liste des choix à droite)
701       - Cliquez sur 'Valider' pour affecter la liste des valeurs sélectionnées
702       au mot-clé simple courant
703       - Cliquez sur 'Annuler' pour restaurer la valeur du mot-clé simple
704       avant toute modification depuis le dernier 'Valider'"""
705
706   def get_aide(self):
707       """
708       Retourne la phrase d'aide indiquant de quel type doivent être les
709       valeurs que doit entrer l'utilisateur
710       """
711       mc = self.node.item.get_definition()
712       type = mc.type[0].__name__  
713       if len(mc.type)>1 :
714           for typ in mc.type[1:] :
715               type = type + ' ou '+typ.__name__
716       if mc.min == mc.max:
717         return "Une liste de "+`mc.min`+" objets de type "+type+" est attendue"
718       else :
719         return "Une liste d'objets de type "+type+" est attendue (min="+`mc.min`+",max="+`mc.max`+')'
720     
721   def sup_valeur(self,name=None):
722       """
723       Supprime la valeur selectionnée de la liste des valeurs et la rajoute
724       à la liste des choix possibles
725       """
726       liste_valeurs = self.Liste_valeurs.get_liste()
727       liste_valeurs.remove(self.selected_valeur)
728       liste_choix = self.node.item.get_definition().into
729       liste_choix = substract_list(liste_choix,liste_valeurs)
730       self.Liste_valeurs.put_liste(liste_valeurs)
731       self.Liste_choix.put_liste(liste_choix)
732       self.selected_valeur = None      
733     
734   def erase_valeur(self):
735       pass
736
737   def get_valeur(self):
738       """
739       Retourne la valeur sélectionnée dans la liste des choix
740       """
741       return self.selected_choix
742
743   def display_valeur(self,val=None):
744       """
745          Affiche la valeur passée en argument dans l'entry de saisie.
746          Par défaut affiche la valeur du mot-clé simple
747       """
748       # Il n'y a pas d'entry pour ce type de panneau
749       return
750
751     
752 class UNIQUE_Panel(newSIMPPanel):
753   """
754   Classe virtuelle servant de classe mère à toutes celles définissant un panneau
755   permettant l'affichage et la saisie d'une valeur unique pour le mot-clé simple
756   """
757
758   def erase_valeur(self):
759       """
760       Efface l'entry de saisie
761       """
762       self.entry.delete(0,END)
763
764   def get_valeur(self):
765       """
766       Retourne la valeur donnée par l'utilisateur
767       """
768       return self.entry.get()
769     
770   def valid_valeur(self):
771       """
772       Teste si la valeur fournie par l'utilisateur est une valeur permise :
773       - si oui, l'enregistre
774       - si non, restaure l'ancienne valeur
775       """
776       if self.parent.modified == 'n' : self.parent.init_modif()
777       valeur = self.get_valeur()
778       self.erase_valeur()
779       anc_val = self.node.item.get_valeur()
780       test = self.node.item.set_valeur(valeur)
781       if not test :
782           mess = "impossible d'évaluer : %s " %`valeur`
783           self.parent.appli.affiche_infos("Valeur du mot-clé non autorisée :"+mess)
784       elif self.node.item.isvalid() :
785           self.parent.appli.affiche_infos('Valeur du mot-clé enregistrée')
786           if self.node.item.get_position()=='global':
787               self.node.etape.verif_all()
788           elif self.node.item.get_position()=='global_jdc':
789               self.node.racine.verif_all()
790           else :
791               self.node.parent.verif()
792           self.node.update()
793           self.node.parent.select()
794       else :
795           cr = self.node.item.get_cr()
796           mess = "Valeur du mot-clé non autorisée :"+cr.get_mess_fatal()
797           self.record_valeur(anc_val,mess=mess)
798
799 class UNIQUE_INTO_Panel(UNIQUE_Panel):
800   """
801   Classe définissant le panel associé aux mots-clés qui demandent
802   à l'utilisateur de choisir une seule valeur parmi une liste de valeurs
803   discrètes
804   """
805   def makeValeurPage(self,page):
806       """
807       Génère la page de saisie d'une seule valeur parmi un ensemble
808       discret de possibles
809       """
810       # récupération de la bulle d'aide et de l'objet mc
811       bulle_aide=self.get_bulle_aide()
812       objet_mc = self.node.item.get_definition()
813       # remplissage du panel
814       self.frame_valeur = Frame(page)
815       self.frame_valeur.pack(fill='both',expand=1)
816       self.frame_valeur.bind("<Button-3>",lambda e,s=self,a=bulle_aide : s.parent.appli.affiche_aide(e,a))
817       self.frame_valeur.bind("<ButtonRelease-3>",self.parent.appli.efface_aide)
818       l_choix=list(objet_mc.into)
819       l_choix.sort()
820       self.label = Label(self.frame_valeur,text='Choisir une valeur :')
821       self.label.pack(side='top')
822       self.frame = Frame(page)
823       self.frame.place(relx=0.33,rely=0.2,relwidth=0.33,relheight=0.6)
824       liste_commandes = (("<Button-1>",self.selectChoix),
825                          ("<Button-3>",self.deselectChoix),
826                          ("<Double-Button-1>",self.record_valeur))
827       self.Liste_choix = ListeChoix(self,self.frame,l_choix,liste_commandes = liste_commandes,
828                                     titre="Valeurs possibles")
829       self.Liste_choix.affiche_liste()
830
831   def get_bulle_aide(self):
832       """
833       Retourne la bulle d'aide affectée au panneau courant (affichée par clic droit)
834       """
835       return """Double-cliquez sur la valeur désirée
836       pour valoriser le mot-clé simple courant"""
837
838 class UNIQUE_ASSD_Panel(UNIQUE_Panel):
839   """
840   Classe servant à définir le panneau associé aux objets qui attendent une valeur unique
841   d'un type dérivé d'ASSD
842   """
843   def valid_valeur_automatique(self):
844       """
845          Réalise la validation d'un concept sans remonter dans le
846          node parent dans le cas ou il n'y a qu'un concept possible (liste de longueur 1)
847          Identique à valid_valeur moins appel de self.node.parent.select()
848          On pourrait supposer que le seul concept présent est valide et donc ne pas
849          réaliser tous les tests de vérification.
850       """
851       if self.parent.modified == 'n' : self.parent.init_modif()
852       valeur = self.get_valeur()
853       self.erase_valeur()
854       anc_val = self.node.item.get_valeur()
855       test = self.node.item.set_valeur(valeur)
856       if not test :
857           mess = "impossible d'évaluer : %s " %`valeur`
858           self.parent.appli.affiche_infos("Valeur du mot-clé non autorisée :"+mess)
859       elif self.node.item.isvalid() :
860           self.parent.appli.affiche_infos('Valeur du mot-clé enregistrée')
861           if self.node.item.get_position()=='global':
862               self.node.etape.verif_all()
863           elif self.node.item.get_position()=='global_jdc':
864               self.node.racine.verif_all()
865           else :
866               self.node.parent.verif()
867           self.node.update()
868           #self.node.parent.select()
869       else :
870           cr = self.node.item.get_cr()
871           mess = "Valeur du mot-clé non autorisée :"+cr.get_mess_fatal()
872           self.record_valeur(anc_val,mess=mess)
873
874   def makeValeurPage(self,page):
875       """
876           Génère la page de saisie de la valeur du mot-clé simple courant qui doit être une 
877           SD de type dérivé d'ASSD
878       """
879       # Récupération de l'aide associée au panneau, de l'aide destinée à l'utilisateur,
880       # et de la liste des SD du bon type (constituant la liste des choix)
881       bulle_aide=self.get_bulle_aide()
882       aide=self.get_aide()
883       aide= justify_text(texte=aide)
884       liste_noms_sd = self.node.item.get_sd_avant_du_bon_type()
885       # Remplissage du panneau
886       self.valeur_choisie = StringVar()
887       self.valeur_choisie.set('')
888       min,max =  self.node.item.GetMinMax()
889       if (min == 1 and min == max and len(liste_noms_sd)==1):
890           if self.valeur_choisie.get() != liste_noms_sd[0]:
891              self.valeur_choisie.set(liste_noms_sd[0])
892              self.valid_valeur_automatique()
893          
894       self.frame_valeur = Frame(page)
895       self.frame_valeur.pack(fill='both',expand=1)
896       self.frame_valeur.bind("<Button-3>",lambda e,s=self,a=bulle_aide : s.parent.appli.affiche_aide(e,a))
897       self.frame_valeur.bind("<ButtonRelease-3>",self.parent.appli.efface_aide)
898       self.listbox = Pmw.ScrolledListBox(self.frame_valeur,
899                                          items=liste_noms_sd,
900                                          labelpos='n',
901                                          label_text="Structures de données du type\n requis par l'objet courant :",
902                                          listbox_height = 6,
903                                          selectioncommand=self.select_valeur_from_list,
904                                          dblclickcommand=lambda s=self,c=self.valid_valeur : s.choose_valeur_from_list(c))
905       self.listbox.place(relx=0.5,rely=0.3,relheight=0.4,anchor='center')
906       Label(self.frame_valeur,text='Structure de donnée choisie :').place(relx=0.05,rely=0.6)
907       #self.label_valeur = Label(self.frame_valeur,textvariable=self.valeur_choisie)
908       Label(self.frame_valeur,textvariable=self.valeur_choisie).place(relx=0.5,rely=0.6)
909       # affichage de la valeur courante
910       self.display_valeur()
911
912   def get_bulle_aide(self):
913       """
914       Retourne l'aide associée au panneau
915       """
916       return "Double-cliquez sur la structure de donnée désirée pour valoriser le mot-clé simple courant"
917
918   def get_aide(self):
919       """
920       Retourne la phrase d'aide indiquant de quel type doit être la valeur à donner par l'utilisateur
921       """
922       mc = self.node.item.get_definition()
923       type = mc.type[0].__name__  
924       if len(mc.type)>1 :
925           for typ in mc.type[1:] :
926               type = type + ' ou '+typ.__name__
927       return  "Un objet de type "+type+" est attendu"
928     
929   def select_valeur_from_list(self):
930       """
931       Affecte à valeur choisie la sélection courante dans la liste des choix proposée
932       """
933       if len(self.listbox.get()) == 0 : return
934       choix = self.listbox.getcurselection()[0]
935       self.valeur_choisie.set(choix)
936
937   def choose_valeur_from_list(self,command):
938       """
939       Affecte à valeur choisie la sélection courante dans la liste des choix proposée
940       Exécute command
941       """
942       if len(self.listbox.get()) == 0 : return
943       choix = self.listbox.getcurselection()[0]
944       self.valeur_choisie.set(choix)
945       apply(command,(),{})
946
947   def get_valeur(self):
948       """
949       Retourne la valeur donnée par l'utilisateur au MCS
950       """
951       return self.valeur_choisie.get()
952     
953   def display_valeur(self):
954       """
955       Affiche la valeur de l'objet pointé par self
956       """
957       valeur = self.node.item.get_valeur()
958       if valeur == None : return # pas de valeur à afficher ...
959       self.valeur_choisie.set(valeur.nom)
960
961   def erase_valeur(self):
962       pass
963
964 class UNIQUE_SDCO_Panel(UNIQUE_ASSD_Panel):
965   """
966   Classe servant à définir le panneau correspondant à un mot-clé simple
967   qui attend une valeur unique de type dérivé d'ASSD ou non encore
968   existante (type CO(...) utilisé dans les macros uniquement)
969   """
970   def makeValeurPage(self,page):
971       """
972       Génère la page de saisie de la valeur du mot-clé simple courant qui doit être une SD de type dérivé
973       d'ASSD
974       """
975       # Récupération de l'aide associée au panneau, de l'aide destinée à l'utilisateur,
976       # et de la liste des SD du bon type (constituant la liste des choix)
977       bulle_aide=self.get_bulle_aide()
978       aide=self.get_aide()
979       aide= justify_text(texte=aide)
980       liste_noms_sd = self.node.item.get_sd_avant_du_bon_type()
981       # Remplissage du panneau
982       self.frame_valeur = Frame(page)
983       self.frame_valeur.pack(fill='both',expand=1)
984       self.frame_valeur.bind("<Button-3>",lambda e,s=self,a=bulle_aide : s.parent.appli.affiche_aide(e,a))
985       self.frame_valeur.bind("<ButtonRelease-3>",self.parent.appli.efface_aide)
986       # affichage de la liste des SD existantes et du bon type
987       self.listbox = Pmw.ScrolledListBox(self.frame_valeur,
988                                          items=liste_noms_sd,
989                                          labelpos='n',
990                                          label_text="Structures de données du type\n requis par l'objet courant :",
991                                          listbox_height = 6,
992                                          selectioncommand=self.select_valeur_from_list,
993                                          dblclickcommand=lambda s=self,c=self.valid_valeur : s.choose_valeur_from_list(c))
994       self.listbox.place(relx=0.5,rely=0.3,relheight=0.4,anchor='center')
995       # affichage du bouton 'Nouveau concept'
996       self.b_co = Pmw.OptionMenu(self.frame_valeur,labelpos='w',label_text = "Nouveau concept : ",
997                                  items = ('NON','OUI'),menubutton_width=10)
998       self.b_co.configure(command = lambda e,s=self : s.ask_new_concept())
999       self.b_co.place(relx=0.05,rely=0.6,anchor='w')
1000       self.label_co = Label(self.frame_valeur,text='Nom du nouveau concept :')
1001       self.entry_co = Entry(self.frame_valeur)
1002       self.entry_co.bind('<Return>',self.valid_nom_concept_co)
1003       # affichage du label de la structure de donnée choisie
1004       self.l_resu = Label(self.frame_valeur,text='Structure de donnée choisie :')
1005       self.valeur_choisie = StringVar()
1006       self.label_valeur = Label(self.frame_valeur,textvariable=self.valeur_choisie)
1007       self.frame_valeur.update()
1008       self.aide = Label(self.frame_valeur,
1009                         text = aide,
1010                         wraplength=int(self.frame_valeur.winfo_width()*0.8),
1011                         justify='center')
1012       self.aide.place(relx=0.5,rely=0.85,anchor='n')
1013       # affichage de la valeur courante
1014       self.display_valeur()
1015       
1016   def get_bulle_aide(self):
1017       """
1018       Retourne la bulle d'aide du panneau
1019       """
1020       return """Double-cliquez sur la structure de donnée désirée
1021       pour valoriser le mot-clé simple courant ou cliquez sur NOUVEAU CONCEPT pour
1022       entrer le nom d'un concept non encore existant"""
1023
1024   def valid_valeur(self):
1025       """
1026       Teste si la valeur fournie par l'utilisateur est une valeur permise :
1027       - si oui, l'enregistre
1028       - si non, restaure l'ancienne valeur
1029       """
1030       if self.parent.modified == 'n' : self.parent.init_modif()
1031       valeur = self.get_valeur()
1032       self.erase_valeur()
1033       anc_val = self.node.item.get_valeur()
1034       test_CO=self.node.item.is_CO(anc_val)
1035       test = self.node.item.set_valeur(valeur)
1036       if not test :
1037           mess = "impossible d'évaluer : %s " %`valeur`
1038           self.parent.appli.affiche_infos("Valeur du mot-clé non autorisée :"+mess)
1039           return
1040       elif self.node.item.isvalid() :
1041           self.parent.appli.affiche_infos('Valeur du mot-clé enregistrée')
1042           if test_CO:
1043              # il faut egalement propager la destruction de l'ancien concept
1044              self.node.item.delete_valeur_co(valeur=anc_val)
1045              # et on force le recalcul des concepts de sortie de l'etape
1046              self.node.item.object.etape.get_type_produit(force=1)
1047              # et le recalcul du contexte
1048              self.node.item.object.etape.parent.reset_context()
1049           self.node.parent.select()
1050       else :
1051           cr = self.node.item.get_cr()
1052           mess = "Valeur du mot-clé non autorisée :"+cr.get_mess_fatal()
1053           self.record_valeur(anc_val,mess=mess)
1054           return
1055       if self.node.item.get_position()=='global':
1056           self.node.etape.verif_all()
1057       elif self.node.item.get_position()=='global_jdc':
1058           self.node.racine.verif_all()
1059       else :
1060           self.node.parent.verif()
1061       self.node.update()
1062
1063   def valid_nom_concept_co(self,event=None):
1064       """
1065       Lit le nom donné par l'utilisateur au concept de type CO qui doit être
1066       la valeur du MCS courant et stocke cette valeur
1067       """
1068       if self.parent.modified == 'n' : self.parent.init_modif()
1069       anc_val = self.node.item.get_valeur()
1070       nom_concept = self.entry_co.get()
1071       test,mess=self.node.item.set_valeur_co(nom_concept)
1072       if not test:
1073           # On n'a pas pu créer le concept
1074           self.parent.appli.affiche_infos(mess)
1075           return
1076       elif self.node.item.isvalid() :
1077           self.parent.appli.affiche_infos('Valeur du mot-clé enregistrée')
1078           self.node.parent.select()
1079       else :
1080           cr = self.node.item.get_cr()
1081           mess = "Valeur du mot-clé non autorisée :"+cr.get_mess_fatal()
1082           self.record_valeur(anc_val,mess=mess)
1083           return
1084       if self.node.item.get_position()=='global':
1085           self.node.etape.verif_all()
1086       elif self.node.item.get_position()=='global_jdc':
1087           self.node.racine.verif_all()
1088       else :
1089           self.node.parent.verif()
1090       if self.node.item.isvalid():
1091           self.node.parent.select()
1092       self.node.update()
1093
1094   def ask_new_concept(self):
1095       """
1096       Crée une entry dans le panneau d'un MCS qui attend un concept OU un CO() afin de
1097       permettre à l'utilisateur de donner le nom du nouveau concept
1098       """
1099       new_concept = self.b_co.getcurselection()
1100       if new_concept == 'OUI':
1101           self.label_co.place(relx=0.05,rely=0.7)
1102           self.entry_co.place(relx=0.45,rely=0.7,relwidth=0.25)
1103           self.l_resu.place_forget()
1104           self.label_valeur.place_forget()
1105           self.entry_co.focus()
1106       elif new_concept == 'NON':
1107           # On est passe de OUI à NON, on supprime la valeur
1108 # PN correction de bug (on passe de non a non et cela supprime la valeur)
1109 # ajout du if de le ligne suivane
1110           if self.node.item.is_CO():
1111                 self.node.item.delete_valeur_co()
1112                 self.record_valeur(name=None,mess="Suppression CO enregistrée")
1113                 self.label_co.place_forget()
1114                 self.entry_co.place_forget()
1115                 self.l_resu.place(relx=0.05,rely=0.7)
1116                 self.label_valeur.place(relx=0.45,rely=0.7)
1117           
1118   def display_valeur(self):
1119       """
1120       Affiche la valeur de l'objet pointé par self
1121       """
1122       valeur = self.node.item.get_valeur()
1123       if valeur == None or valeur == '': 
1124          self.valeur_choisie.set('')
1125          return # pas de valeur à afficher ...
1126       # il faut configurer le bouton si la valeur est un objet CO
1127       # sinon afficher le nom du concept dans self.valeur_choisie
1128       if self.node.item.is_CO():
1129           self.b_co.invoke('OUI')
1130           self.entry_co.insert(0,valeur.nom)
1131       else:
1132           self.valeur_choisie.set(valeur.nom)
1133
1134   def record_valeur(self,name=None,mess='Valeur du mot-clé enregistrée'):
1135       """
1136       Enregistre  val comme valeur de self.node.item.object SANS faire de test de validité
1137       """
1138       if self.parent.modified == 'n' : self.parent.init_modif()
1139       if name != None:
1140           valeur =name
1141       else :
1142           self.entry_co.delete(0,END)
1143           valeur= self.entry_co.get()
1144       self.node.item.set_valeur_co(valeur)
1145       self.parent.appli.affiche_infos(mess)
1146       # On met a jour le display dans le panneau
1147       self.display_valeur()
1148       if self.node.item.get_position()=='global':
1149           self.node.etape.verif_all()
1150       elif self.node.item.get_position()=='global_jdc':
1151           self.node.racine.verif_all()
1152       else :
1153           self.node.parent.verif()
1154       if self.node.item.isvalid():
1155           self.node.parent.select()
1156       self.node.update()
1157
1158
1159 class UNIQUE_BASE_Panel(UNIQUE_Panel):
1160   """
1161   Classe servant à définir le panneau associé aux mots-clés simples qui attendent
1162   une valeur d'un type de base (entier, réel ou string).
1163   """
1164   def makeValeurPage(self,page):
1165       """
1166       Génère la page de saisie de la valeur du mot-clé simple courant qui doit être de type
1167       de base cad entier, réel, string ou complexe
1168       """
1169       # Récupération de l'aide associée au panneau, de l'aide destinée à l'utilisateur,
1170       # et de la liste des SD du bon type (constituant la liste des choix)
1171       bulle_aide=self.get_bulle_aide()
1172       aide=self.get_aide()
1173       aide= justify_text(texte=aide)
1174       liste_noms_sd = self.node.item.get_sd_avant_du_bon_type()
1175       # Remplissage du panneau
1176       self.frame_valeur = Frame(page)
1177       self.frame_valeur.pack(fill='both',expand=1)
1178       self.frame_valeur.bind("<Button-3>",lambda e,s=self,a=bulle_aide : s.parent.appli.affiche_aide(e,a))
1179       self.frame_valeur.bind("<ButtonRelease-3>",self.parent.appli.efface_aide)
1180       self.label = Label(self.frame_valeur,text='Valeur :')
1181       self.label.place(relx=0.1,rely=0.5)
1182       self.entry = Entry(self.frame_valeur,relief='sunken')
1183       self.entry.place(relx=0.28,rely=0.5,relwidth=0.6)
1184       self.entry.bind("<Return>",lambda e,c=self.valid_valeur:c())
1185       self.entry.focus()
1186       # aide associée au panneau
1187       self.frame_valeur.update()
1188       self.aide = Label(self.frame_valeur, 
1189                         text = aide,
1190                         wraplength=int(self.frame_valeur.winfo_width()*0.8),
1191                         justify='center')
1192       self.aide.place(relx=0.5,rely=0.7,anchor='n')
1193       # affichage de la valeur du MCS
1194       self.display_valeur()
1195
1196   def get_aide(self):
1197       """
1198       Retourne la phrase d'aide indiquant de quel type doit être la valeur
1199       du mot-clé simple fournie par l'utilisateur
1200       """
1201       mc = self.node.item.get_definition()
1202       d_aides = { 'TXM' : "Une chaîne de caractères est attendue",
1203                   'R'   : "Un réel est attendu",
1204                   'I'   : "Un entier est attendu"}
1205       type = mc.type[0]
1206       return d_aides.get(type,"Type de base inconnu")
1207
1208   def get_bulle_aide(self):
1209       """
1210       Retourne la bulle d'aide associée au panneau et affichée par clic droit
1211       """
1212       return """Saisissez la valeur que vous voulez affecter au mot-clé simple
1213       dans la zone de saisie et pressez <Return>"""
1214       
1215   def display_valeur(self):
1216       """
1217       Affiche la valeur de l'objet pointé par self
1218       """
1219       valeur = self.node.item.get_valeur()
1220       if valeur == None : return # pas de valeur à afficher ...
1221       self.entry.delete(0,END)
1222       self.entry.insert(0,valeur)
1223       self.entry.focus()
1224       
1225 class UNIQUE_COMP_Panel(UNIQUE_Panel):
1226   """
1227   Classe servant à définir le panneau associé aux mots-clés simples
1228   qui attendent une valeur de type complexe
1229   """
1230   def makeValeurPage(self,page):
1231       """
1232       Génère la page de saisie de la valeur du mot-clé simple courant qui doit être de type
1233       de base cad entier, réel, string ou complexe
1234       """
1235       # Récupération de l'aide associée au panneau et de l'aide destinée à l'utilisateur
1236       bulle_aide=self.get_bulle_aide()
1237       aide=self.get_aide()
1238       aide= justify_text(texte=aide)
1239       # Remplissage du panneau
1240       self.frame_valeur = Frame(page)
1241       self.frame_valeur.pack(fill='both',expand=1)
1242       self.frame_valeur.bind("<Button-3>",lambda e,s=self,a=bulle_aide : s.parent.appli.affiche_aide(e,a))
1243       self.frame_valeur.bind("<ButtonRelease-3>",self.parent.appli.efface_aide)
1244       self.label = Label(self.frame_valeur,text='Valeur :')
1245       self.label.place(relx=0.1,rely=0.5)
1246       self.typ_cplx=StringVar()
1247       self.typ_cplx.set('RI')
1248       rb1 = Radiobutton(self.frame_valeur, text='RI',variable=self.typ_cplx,value='RI')
1249       rb2 = Radiobutton(self.frame_valeur, text='MP',variable=self.typ_cplx,value='MP')
1250       self.entry1 = Pmw.EntryField(self.frame_valeur,validate='real')
1251       self.entry2 = Pmw.EntryField(self.frame_valeur,validate='real')
1252       rb1.place(relx=0.05,rely = 0.4)
1253       rb2.place(relx=0.05,rely = 0.6)
1254       self.entry1.component('entry').bind("<Return>",lambda e,s=self:s.entry2.component('entry').focus())
1255       self.entry2.component('entry').bind("<Return>",lambda e,c=self.valid_valeur:c())
1256       self.entry1.place(relx=0.27,rely = 0.5,relwidth=0.35)
1257       self.entry2.place(relx=0.65,rely = 0.5,relwidth=0.35)
1258       self.entry1.focus()
1259       self.frame_valeur.update()
1260       self.aide = Label(self.frame_valeur,
1261                         text = aide,
1262                         wraplength=int(self.frame_valeur.winfo_width()*0.8),
1263                         justify='center')
1264       self.aide.place(relx=0.5,rely=0.7,anchor='n')
1265
1266   def get_bulle_aide(self):
1267       """
1268       Retourne la bulle d'aide du panneau
1269       """
1270       return """-Choisissez votre format de saisie du complexe :
1271       \t 'RI' = parties réelle et imaginaire
1272       \t 'MP' = module/phase (en degrés)
1273       - Saisissez ensuite dans les deux zones de saisie les deux nombres attendus"""
1274
1275   def get_aide(self):
1276       """
1277       Retourne la phrase d'aide décrivant le type de la valeur que peut prendre
1278       le mot-clé simple courant
1279       """
1280       return 'Un complexe est attendu'
1281
1282   def get_valeur(self):
1283       """
1284       Retourne le complexe saisi par l'utilisateur
1285       """
1286       l=[]
1287       l.append(self.typ_cplx.get())
1288       l.append(string.atof(self.entry1.get()))
1289       l.append(string.atof(self.entry2.get()))
1290       return `tuple(l)`
1291
1292   def erase_valeur(self):
1293       """
1294       Efface les entries de saisie
1295       """
1296       self.typ_cplx = 'RI'
1297       self.entry1.delete(0,END)
1298       self.entry2.delete(0,END)
1299       
1300 class SIMPTreeItem(Objecttreeitem.AtomicObjectTreeItem):
1301   panel = newSIMPPanel
1302
1303   def init(self) :
1304       self.expandable = 0
1305       self.affect_panel()
1306
1307   def affect_panel(self):
1308       """
1309       Cette méthode attribue le panel à l'objet pointé par self en fonction de la
1310       nature de la valeur demandée pour cet objet
1311       """
1312       if self.wait_shell():
1313           # l'objet attend un shell
1314           self.panel = SHELLPanel
1315       elif self.wait_into():
1316           # l'objet prend sa (ses) valeur(s) dans un ensemble discret de valeurs
1317           min,max = self.GetMinMax()
1318           # PN : 
1319           # Remplacement du if ??
1320           #if max != 1 and ((min != 0 and min != max) or (min == 0)):
1321           assert (min <= max)
1322           if max > 1 :
1323              # l'objet attend une liste de valeurs
1324              self.panel = PLUSIEURS_INTO_Panel
1325           else:
1326              # l'objet n'attend qu'une seule valeur
1327              self.panel = UNIQUE_INTO_Panel
1328       else:
1329           # l'objet prend une ou des valeurs à priori quelconques
1330           min,max = self.GetMinMax()
1331           if max != 1 :
1332               # on attend une liste de valeurs mais de quel type ?
1333               if self.wait_assd():
1334                   # on attend une liste de SD
1335                   self.panel = PLUSIEURS_ASSD_Panel
1336               else:
1337                   # on attend une liste de valeurs de types debase (entiers, réels,...)
1338                   self.panel = PLUSIEURS_BASE_Panel
1339           else:
1340               # on n'attend qu'une seule valeur mais de quel type ?
1341               if self.wait_co():
1342                   # on attend une SD ou un objet de la classe CO (qui n'existe pas encore)
1343                   self.panel = UNIQUE_SDCO_Panel
1344               elif self.wait_assd():
1345                   # on attend une SD
1346                   self.panel = UNIQUE_ASSD_Panel
1347               else:
1348                   # on attend une valeur d'un type de base (entier,réel,...)
1349                   if self.wait_complex():
1350                       # on attend un complexe
1351                       self.panel = UNIQUE_COMP_Panel
1352                   else:
1353                       # on attend un entier, un réel ou une string
1354                       self.panel = UNIQUE_BASE_Panel
1355       
1356   def SetText(self, text):
1357     try:
1358       value = eval(text)
1359       self.object.setval(value)
1360     except:
1361       pass
1362
1363   def GetIconName(self):
1364     if self.isvalid():
1365       return "ast-green-ball"
1366     elif self.object.isoblig():
1367       return "ast-red-ball"
1368     else:
1369       return "ast-yel-ball"
1370
1371   def GetText(self):
1372     """
1373     Classe SIMPTreeItem
1374     Retourne le texte à afficher dans l'arbre représentant la valeur de l'objet
1375     pointé par self 
1376     """
1377     text= self.object.GetText()
1378     return text
1379
1380   def wait_co(self):
1381       """
1382       Méthode booléenne qui retourne 1 si l'objet pointé par self
1383       attend un objet de type ASSD qui n'existe pas encore (type CO()),
1384       0 sinon
1385       """
1386       return self.object.wait_co()
1387
1388   def wait_geom(self):
1389       """
1390       Méthode booléenne qui retourne 1 si l'objet pointé par self
1391       attend un objet GEOM, 0 sinon
1392       """
1393       return self.object.wait_geom()
1394     
1395   def wait_complex(self):
1396       """ Méthode booléenne qui retourne 1 si l'objet pointé par self
1397       attend un complexe, 0 sinon """
1398       if 'C' in self.object.definition.type:
1399           return 1
1400       else:
1401           return 0
1402
1403   def wait_reel(self):
1404       """ Méthode booléenne qui retourne 1 si l'objet pointé par self
1405       attend un réel, 0 sinon """
1406       if 'R' in self.object.definition.type:
1407           return 1
1408       else:
1409           return 0
1410         
1411   def wait_shell(self):
1412       """ Méthode booléenne qui retourne 1 si l'objet pointé par self
1413       attend un shell, 0 sinon """
1414       if 'shell' in self.object.definition.type:
1415           return 1
1416       else:
1417           return 0
1418
1419   def wait_into(self):
1420       """ Méthode booléenne qui retourne 1 si l'objet pointé par self
1421       prend ses valeurs dans un ensemble discret (into), 0 sinon """
1422       if self.object.definition.into != None :
1423           return 1
1424       else:
1425           return 0
1426
1427   def wait_assd(self):
1428       """Méthode booléenne qui retourne 1 si l'objet pointé par self
1429       attend un objet de type ASSD ou dérivé, 0 sinon """
1430       return self.object.wait_assd()
1431     
1432   def getval(self):
1433       return self.object.getval()
1434     
1435   def GetMinMax(self):
1436       """ Retourne les valeurs min et max de la définition de object """
1437       return self.object.get_min_max()
1438
1439   def GetMultiplicite(self):
1440       """ A préciser.
1441           Retourne la multiplicité des valeurs affectées à l'objet
1442           représenté par l'item. Pour le moment retourne invariablement 1.
1443       """
1444       return 1
1445
1446   def GetType(self):
1447       """ 
1448           Retourne le type de valeur attendu par l'objet représenté par l'item.
1449       """
1450       return self.object.get_type()
1451
1452   def GetIntervalle(self):
1453       """ 
1454            Retourne le domaine de valeur attendu par l'objet représenté 
1455            par l'item.
1456       """
1457       return self.object.getintervalle()
1458
1459   def IsInIntervalle(self,valeur):
1460       """ 
1461           Retourne 1 si la valeur est dans l'intervalle permis par
1462           l'objet représenté par l'item.
1463       """
1464       return self.object.isinintervalle(valeur)
1465
1466   def set_valeur_co(self,nom_co):
1467       """
1468       Affecte au MCS pointé par self l'objet de type CO et de nom nom_co
1469       """
1470       return self.object.set_valeur_co(nom_co)
1471       
1472   def get_sd_avant_du_bon_type(self):
1473       """
1474       Retourne la liste des noms des SD présentes avant l'étape qui contient
1475       le MCS pointé par self et du type requis par ce MCS
1476       """
1477       return self.object.etape.parent.get_sd_avant_du_bon_type(self.object.etape,
1478                                                                self.object.definition.type)
1479     
1480   def GetListeValeurs(self) :
1481       """ Retourne la liste des valeurs de object """
1482       return self.object.get_liste_valeurs()
1483     
1484   def verif(self):
1485       pass
1486
1487   def isvalid(self):
1488     return self.object.isvalid()
1489
1490   def eval_valeur(self,valeur):
1491       """ Lance l'interprétation de 'valeur' (chaîne de caractères) comme valeur
1492       de l'objet pointé par self :
1493         - retourne l'objet associé si on a pu interpréter (entier, réel, ASSD,...)
1494         - retourne 'valeur' (chaîne de caractères) sinon """
1495       return self.object.eval_valeur(valeur)
1496
1497   def is_CO(self,valeur=None):
1498       """
1499          Indique si valeur est un concept produit de la macro
1500          Cette méthode n'a de sens que pour un MCSIMP d'une MACRO
1501          Si valeur vaut None on teste la valeur du mot cle
1502       """
1503       # Pour savoir si un concept est un nouveau concept de macro
1504       # on regarde s'il est présent dans l'attribut sdprods de l'étape
1505       # ou si son nom de classe est CO.
1506       # Il faut faire les 2 tests car une macro non valide peut etre
1507       # dans un etat pas tres catholique avec des CO pas encore types
1508       # et donc pas dans sdprods (resultat d'une exception dans type_sdprod)
1509       if not valeur:valeur=self.object.valeur
1510       if valeur in self.object.etape.sdprods:return 1
1511       if type(valeur) is not types.ClassType:return 0
1512       if valeur.__class__.__name__ == 'CO':return 1
1513       return 0
1514
1515   def delete_valeur_co(self,valeur=None):
1516       """
1517            Supprime la valeur du mot cle (de type CO)
1518            il faut propager la destruction aux autres etapes
1519       """
1520       if not valeur : valeur=self.object.valeur
1521       # XXX faut il vraiment appeler del_sdprod ???
1522       #self.object.etape.parent.del_sdprod(valeur)
1523       self.object.etape.parent.delete_concept(valeur)
1524
1525 import Accas
1526 treeitem = SIMPTreeItem
1527 objet = Accas.MCSIMP
1528