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