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