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