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