1 # -*- coding: utf-8 -*-
2 # CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
20 # ======================================================================
21 import os,sys,string,re,types,traceback
27 from Ihm import CONNECTOR
30 __version__="$Name: $"
31 __Id__="$Id: treewidget.py,v 1.22 2005/06/01 15:18:16 eficas Exp $"
34 Fonte_Standard = fontes.standard
37 def __init__(self,appli,jdc_item,scrolledcanvas,command = None,rmenu=None):
39 self.scrolledcanvas = scrolledcanvas
40 self.canvas = self.scrolledcanvas.component('canvas')
41 self.canvas.bind("<Key-Prior>", self.page_up)
42 self.canvas.bind("<Key-Next>", self.page_down)
43 self.canvas.bind("<Key-Up>", self.unit_up)
44 self.canvas.bind("<Key-Down>", self.unit_down)
45 self.canvas.bind("<Key-Left>", self.mot_up)
46 self.canvas.bind("<Key-Right>", self.mot_down)
47 self.canvas.bind("<1>", self.canvas_select)
49 self.command = command
54 self.node_selected = None
57 def canvas_select(self,event):
58 self.canvas.focus_set()
60 def page_up(self,event):
61 event.widget.yview_scroll(-1, "page")
62 def page_down(self,event):
63 event.widget.yview_scroll(1, "page")
64 def unit_up(self,event):
65 event.widget.yview_scroll(-1, "unit")
66 def unit_down(self,event):
67 event.widget.yview_scroll(1, "unit")
69 def mot_down(self,event):
70 self.select_next(None)
71 self.canvas.focus_set()
73 def mot_up(self,event):
74 self.node_selected.select_mot_previous()
75 self.canvas.focus_set()
77 def build_children(self):
78 """ Construit la liste des enfants de self """
80 child = self.item.itemNode(self,self.item,self.command,self.rmenu)
81 self.children.append(child)
82 child.state='expanded'
85 """ Dessine l'arbre """
88 for child in self.children:
90 lasty = child.lasty + 15
91 self.children[0].select()
92 self.resizescrollregion()
94 def deselectall(self):
95 """ déselectionne tous les éléments de l'arbre """
96 if self.node_selected :
97 self.node_selected.deselect()
100 """ Update tous les éléments de l'arbre """
101 for child in self.children:
104 def update_valid(self) :
105 """Cette methode a pour but de mettre a jour la validite du noeud
106 et de propager la demande de mise à jour à son parent
110 def resizescrollregion(self):
111 x0,y0,x1,y1=self.canvas.bbox(ALL)
112 # On ajoute une marge approximativement de la moitié du canvas
113 y1=y1+self.canvas.winfo_height()/2
114 self.canvas.configure(scrollregion = (x0,y0,x1,y1))
116 def select_next(self,event):
117 self.node_selected.select_next()
118 self.canvas.focus_set()
120 def select_previous(self,event):
121 self.node_selected.select_previous()
123 def full_creation(self,name,index):
125 # A changer lorsqu'il y aura plusieurs jdc ouverts en même temps
126 self.children[0].full_creation(name,index)
130 traceback.print_stack()
131 for child in self.children :
132 self.verif_all_children()
135 x1, y1, x2, y2=apply(self.canvas.bbox, items)
136 while x2 > self.canvas.canvasx(0)+self.canvas.winfo_width():
137 old=self.canvas.canvasx(0)
138 self.canvas.xview_scroll( 1, 'units')
139 # avoid endless loop if we can't scroll
140 if old == self.canvas.canvasx(0):
142 while y2 > self.canvas.canvasy(0)+self.canvas.winfo_height():
143 old=self.canvas.canvasy(0)
144 self.canvas.yview_scroll( 1, 'units')
145 if old == self.canvas.canvasy(0):
147 # done in this order to ensure upper-left of object is visible
148 while x1 < self.canvas.canvasx(0):
149 old=self.canvas.canvasx(0)
150 self.canvas.xview_scroll( -1, 'units')
151 if old == self.canvas.canvasx(0):
153 while y1 < self.canvas.canvasy(0):
154 old=self.canvas.canvasy(0)
155 self.canvas.yview_scroll( -1, 'units')
156 if old == self.canvas.canvasy(0):
160 def __init__(self,parent,item,command=None,rmenu=None):
166 self.command = command
168 self.tree = self.parent.tree
169 self.appli = self.parent.appli
170 self.canvas = self.parent.canvas
174 self.state='collapsed'
177 self.x = self.y =None
181 if self.parent is self.tree:
184 self.racine = self.parent.racine
186 # etape = noeud d'étape auquel appartient self
187 # = self si c'est lui-même
188 #if isinstance(self.parent,Tree) :
189 # on est sur un noeud de JDC
191 #elif isinstance(self.parent.parent,Tree) :
192 # on est sur un noeud d'étape
195 # on est sur un noeud de mot-clé
196 #self.etape=self.parent.etape
203 self.connections.append(self.item._object)
204 CONNECTOR.Connect(self.item._object,"add",self.onAdd,())
205 CONNECTOR.Connect(self.item._object,"supp",self.onSupp,())
206 CONNECTOR.Connect(self.item._object,"valid",self.onValid,())
207 if self.item.object is not self.item._object:
208 CONNECTOR.Connect(self.item.object,"add",self.onAdd,())
209 CONNECTOR.Connect(self.item.object,"supp",self.onSupp,())
210 CONNECTOR.Connect(self.item.object,"valid",self.onValid,())
211 self.connections.append(self.item.object)
213 def disconnect(self):
214 for c in self.connections:
215 CONNECTOR.Disconnect(c,"add",self.onAdd,())
216 CONNECTOR.Disconnect(c,"supp",self.onSupp,())
217 CONNECTOR.Disconnect(c,"valid",self.onValid,())
221 """ appele a la destruction du noeud """
222 #print "NOEUD DETRUIT",self,self.item.GetLabelText()[0]
224 def force_select(self):
226 # le noeud est selectionné. On force la reconstruction du panel associé
227 if self.command:apply(self.command,(None,))
231 #print "onValid : l'item a changé de validité ",self.item,self.item.object,self.item.object.isvalid()
232 self.update_node_valid()
233 self.update_node_label()
234 self.update_node_texte()
236 def onAdd(self,objet):
237 #print "onAdd : un objet a été ajouté aux fils de l'item ",self.item.object,objet
239 old_nodes=self.children
241 self.redraw_children(old_nodes)
244 def onSupp(self,objet):
245 #print "onSupp : un objet a été supprimé des fils de l'item ",self.item.object,objet
247 old_nodes=self.children
249 self.redraw_children(old_nodes)
252 def update_nodes(self):
253 #print "update_nodes",self
255 inodes=iter(self.children)
256 sublist=self.item._GetSubList()
263 if old_item in sublist:break
264 #print "item supprime",old_item
266 if item is old_item:break
267 #print "item ajoute",item
268 child = item.itemNode(self,item,self.command,self.rmenu)
269 newnodes.append(child)
271 if old_item is None and item is None:break
273 #print "item conserve",item
274 newnodes.append(node)
276 self.children=newnodes
297 if not self.children : return
298 for child in self.children:
302 def redraw_children(self,old_nodes):
303 #print "redraw_children",old_nodes
309 inodes=iter(old_nodes)
310 iliste=iter(self.children)
311 # on parcourt la liste des anciens noeuds (node)
312 # et la liste des nouveaux noeuds (new_node) en parallele (iterateurs)
317 #print "ancien noeud",node
318 if node in self.children:break # ancien noeud toujours present
319 #print "noeud supprime",node,node.item.GetLabelText()[0]
320 dy=node.y-node.lasty -20
321 #print "deplacer noeuds",y,dy
322 node.move_nodes(y,dy)
324 #supp_nodes.append(node)
326 for new_node in iliste:
327 #print "nouveau noeud",new_node
328 if new_node in old_nodes: break # nouveau noeud deja present
329 #print "noeud ajoute",new_node,new_node.item.GetLabelText()[0]
330 y=self.draw_node(new_node,x,y)
332 if node is None and new_node is None : break
334 if node is new_node: # ancien noeud
335 #print "noeud conserve",node
336 node.update_label_texte()
337 y=y+node.lasty-node.y +20
339 self.racine.update_coords()
340 self.canvas.delete('line')
341 self.racine.trace_ligne()
342 self.tree.resizescrollregion()
343 # Mettre à 1 pour verifier les cycles entre objets node
346 #from Misc import Cyclops
347 #z = Cyclops.CycleFinder()
349 #for o in supp_nodes:
357 def tag_move_nodes(self,y):
358 """ Marque pour deplacement tous les noeuds au dela de l'ordonnée y """
359 self.canvas.dtag(ALL,'move')
360 # on marque tous les ids au dela de y
361 x0, y0, x1, y1 = self.canvas.bbox(ALL)
362 self.canvas.addtag_overlapping('move',x0,y,x1,y1)
364 def move_nodes(self,y,dy):
365 """ Déplace de l'incrément dy les noeuds au dela de l'ordonnée y """
366 self.tag_move_nodes(y)
367 # on déplace tous les items de dy
368 self.canvas.move('move',0,dy)
370 def draw_node(self,new_node,x,y):
371 """ Dessine le noeud new_node en x,y en deplacant les noeuds existants
373 Retourne la position du premier des noeuds deplaces
375 self.tag_move_nodes(y)
376 #if new_node.item.isactif():
377 #new_node.state = 'expanded'
378 new_node.state = 'expanded'
380 dy=(new_node.get_nb_children()+1)*20
381 #print "deplacer noeuds",y,dy
382 self.canvas.move('move',0,dy)
383 return new_node.lasty+20
385 def build_children(self):
386 """ Construit la liste des enfants de self """
388 sublist = self.item._GetSubList()
389 if not sublist : return
390 for item in sublist :
391 child = item.itemNode(self,item,self.command,self.rmenu)
392 self.children.append(child)
394 #-----------------------------------------------
395 # Méthodes de sélection/déselection d'un noeud
396 #-----------------------------------------------
398 def select(self, event=None):
400 Rend le noeud courant (self) sélectionné et déselectionne
404 if not self.children : self.build_children()
405 self.tree.deselectall()
407 self.tree.node_selected = self
408 if self.command:apply(self.command,(self,))
412 def deselect(self, event=None):
413 """ Déselectionne self """
415 if self.displayed == 1 : self.dehighlight()
417 def make_visible(self):
418 """ Rend l'objet self visible cad déplace le scroll pour que self soit dans
421 lchild=self.last_child()
422 self.tree.see((self.image_id,lchild.image_id))
424 def select_next(self,ind=0):
425 """ on doit chercher à sélectionner dans l'ordre:
426 - son premier fils s'il est affiché
427 - son frère cadet s'il existe
428 - son oncle (benjamin de son père)
429 - ... appel récursif ...
431 if self.state=='expanded' and len(self.children) > ind:
432 self.children[ind].select()
434 index = self.parent.children.index(self) + 1
436 if isinstance(self.parent,TREE) :
438 self.children[ind].select()
440 self.children[0].select()
442 self.parent.select_next(index)
444 self.parent.select_next(index)
446 def select_mot_previous(self):
447 index = self.parent.children.index(self) - 1
450 self.parent.children[index].select()
456 def select_previous(self):
457 """ on doit d'abord sélectionner(dans l'ordre) :
461 index = self.parent.children.index(self) + 1
463 self.parent.children[index].select()
467 def popup(self,event=None):
469 Declenche le traitement associé au clic droit de la souris
472 if not self.rmenu:return
473 apply(self.rmenu,(self,event))
475 #-----------------------------------------------
476 # Méthodes de recherche d'informations
477 #-----------------------------------------------
478 def geticonimage(self,name=None):
480 Retourne l'image qui doit être associée à self
483 name = self.item.GetIconName()
484 if not name or name == 'aucune' :
486 return images.get_image(name)
488 def get_nb_children(self):
489 """ Retourne le nombre d'enfants affichés de self """
491 if self.state =='collapsed' : return nb
492 for child in self.children :
493 nb = nb + 1 + child.get_nb_children()
496 def get_liste_id(self):
497 """ Retourne la liste de tous les id (filiation comprise) de self """
499 for child in self.children:
500 liste.extend(child.get_liste_id())
503 def get_node_fils(self,name) :
504 """ Retourne le fils de self de nom name s'il existe"""
505 for child in self.children:
506 if child.item.get_nom() == name: return child
509 #-----------------------------------------------
510 # Méthodes d'affichage d'un noeud
511 #-----------------------------------------------
513 """ Permet de tracer le noeud self """
514 # le début du noeud est en x,y
520 # choix de l'icone à afficher : + ou -
521 if self.item.IsExpandable():
522 if self.state == 'expanded':
523 iconname = "minusnode"
524 callback = self.collapse
526 iconname = "plusnode"
527 callback = self.expand
528 image = self.geticonimage(name=iconname)
529 self.icone_id = self.canvas.create_image(self.x, self.y, image=image)
530 self.callback_id=self.canvas.tag_bind(self.icone_id, "<1>", callback)
531 self.id.append(self.icone_id)
532 # création de la ligne horizontale
533 self.ligne_id = self.canvas.create_line(self.x,self.y,self.x+10,self.y)
534 self.id.append(self.ligne_id)
535 self.canvas.tag_lower(self.ligne_id)
536 # affichage de l'icone (carre ,rond, ovale ...) de couleur
537 image = self.geticonimage()
539 self.image_id = self.canvas.create_image(self.x+15,self.y,image = image)
540 self.select_id2=self.canvas.tag_bind(self.image_id,"<1>",self.select)
541 self.popup_id2=self.canvas.tag_bind(self.image_id,"<3>",self.popup)
542 self.id.append(self.image_id)
545 # affichage du texte : nom de l'objet (ETAPE ou MOT-CLE) et sa valeur
547 if self.state == 'expanded' :
548 if not self.children : self.build_children()
549 if len(self.children) > 0:
551 self.lasty = self.children[-1].lasty
553 def drawchildren(self):
554 """ Dessine les enfants de self """
557 for child in self.children:
559 nb = child.get_nb_children()
564 """ Affiche les deux zones de texte après l'icône de couleur de l'objet """
565 if self.image_id != None :
570 # nom,fonte et couleur de l'objet du noeud à afficher
571 labeltext,fonte,couleur = self.item.GetLabelText()
572 if labeltext == '' : labeltext = ' '
573 if fonte == None : fonte = Fonte_Standard
574 if couleur == None : couleur = 'black'
575 # création du widget label
576 self.label = Label(self.canvas,
581 self.label_id = self.canvas.create_window(textx,texty,window=self.label,anchor='w')
582 self.id.append(self.label_id)
583 # bindings sur le widget label
584 self.select_id=self.label.bind("<1>", self.select)
585 self.popup_id=self.label.bind("<3>", self.popup)
586 self.enter_id=self.label.bind("<Enter>",self.enter)
587 self.leave_id=self.label.bind("<Leave>",self.leave)
588 # valeur de cet objet à afficher
589 x0, y0, x1, y1 = self.canvas.bbox(self.label_id)
590 textx = max(x1, 200) + 10
591 text = self.item.GetText() or " "
592 self.text = Label(self.canvas, text=text,
593 bd=0, padx=2, pady=2,background='gray95',
599 self.text_id = self.canvas.create_window(textx, texty,anchor="w", window=self.text)
600 self.id.append(self.text_id)
602 def highlight(self,event=None):
603 """ Met en surbrillance self"""
604 if hasattr(self,'label'):
605 self.label.configure(fg='white',bg='#00008b')
607 def dehighlight(self,event=None):
608 """ Rétablit l'affichage normal de self"""
609 if hasattr(self,'label'):
610 self.label.configure(fg='black',bg='gray95')
612 def enter(self,event=None):
613 """ Met en surbrillance self et affiche le fr de l'objet """
615 fr = self.item.get_fr()
616 self.appli.affiche_infos(fr)
618 def leave(self,event=None):
619 """ Rétablit l'affichage normal de self et efface le fr de l'objet """
620 if not self.selected :
622 self.appli.affiche_infos('')
624 def collapse_children(self):
625 """ Collapse récursivement tous les descendants de self """
626 if not self.children : return
627 for child in self.children:
628 child.state='collapsed'
629 child.collapse_children()
631 def collapse(self,event = None):
632 """ Collapse self et descendants et retrace self """
633 nb = self.get_nb_children()
634 self.state = 'collapsed'
635 self.collapse_children()
639 def expand_node(self,event = None):
640 """ Expanse self et le retrace """
641 if self.state == 'expanded':return
642 #if not self.item.isactif() : return
643 if not self.children : self.build_children()
644 self.state = 'expanded'
645 nb = self.get_nb_children()
648 def expand(self,event = None):
649 """ Expanse self et le retrace """
654 """ Redessine self : nb est le décalage à introduire
655 en dessous de self pour le redessiner """
656 # nb = nombre d'items de décalage
658 # on efface self et on le redessine
660 self.draw(self.x,self.y)
661 # Il n'est pas nécessaire d'appeler update
662 # il suffit d'updater les coordonnees et de retracer les lignes
663 self.racine.update_coords()
664 self.racine.trace_ligne()
666 self.tree.resizescrollregion()
668 def update_coords(self):
669 """ Permet d'updater les coordonnes de self et de tous ses enfants"""
670 if self.displayed == 0 : return
671 if self.image_id != None :
672 coords = self.canvas.coords(self.image_id)
673 self.x = coords[0]-15
675 coords = self.canvas.coords(self.label_id)
676 self.x = coords[0]-15
679 if self.state == 'expanded' :
680 for child in self.children:
681 if child.displayed != 0:
682 child.update_coords()
683 self.lasty = child.lasty
685 def update_icone(self):
686 """ Met à jour les icônes de tous les noeuds : teste la validité de l'objet
687 Cette méthode est très lente, trop !!"""
688 if self.image_id != None :
689 image = self.geticonimage()
690 self.canvas.itemconfig(self.image_id,image=image)
691 if self.state == 'expanded':
692 for child in self.children:
693 if child.displayed != 0:
696 def update_label_texte(self):
697 """ Met a jour le label du noeud et celui de tous ses fils ouverts """
698 self.update_node_label()
699 if self.state == 'expanded' :
700 for child in self.children:
701 if child.displayed != 0 : child.update_label_texte()
703 def update_texte(self):
704 """ Met à jour les noms des SD et valeurs des mots-clés """
705 self.update_node_texte()
706 if self.state == 'expanded' :
707 for child in self.children:
708 if child.displayed != 0 : child.update_texte()
710 def update_node_label(self):
711 """ Met a jour le label du noeud """
712 # nom,fonte et couleur de l'objet du noeud à afficher
713 labeltext,fonte,couleur = self.item.GetLabelText()
714 if labeltext == '' : labeltext = ' '
715 if fonte == None : fonte = Fonte_Standard
716 if couleur == None : couleur = 'black'
717 self.label.configure(text=labeltext,font=fonte)
719 def update_node_texte(self):
720 """ Met à jour les noms des SD et valeurs des mots-clés """
721 text = self.item.GetText()
722 if text == None : text = ''
723 self.text.configure(text=text)
725 def update_node_valid(self) :
726 """Cette methode remet a jour la validite du noeud (icone)
729 if self.image_id != None :
730 image = self.geticonimage()
731 self.canvas.itemconfig(self.image_id,image=image)
733 def update_valid(self) :
734 """Cette methode a pour but de mettre a jour la validite du noeud
735 et de propager la demande de mise à jour à son parent
737 self.update_node_valid()
738 self.parent.update_valid()
740 def update(self,event=None) :
742 Cette méthode est appelée pour demander l update d un noeud
743 d'un jeu de commandes
744 Cette demande est transmise au noeud racine (le JDC) qui update
745 tout l arbre représentant le jeu de commandes
746 Pendant cette mise à jour, on appelle la méthode isvalid qui
747 fera l update de tous les objets déclarés modifiés lors des
749 La métode isvalid est en général appelée par l intermédiaire de
750 update_icone -> geticonimage -> GetIconName
753 #traceback.print_stack()
754 self.racine.update_coords()
755 self.racine.trace_ligne()
756 self.racine.update_icone()
757 self.racine.update_texte()
758 self.tree.resizescrollregion()
760 def efface_node(self):
761 if self.displayed != 0:
762 self.label.unbind("<1>", self.select_id)
763 self.label.unbind("<3>", self.popup_id)
764 self.label.unbind("<Enter>",self.enter_id)
765 self.label.unbind("<Leave>",self.leave_id)
766 self.canvas.tag_unbind(self.image_id,"<1>",self.select_id2)
767 self.canvas.tag_unbind(self.image_id,"<3>",self.popup_id2)
768 if self.item.IsExpandable():
769 self.canvas.tag_unbind(self.icone_id, "<1>", self.callback_id)
774 self.canvas.delete(id)
785 """ Efface du canvas les id associés à self : cad les siens et ceux
788 if not self.children : return
789 for child in self.children:
793 """ Déplace de l'incrément dy tous les id en dessous de self """
794 # il faut marquer tous les suivants de self
795 bbox1 = self.canvas.bbox(ALL)
796 self.canvas.dtag(ALL,'move')
797 self.canvas.delete('line')
799 self.canvas.addtag_overlapping('move',bbox1[0],self.y +10,bbox1[2],bbox1[3])
801 print "Erreur dans move :"
804 print self.item.getObject()
805 print self.item.getObject().definition.label
808 # on déplace tous les items de dy
809 self.canvas.move('move',0,dy)
811 def trace_ligne(self):
812 """ Dessine les lignes verticales entre frères et entre père et premier fils"""
813 if self.state=='collapsed' : return
814 if len(self.children)==0 : return
815 # on est bien dans le cas d'un noeud expansé avec enfants ...
816 # il faut rechercher l'ordonnée du dernier fils de self
817 y_end = self.children[-1].y
818 ligne = self.canvas.create_line(self.x+15,self.y,self.x+15,y_end,tags='line')
819 self.canvas.tag_lower(ligne)
820 for child in self.children :
824 print "Erreur dans trace_ligne :"
826 print child.item.getObject()
828 def last_child(self):
830 if self.state == 'expanded' and self.children:
831 lchild= self.children[-1].last_child()
834 #------------------------------------------------------------------
835 # Méthodes de création et destruction de noeuds
836 # Certaines de ces méthodes peuvent être appelées depuis l'externe
837 #------------------------------------------------------------------
838 def replace_node(self,node1,node2):
839 """ Remplace le noeud 1 par le noeud 2 dans la liste des enfants de self"""
841 index= self.children.index(node1)
842 self.delete_node_child(node1)
843 self.children.insert(index,node2)
845 def replace_enfant(self,item):
846 """ Retourne le noeud fils à éventuellement remplacer """
848 return self.get_node_fils(item.get_nom())
850 def full_creation(self,name,pos=None):
852 Interface avec ACCAS : création de l'objet de nom name et
853 du noeud associé. Retourne le noeud fils ainsi créé
856 #print "full_creation",name,pos,self.item
857 item = self.item.additem(name,pos)
858 if item == None or item == 0:
859 # impossible d'ajouter le noeud de nom : name
862 enfant = self.replace_enfant(item)
864 # un fils de même nom existe déjà : on le remplace
865 child = item.itemNode(self,item,self.command,self.rmenu)
866 self.replace_node(enfant,child)
868 child = item.itemNode(self, item,self.command,self.rmenu)
870 self.children.append(child)
872 self.children.insert(pos,child)
875 def append_brother_BAK(self,name,pos='after',retour='non'):
877 Permet d'ajouter un frère à self
878 par défaut on l'ajoute après self
882 # on veut ajouter le frère de nom name directement avant ou après self
883 index = self.parent.children.index(self)
889 print str(pos)," n'est pas un index valide pour append_brother"
891 return self.parent.append_child(name,pos=index,retour=retour)
893 def append_node_child(self,fils,pos=None,verif='oui'):
895 Fait appel à la création complète de fils et à la vérification
896 des conditions en fonction du contexte
897 Attention : fils peut être un nom ou déjà un object (cas d'une copie)
900 if not self.children : self.build_children()
902 if type(fils) == types.InstanceType:
903 pos = self.item.get_index_child(fils.nom)
905 pos = self.item.get_index_child(fils)
906 child = self.full_creation(fils,pos)
908 # on n'a pas pu créer le noeud fils
910 self.state = 'expanded'
912 if child.item.isactif():
913 child.state = 'expanded'
914 if not child.children : child.build_children()
916 child.verif_condition()
917 self.verif_condition()
920 def append_brother(self,name,pos='after',retour='non'):
922 Permet d'ajouter un objet frère à l'objet associé au noeud self
923 par défaut on l'ajoute immédiatement après
926 # on veut ajouter le frère de nom name directement avant ou après self
927 index = self.parent.children.index(self)
933 print str(pos)," n'est pas un index valide pour append_brother"
935 return self.parent.append_child(name,pos=index)
937 def append_child(self,name,pos=None,verif='oui',retour='non'):
939 Methode pour ajouter un objet fils à l'objet associé au noeud self.
940 On peut l'ajouter en début de liste (pos='first'), en fin (pos='last')
941 ou en position intermédiaire.
942 Si pos vaut None, on le place à la position du catalogue.
944 #print "append_child",self,self.children
948 index = len(self.children)
949 elif type(pos) == types.IntType :
952 elif type(pos) == types.InstanceType:
953 # pos est un item. Il faut inserer name apres pos
954 index = self.item.get_index(pos) +1
955 elif type(name) == types.InstanceType:
956 index = self.item.get_index_child(name.nom)
958 index = self.item.get_index_child(name)
959 obj=self.item.additem(name,index)
963 #print "append_child",index,self.children
964 child=self.children[index]
968 def append_child_BAK(self,name,pos=None,verif='oui',retour='non'):
970 Permet d'ajouter un fils à self
971 on peut l'ajouter en fin de liste (défaut) ou en début
978 index = len(self.children)
979 elif pos != None and type(pos) == types.IntType :
980 # on donne la position depuis l'extérieur
981 # (appel de append_child par append_brother par exemple)
983 elif type(pos) == types.InstanceType:
984 # pos est un item. Il faut inserer name apres pos
985 index = self.item.get_index(pos) +1
987 if type(name) == types.InstanceType:
988 index = self.item.get_index_child(name.nom)
990 index = self.item.get_index_child(name)
991 nbold = self.get_nb_children()
992 self.state='expanded'
993 child = self.append_node_child(name,pos=index)
995 # on n'a pas pu créer le fils
997 nbnew = self.get_nb_children()
998 self.redraw(nbnew-nbold)
1000 if retour == 'oui': return child
1002 def delete_node_child_BAK(self,child):
1003 """ Supprime child des enfants de self et les id associés """
1006 self.children.remove(child)
1007 self.canvas.update()
1009 def delete_child_BAK(self,child):
1011 Supprime child des enfants de self, tous les id associés
1015 if self.item.suppitem(child.item):
1016 self.delete_node_child(child)
1023 Méthode externe pour la destruction de l'objet associé au noeud
1024 La mise à jour des noeuds est faite par onSupp sur notification
1026 index = self.parent.children.index(self) - 1
1027 if index < 0 : index =0
1029 ret=self.parent.item.suppitem(self.item)
1032 brothers=self.parent.children
1034 toselect=brothers[index]
1036 toselect=self.parent
1039 def delete_BAK(self):
1040 """ Méthode externe pour la destruction du noeud ET de l'objet
1041 Gère l'update du canvas"""
1044 nbold = pere.get_nb_children()
1046 if self.parent.children.index(self) > 0 :
1047 index = self.parent.children.index(self) - 1
1050 if self.parent.delete_child(self):
1051 if self.item.get_position() == 'global':
1052 self.etape.verif_all()
1053 elif self.item.get_position() == 'global_jdc':
1054 self.racine.verif_all()
1056 self.parent.verif_condition()
1058 print 'Erreur dans la destruction de ',self.item.get_nom(),' dans delete'
1060 nbnew = pere.get_nb_children()
1061 pere.redraw(nbnew-nbold)
1063 # Le noeud n'est pas au 1er niveau
1064 if pere.parent.parent != None:
1067 enfants = self.parent.children
1069 enfants[index].select()
1072 enfants[index+1].select()
1074 # on est avant debut
1077 def doPaste(self,node_selected):
1078 self.appli.message="Vous ne pouvez copier que des commandes ou des mots-clés facteurs !"
1081 def doPaste_Commande(self,objet_a_copier):
1083 Réalise la copie de l'objet passé en argument qui est nécessairement
1086 child = self.append_brother(objet_a_copier,retour='oui')
1089 #--------------------------------------------------------------
1090 # Méthodes de vérification du contexte et de validité du noeud
1091 #--------------------------------------------------------------
1092 def verif_all(self):
1094 traceback.print_stack()
1095 self.verif_all_children()
1097 def verif_all_children(self):
1099 traceback.print_stack()
1100 if not self.children : self.build_children()
1102 for child in self.children :
1103 child.verif_all_children()
1107 Lance la vérification des conditions des blocs de self et le cas
1108 échéant redessine self
1111 traceback.print_stack()
1112 nbold = self.get_nb_children()
1113 test = self.verif_condition()
1114 nbnew = self.get_nb_children()
1116 self.redraw(nbnew-nbold)
1118 def verif_condition(self):
1120 on lance la vérification des conditions de chaque bloc de self
1121 on crée ou supprime les noeuds concernés
1122 (self est d'un niveau inférieur ou égal à l'ETAPE)
1125 traceback.print_stack()
1127 l_bloc_arajouter,l_bloc_aenlever = self.verif_condition_bloc()
1128 if len(l_bloc_arajouter) > 0:
1130 for mc in l_bloc_arajouter:
1131 self.append_node_child(mc,verif='non')
1132 if len(l_bloc_aenlever) > 0:
1134 for mc in l_bloc_aenlever:
1135 mocle = self.get_node_fils(mc)
1136 self.delete_child(mocle)
1137 l_mc_presents = self.item.get_liste_mc_presents()
1138 l_mc_arajouter= self.verif_condition_regles(l_mc_presents)
1139 if len(l_mc_arajouter) > 0:
1141 for mc in l_mc_arajouter:
1142 self.append_node_child(mc,verif='non')
1143 if len(l_mc_arajouter)+len(l_bloc_arajouter)+len(l_bloc_aenlever) != 0 :
1144 self.verif_condition()
1147 def verif_condition_bloc(self):
1149 traceback.print_stack()
1150 return self.item.verif_condition_bloc()
1152 def verif_condition_regles(self,l_mc_presents):
1154 traceback.print_stack()
1155 return self.item.verif_condition_regles(l_mc_presents)