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