]> SALOME platform Git repositories - tools/eficas.git/blob - Editeur/composimp.py
Salome HOME
PN : Choix automatique du concept lorsqu'un seul choix est possible.
[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 makeValeurPage(self,page):
797       """
798           Génère la page de saisie de la valeur du mot-clé simple courant qui doit être une 
799           SD de type dérivé d'ASSD
800       """
801       # Récupération de l'aide associée au panneau, de l'aide destinée à l'utilisateur,
802       # et de la liste des SD du bon type (constituant la liste des choix)
803       bulle_aide=self.get_bulle_aide()
804       aide=self.get_aide()
805       aide= justify_text(texte=aide)
806       liste_noms_sd = self.node.item.get_sd_avant_du_bon_type()
807       # Remplissage du panneau
808       self.valeur_choisie = StringVar()
809       self.valeur_choisie.set('')
810       min,max =  self.node.item.GetMinMax()
811       if (min == 1 and min == max and len(liste_noms_sd)==1):
812           self.valeur_choisie.set(liste_noms_sd[0])
813           self.valid_valeur()
814          
815       self.frame_valeur = Frame(page)
816       self.frame_valeur.pack(fill='both',expand=1)
817       self.frame_valeur.bind("<Button-3>",lambda e,s=self,a=bulle_aide : s.parent.appli.affiche_aide(e,a))
818       self.frame_valeur.bind("<ButtonRelease-3>",self.parent.appli.efface_aide)
819       self.listbox = Pmw.ScrolledListBox(self.frame_valeur,
820                                          items=liste_noms_sd,
821                                          labelpos='n',
822                                          label_text="Structures de données du type\n requis par l'objet courant :",
823                                          listbox_height = 6,
824                                          selectioncommand=self.select_valeur_from_list,
825                                          dblclickcommand=lambda s=self,c=self.valid_valeur : s.choose_valeur_from_list(c))
826       self.listbox.place(relx=0.5,rely=0.3,relheight=0.4,anchor='center')
827       Label(self.frame_valeur,text='Structure de donnée choisie :').place(relx=0.05,rely=0.6)
828       #self.label_valeur = Label(self.frame_valeur,textvariable=self.valeur_choisie)
829       Label(self.frame_valeur,textvariable=self.valeur_choisie).place(relx=0.5,rely=0.6)
830       # affichage de la valeur courante
831       self.display_valeur()
832
833   def get_bulle_aide(self):
834       """
835       Retourne l'aide associée au panneau
836       """
837       return "Double-cliquez sur la structure de donnée désirée pour valoriser le mot-clé simple courant"
838
839   def get_aide(self):
840       """
841       Retourne la phrase d'aide indiquant de quel type doit être la valeur à donner par l'utilisateur
842       """
843       mc = self.node.item.get_definition()
844       type = mc.type[0].__name__  
845       if len(mc.type)>1 :
846           for typ in mc.type[1:] :
847               type = type + ' ou '+typ.__name__
848       return  "Un objet de type "+type+" est attendu"
849     
850   def select_valeur_from_list(self):
851       """
852       Affecte à valeur choisie la sélection courante dans la liste des choix proposée
853       """
854       if len(self.listbox.get()) == 0 : return
855       choix = self.listbox.getcurselection()[0]
856       self.valeur_choisie.set(choix)
857
858   def choose_valeur_from_list(self,command):
859       """
860       Affecte à valeur choisie la sélection courante dans la liste des choix proposée
861       Exécute command
862       """
863       if len(self.listbox.get()) == 0 : return
864       choix = self.listbox.getcurselection()[0]
865       self.valeur_choisie.set(choix)
866       apply(command,(),{})
867
868   def get_valeur(self):
869       """
870       Retourne la valeur donnée par l'utilisateur au MCS
871       """
872       return self.valeur_choisie.get()
873     
874   def display_valeur(self):
875       """
876       Affiche la valeur de l'objet pointé par self
877       """
878       valeur = self.node.item.get_valeur()
879       if valeur == None : return # pas de valeur à afficher ...
880       self.valeur_choisie.set(valeur.nom)
881
882   def erase_valeur(self):
883       pass
884
885 class UNIQUE_SDCO_Panel(UNIQUE_ASSD_Panel):
886   """
887   Classe servant à définir le panneau correspondant à un mot-clé simple
888   qui attend une valeur unique de type dérivé d'ASSD ou non encore
889   existante (type CO(...) utilisé dans les macros uniquement)
890   """
891   def makeValeurPage(self,page):
892       """
893       Génère la page de saisie de la valeur du mot-clé simple courant qui doit être une SD de type dérivé
894       d'ASSD
895       """
896       # Récupération de l'aide associée au panneau, de l'aide destinée à l'utilisateur,
897       # et de la liste des SD du bon type (constituant la liste des choix)
898       bulle_aide=self.get_bulle_aide()
899       aide=self.get_aide()
900       aide= justify_text(texte=aide)
901       liste_noms_sd = self.node.item.get_sd_avant_du_bon_type()
902       # Remplissage du panneau
903       self.frame_valeur = Frame(page)
904       self.frame_valeur.pack(fill='both',expand=1)
905       self.frame_valeur.bind("<Button-3>",lambda e,s=self,a=bulle_aide : s.parent.appli.affiche_aide(e,a))
906       self.frame_valeur.bind("<ButtonRelease-3>",self.parent.appli.efface_aide)
907       # affichage de la liste des SD existantes et du bon type
908       self.listbox = Pmw.ScrolledListBox(self.frame_valeur,
909                                          items=liste_noms_sd,
910                                          labelpos='n',
911                                          label_text="Structures de données du type\n requis par l'objet courant :",
912                                          listbox_height = 6,
913                                          selectioncommand=self.select_valeur_from_list,
914                                          dblclickcommand=lambda s=self,c=self.valid_valeur : s.choose_valeur_from_list(c))
915       self.listbox.place(relx=0.5,rely=0.3,relheight=0.4,anchor='center')
916       # affichage du bouton 'Nouveau concept'
917       self.b_co = Pmw.OptionMenu(self.frame_valeur,labelpos='w',label_text = "Nouveau concept : ",
918                                  items = ('NON','OUI'),menubutton_width=10)
919       self.b_co.configure(command = lambda e,s=self : s.ask_new_concept())
920       self.b_co.place(relx=0.05,rely=0.6,anchor='w')
921       self.label_co = Label(self.frame_valeur,text='Nom du nouveau concept :')
922       self.entry_co = Entry(self.frame_valeur)
923       self.entry_co.bind('<Return>',self.valid_nom_concept_co)
924       # affichage du label de la structure de donnée choisie
925       self.l_resu = Label(self.frame_valeur,text='Structure de donnée choisie :')
926       self.valeur_choisie = StringVar()
927       self.label_valeur = Label(self.frame_valeur,textvariable=self.valeur_choisie)
928       self.frame_valeur.update()
929       self.aide = Label(self.frame_valeur,
930                         text = aide,
931                         wraplength=int(self.frame_valeur.winfo_width()*0.8),
932                         justify='center')
933       self.aide.place(relx=0.5,rely=0.85,anchor='n')
934       # affichage de la valeur courante
935       self.display_valeur()
936       
937   def get_bulle_aide(self):
938       """
939       Retourne la bulle d'aide du panneau
940       """
941       return """Double-cliquez sur la structure de donnée désirée
942       pour valoriser le mot-clé simple courant ou cliquez sur NOUVEAU CONCEPT pour
943       entrer le nom d'un concept non encore existant"""
944
945   def valid_valeur(self):
946       """
947       Teste si la valeur fournie par l'utilisateur est une valeur permise :
948       - si oui, l'enregistre
949       - si non, restaure l'ancienne valeur
950       """
951       if self.parent.modified == 'n' : self.parent.init_modif()
952       valeur = self.get_valeur()
953       self.erase_valeur()
954       anc_val = self.node.item.get_valeur()
955       test_CO=self.node.item.is_CO(anc_val)
956       test = self.node.item.set_valeur(valeur)
957       if not test :
958           mess = "impossible d'évaluer : %s " %`valeur`
959           self.parent.appli.affiche_infos("Valeur du mot-clé non autorisée :"+mess)
960           return
961       elif self.node.item.isvalid() :
962           self.parent.appli.affiche_infos('Valeur du mot-clé enregistrée')
963           if test_CO:
964              # il faut egalement propager la destruction de l'ancien concept
965              self.node.item.delete_valeur_co(valeur=anc_val)
966              # et on force le recalcul des concepts de sortie de l'etape
967              self.node.item.object.etape.get_type_produit(force=1)
968              # et le recalcul du contexte
969              self.node.item.object.etape.parent.reset_context()
970           self.node.parent.select()
971       else :
972           cr = self.node.item.get_cr()
973           mess = "Valeur du mot-clé non autorisée :"+cr.get_mess_fatal()
974           self.record_valeur(anc_val,mess=mess)
975           return
976       if self.node.item.get_position()=='global':
977           self.node.etape.verif_all()
978       elif self.node.item.get_position()=='global_jdc':
979           self.node.racine.verif_all()
980       else :
981           self.node.parent.verif()
982       self.node.update()
983
984   def valid_nom_concept_co(self,event=None):
985       """
986       Lit le nom donné par l'utilisateur au concept de type CO qui doit être
987       la valeur du MCS courant et stocke cette valeur
988       """
989       if self.parent.modified == 'n' : self.parent.init_modif()
990       anc_val = self.node.item.get_valeur()
991       nom_concept = self.entry_co.get()
992       test,mess=self.node.item.set_valeur_co(nom_concept)
993       if not test:
994           # On n'a pas pu créer le concept
995           self.parent.appli.affiche_infos(mess)
996           return
997       elif self.node.item.isvalid() :
998           self.parent.appli.affiche_infos('Valeur du mot-clé enregistrée')
999           self.node.parent.select()
1000       else :
1001           cr = self.node.item.get_cr()
1002           mess = "Valeur du mot-clé non autorisée :"+cr.get_mess_fatal()
1003           self.record_valeur(anc_val,mess=mess)
1004           return
1005       if self.node.item.get_position()=='global':
1006           self.node.etape.verif_all()
1007       elif self.node.item.get_position()=='global_jdc':
1008           self.node.racine.verif_all()
1009       else :
1010           self.node.parent.verif()
1011       if self.node.item.isvalid():
1012           self.node.parent.select()
1013       self.node.update()
1014
1015   def ask_new_concept(self):
1016       """
1017       Crée une entry dans le panneau d'un MCS qui attend un concept OU un CO() afin de
1018       permettre à l'utilisateur de donner le nom du nouveau concept
1019       """
1020       new_concept = self.b_co.getcurselection()
1021       if new_concept == 'OUI':
1022           self.label_co.place(relx=0.05,rely=0.7)
1023           self.entry_co.place(relx=0.45,rely=0.7,relwidth=0.25)
1024           self.l_resu.place_forget()
1025           self.label_valeur.place_forget()
1026           self.entry_co.focus()
1027       elif new_concept == 'NON':
1028           # On est passe de OUI à NON, on supprime la valeur
1029           self.node.item.delete_valeur_co()
1030           self.record_valeur(name=None,mess="Suppression CO enregistrée")
1031           self.label_co.place_forget()
1032           self.entry_co.place_forget()
1033           self.l_resu.place(relx=0.05,rely=0.7)
1034           self.label_valeur.place(relx=0.45,rely=0.7)
1035           
1036   def display_valeur(self):
1037       """
1038       Affiche la valeur de l'objet pointé par self
1039       """
1040       valeur = self.node.item.get_valeur()
1041       if valeur == None or valeur == '': 
1042          self.valeur_choisie.set('')
1043          return # pas de valeur à afficher ...
1044       # il faut configurer le bouton si la valeur est un objet CO
1045       # sinon afficher le nom du concept dans self.valeur_choisie
1046       if self.node.item.is_CO():
1047           self.b_co.invoke('OUI')
1048           self.entry_co.insert(0,valeur.nom)
1049       else:
1050           self.valeur_choisie.set(valeur.nom)
1051
1052   def record_valeur(self,name=None,mess='Valeur du mot-clé enregistrée'):
1053       """
1054       Enregistre  val comme valeur de self.node.item.object SANS faire de test de validité
1055       """
1056       if self.parent.modified == 'n' : self.parent.init_modif()
1057       if name != None:
1058           valeur =name
1059       else :
1060           self.entry_co.delete(0,END)
1061           valeur= self.entry_co.get()
1062       self.node.item.set_valeur_co(valeur)
1063       self.parent.appli.affiche_infos(mess)
1064       # On met a jour le display dans le panneau
1065       self.display_valeur()
1066       if self.node.item.get_position()=='global':
1067           self.node.etape.verif_all()
1068       elif self.node.item.get_position()=='global_jdc':
1069           self.node.racine.verif_all()
1070       else :
1071           self.node.parent.verif()
1072       if self.node.item.isvalid():
1073           self.node.parent.select()
1074       self.node.update()
1075
1076
1077 class UNIQUE_BASE_Panel(UNIQUE_Panel):
1078   """
1079   Classe servant à définir le panneau associé aux mots-clés simples qui attendent
1080   une valeur d'un type de base (entier, réel ou string).
1081   """
1082   def makeValeurPage(self,page):
1083       """
1084       Génère la page de saisie de la valeur du mot-clé simple courant qui doit être de type
1085       de base cad entier, réel, string ou complexe
1086       """
1087       # Récupération de l'aide associée au panneau, de l'aide destinée à l'utilisateur,
1088       # et de la liste des SD du bon type (constituant la liste des choix)
1089       bulle_aide=self.get_bulle_aide()
1090       aide=self.get_aide()
1091       aide= justify_text(texte=aide)
1092       liste_noms_sd = self.node.item.get_sd_avant_du_bon_type()
1093       # Remplissage du panneau
1094       self.frame_valeur = Frame(page)
1095       self.frame_valeur.pack(fill='both',expand=1)
1096       self.frame_valeur.bind("<Button-3>",lambda e,s=self,a=bulle_aide : s.parent.appli.affiche_aide(e,a))
1097       self.frame_valeur.bind("<ButtonRelease-3>",self.parent.appli.efface_aide)
1098       self.label = Label(self.frame_valeur,text='Valeur :')
1099       self.label.place(relx=0.1,rely=0.5)
1100       self.entry = Entry(self.frame_valeur,relief='sunken')
1101       self.entry.place(relx=0.28,rely=0.5,relwidth=0.6)
1102       self.entry.bind("<Return>",lambda e,c=self.valid_valeur:c())
1103       self.entry.focus()
1104       # aide associée au panneau
1105       self.frame_valeur.update()
1106       self.aide = Label(self.frame_valeur, 
1107                         text = aide,
1108                         wraplength=int(self.frame_valeur.winfo_width()*0.8),
1109                         justify='center')
1110       self.aide.place(relx=0.5,rely=0.7,anchor='n')
1111       # affichage de la valeur du MCS
1112       self.display_valeur()
1113
1114   def get_aide(self):
1115       """
1116       Retourne la phrase d'aide indiquant de quel type doit être la valeur
1117       du mot-clé simple fournie par l'utilisateur
1118       """
1119       mc = self.node.item.get_definition()
1120       d_aides = { 'TXM' : "Une chaîne de caractères est attendue",
1121                   'R'   : "Un réel est attendu",
1122                   'I'   : "Un entier est attendu"}
1123       type = mc.type[0]
1124       return d_aides.get(type,"Type de base inconnu")
1125
1126   def get_bulle_aide(self):
1127       """
1128       Retourne la bulle d'aide associée au panneau et affichée par clic droit
1129       """
1130       return """Saisissez la valeur que vous voulez affecter au mot-clé simple
1131       dans la zone de saisie et pressez <Return>"""
1132       
1133   def display_valeur(self):
1134       """
1135       Affiche la valeur de l'objet pointé par self
1136       """
1137       valeur = self.node.item.get_valeur()
1138       if valeur == None : return # pas de valeur à afficher ...
1139       self.entry.delete(0,END)
1140       self.entry.insert(0,valeur)
1141       self.entry.focus()
1142       
1143 class UNIQUE_COMP_Panel(UNIQUE_Panel):
1144   """
1145   Classe servant à définir le panneau associé aux mots-clés simples
1146   qui attendent une valeur de type complexe
1147   """
1148   def makeValeurPage(self,page):
1149       """
1150       Génère la page de saisie de la valeur du mot-clé simple courant qui doit être de type
1151       de base cad entier, réel, string ou complexe
1152       """
1153       # Récupération de l'aide associée au panneau et de l'aide destinée à l'utilisateur
1154       bulle_aide=self.get_bulle_aide()
1155       aide=self.get_aide()
1156       aide= justify_text(texte=aide)
1157       # Remplissage du panneau
1158       self.frame_valeur = Frame(page)
1159       self.frame_valeur.pack(fill='both',expand=1)
1160       self.frame_valeur.bind("<Button-3>",lambda e,s=self,a=bulle_aide : s.parent.appli.affiche_aide(e,a))
1161       self.frame_valeur.bind("<ButtonRelease-3>",self.parent.appli.efface_aide)
1162       self.label = Label(self.frame_valeur,text='Valeur :')
1163       self.label.place(relx=0.1,rely=0.5)
1164       self.typ_cplx=StringVar()
1165       self.typ_cplx.set('RI')
1166       rb1 = Radiobutton(self.frame_valeur, text='RI',variable=self.typ_cplx,value='RI')
1167       rb2 = Radiobutton(self.frame_valeur, text='MP',variable=self.typ_cplx,value='MP')
1168       self.entry1 = Pmw.EntryField(self.frame_valeur,validate='real')
1169       self.entry2 = Pmw.EntryField(self.frame_valeur,validate='real')
1170       rb1.place(relx=0.05,rely = 0.4)
1171       rb2.place(relx=0.05,rely = 0.6)
1172       self.entry1.component('entry').bind("<Return>",lambda e,s=self:s.entry2.component('entry').focus())
1173       self.entry2.component('entry').bind("<Return>",lambda e,c=self.valid_valeur:c())
1174       self.entry1.place(relx=0.27,rely = 0.5,relwidth=0.35)
1175       self.entry2.place(relx=0.65,rely = 0.5,relwidth=0.35)
1176       self.entry1.focus()
1177       self.frame_valeur.update()
1178       self.aide = Label(self.frame_valeur,
1179                         text = aide,
1180                         wraplength=int(self.frame_valeur.winfo_width()*0.8),
1181                         justify='center')
1182       self.aide.place(relx=0.5,rely=0.7,anchor='n')
1183
1184   def get_bulle_aide(self):
1185       """
1186       Retourne la bulle d'aide du panneau
1187       """
1188       return """-Choisissez votre format de saisie du complexe :
1189       \t 'RI' = parties réelle et imaginaire
1190       \t 'MP' = module/phase (en degrés)
1191       - Saisissez ensuite dans les deux zones de saisie les deux nombres attendus"""
1192
1193   def get_aide(self):
1194       """
1195       Retourne la phrase d'aide décrivant le type de la valeur que peut prendre
1196       le mot-clé simple courant
1197       """
1198       return 'Un complexe est attendu'
1199
1200   def get_valeur(self):
1201       """
1202       Retourne le complexe saisi par l'utilisateur
1203       """
1204       l=[]
1205       l.append(self.typ_cplx.get())
1206       l.append(string.atof(self.entry1.get()))
1207       l.append(string.atof(self.entry2.get()))
1208       return `tuple(l)`
1209
1210   def erase_valeur(self):
1211       """
1212       Efface les entries de saisie
1213       """
1214       self.typ_cplx = 'RI'
1215       self.entry1.delete(0,END)
1216       self.entry2.delete(0,END)
1217       
1218 class SIMPTreeItem(Objecttreeitem.AtomicObjectTreeItem):
1219   panel = newSIMPPanel
1220
1221   def init(self) :
1222       self.expandable = 0
1223       self.affect_panel()
1224
1225   def affect_panel(self):
1226       """
1227       Cette méthode attribue le panel à l'objet pointé par self en fonction de la
1228       nature de la valeur demandée pour cet objet
1229       """
1230       if self.wait_shell():
1231           # l'objet attend un shell
1232           self.panel = SHELLPanel
1233       elif self.wait_into():
1234           # l'objet prend sa (ses) valeur(s) dans un ensemble discret de valeurs
1235           min,max = self.GetMinMax()
1236           if max != 1 and ((min != 0 and min != max) or (min == 0)):
1237              # l'objet attend une liste de valeurs
1238              self.panel = PLUSIEURS_INTO_Panel
1239           else:
1240              # l'objet n'attend qu'une seule valeur
1241              self.panel = UNIQUE_INTO_Panel
1242       else:
1243           # l'objet prend une ou des valeurs à priori quelconques
1244           min,max = self.GetMinMax()
1245           if max != 1 :
1246               # on attend une liste de valeurs mais de quel type ?
1247               if self.wait_assd():
1248                   # on attend une liste de SD
1249                   self.panel = PLUSIEURS_ASSD_Panel
1250               else:
1251                   # on attend une liste de valeurs de types debase (entiers, réels,...)
1252                   self.panel = PLUSIEURS_BASE_Panel
1253           else:
1254               # on n'attend qu'une seule valeur mais de quel type ?
1255               if self.wait_co():
1256                   # on attend une SD ou un objet de la classe CO (qui n'existe pas encore)
1257                   self.panel = UNIQUE_SDCO_Panel
1258               elif self.wait_assd():
1259                   # on attend une SD
1260                   self.panel = UNIQUE_ASSD_Panel
1261               else:
1262                   # on attend une valeur d'un type de base (entier,réel,...)
1263                   if self.wait_complex():
1264                       # on attend un complexe
1265                       self.panel = UNIQUE_COMP_Panel
1266                   else:
1267                       # on attend un entier, un réel ou une string
1268                       self.panel = UNIQUE_BASE_Panel
1269       
1270   def SetText(self, text):
1271     try:
1272       value = eval(text)
1273       self.object.setval(value)
1274     except:
1275       pass
1276
1277   def GetIconName(self):
1278     if self.isvalid():
1279       return "ast-green-ball"
1280     elif self.object.isoblig():
1281       return "ast-red-ball"
1282     else:
1283       return "ast-yel-ball"
1284
1285   def GetText(self):
1286     """
1287     Classe SIMPTreeItem
1288     Retourne le texte à afficher dans l'arbre représentant la valeur de l'objet
1289     pointé par self 
1290     """
1291     text= self.object.GetText()
1292     return text
1293
1294   def wait_co(self):
1295       """
1296       Méthode booléenne qui retourne 1 si l'objet pointé par self
1297       attend un objet de type ASSD qui n'existe pas encore (type CO()),
1298       0 sinon
1299       """
1300       return self.object.wait_co()
1301
1302   def wait_geom(self):
1303       """
1304       Méthode booléenne qui retourne 1 si l'objet pointé par self
1305       attend un objet GEOM, 0 sinon
1306       """
1307       return self.object.wait_geom()
1308     
1309   def wait_complex(self):
1310       """ Méthode booléenne qui retourne 1 si l'objet pointé par self
1311       attend un complexe, 0 sinon """
1312       if 'C' in self.object.definition.type:
1313           return 1
1314       else:
1315           return 0
1316
1317   def wait_reel(self):
1318       """ Méthode booléenne qui retourne 1 si l'objet pointé par self
1319       attend un réel, 0 sinon """
1320       if 'R' in self.object.definition.type:
1321           return 1
1322       else:
1323           return 0
1324         
1325   def wait_shell(self):
1326       """ Méthode booléenne qui retourne 1 si l'objet pointé par self
1327       attend un shell, 0 sinon """
1328       if 'shell' in self.object.definition.type:
1329           return 1
1330       else:
1331           return 0
1332
1333   def wait_into(self):
1334       """ Méthode booléenne qui retourne 1 si l'objet pointé par self
1335       prend ses valeurs dans un ensemble discret (into), 0 sinon """
1336       if self.object.definition.into != None :
1337           return 1
1338       else:
1339           return 0
1340
1341   def wait_assd(self):
1342       """Méthode booléenne qui retourne 1 si l'objet pointé par self
1343       attend un objet de type ASSD ou dérivé, 0 sinon """
1344       return self.object.wait_assd()
1345     
1346   def getval(self):
1347       return self.object.getval()
1348     
1349   def GetMinMax(self):
1350       """ Retourne les valeurs min et max de la définition de object """
1351       return self.object.get_min_max()
1352
1353   def GetMultiplicite(self):
1354       """ A préciser.
1355           Retourne la multiplicité des valeurs affectées à l'objet
1356           représenté par l'item. Pour le moment retourne invariablement 1.
1357       """
1358       return 1
1359
1360   def GetType(self):
1361       """ 
1362           Retourne le type de valeur attendu par l'objet représenté par l'item.
1363       """
1364       return self.object.get_type()
1365
1366   def GetIntervalle(self):
1367       """ 
1368            Retourne le domaine de valeur attendu par l'objet représenté 
1369            par l'item.
1370       """
1371       return self.object.getintervalle()
1372
1373   def IsInIntervalle(self,valeur):
1374       """ 
1375           Retourne 1 si la valeur est dans l'intervalle permis par
1376           l'objet représenté par l'item.
1377       """
1378       return self.object.isinintervalle(valeur)
1379
1380   def set_valeur_co(self,nom_co):
1381       """
1382       Affecte au MCS pointé par self l'objet de type CO et de nom nom_co
1383       """
1384       return self.object.set_valeur_co(nom_co)
1385       
1386   def get_sd_avant_du_bon_type(self):
1387       """
1388       Retourne la liste des noms des SD présentes avant l'étape qui contient
1389       le MCS pointé par self et du type requis par ce MCS
1390       """
1391       return self.object.etape.parent.get_sd_avant_du_bon_type(self.object.etape,
1392                                                                self.object.definition.type)
1393     
1394   def GetListeValeurs(self) :
1395       """ Retourne la liste des valeurs de object """
1396       return self.object.get_liste_valeurs()
1397     
1398   def verif(self):
1399       pass
1400
1401   def isvalid(self):
1402     return self.object.isvalid()
1403
1404   def eval_valeur(self,valeur):
1405       """ Lance l'interprétation de 'valeur' (chaîne de caractères) comme valeur
1406       de l'objet pointé par self :
1407         - retourne l'objet associé si on a pu interpréter (entier, réel, ASSD,...)
1408         - retourne 'valeur' (chaîne de caractères) sinon """
1409       return self.object.eval_valeur(valeur)
1410
1411   def is_CO(self,valeur=None):
1412       """
1413          Indique si valeur est un concept produit de la macro
1414          Cette méthode n'a de sens que pour un MCSIMP d'une MACRO
1415          Si valeur vaut None on teste la valeur du mot cle
1416       """
1417       # Pour savoir si un concept est un nouveau concept de macro
1418       # on regarde s'il est présent dans l'attribut sdprods de l'étape
1419       # ou si son nom de classe est CO.
1420       # Il faut faire les 2 tests car une macro non valide peut etre
1421       # dans un etat pas tres catholique avec des CO pas encore types
1422       # et donc pas dans sdprods (resultat d'une exception dans type_sdprod)
1423       if not valeur:valeur=self.object.valeur
1424       if valeur in self.object.etape.sdprods:return 1
1425       if type(valeur) is not types.ClassType:return 0
1426       if valeur.__class__.__name__ == 'CO':return 1
1427       return 0
1428
1429   def delete_valeur_co(self,valeur=None):
1430       """
1431            Supprime la valeur du mot cle (de type CO)
1432            il faut propager la destruction aux autres etapes
1433       """
1434       if not valeur : valeur=self.object.valeur
1435       # XXX faut il vraiment appeler del_sdprod ???
1436       #self.object.etape.parent.del_sdprod(valeur)
1437       self.object.etape.parent.delete_concept(valeur)
1438
1439 import Accas
1440 treeitem = SIMPTreeItem
1441 objet = Accas.MCSIMP
1442