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