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