Salome HOME
60a4c63a2cadfa4824c3cf3584b0c4885ba6a30e
[tools/eficas.git] / Editeur / treewidget.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 import os,sys,string,re,types,traceback
21 from Tkinter import *
22
23
24 import fontes
25 import images
26
27 #
28 __version__="$Name:  $"
29 __Id__="$Id: treewidget.py,v 1.5 2002/05/15 15:31:59 eficas Exp $"
30 #
31
32 Fonte_Standard = fontes.standard
33
34 class Tree :
35     def __init__(self,appli,jdc_item,scrolledcanvas,command = None):
36         self.item = jdc_item
37         self.scrolledcanvas = scrolledcanvas
38         self.canvas = self.scrolledcanvas.component('canvas')
39         self.canvas.bind("<Key-Prior>", self.page_up)
40         self.canvas.bind("<Key-Next>", self.page_down)
41         self.canvas.bind("<Key-Up>", self.unit_up)
42         self.canvas.bind("<Key-Down>", self.unit_down)             
43         self.tree = self
44         self.command = command
45         self.appli = appli
46         self.parent = None
47         self.racine = self
48         self.node_selected = None
49         self.build_children()
50
51     def page_up(self,event):
52         event.widget.yview_scroll(-1, "page")
53     def page_down(self,event):
54         event.widget.yview_scroll(1, "page")
55     def unit_up(self,event):
56         event.widget.yview_scroll(-1, "unit")
57     def unit_down(self,event):
58         event.widget.yview_scroll(1, "unit")              
59
60     def build_children(self):
61         """ Construit la liste des enfants de self """
62         self.children = []
63         child = Node(self,self.item,self.command)
64         self.children.append(child)
65         child.state='expanded'
66
67     def draw(self):
68         """ Dessine l'arbre """
69         lasty = 8
70         x = 5
71         for child in self.children:
72             child.draw(x,lasty)
73             lasty = child.lasty + 15
74             child.trace_ligne()
75         #self.update()
76         self.children[0].select()
77         self.resizescrollregion()
78
79     def deselectall_old(self):
80         """ déselectionne tous les éléments de l'arbre """
81         for child in self.children:
82             child.deselect()
83
84     def deselectall(self):
85         """ déselectionne tous les éléments de l'arbre """
86         if self.node_selected :
87             self.node_selected.deselect()
88             
89     def update(self):
90         """ Update tous les éléments de l'arbre """
91         for child in self.children:
92             child.update()
93
94     def resizescrollregion(self):
95         self.scrolledcanvas.resizescrollregion()
96
97     def select_next(self,event):
98         self.node_selected.select_next()
99
100     def select_previous(self,event):
101         self.node_selected.select_previous()
102
103     def full_creation(self,name,index):
104         # A changer lorsqu'il y aura plusieurs jdc ouverts en même temps
105         self.children[0].full_creation(name,index)
106
107     def verif_all(self):
108         for child in self.children :
109             self.verif_all_children()
110             
111 class Node :
112     def __init__(self,parent,item,command=None):
113         self.parent = parent
114         self.item = item
115         self.command = command
116         self.tree = self.parent.tree
117         self.appli = self.parent.appli
118         self.canvas = self.parent.canvas
119         self.init()
120         #self.build_children()
121
122     def init(self):
123         self.state='collapsed'
124         self.displayed = 0
125         self.selected = 0
126         self.x = self.y  =None
127         self.lasty = 0
128         self.children = None
129         self.id = []
130         # etape = noeud d'étape auquel appartient self
131         # = self si c'est lui-même
132         if isinstance(self.parent,Tree) :
133             # on est  sur un noeud de JDC
134             self.racine=self
135             self.etape=None
136             self.nature='JDC'
137         elif isinstance(self.parent.parent,Tree) :
138             # on est sur un noeud d'étape
139             self.racine = self.parent
140             self.etape=self
141             self.nature = 'ETAPE'
142         else :
143             # on est sur un noeud de mot-clé
144             self.racine = self.parent.racine
145             self.etape=self.parent.etape
146             self.nature = 'MOTCLE'
147
148     def build_children(self):
149         """ Construit la liste des enfants de self """
150         self.children = []
151         sublist = self.item._GetSubList()
152         if not sublist : return
153         for item in sublist :
154             child = Node(self,item,self.command)
155             self.children.append(child)
156             
157     #-----------------------------------------------
158     # Méthodes de sélection/déselection d'un noeud
159     #-----------------------------------------------
160     
161     def select(self, event=None):
162         """
163         Rend le noeud courant (self) sélectionné et déselectionne
164         tous les autres
165         """
166         if not self.children : self.build_children()
167         self.tree.deselectall()
168         self.selected = 1
169         self.tree.node_selected = self
170         if self.command:apply(self.command,(self,))
171         self.highlight()
172         self.canvas.focus_force()
173         #self.make_visible()
174
175     def deselect_old(self, event=None):
176         """ Déselectionne self """
177         self.selected = 0
178         if self.displayed == 1:
179             self.dehighlight()
180         for child in self.children:
181             child.deselect()
182
183     def deselect(self, event=None):
184         """ Déselectionne self """
185         self.selected = 0
186         if self.displayed == 1 : self.dehighlight()
187             
188     def make_visible(self):
189         """ Rend l'objet self visible cad déplace le scroll pour que self soit dans
190         la fenêtre de visu"""
191         x0,y0,x1,y1 = self.canvas.bbox(ALL)
192         self.canvas.yview("moveto",self.y/y1)
193         
194     def select_next(self,ind=0):
195         """ on doit chercher à sélectionner dans l'ordre:
196                 - son premier fils s'il est affiché
197                 - son frère cadet s'il existe
198                 - son oncle (benjamin de son père)
199                 - ... appel récursif ...
200         """
201         if self.state=='expanded' and len(self.children) > ind:
202             self.children[ind].select()
203         else :
204             index = self.parent.children.index(self) + 1
205             if isinstance(self.parent,TREE) :
206                 try:
207                     self.children[ind].select()
208                 except:
209                     self.children[0].select()
210             else :                
211                 self.parent.select_next(index)
212
213     def select_previous(self):
214         """ on doit d'abord sélectionner(dans l'ordre) :
215              - son frère aîné
216              - son père
217         """
218         index = self.parent.children.index(self) + 1
219         try :
220             self.parent.children[index].select()
221         except:
222             self.parent.select()
223     #-----------------------------------------------
224     # Méthodes de recherche d'informations
225     #-----------------------------------------------
226     def geticonimage(self,name=None):
227         """
228         Retourne l'image qui doit être associée à self
229         """
230         if not name :
231             name = self.item.GetIconName()
232         if not name or name == 'aucune' :
233             return None
234         return images.get_image(name)
235
236     def get_nb_children(self):
237         """ Retourne le nombre d'enfants affichés de self """
238         nb = 0
239         if self.state =='collapsed' :  return nb
240         for child in self.children :
241             nb = nb + 1 + child.get_nb_children()
242         return nb
243
244     def get_liste_id(self):
245         """ Retourne la liste de tous les id (filiation comprise) de self """
246         liste = self.id
247         for child in self.children:
248             liste.extend(child.get_liste_id())
249         return liste
250
251     def get_node_fils(self,name) :
252         """ Retourne le fils de self de nom name s'il existe"""
253         for child in self.children:
254             if child.item.get_nom() == name: return child
255         return None
256     #-----------------------------------------------
257     # Méthodes d'affichage d'un noeud
258     #-----------------------------------------------
259     def draw(self,x,y):
260         """ Permet de tracer le noeud self """
261         # le début du noeud est en x,y
262         self.x = x
263         self.y = y
264         self.lasty = y
265         self.displayed = 1
266         self.id=[]
267         # choix de l'icone à afficher : + ou -
268         if self.item.IsExpandable():
269             if self.state == 'expanded':
270                 iconname = "minusnode"
271                 callback = self.collapse
272             else:
273                 iconname = "plusnode"
274                 callback = self.expand
275             image = self.geticonimage(name=iconname)
276             self.icone_id = self.canvas.create_image(self.x, self.y, image=image)
277             self.canvas.tag_bind(self.icone_id, "<1>", callback)
278             self.id.append(self.icone_id)
279         # création de la ligne horizontale
280         self.ligne_id = self.canvas.create_line(self.x,self.y,self.x+10,self.y)
281         self.id.append(self.ligne_id)
282         self.canvas.tag_lower(self.ligne_id)
283         # affichage de l'icone (carre ,rond, ovale ...) de couleur
284         image = self.geticonimage()
285         if image != None :
286             self.image_id = self.canvas.create_image(self.x+15,self.y,image = image)
287             self.canvas.tag_bind(self.image_id,"<1>",self.select)
288             self.id.append(self.image_id)
289         else:
290             self.image_id = None
291         # affichage du texte : nom de l'objet (ETAPE ou MOT-CLE) et sa valeur
292         self.drawtext()
293         if self.state == 'expanded' :
294             if not self.children : self.build_children()
295             if len(self.children) > 0:
296                 self.drawchildren()
297                 self.lasty = self.children[-1].lasty
298    
299     def drawchildren(self):
300         """ Dessine les enfants de self """
301         y = self.y + 20
302         x = self.x + 15
303         for child in self.children:
304             child.draw(x,y)
305             nb = child.get_nb_children()
306             y = y + 20*(nb+1)
307
308     def drawtext(self):
309         """ Affiche les deux zones de texte après l'icône de couleur de l'objet """
310         if self.image_id != None :
311             textx = self.x + 30
312         else:
313             textx = self.x + 15
314         texty = self.y
315         # nom,fonte et couleur de l'objet du noeud à afficher
316         labeltext,fonte,couleur = self.item.GetLabelText()
317         if labeltext    == ''   : labeltext = '   '
318         if fonte        == None : fonte = Fonte_Standard
319         if couleur      == None : couleur = 'black'
320         # création du widget label
321         self.label = Label(self.canvas,
322                            text = labeltext,
323                            fg = couleur,
324                            bg = 'gray95',
325                            font=fonte)
326         self.label_id = self.canvas.create_window(textx,texty,window=self.label,anchor='w')
327         self.id.append(self.label_id)
328         # bindings sur le widget label
329         self.label.bind("<1>", self.select)
330         self.label.bind("<Enter>",self.enter)
331         self.label.bind("<Leave>",self.leave)
332         # valeur de cet objet à afficher
333         x0, y0, x1, y1 = self.canvas.bbox(self.label_id)
334         textx = max(x1, 200) + 10
335         text = self.item.GetText() or " "
336         self.text = Label(self.canvas, text=text,
337                             bd=0, padx=2, pady=2,background='gray95',
338                             font=fonte)
339         if self.selected:
340             self.highlight()
341         else:
342             self.dehighlight()
343         self.text_id = self.canvas.create_window(textx, texty,anchor="w", window=self.text)
344         self.id.append(self.text_id)
345         # Redefinit la region de scroll du canvas pour inclure tous les items créés
346         self.tree.scrolledcanvas.resizescrollregion()
347         
348     def highlight(self,event=None):
349         """ Met en surbrillance self"""
350         if hasattr(self,'label'):
351             self.label.configure(fg='white',bg='#00008b')
352             
353     def dehighlight(self,event=None):
354         """ Rétablit l'affichage normal de self"""
355         if hasattr(self,'label'):
356             self.label.configure(fg='black',bg='gray95')
357
358     def enter(self,event=None):
359         """ Met en surbrillance self et affiche le fr de l'objet """
360         self.highlight()
361         fr = self.item.get_fr()
362         self.appli.affiche_infos(fr)
363         
364     def leave(self,event=None):
365         """ Rétablit l'affichage normal de self et efface le fr de l'objet """
366         if not self.selected :
367             self.dehighlight()
368         self.appli.affiche_infos('')
369
370     def collapse_children(self):
371         """ Collapse récursivement tous les descendants de self """
372         if not self.children : return
373         for child in self.children:
374             child.state='collapsed'
375             child.displayed = 0
376             child.collapse_children()
377             
378     def collapse(self,event = None):
379         """ Collapse self et descendants et retrace self """
380         nb = self.get_nb_children()
381         self.state = 'collapsed'
382         self.collapse_children()
383         self.efface()
384         try:
385             self.move(-20*nb)
386         except:
387             pass
388         self.draw(self.x,self.y)
389         self.select()
390         self.update()
391
392     def expand(self,event = None):
393         """ Expanse self et le retrace """
394         if not self.item.isactif() : return
395         if not self.children : self.build_children()
396         self.state = 'expanded'
397         nb = self.get_nb_children()
398         self.move(20*nb)
399         self.efface()
400         self.draw(self.x,self.y)
401         self.select()
402         self.update()
403
404     def redraw(self,nb):
405         """ Redessine self :  nb est le décalage à introduire
406             en dessous de self pour le redessiner """
407         # nb = nombre d'items de décalage
408         self.move(20*nb)
409         # on efface self et on le redessine
410         self.efface()
411         self.draw(self.x,self.y)
412         self.update()
413         
414     def update_coords(self):
415         """ Permet d'updater les coordonnes de self et de tous ses enfants"""
416         if self.displayed == 0 : return
417         if self.image_id != None :
418             coords = self.canvas.coords(self.image_id)
419             self.x = coords[0]-15
420         else:
421             coords = self.canvas.coords(self.label_id)
422             self.x = coords[0]-15
423         self.y = coords[1]
424         if self.state == 'expanded' :
425             for child in self.children:
426                 if child.displayed != 0:
427                     child.update_coords()
428
429     def update_icone(self):
430         """ Met à jour les icônes de tous les noeuds : teste la validité de l'objet
431         Cette méthode est très lente, trop !!"""
432         if self.image_id != None :
433             image = self.geticonimage()
434             self.canvas.itemconfig(self.image_id,image=image)
435         if self.state == 'expanded':
436             for child in self.children:
437                 if child.displayed != 0:
438                     child.update_icone()
439
440     def update_texte(self):
441         """ Met à jour les noms des SD et valeurs des mots-clés """
442         text = self.item.GetText()
443         if text == None : text = ''
444         self.text.configure(text=text)
445         if self.state == 'expanded' :
446             for child in self.children:
447                 if child.displayed != 0 : child.update_texte()
448         
449     def update(self,event=None) :
450         """ Classe Node :
451             Cette méthode est appelée pour demander l update d un noeud 
452              d'un jeu de commandes
453              Cette demande est transmise au noeud racine (le JDC) qui update
454              tout l arbre représentant le jeu de commandes
455              Pendant cette mise à jour, on appelle la méthode isvalid qui
456              fera l update de tous les objets déclarés modifiés lors des
457              actions précédentes
458              La métode isvalid est en général appelée par l intermédiaire de
459              update_icone -> geticonimage -> GetIconName
460         """
461         self.racine.update_coords()
462         self.racine.trace_ligne()
463         self.racine.update_icone()
464         self.racine.update_texte()
465         self.tree.resizescrollregion()
466
467     def efface(self):
468         """ Efface du canvas les id associés à self : cad les siens et ceux
469             de ses enfants """
470         for id in self.id :
471             self.canvas.delete(id)
472         if not self.children : return
473         for child in self.children:
474             child.efface()
475
476     def move(self,dy):
477         """ Déplace de l'incrément dy tous les id en dessous de self """
478         # il faut marquer tous les suivants de self
479         bbox1 = self.canvas.bbox(ALL)
480         self.canvas.dtag(ALL,'move')
481         self.canvas.delete('line')
482         try:
483             self.canvas.addtag_overlapping('move',bbox1[0],self.y +10,bbox1[2],bbox1[3])
484         except:
485             print "Erreur dans move :"
486             print self
487             print self.item
488             print self.item.object
489             print self.item.object.definition.label
490             print 'y=',self.y
491             print 'dy=',dy
492         # on déplace tous les items de dy
493         self.canvas.move('move',0,dy)
494         # il faut réactualiser la zone de scroll
495         self.tree.resizescrollregion()
496
497     def trace_ligne(self):
498         """ Dessine les lignes verticales entre frères et entre père et premier fils"""
499         if self.state=='collapsed' : return
500         #if self.displayed == 0 : return
501         if len(self.children)==0 : return
502         # on est bien dans le cas d'un noeud expansé avec enfants ...
503         # il faut rechercher l'ordonnée du dernier fils de self
504         y_end = self.children[-1].y
505         ligne = self.canvas.create_line(self.x+15,self.y,self.x+15,y_end,tags='line')
506         self.canvas.tag_lower(ligne)
507         for child in self.children :
508             try:
509                 child.trace_ligne()
510             except:
511                 print "Erreur dans trace_ligne :"
512                 print child
513                 print child.item.object
514
515     def make_visible_OBSOLETE(self,nb):
516         """ Cette méthode a pour but de rendre le noeud self (avec tous ses descendants
517         affichés) visible dans le canvas """
518         x = self.canvas.canvasx(self.canvas.cget('width'))
519         y = self.canvas.canvasy(self.canvas.cget('height'))
520         #print 'x,y =',x,y
521         x0,y0,x1,y1 = self.canvas.bbox(ALL)
522         #print 'x0,y1=',x0,y1
523         y_deb = self.y
524         nb = self.get_nb_children()
525         y_fin = y_deb + 20*nb
526         #print 'y_deb,y_fin=',y_deb,y_fin
527         
528     #------------------------------------------------------------------
529     # Méthodes de création et destruction de noeuds
530     # Certaines de ces méthodes peuvent être appelées depuis l'externe
531     #------------------------------------------------------------------
532     def replace_node(self,node1,node2):
533         """ Remplace le noeud 1 par le noeud 2 dans la liste des enfants de self"""
534         index= self.children.index(node1)
535         self.delete_node_child(node1)
536         self.children.insert(index,node2)
537         
538     def full_creation(self,name,pos=None):
539         """
540             Interface avec ACCAS : création de l'objet de nom name et
541             du noeud associé. Retourne le noeud fils ainsi créé
542         """
543         item = self.item.additem(name,pos)
544         if item == None or item == 0:
545             # impossible d'ajouter le noeud de nom : name
546             return 0
547         nature = item.get_nature()
548         if nature in ("COMMANDE","OPERATEUR","PROCEDURE","COMMENTAIRE",
549                       "PARAMETRE","COMMANDE_COMMENTARISEE","PARAMETRE_EVAL"):
550             # on veut ajouter une commande ou un commentaire ou un paramètre
551             # il ne faut pas rechercher un même objet déjà existant
552             # à modifier : il faut tester l'attribut 'repetable' 
553             enfant = None
554         elif self.item.object.isMCList():
555             # Dans ce cas on ne fait pas de remplacement. On ne cherche pas un objet de meme nom
556             enfant=None
557         else :
558             enfant = self.get_node_fils(item.get_nom())
559         if enfant :
560             # un fils de même nom existe déjà : on remplace
561             # un MCFACT (ou une MCList) par une (autre) MCList
562             child = Node(self,item,self.command)
563             self.replace_node(enfant,child)
564         else :            
565             child = Node(self, item,self.command)
566             if pos is None:
567                 self.children.append(child)
568             else :
569                 self.children.insert(pos,child)
570         return child
571
572     def append_brother(self,name,pos='after',retour='non'):
573         """
574         Permet d'ajouter un frère à self
575         par défaut on l'ajoute après self
576         Méthode externe
577         """
578         # on veut ajouter le frère de nom name directement avant ou après self
579         index = self.parent.children.index(self)
580         if pos == 'before':
581             index = index
582         elif pos == 'after':
583             index = index +1
584         else:
585             print str(pos)," n'est pas un index valide pour append_brother"
586             return
587         return self.parent.append_child(name,pos=index,retour=retour)
588     
589     def append_node_child(self,fils,pos=None,verif='oui'):
590         """
591         Fait appel à la création complète de fils et à la vérification
592         des conditions en fonction du contexte
593         Attention : fils peut être un nom ou déjà un object (cas d'une copie)
594         """
595         if not self.children : self.build_children()
596         if pos == None :
597             #pos = len(self.children)
598             if type(fils) == types.InstanceType:
599                 pos = self.item.get_index_child(fils.nom)
600             else:
601                 pos = self.item.get_index_child(fils)
602         child = self.full_creation(fils,pos)
603         if child == 0 :
604             # on n'a pas pu créer le noeud fils
605             return 0
606         child.displayed = 1
607         self.state = 'expanded'
608         if verif == 'oui':
609             if not child.children : child.build_children()
610             test = child.item.isMCList()
611             if test :
612                 child.children[-1].verif_condition()
613             else :
614                 child.verif_condition()
615             self.verif_condition()
616         return child
617             
618     def append_child(self,name,pos=None,verif='oui',retour='non'):
619         """
620         Permet d'ajouter un fils à self
621         on peut l'ajouter en fin de liste (défaut) ou en début
622         Méthode externe
623         """
624         if pos == 'first':
625             index = 0
626         elif pos == 'last':
627             index = len(self.children)
628         elif pos != None and type(pos) == types.IntType :
629             # on donne la position depuis l'extérieur
630             # (appel de append_child par append_brother par exemple)
631             index = pos
632         elif type(pos) == types.InstanceType:
633             # pos est un item. Il faut inserer name apres pos
634             index = self.item.get_index(pos) +1
635         else :
636             if type(name) == types.InstanceType:
637                 index = self.item.get_index_child(name.nom)
638             else:
639                 index = self.item.get_index_child(name)
640         nbold = self.get_nb_children()
641         self.state='expanded'
642         child = self.append_node_child(name,pos=index)
643         if child == 0 :
644             # on n'a pas pu créer le fils
645             return 0
646         nbnew = self.get_nb_children()
647         self.redraw(nbnew-nbold)
648         child.select()
649         child.expand()
650         #child.make_visible()
651         if retour == 'oui': return child
652
653     def delete_node_child(self,child):
654         """ Supprime child des enfants de self et les id associés """
655         child.efface()
656         child.displayed = 0
657         self.children.remove(child)
658         self.canvas.update()
659         
660     def delete_child(self,child):
661         """ 
662             Supprime child des enfants de self, tous les id associés
663             ET l'objet associé 
664         """
665         if self.item.suppitem(child.item):
666             self.delete_node_child(child)
667             return 1
668         else :
669             return 0
670                     
671     def delete(self):
672         """ Méthode externe pour la destruction du noeud ET de l'objet
673             Gère l'update du canvas"""
674         if self.parent.item.isMCList():
675             pere = self.parent.parent
676             nbold = pere.get_nb_children()
677             if self.parent.delete_child(self):
678                 self.parent.traite_mclist()
679             if self.item.get_position() == 'global':
680                 self.etape.verif_all()
681             elif self.item.get_position() == 'global_jdc':
682                 self.racine.verif_all()
683             else:
684                 self.parent.verif_condition()
685             nbnew = pere.get_nb_children()
686         else:
687             pere = self.parent
688             nbold = pere.get_nb_children()
689             if self.parent.delete_child(self):
690                 if self.item.get_position() == 'global':
691                     self.etape.verif_all()
692                 elif self.item.get_position() == 'global_jdc':
693                     self.racine.verif_all()
694                 else:
695                     self.parent.verif_condition()
696             else :
697                 print 'Erreur dans la destruction de ',self.item.get_nom(),' dans delete'
698             nbnew = pere.get_nb_children()
699         pere.redraw(nbnew-nbold)
700         pere.select()
701
702     def copynode(self,node,pos) :
703         """ node est le noeud à copier à la position pos de self ( = parent de node) """
704         objet_copie = node.item.get_copie_objet()
705         child = self.full_creation(node.item,pos)
706         child.displayed = node.displayed
707         #child.image_id = node.image_id
708         #child.label_id = node.label_id
709         if child.item.get_nature() == "MCList":
710             child.item.object[-1].mc_liste = objet_copie.mc_liste
711         else :
712             try :
713                 child.item.object.mc_liste = objet_copie.mc_liste
714             except:
715                 traceback.print_exc()
716     #--------------------------------------------------------------
717     # Méthodes de vérification du contexte et de validité du noeud
718     #--------------------------------------------------------------
719     def traite_mclist_OLD(self):
720         """ Dans le cas d'une MCList il faut vérifier qu'elle n'est pas vide
721             ou réduite à un seul élément suite à une destruction
722         """
723         # self représente une MCList
724         print "on passe par traite_mclist ",len(self.item)
725         if len(self.item) == 0 :
726             # la liste est vide : il faut la supprimer
727             self.delete()
728         elif len(self.item) == 1:
729             # il ne reste plus qu'un élément dans la liste
730             # il faut supprimer la liste et créer directement l'objet
731             index = self.parent.children.index(self)
732             noeud = self.children[0]
733             if self.parent.delete_child(self):
734                 self.parent.append_node_child(noeud.item,pos=index,verif='non')
735             else:
736                 print "destruction de self impossible !"
737             #if self.parent.delete_child(self):
738             #    self.parent.copynode(self.children[0],index)
739             #else :
740             #    print 'erreur dans la destruction de :',self.item.get_nom(),' dans traite_mclist'
741         else :
742             return
743
744     def traite_mclist(self):
745         """ Dans le cas d'une MCList il faut vérifier qu'elle n'est pas vide
746             ou réduite à un seul élément suite à une destruction
747         """
748         # self représente une MCList
749         if len(self.item) == 0 :
750             # la liste est vide : il faut la supprimer
751             self.delete()
752         elif len(self.item) == 1:
753             # il ne reste plus qu'un élément dans la liste
754             # il faut supprimer la liste et créer directement l'objet
755             index = self.parent.children.index(self)
756             noeud = self.children[0]
757             noeud.parent = self.parent
758             self.parent.delete_node_child(self)
759             self.parent.item.replace_child(self.item,noeud.item)
760             self.parent.children.insert(index,noeud)
761         else :
762             return
763             
764     def verif_all(self):
765         self.verif_all_children()
766             
767     def verif_all_children(self):
768         if not self.children : self.build_children()
769         if self.nature != 'JDC' :
770             self.verif()
771         for child in self.children :
772             child.verif_all_children()
773
774     def verif(self) :
775         """ 
776             Lance la vérification des conditions des blocs de self et le cas
777             échéant redessine self 
778         """
779         nbold = self.get_nb_children()
780         test = self.verif_condition()
781         nbnew = self.get_nb_children()
782         if test != 0 :
783             self.redraw(nbnew-nbold)
784
785     def verif_condition(self):
786         """
787         on lance la vérification des conditions de chaque bloc de self
788         on crée ou supprime les noeuds concernés
789         (self est d'un niveau inférieur ou égal à l'ETAPE)
790         """
791         if self.item.object.__class__.__name__ == 'ETAPE_NIVEAU': return 0
792         test = 0
793         l_bloc_arajouter,l_bloc_aenlever = self.verif_condition_bloc()
794         if len(l_bloc_arajouter) > 0:
795             test = 1
796             for mc in l_bloc_arajouter:
797                 self.append_node_child(mc,verif='non')
798         if len(l_bloc_aenlever) > 0:
799             test = 1
800             for mc in l_bloc_aenlever:
801                 mocle = self.get_node_fils(mc)
802                 self.delete_child(mocle)
803         l_mc_presents = self.item.get_liste_mc_presents()
804         l_mc_arajouter= self.verif_condition_regles(l_mc_presents)
805         if len(l_mc_arajouter) > 0:
806             test = 1
807             for mc in l_mc_arajouter:
808                 self.append_node_child(mc,verif='non')
809         if len(l_mc_arajouter)+len(l_bloc_arajouter)+len(l_bloc_aenlever) != 0 :
810             self.verif_condition()
811         return test
812         
813     def verif_condition_bloc(self):
814         return self.item.verif_condition_bloc()
815
816     def verif_condition_regles(self,l_mc_presents):
817         return self.item.verif_condition_regles(l_mc_presents)
818     
819