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.20 2005/04/13 14:59:31 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_label_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 #print "onAdd:nodes",self.children
242 self.redraw_children(old_nodes)
245 def onSupp(self,objet):
246 #print "onSupp : un objet a été supprimé des fils de l'item ",self.item.object,objet
248 old_nodes=self.children
250 #print "onSupp:nodes",self.children
251 self.redraw_children(old_nodes)
254 def update_nodes(self):
255 #print "update_nodes",self
257 inodes=iter(self.children)
258 sublist=self.item._GetSubList()
260 #print "update_nodes",self.children
261 #print "update_nodes",sublist
267 if old_item in sublist:break
268 #print "item supprime",old_item
270 if item is old_item:break
271 #print "item ajoute",item
272 child = item.itemNode(self,item,self.command,self.rmenu)
273 newnodes.append(child)
275 if old_item is None and item is None:break
277 #print "item conserve",item
278 newnodes.append(node)
280 self.children=newnodes
301 if not self.children : return
302 for child in self.children:
306 def redraw_children(self,old_nodes):
307 #print "redraw_children",old_nodes
313 inodes=iter(old_nodes)
314 iliste=iter(self.children)
315 # on parcourt la liste des anciens noeuds (node)
316 # et la liste des nouveaux noeuds (new_node) en parallele (iterateurs)
321 #print "ancien noeud",node
322 if node in self.children:break # ancien noeud toujours present
323 #print "noeud supprime",node,node.item.GetLabelText()[0]
324 dy=node.y-node.lasty -20
325 #print "deplacer noeuds",y,dy
326 node.move_nodes(y,dy)
328 #supp_nodes.append(node)
330 for new_node in iliste:
331 #print "nouveau noeud",new_node
332 if new_node in old_nodes: break # nouveau noeud deja present
333 #print "noeud ajoute",new_node,new_node.item.GetLabelText()[0]
334 y=self.draw_node(new_node,x,y)
336 if node is None and new_node is None : break
338 if node is new_node: # ancien noeud
339 #print "noeud conserve",node
340 node.update_label_texte()
341 y=y+node.lasty-node.y +20
343 self.racine.update_coords()
344 self.canvas.delete('line')
345 self.racine.trace_ligne()
346 self.tree.resizescrollregion()
347 # Mettre à 1 pour verifier les cycles entre objets node
350 #from Misc import Cyclops
351 #z = Cyclops.CycleFinder()
353 #for o in supp_nodes:
361 def tag_move_nodes(self,y):
362 """ Marque pour deplacement tous les noeuds au dela de l'ordonnée y """
363 self.canvas.dtag(ALL,'move')
364 # on marque tous les ids au dela de y
365 x0, y0, x1, y1 = self.canvas.bbox(ALL)
366 self.canvas.addtag_overlapping('move',x0,y,x1,y1)
368 def move_nodes(self,y,dy):
369 """ Déplace de l'incrément dy les noeuds au dela de l'ordonnée y """
370 self.tag_move_nodes(y)
371 # on déplace tous les items de dy
372 self.canvas.move('move',0,dy)
374 def draw_node(self,new_node,x,y):
375 """ Dessine le noeud new_node en x,y en deplacant les noeuds existants
377 Retourne la position du premier des noeuds deplaces
379 self.tag_move_nodes(y)
380 #if new_node.item.isactif():
381 #new_node.state = 'expanded'
382 new_node.state = 'expanded'
384 dy=(new_node.get_nb_children()+1)*20
385 #print "deplacer noeuds",y,dy
386 self.canvas.move('move',0,dy)
387 return new_node.lasty+20
389 def build_children(self):
390 """ Construit la liste des enfants de self """
392 sublist = self.item._GetSubList()
393 if not sublist : return
394 for item in sublist :
395 child = item.itemNode(self,item,self.command,self.rmenu)
396 self.children.append(child)
398 #-----------------------------------------------
399 # Méthodes de sélection/déselection d'un noeud
400 #-----------------------------------------------
402 def select(self, event=None):
404 Rend le noeud courant (self) sélectionné et déselectionne
408 #traceback.print_stack()
409 if not self.children : self.build_children()
410 #if self.selected and self.tree.node_selected is self: return
411 self.tree.deselectall()
413 self.tree.node_selected = self
414 if self.command:apply(self.command,(self,))
418 def deselect(self, event=None):
419 """ Déselectionne self """
421 if self.displayed == 1 : self.dehighlight()
423 def make_visible(self):
424 """ Rend l'objet self visible cad déplace le scroll pour que self soit dans
427 lchild=self.last_child()
428 self.tree.see((self.image_id,lchild.image_id))
430 def select_next(self,ind=0):
431 """ on doit chercher à sélectionner dans l'ordre:
432 - son premier fils s'il est affiché
433 - son frère cadet s'il existe
434 - son oncle (benjamin de son père)
435 - ... appel récursif ...
437 if self.state=='expanded' and len(self.children) > ind:
438 self.children[ind].select()
440 index = self.parent.children.index(self) + 1
442 if isinstance(self.parent,TREE) :
444 self.children[ind].select()
446 self.children[0].select()
448 self.parent.select_next(index)
450 self.parent.select_next(index)
452 def select_mot_previous(self):
453 index = self.parent.children.index(self) - 1
456 self.parent.children[index].select()
462 def select_previous(self):
463 """ on doit d'abord sélectionner(dans l'ordre) :
467 index = self.parent.children.index(self) + 1
469 self.parent.children[index].select()
473 def popup(self,event=None):
475 Declenche le traitement associé au clic droit de la souris
478 if not self.rmenu:return
479 apply(self.rmenu,(self,event))
481 #-----------------------------------------------
482 # Méthodes de recherche d'informations
483 #-----------------------------------------------
484 def geticonimage(self,name=None):
486 Retourne l'image qui doit être associée à self
489 name = self.item.GetIconName()
490 if not name or name == 'aucune' :
492 return images.get_image(name)
494 def get_nb_children(self):
495 """ Retourne le nombre d'enfants affichés de self """
497 if self.state =='collapsed' : return nb
498 for child in self.children :
499 nb = nb + 1 + child.get_nb_children()
502 def get_liste_id(self):
503 """ Retourne la liste de tous les id (filiation comprise) de self """
505 for child in self.children:
506 liste.extend(child.get_liste_id())
509 def get_node_fils(self,name) :
510 """ Retourne le fils de self de nom name s'il existe"""
511 for child in self.children:
512 if child.item.get_nom() == name: return child
515 #-----------------------------------------------
516 # Méthodes d'affichage d'un noeud
517 #-----------------------------------------------
519 """ Permet de tracer le noeud self """
520 # le début du noeud est en x,y
526 # choix de l'icone à afficher : + ou -
527 if self.item.IsExpandable():
528 if self.state == 'expanded':
529 iconname = "minusnode"
530 callback = self.collapse
532 iconname = "plusnode"
533 callback = self.expand
534 image = self.geticonimage(name=iconname)
535 self.icone_id = self.canvas.create_image(self.x, self.y, image=image)
536 self.callback_id=self.canvas.tag_bind(self.icone_id, "<1>", callback)
537 self.id.append(self.icone_id)
538 # création de la ligne horizontale
539 self.ligne_id = self.canvas.create_line(self.x,self.y,self.x+10,self.y)
540 self.id.append(self.ligne_id)
541 self.canvas.tag_lower(self.ligne_id)
542 # affichage de l'icone (carre ,rond, ovale ...) de couleur
543 image = self.geticonimage()
545 self.image_id = self.canvas.create_image(self.x+15,self.y,image = image)
546 self.select_id2=self.canvas.tag_bind(self.image_id,"<1>",self.select)
547 self.popup_id2=self.canvas.tag_bind(self.image_id,"<3>",self.popup)
548 self.id.append(self.image_id)
551 # affichage du texte : nom de l'objet (ETAPE ou MOT-CLE) et sa valeur
553 if self.state == 'expanded' :
554 if not self.children : self.build_children()
555 if len(self.children) > 0:
557 self.lasty = self.children[-1].lasty
559 def drawchildren(self):
560 """ Dessine les enfants de self """
563 for child in self.children:
565 nb = child.get_nb_children()
570 """ Affiche les deux zones de texte après l'icône de couleur de l'objet """
571 if self.image_id != None :
576 # nom,fonte et couleur de l'objet du noeud à afficher
577 labeltext,fonte,couleur = self.item.GetLabelText()
578 if labeltext == '' : labeltext = ' '
579 if fonte == None : fonte = Fonte_Standard
580 if couleur == None : couleur = 'black'
581 # création du widget label
582 self.label = Label(self.canvas,
587 self.label_id = self.canvas.create_window(textx,texty,window=self.label,anchor='w')
588 self.id.append(self.label_id)
589 # bindings sur le widget label
590 self.select_id=self.label.bind("<1>", self.select)
591 self.popup_id=self.label.bind("<3>", self.popup)
592 self.enter_id=self.label.bind("<Enter>",self.enter)
593 self.leave_id=self.label.bind("<Leave>",self.leave)
594 # valeur de cet objet à afficher
595 x0, y0, x1, y1 = self.canvas.bbox(self.label_id)
596 textx = max(x1, 200) + 10
597 text = self.item.GetText() or " "
598 self.text = Label(self.canvas, text=text,
599 bd=0, padx=2, pady=2,background='gray95',
605 self.text_id = self.canvas.create_window(textx, texty,anchor="w", window=self.text)
606 self.id.append(self.text_id)
608 def highlight(self,event=None):
609 """ Met en surbrillance self"""
610 if hasattr(self,'label'):
611 self.label.configure(fg='white',bg='#00008b')
613 def dehighlight(self,event=None):
614 """ Rétablit l'affichage normal de self"""
615 if hasattr(self,'label'):
616 self.label.configure(fg='black',bg='gray95')
618 def enter(self,event=None):
619 """ Met en surbrillance self et affiche le fr de l'objet """
621 fr = self.item.get_fr()
622 self.appli.affiche_infos(fr)
624 def leave(self,event=None):
625 """ Rétablit l'affichage normal de self et efface le fr de l'objet """
626 if not self.selected :
628 self.appli.affiche_infos('')
630 def collapse_children(self):
631 """ Collapse récursivement tous les descendants de self """
632 if not self.children : return
633 for child in self.children:
634 child.state='collapsed'
635 child.collapse_children()
637 def collapse(self,event = None):
638 """ Collapse self et descendants et retrace self """
639 nb = self.get_nb_children()
640 self.state = 'collapsed'
641 self.collapse_children()
645 def expand_node(self,event = None):
646 """ Expanse self et le retrace """
647 if self.state == 'expanded':return
648 #if not self.item.isactif() : return
649 if not self.children : self.build_children()
650 self.state = 'expanded'
651 nb = self.get_nb_children()
654 def expand(self,event = None):
655 """ Expanse self et le retrace """
660 """ Redessine self : nb est le décalage à introduire
661 en dessous de self pour le redessiner """
662 # nb = nombre d'items de décalage
664 # on efface self et on le redessine
666 self.draw(self.x,self.y)
667 # Il n'est pas nécessaire d'appeler update
668 # il suffit d'updater les coordonnees et de retracer les lignes
669 self.racine.update_coords()
670 self.racine.trace_ligne()
672 self.tree.resizescrollregion()
674 def update_coords(self):
675 """ Permet d'updater les coordonnes de self et de tous ses enfants"""
676 if self.displayed == 0 : return
677 if self.image_id != None :
678 coords = self.canvas.coords(self.image_id)
679 self.x = coords[0]-15
681 coords = self.canvas.coords(self.label_id)
682 self.x = coords[0]-15
685 if self.state == 'expanded' :
686 for child in self.children:
687 if child.displayed != 0:
688 child.update_coords()
689 self.lasty = child.lasty
691 def update_icone(self):
692 """ Met à jour les icônes de tous les noeuds : teste la validité de l'objet
693 Cette méthode est très lente, trop !!"""
694 if self.image_id != None :
695 image = self.geticonimage()
696 self.canvas.itemconfig(self.image_id,image=image)
697 if self.state == 'expanded':
698 for child in self.children:
699 if child.displayed != 0:
702 def update_label_texte(self):
703 # nom,fonte et couleur de l'objet du noeud à afficher
704 labeltext,fonte,couleur = self.item.GetLabelText()
705 if labeltext == '' : labeltext = ' '
706 if fonte == None : fonte = Fonte_Standard
707 if couleur == None : couleur = 'black'
708 self.label.configure(text=labeltext,font=fonte)
709 if self.state == 'expanded' :
710 for child in self.children:
711 if child.displayed != 0 : child.update_label_texte()
713 def update_texte(self):
714 """ Met à jour les noms des SD et valeurs des mots-clés """
715 text = self.item.GetText()
716 if text == None : text = ''
717 self.text.configure(text=text)
718 if self.state == 'expanded' :
719 for child in self.children:
720 if child.displayed != 0 : child.update_texte()
722 def update_node_valid(self) :
723 """Cette methode remet a jour la validite du noeud (icone)
726 if self.image_id != None :
727 image = self.geticonimage()
728 self.canvas.itemconfig(self.image_id,image=image)
730 def update_valid(self) :
731 """Cette methode a pour but de mettre a jour la validite du noeud
732 et de propager la demande de mise à jour à son parent
734 self.update_node_valid()
735 self.parent.update_valid()
737 def update(self,event=None) :
739 Cette méthode est appelée pour demander l update d un noeud
740 d'un jeu de commandes
741 Cette demande est transmise au noeud racine (le JDC) qui update
742 tout l arbre représentant le jeu de commandes
743 Pendant cette mise à jour, on appelle la méthode isvalid qui
744 fera l update de tous les objets déclarés modifiés lors des
746 La métode isvalid est en général appelée par l intermédiaire de
747 update_icone -> geticonimage -> GetIconName
750 #traceback.print_stack()
751 self.racine.update_coords()
752 self.racine.trace_ligne()
753 self.racine.update_icone()
754 self.racine.update_texte()
755 self.tree.resizescrollregion()
757 def efface_node(self):
758 if self.displayed != 0:
759 self.label.unbind("<1>", self.select_id)
760 self.label.unbind("<3>", self.popup_id)
761 self.label.unbind("<Enter>",self.enter_id)
762 self.label.unbind("<Leave>",self.leave_id)
763 self.canvas.tag_unbind(self.image_id,"<1>",self.select_id2)
764 self.canvas.tag_unbind(self.image_id,"<3>",self.popup_id2)
765 if self.item.IsExpandable():
766 self.canvas.tag_unbind(self.icone_id, "<1>", self.callback_id)
771 self.canvas.delete(id)
782 """ Efface du canvas les id associés à self : cad les siens et ceux
785 if not self.children : return
786 for child in self.children:
790 """ Déplace de l'incrément dy tous les id en dessous de self """
791 # il faut marquer tous les suivants de self
792 bbox1 = self.canvas.bbox(ALL)
793 self.canvas.dtag(ALL,'move')
794 self.canvas.delete('line')
796 self.canvas.addtag_overlapping('move',bbox1[0],self.y +10,bbox1[2],bbox1[3])
798 print "Erreur dans move :"
801 print self.item.getObject()
802 print self.item.getObject().definition.label
805 # on déplace tous les items de dy
806 self.canvas.move('move',0,dy)
808 def trace_ligne(self):
809 """ Dessine les lignes verticales entre frères et entre père et premier fils"""
810 if self.state=='collapsed' : return
811 if len(self.children)==0 : return
812 # on est bien dans le cas d'un noeud expansé avec enfants ...
813 # il faut rechercher l'ordonnée du dernier fils de self
814 y_end = self.children[-1].y
815 ligne = self.canvas.create_line(self.x+15,self.y,self.x+15,y_end,tags='line')
816 self.canvas.tag_lower(ligne)
817 for child in self.children :
821 print "Erreur dans trace_ligne :"
823 print child.item.getObject()
825 def last_child(self):
827 if self.state == 'expanded' and self.children:
828 lchild= self.children[-1].last_child()
831 #------------------------------------------------------------------
832 # Méthodes de création et destruction de noeuds
833 # Certaines de ces méthodes peuvent être appelées depuis l'externe
834 #------------------------------------------------------------------
835 def replace_node(self,node1,node2):
836 """ Remplace le noeud 1 par le noeud 2 dans la liste des enfants de self"""
838 index= self.children.index(node1)
839 self.delete_node_child(node1)
840 self.children.insert(index,node2)
842 def replace_enfant(self,item):
843 """ Retourne le noeud fils à éventuellement remplacer """
845 return self.get_node_fils(item.get_nom())
847 def full_creation(self,name,pos=None):
849 Interface avec ACCAS : création de l'objet de nom name et
850 du noeud associé. Retourne le noeud fils ainsi créé
853 #print "full_creation",name,pos,self.item
854 item = self.item.additem(name,pos)
855 if item == None or item == 0:
856 # impossible d'ajouter le noeud de nom : name
859 enfant = self.replace_enfant(item)
861 # un fils de même nom existe déjà : on le remplace
862 child = item.itemNode(self,item,self.command,self.rmenu)
863 self.replace_node(enfant,child)
865 child = item.itemNode(self, item,self.command,self.rmenu)
867 self.children.append(child)
869 self.children.insert(pos,child)
872 def append_brother_BAK(self,name,pos='after',retour='non'):
874 Permet d'ajouter un frère à self
875 par défaut on l'ajoute après self
879 # on veut ajouter le frère de nom name directement avant ou après self
880 index = self.parent.children.index(self)
886 print str(pos)," n'est pas un index valide pour append_brother"
888 return self.parent.append_child(name,pos=index,retour=retour)
890 def append_node_child(self,fils,pos=None,verif='oui'):
892 Fait appel à la création complète de fils et à la vérification
893 des conditions en fonction du contexte
894 Attention : fils peut être un nom ou déjà un object (cas d'une copie)
897 if not self.children : self.build_children()
899 if type(fils) == types.InstanceType:
900 pos = self.item.get_index_child(fils.nom)
902 pos = self.item.get_index_child(fils)
903 child = self.full_creation(fils,pos)
905 # on n'a pas pu créer le noeud fils
907 self.state = 'expanded'
909 if child.item.isactif():
910 child.state = 'expanded'
911 if not child.children : child.build_children()
913 child.verif_condition()
914 self.verif_condition()
917 def append_brother(self,name,pos='after',retour='non'):
919 Permet d'ajouter un objet frère à l'objet associé au noeud self
920 par défaut on l'ajoute immédiatement après
923 # on veut ajouter le frère de nom name directement avant ou après self
924 index = self.parent.children.index(self)
930 print str(pos)," n'est pas un index valide pour append_brother"
932 return self.parent.append_child(name,pos=index)
934 def append_child(self,name,pos=None,verif='oui',retour='non'):
936 Methode pour ajouter un objet fils à l'objet associé au noeud self.
937 On peut l'ajouter en début de liste (pos='first'), en fin (pos='last')
938 ou en position intermédiaire.
939 Si pos vaut None, on le place à la position du catalogue.
941 #print "append_child",self,self.children
945 index = len(self.children)
946 elif type(pos) == types.IntType :
949 elif type(pos) == types.InstanceType:
950 # pos est un item. Il faut inserer name apres pos
951 index = self.item.get_index(pos) +1
952 elif type(name) == types.InstanceType:
953 index = self.item.get_index_child(name.nom)
955 index = self.item.get_index_child(name)
956 obj=self.item.additem(name,index)
960 #print "append_child",index,self.children
961 child=self.children[index]
965 def append_child_BAK(self,name,pos=None,verif='oui',retour='non'):
967 Permet d'ajouter un fils à self
968 on peut l'ajouter en fin de liste (défaut) ou en début
975 index = len(self.children)
976 elif pos != None and type(pos) == types.IntType :
977 # on donne la position depuis l'extérieur
978 # (appel de append_child par append_brother par exemple)
980 elif type(pos) == types.InstanceType:
981 # pos est un item. Il faut inserer name apres pos
982 index = self.item.get_index(pos) +1
984 if type(name) == types.InstanceType:
985 index = self.item.get_index_child(name.nom)
987 index = self.item.get_index_child(name)
988 nbold = self.get_nb_children()
989 self.state='expanded'
990 child = self.append_node_child(name,pos=index)
992 # on n'a pas pu créer le fils
994 nbnew = self.get_nb_children()
995 self.redraw(nbnew-nbold)
997 if retour == 'oui': return child
999 def delete_node_child_BAK(self,child):
1000 """ Supprime child des enfants de self et les id associés """
1002 self.children.remove(child)
1003 self.canvas.update()
1005 def delete_child_BAK(self,child):
1007 Supprime child des enfants de self, tous les id associés
1010 if self.item.suppitem(child.item):
1011 self.delete_node_child(child)
1018 Méthode externe pour la destruction de l'objet associé au noeud
1019 La mise à jour des noeuds est faite par onSupp sur notification
1021 index = self.parent.children.index(self) - 1
1022 if index < 0 : index =0
1025 ret=self.parent.item.suppitem(self.item)
1028 brothers=self.parent.children
1030 toselect=brothers[index]
1032 toselect=self.parent
1035 def delete_BAK(self):
1036 """ Méthode externe pour la destruction du noeud ET de l'objet
1037 Gère l'update du canvas"""
1040 nbold = pere.get_nb_children()
1042 if self.parent.children.index(self) > 0 :
1043 index = self.parent.children.index(self) - 1
1046 if self.parent.delete_child(self):
1047 if self.item.get_position() == 'global':
1048 self.etape.verif_all()
1049 elif self.item.get_position() == 'global_jdc':
1050 self.racine.verif_all()
1052 self.parent.verif_condition()
1054 print 'Erreur dans la destruction de ',self.item.get_nom(),' dans delete'
1056 nbnew = pere.get_nb_children()
1057 pere.redraw(nbnew-nbold)
1059 # Le noeud n'est pas au 1er niveau
1060 if pere.parent.parent != None:
1063 enfants = self.parent.children
1065 enfants[index].select()
1068 enfants[index+1].select()
1070 # on est avant debut
1073 def doPaste(self,node_selected):
1074 self.appli.message="Vous ne pouvez copier que des commandes ou des mots-clés facteurs !"
1077 def doPaste_Commande(self,objet_a_copier):
1079 Réalise la copie de l'objet passé en argument qui est nécessairement
1083 child = self.append_brother(objet_a_copier,retour='oui')
1086 #--------------------------------------------------------------
1087 # Méthodes de vérification du contexte et de validité du noeud
1088 #--------------------------------------------------------------
1089 def verif_all(self):
1091 traceback.print_stack()
1092 self.verif_all_children()
1094 def verif_all_children(self):
1096 traceback.print_stack()
1097 if not self.children : self.build_children()
1099 for child in self.children :
1100 child.verif_all_children()
1104 Lance la vérification des conditions des blocs de self et le cas
1105 échéant redessine self
1108 traceback.print_stack()
1109 nbold = self.get_nb_children()
1110 test = self.verif_condition()
1111 nbnew = self.get_nb_children()
1113 self.redraw(nbnew-nbold)
1115 def verif_condition(self):
1117 on lance la vérification des conditions de chaque bloc de self
1118 on crée ou supprime les noeuds concernés
1119 (self est d'un niveau inférieur ou égal à l'ETAPE)
1122 traceback.print_stack()
1124 l_bloc_arajouter,l_bloc_aenlever = self.verif_condition_bloc()
1125 if len(l_bloc_arajouter) > 0:
1127 for mc in l_bloc_arajouter:
1128 self.append_node_child(mc,verif='non')
1129 if len(l_bloc_aenlever) > 0:
1131 for mc in l_bloc_aenlever:
1132 mocle = self.get_node_fils(mc)
1133 self.delete_child(mocle)
1134 l_mc_presents = self.item.get_liste_mc_presents()
1135 l_mc_arajouter= self.verif_condition_regles(l_mc_presents)
1136 if len(l_mc_arajouter) > 0:
1138 for mc in l_mc_arajouter:
1139 self.append_node_child(mc,verif='non')
1140 if len(l_mc_arajouter)+len(l_bloc_arajouter)+len(l_bloc_aenlever) != 0 :
1141 self.verif_condition()
1144 def verif_condition_bloc(self):
1146 traceback.print_stack()
1147 return self.item.verif_condition_bloc()
1149 def verif_condition_regles(self,l_mc_presents):
1151 traceback.print_stack()
1152 return self.item.verif_condition_regles(l_mc_presents)