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.24 2005/06/10 14:59:37 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:
105 """ supprime tous les éléments de l'arbre """
106 for child in self.children:
109 def update_valid(self) :
110 """Cette methode a pour but de mettre a jour la validite du noeud
111 et de propager la demande de mise à jour à son parent
115 def resizescrollregion(self):
116 x0,y0,x1,y1=self.canvas.bbox(ALL)
117 # On ajoute une marge approximativement de la moitié du canvas
118 y1=y1+self.canvas.winfo_height()/2
119 self.canvas.configure(scrollregion = (x0,y0,x1,y1))
121 def select_next(self,event):
122 self.node_selected.select_next()
123 self.canvas.focus_set()
125 def select_previous(self,event):
126 self.node_selected.select_previous()
128 def full_creation(self,name,index):
130 # A changer lorsqu'il y aura plusieurs jdc ouverts en même temps
131 self.children[0].full_creation(name,index)
135 traceback.print_stack()
136 for child in self.children :
137 self.verif_all_children()
140 x1, y1, x2, y2=apply(self.canvas.bbox, items)
141 while x2 > self.canvas.canvasx(0)+self.canvas.winfo_width():
142 old=self.canvas.canvasx(0)
143 self.canvas.xview_scroll( 1, 'units')
144 # avoid endless loop if we can't scroll
145 if old == self.canvas.canvasx(0):
147 while y2 > self.canvas.canvasy(0)+self.canvas.winfo_height():
148 old=self.canvas.canvasy(0)
149 self.canvas.yview_scroll( 1, 'units')
150 if old == self.canvas.canvasy(0):
152 # done in this order to ensure upper-left of object is visible
153 while x1 < self.canvas.canvasx(0):
154 old=self.canvas.canvasx(0)
155 self.canvas.xview_scroll( -1, 'units')
156 if old == self.canvas.canvasx(0):
158 while y1 < self.canvas.canvasy(0):
159 old=self.canvas.canvasy(0)
160 self.canvas.yview_scroll( -1, 'units')
161 if old == self.canvas.canvasy(0):
165 def __init__(self,parent,item,command=None,rmenu=None):
171 self.command = command
173 self.tree = self.parent.tree
174 self.appli = self.parent.appli
175 self.canvas = self.parent.canvas
179 self.state='collapsed'
182 self.x = self.y =None
186 if self.parent is self.tree:
189 self.racine = self.parent.racine
196 self.connections.append(self.item._object)
197 CONNECTOR.Connect(self.item._object,"add",self.onAdd,())
198 CONNECTOR.Connect(self.item._object,"supp",self.onSupp,())
199 CONNECTOR.Connect(self.item._object,"valid",self.onValid,())
200 if self.item.object is not self.item._object:
201 CONNECTOR.Connect(self.item.object,"add",self.onAdd,())
202 CONNECTOR.Connect(self.item.object,"supp",self.onSupp,())
203 CONNECTOR.Connect(self.item.object,"valid",self.onValid,())
204 self.connections.append(self.item.object)
206 def disconnect(self):
207 for c in self.connections:
208 CONNECTOR.Disconnect(c,"add",self.onAdd,())
209 CONNECTOR.Disconnect(c,"supp",self.onSupp,())
210 CONNECTOR.Disconnect(c,"valid",self.onValid,())
214 """ appele a la destruction du noeud """
215 #print "NOEUD DETRUIT",self,self.item.GetLabelText()[0]
217 def force_select(self):
219 # le noeud est selectionné. On force la reconstruction du panel associé
220 if self.command:apply(self.command,(None,))
224 #print "onValid : l'item a changé de validité ",self.item,self.item.object,self.item.object.isvalid()
225 self.update_node_valid()
226 self.update_node_label()
227 self.update_node_texte()
228 if self.selected and self.command:
231 def onAdd(self,objet):
232 #print "onAdd : un objet a été ajouté aux fils de l'item ",self.item.object,objet
234 old_nodes=self.children
236 self.redraw_children(old_nodes)
239 def onSupp(self,objet):
240 #print "onSupp : un objet a été supprimé des fils de l'item ",self.item.object,objet
242 old_nodes=self.children
244 self.redraw_children(old_nodes)
247 def update_nodes(self):
248 #print "update_nodes",self
250 inodes=iter(self.children)
251 sublist=self.item._GetSubList()
258 if old_item in sublist:break
259 #print "item supprime",old_item
261 if item is old_item:break
262 #print "item ajoute",item
263 child = item.itemNode(self,item,self.command,self.rmenu)
264 newnodes.append(child)
266 if old_item is None and item is None:break
268 #print "item conserve",item
269 newnodes.append(node)
271 self.children=newnodes
292 if not self.children : return
293 for child in self.children:
297 def redraw_children(self,old_nodes):
298 #print "redraw_children",old_nodes
304 inodes=iter(old_nodes)
305 iliste=iter(self.children)
306 # on parcourt la liste des anciens noeuds (node)
307 # et la liste des nouveaux noeuds (new_node) en parallele (iterateurs)
312 #print "ancien noeud",node
313 if node in self.children:break # ancien noeud toujours present
314 #print "noeud supprime",node,node.item.GetLabelText()[0]
315 dy=node.y-node.lasty -20
316 #print "deplacer noeuds",y,dy
317 node.move_nodes(y,dy)
319 #supp_nodes.append(node)
321 for new_node in iliste:
322 #print "nouveau noeud",new_node
323 if new_node in old_nodes: break # nouveau noeud deja present
324 #print "noeud ajoute",new_node,new_node.item.GetLabelText()[0]
325 y=self.draw_node(new_node,x,y)
327 if node is None and new_node is None : break
329 if node is new_node: # ancien noeud
330 #print "noeud conserve",node
331 node.update_node_label()
332 y=y+node.lasty-node.y +20
334 self.racine.update_coords()
335 self.canvas.delete('line')
336 self.racine.trace_ligne()
337 self.tree.resizescrollregion()
338 # Mettre à 1 pour verifier les cycles entre objets node
341 #from Misc import Cyclops
342 #z = Cyclops.CycleFinder()
344 #for o in supp_nodes:
352 def tag_move_nodes(self,y):
353 """ Marque pour deplacement tous les noeuds au dela de l'ordonnée y """
354 self.canvas.dtag(ALL,'move')
355 # on marque tous les ids au dela de y
356 x0, y0, x1, y1 = self.canvas.bbox(ALL)
357 self.canvas.addtag_overlapping('move',x0,y,x1,y1)
359 def move_nodes(self,y,dy):
360 """ Déplace de l'incrément dy les noeuds au dela de l'ordonnée y """
361 self.tag_move_nodes(y)
362 # on déplace tous les items de dy
363 self.canvas.move('move',0,dy)
365 def draw_node(self,new_node,x,y):
366 """ Dessine le noeud new_node en x,y en deplacant les noeuds existants
368 Retourne la position du premier des noeuds deplaces
370 self.tag_move_nodes(y)
371 #if new_node.item.isactif():
372 #new_node.state = 'expanded'
373 new_node.state = 'expanded'
375 dy=(new_node.get_nb_children()+1)*20
376 #print "deplacer noeuds",y,dy
377 self.canvas.move('move',0,dy)
378 return new_node.lasty+20
380 def build_children(self):
381 """ Construit la liste des enfants de self """
383 sublist = self.item._GetSubList()
384 if not sublist : return
385 for item in sublist :
386 child = item.itemNode(self,item,self.command,self.rmenu)
387 self.children.append(child)
389 #-----------------------------------------------
390 # Méthodes de sélection/déselection d'un noeud
391 #-----------------------------------------------
393 def select(self, event=None):
395 Rend le noeud courant (self) sélectionné et déselectionne
399 if not self.children : self.build_children()
400 self.tree.deselectall()
402 self.tree.node_selected = self
403 if self.command:apply(self.command,(self,))
407 def deselect(self, event=None):
408 """ Déselectionne self """
410 if self.displayed == 1 : self.dehighlight()
412 def make_visible(self):
413 """ Rend l'objet self visible cad déplace le scroll pour que self soit dans
416 lchild=self.last_child()
417 self.tree.see((self.image_id,lchild.image_id))
419 def select_next(self,ind=0):
420 """ on doit chercher à sélectionner dans l'ordre:
421 - son premier fils s'il est affiché
422 - son frère cadet s'il existe
423 - son oncle (benjamin de son père)
424 - ... appel récursif ...
426 if self.state=='expanded' and len(self.children) > ind:
427 self.children[ind].select()
429 index = self.parent.children.index(self) + 1
431 if isinstance(self.parent,TREE) :
433 self.children[ind].select()
435 self.children[0].select()
437 self.parent.select_next(index)
439 self.parent.select_next(index)
441 def select_mot_previous(self):
442 index = self.parent.children.index(self) - 1
445 self.parent.children[index].select()
451 def select_previous(self):
452 """ on doit d'abord sélectionner(dans l'ordre) :
456 index = self.parent.children.index(self) + 1
458 self.parent.children[index].select()
462 def popup(self,event=None):
464 Declenche le traitement associé au clic droit de la souris
467 if not self.rmenu:return
468 apply(self.rmenu,(self,event))
470 #-----------------------------------------------
471 # Méthodes de recherche d'informations
472 #-----------------------------------------------
473 def geticonimage(self,name=None):
475 Retourne l'image qui doit être associée à self
478 name = self.item.GetIconName()
479 if not name or name == 'aucune' :
481 return images.get_image(name)
483 def get_nb_children(self):
484 """ Retourne le nombre d'enfants affichés de self """
486 if self.state =='collapsed' : return nb
487 for child in self.children :
488 nb = nb + 1 + child.get_nb_children()
491 def get_liste_id(self):
492 """ Retourne la liste de tous les id (filiation comprise) de self """
494 for child in self.children:
495 liste.extend(child.get_liste_id())
498 def get_node_fils(self,name) :
499 """ Retourne le fils de self de nom name s'il existe"""
500 for child in self.children:
501 if child.item.get_nom() == name: return child
504 #-----------------------------------------------
505 # Méthodes d'affichage d'un noeud
506 #-----------------------------------------------
508 """ Permet de tracer le noeud self """
509 # le début du noeud est en x,y
515 # choix de l'icone à afficher : + ou -
516 if self.item.IsExpandable():
517 if self.state == 'expanded':
518 iconname = "minusnode"
519 callback = self.collapse
521 iconname = "plusnode"
522 callback = self.expand
523 image = self.geticonimage(name=iconname)
524 self.icone_id = self.canvas.create_image(self.x, self.y, image=image)
525 self.callback_id=self.canvas.tag_bind(self.icone_id, "<1>", callback)
526 self.id.append(self.icone_id)
527 # création de la ligne horizontale
528 self.ligne_id = self.canvas.create_line(self.x,self.y,self.x+10,self.y)
529 self.id.append(self.ligne_id)
530 self.canvas.tag_lower(self.ligne_id)
531 # affichage de l'icone (carre ,rond, ovale ...) de couleur
532 image = self.geticonimage()
534 self.image_id = self.canvas.create_image(self.x+15,self.y,image = image)
535 self.select_id2=self.canvas.tag_bind(self.image_id,"<1>",self.select)
536 self.popup_id2=self.canvas.tag_bind(self.image_id,"<3>",self.popup)
537 self.id.append(self.image_id)
540 # affichage du texte : nom de l'objet (ETAPE ou MOT-CLE) et sa valeur
542 if self.state == 'expanded' :
543 if not self.children : self.build_children()
544 if len(self.children) > 0:
546 self.lasty = self.children[-1].lasty
548 def drawchildren(self):
549 """ Dessine les enfants de self """
552 for child in self.children:
554 nb = child.get_nb_children()
559 """ Affiche les deux zones de texte après l'icône de couleur de l'objet """
560 if self.image_id != None :
565 # nom,fonte et couleur de l'objet du noeud à afficher
566 labeltext,fonte,couleur = self.item.GetLabelText()
567 if labeltext == '' : labeltext = ' '
568 if fonte == None : fonte = Fonte_Standard
569 if couleur == None : couleur = 'black'
570 # création du widget label
571 self.label = Label(self.canvas,
576 self.label_id = self.canvas.create_window(textx,texty,window=self.label,anchor='w')
577 self.id.append(self.label_id)
578 # bindings sur le widget label
579 self.select_id=self.label.bind("<1>", self.select)
580 self.popup_id=self.label.bind("<3>", self.popup)
581 self.enter_id=self.label.bind("<Enter>",self.enter)
582 self.leave_id=self.label.bind("<Leave>",self.leave)
583 # valeur de cet objet à afficher
584 x0, y0, x1, y1 = self.canvas.bbox(self.label_id)
585 textx = max(x1, 200) + 10
586 text = self.item.GetText() or " "
587 self.text = Label(self.canvas, text=text,
588 bd=0, padx=2, pady=2,background='gray95',
594 self.text_id = self.canvas.create_window(textx, texty,anchor="w", window=self.text)
595 self.id.append(self.text_id)
597 def highlight(self,event=None):
598 """ Met en surbrillance self"""
599 if hasattr(self,'label'):
600 self.label.configure(fg='white',bg='#00008b')
602 def dehighlight(self,event=None):
603 """ Rétablit l'affichage normal de self"""
604 if hasattr(self,'label'):
605 self.label.configure(fg='black',bg='gray95')
607 def enter(self,event=None):
608 """ Met en surbrillance self et affiche le fr de l'objet """
610 fr = self.item.get_fr()
611 self.appli.affiche_infos(fr)
613 def leave(self,event=None):
614 """ Rétablit l'affichage normal de self et efface le fr de l'objet """
615 if not self.selected :
617 self.appli.affiche_infos('')
619 def collapse_children(self):
620 """ Collapse récursivement tous les descendants de self """
621 if not self.children : return
622 for child in self.children:
623 child.state='collapsed'
624 child.collapse_children()
626 def collapse(self,event = None):
627 """ Collapse self et descendants et retrace self """
628 nb = self.get_nb_children()
629 self.state = 'collapsed'
630 self.collapse_children()
634 def expand_node(self,event = None):
635 """ Expanse self et le retrace """
636 if self.state == 'expanded':return
637 #if not self.item.isactif() : return
638 if not self.children : self.build_children()
639 self.state = 'expanded'
640 nb = self.get_nb_children()
643 def expand(self,event = None):
644 """ Expanse self et le retrace """
649 """ Redessine self : nb est le décalage à introduire
650 en dessous de self pour le redessiner """
651 # nb = nombre d'items de décalage
653 # on efface self et on le redessine
655 self.draw(self.x,self.y)
656 # Il n'est pas nécessaire d'appeler update
657 # il suffit d'updater les coordonnees et de retracer les lignes
658 self.racine.update_coords()
659 self.racine.trace_ligne()
661 self.tree.resizescrollregion()
663 def update_coords(self):
664 """ Permet d'updater les coordonnes de self et de tous ses enfants"""
665 if self.displayed == 0 : return
666 if self.image_id != None :
667 coords = self.canvas.coords(self.image_id)
668 self.x = coords[0]-15
670 coords = self.canvas.coords(self.label_id)
671 self.x = coords[0]-15
674 if self.state == 'expanded' :
675 for child in self.children:
676 if child.displayed != 0:
677 child.update_coords()
678 self.lasty = child.lasty
680 def update_icone(self):
681 """ Met à jour les icônes de tous les noeuds : teste la validité de l'objet
682 Cette méthode est très lente, trop !!"""
683 if self.image_id != None :
684 image = self.geticonimage()
685 self.canvas.itemconfig(self.image_id,image=image)
686 if self.state == 'expanded':
687 for child in self.children:
688 if child.displayed != 0:
691 def update_label_texte(self):
692 """ Met a jour le label du noeud et celui de tous ses fils ouverts """
693 self.update_node_label()
694 if self.state == 'expanded' :
695 for child in self.children:
696 if child.displayed != 0 : child.update_label_texte()
698 def update_texte(self):
699 """ Met à jour les noms des SD et valeurs des mots-clés """
700 self.update_node_texte()
701 if self.state == 'expanded' :
702 for child in self.children:
703 if child.displayed != 0 : child.update_texte()
705 def update_node_label(self):
706 """ Met a jour le label du noeud """
707 if self.displayed == 0 : return
708 # nom,fonte et couleur de l'objet du noeud à afficher
709 labeltext,fonte,couleur = self.item.GetLabelText()
710 if labeltext == '' : labeltext = ' '
711 if fonte == None : fonte = Fonte_Standard
712 if couleur == None : couleur = 'black'
713 self.label.configure(text=labeltext,font=fonte)
715 def update_node_texte(self):
716 """ Met à jour les noms des SD et valeurs des mots-clés """
717 if self.displayed == 0 : return
718 text = self.item.GetText()
719 if text == None : text = ''
720 self.text.configure(text=text)
722 def update_node_valid(self) :
723 """Cette methode remet a jour la validite du noeud (icone)
726 if self.displayed == 0 : return
727 if self.image_id != None :
728 image = self.geticonimage()
729 self.canvas.itemconfig(self.image_id,image=image)
731 def update_valid(self) :
732 """Cette methode a pour but de mettre a jour la validite du noeud
733 et de propager la demande de mise à jour à son parent
735 self.update_node_valid()
736 self.parent.update_valid()
738 def update(self,event=None) :
740 Cette méthode est appelée pour demander l update d un noeud
741 d'un jeu de commandes
742 Cette demande est transmise au noeud racine (le JDC) qui update
743 tout l arbre représentant le jeu de commandes
744 Pendant cette mise à jour, on appelle la méthode isvalid qui
745 fera l update de tous les objets déclarés modifiés lors des
747 La métode isvalid est en général appelée par l intermédiaire de
748 update_icone -> geticonimage -> GetIconName
751 #traceback.print_stack()
752 self.racine.update_coords()
753 self.racine.trace_ligne()
754 self.racine.update_icone()
755 self.racine.update_texte()
756 self.racine.update_label_texte()
757 self.tree.resizescrollregion()
759 def efface_node(self):
760 if self.displayed != 0:
761 self.label.unbind("<1>", self.select_id)
762 self.label.unbind("<3>", self.popup_id)
763 self.label.unbind("<Enter>",self.enter_id)
764 self.label.unbind("<Leave>",self.leave_id)
765 self.canvas.tag_unbind(self.image_id,"<1>",self.select_id2)
766 self.canvas.tag_unbind(self.image_id,"<3>",self.popup_id2)
767 if self.item.IsExpandable():
768 self.canvas.tag_unbind(self.icone_id, "<1>", self.callback_id)
773 self.canvas.delete(id)
784 """ Efface du canvas les id associés à self : cad les siens et ceux
787 if not self.children : return
788 for child in self.children:
792 """ Déplace de l'incrément dy tous les id en dessous de self """
793 # il faut marquer tous les suivants de self
794 bbox1 = self.canvas.bbox(ALL)
795 self.canvas.dtag(ALL,'move')
796 self.canvas.delete('line')
798 self.canvas.addtag_overlapping('move',bbox1[0],self.y +10,bbox1[2],bbox1[3])
800 print "Erreur dans move :"
803 print self.item.getObject()
804 print self.item.getObject().definition.label
807 # on déplace tous les items de dy
808 self.canvas.move('move',0,dy)
810 def trace_ligne(self):
811 """ Dessine les lignes verticales entre frères et entre père et premier fils"""
812 if self.state=='collapsed' : return
813 if len(self.children)==0 : return
814 # on est bien dans le cas d'un noeud expansé avec enfants ...
815 # il faut rechercher l'ordonnée du dernier fils de self
816 y_end = self.children[-1].y
817 ligne = self.canvas.create_line(self.x+15,self.y,self.x+15,y_end,tags='line')
818 self.canvas.tag_lower(ligne)
819 for child in self.children :
823 print "Erreur dans trace_ligne :"
825 print child.item.getObject()
827 def last_child(self):
829 if self.state == 'expanded' and self.children:
830 lchild= self.children[-1].last_child()
833 #------------------------------------------------------------------
834 # Méthodes de création et destruction de noeuds
835 # Certaines de ces méthodes peuvent être appelées depuis l'externe
836 #------------------------------------------------------------------
837 def replace_node(self,node1,node2):
838 """ Remplace le noeud 1 par le noeud 2 dans la liste des enfants de self"""
840 index= self.children.index(node1)
841 self.delete_node_child(node1)
842 self.children.insert(index,node2)
844 def replace_enfant(self,item):
845 """ Retourne le noeud fils à éventuellement remplacer """
847 return self.get_node_fils(item.get_nom())
849 def full_creation(self,name,pos=None):
851 Interface avec ACCAS : création de l'objet de nom name et
852 du noeud associé. Retourne le noeud fils ainsi créé
855 #print "full_creation",name,pos,self.item
856 item = self.item.additem(name,pos)
857 if item == None or item == 0:
858 # impossible d'ajouter le noeud de nom : name
861 enfant = self.replace_enfant(item)
863 # un fils de même nom existe déjà : on le remplace
864 child = item.itemNode(self,item,self.command,self.rmenu)
865 self.replace_node(enfant,child)
867 child = item.itemNode(self, item,self.command,self.rmenu)
869 self.children.append(child)
871 self.children.insert(pos,child)
874 def append_brother_BAK(self,name,pos='after',retour='non'):
876 Permet d'ajouter un frère à self
877 par défaut on l'ajoute après self
881 # on veut ajouter le frère de nom name directement avant ou après self
882 index = self.parent.children.index(self)
888 print str(pos)," n'est pas un index valide pour append_brother"
890 return self.parent.append_child(name,pos=index,retour=retour)
892 def append_node_child(self,fils,pos=None,verif='oui'):
894 Fait appel à la création complète de fils et à la vérification
895 des conditions en fonction du contexte
896 Attention : fils peut être un nom ou déjà un object (cas d'une copie)
899 if not self.children : self.build_children()
901 if type(fils) == types.InstanceType:
902 pos = self.item.get_index_child(fils.nom)
904 pos = self.item.get_index_child(fils)
905 child = self.full_creation(fils,pos)
907 # on n'a pas pu créer le noeud fils
909 self.state = 'expanded'
911 if child.item.isactif():
912 child.state = 'expanded'
913 if not child.children : child.build_children()
915 child.verif_condition()
916 self.verif_condition()
919 def append_brother(self,name,pos='after',retour='non'):
921 Permet d'ajouter un objet frère à l'objet associé au noeud self
922 par défaut on l'ajoute immédiatement après
925 # on veut ajouter le frère de nom name directement avant ou après self
926 index = self.parent.children.index(self)
932 print str(pos)," n'est pas un index valide pour append_brother"
934 return self.parent.append_child(name,pos=index)
936 def append_child(self,name,pos=None,verif='oui',retour='non'):
938 Methode pour ajouter un objet fils à l'objet associé au noeud self.
939 On peut l'ajouter en début de liste (pos='first'), en fin (pos='last')
940 ou en position intermédiaire.
941 Si pos vaut None, on le place à la position du catalogue.
943 #print "append_child",self,self.children
947 index = len(self.children)
948 elif type(pos) == types.IntType :
951 elif type(pos) == types.InstanceType:
952 # pos est un item. Il faut inserer name apres pos
953 index = self.item.get_index(pos) +1
954 elif type(name) == types.InstanceType:
955 index = self.item.get_index_child(name.nom)
957 index = self.item.get_index_child(name)
958 obj=self.item.additem(name,index)
962 #print "append_child",index,self.children
963 child=self.children[index]
967 def append_child_BAK(self,name,pos=None,verif='oui',retour='non'):
969 Permet d'ajouter un fils à self
970 on peut l'ajouter en fin de liste (défaut) ou en début
977 index = len(self.children)
978 elif pos != None and type(pos) == types.IntType :
979 # on donne la position depuis l'extérieur
980 # (appel de append_child par append_brother par exemple)
982 elif type(pos) == types.InstanceType:
983 # pos est un item. Il faut inserer name apres pos
984 index = self.item.get_index(pos) +1
986 if type(name) == types.InstanceType:
987 index = self.item.get_index_child(name.nom)
989 index = self.item.get_index_child(name)
990 nbold = self.get_nb_children()
991 self.state='expanded'
992 child = self.append_node_child(name,pos=index)
994 # on n'a pas pu créer le fils
996 nbnew = self.get_nb_children()
997 self.redraw(nbnew-nbold)
999 if retour == 'oui': return child
1001 def delete_node_child_BAK(self,child):
1002 """ Supprime child des enfants de self et les id associés """
1005 self.children.remove(child)
1006 self.canvas.update()
1008 def delete_child_BAK(self,child):
1010 Supprime child des enfants de self, tous les id associés
1014 if self.item.suppitem(child.item):
1015 self.delete_node_child(child)
1022 Méthode externe pour la destruction de l'objet associé au noeud
1023 La mise à jour des noeuds est faite par onSupp sur notification
1025 index = self.parent.children.index(self) - 1
1026 if index < 0 : index =0
1028 ret=self.parent.item.suppitem(self.item)
1031 brothers=self.parent.children
1033 toselect=brothers[index]
1035 toselect=self.parent
1038 def delete_BAK(self):
1039 """ Méthode externe pour la destruction du noeud ET de l'objet
1040 Gère l'update du canvas"""
1043 nbold = pere.get_nb_children()
1045 if self.parent.children.index(self) > 0 :
1046 index = self.parent.children.index(self) - 1
1049 if self.parent.delete_child(self):
1050 if self.item.get_position() == 'global':
1051 self.etape.verif_all()
1052 elif self.item.get_position() == 'global_jdc':
1053 self.racine.verif_all()
1055 self.parent.verif_condition()
1057 print 'Erreur dans la destruction de ',self.item.get_nom(),' dans delete'
1059 nbnew = pere.get_nb_children()
1060 pere.redraw(nbnew-nbold)
1062 # Le noeud n'est pas au 1er niveau
1063 if pere.parent.parent != None:
1066 enfants = self.parent.children
1068 enfants[index].select()
1071 enfants[index+1].select()
1073 # on est avant debut
1076 def doPaste(self,node_selected):
1077 self.appli.message="Vous ne pouvez copier que des commandes ou des mots-clés facteurs !"
1080 def doPaste_Commande(self,objet_a_copier):
1082 Réalise la copie de l'objet passé en argument qui est nécessairement
1085 child = self.append_brother(objet_a_copier,retour='oui')
1088 #--------------------------------------------------------------
1089 # Méthodes de vérification du contexte et de validité du noeud
1090 #--------------------------------------------------------------
1091 def verif_all(self):
1093 traceback.print_stack()
1094 self.verif_all_children()
1096 def verif_all_children(self):
1098 traceback.print_stack()
1099 if not self.children : self.build_children()
1101 for child in self.children :
1102 child.verif_all_children()
1106 Lance la vérification des conditions des blocs de self et le cas
1107 échéant redessine self
1110 traceback.print_stack()
1111 nbold = self.get_nb_children()
1112 test = self.verif_condition()
1113 nbnew = self.get_nb_children()
1115 self.redraw(nbnew-nbold)
1117 def verif_condition(self):
1119 on lance la vérification des conditions de chaque bloc de self
1120 on crée ou supprime les noeuds concernés
1121 (self est d'un niveau inférieur ou égal à l'ETAPE)
1124 traceback.print_stack()
1126 l_bloc_arajouter,l_bloc_aenlever = self.verif_condition_bloc()
1127 if len(l_bloc_arajouter) > 0:
1129 for mc in l_bloc_arajouter:
1130 self.append_node_child(mc,verif='non')
1131 if len(l_bloc_aenlever) > 0:
1133 for mc in l_bloc_aenlever:
1134 mocle = self.get_node_fils(mc)
1135 self.delete_child(mocle)
1136 l_mc_presents = self.item.get_liste_mc_presents()
1137 l_mc_arajouter= self.verif_condition_regles(l_mc_presents)
1138 if len(l_mc_arajouter) > 0:
1140 for mc in l_mc_arajouter:
1141 self.append_node_child(mc,verif='non')
1142 if len(l_mc_arajouter)+len(l_bloc_arajouter)+len(l_bloc_aenlever) != 0 :
1143 self.verif_condition()
1146 def verif_condition_bloc(self):
1148 traceback.print_stack()
1149 return self.item.verif_condition_bloc()
1151 def verif_condition_regles(self,l_mc_presents):
1153 traceback.print_stack()
1154 return self.item.verif_condition_regles(l_mc_presents)