]> SALOME platform Git repositories - tools/eficas.git/blob - Editeur/treewidget.py
Salome HOME
CCAR: creation V1_13a1 a partir de la branche Liv-V1_12
[tools/eficas.git] / Editeur / treewidget.py
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.
9 #
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.
14 #
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.
18 #
19 #
20 # ======================================================================
21 import os,sys,string,re,types,traceback
22 from Tkinter import *
23
24
25 import fontes
26 import images
27 from Ihm import CONNECTOR
28
29 #
30 __version__="$Name:  $"
31 __Id__="$Id: treewidget.py,v 1.32.2.1 2007-06-15 16:23:33 cchris Exp $"
32 #
33
34 Fonte_Standard = fontes.standard
35
36 class Tree :
37     def __init__(self,appli,jdc_item,scrolledcanvas,command = None,rmenu=None):
38         self.item = jdc_item
39         self.scrolledcanvas = scrolledcanvas
40         self.canvas = self.scrolledcanvas.component('canvas')
41         #resolution
42         resolution= self.canvas.winfo_screenwidth()/(self.canvas.winfo_screenmmwidth()/25.4*72)
43         self.DDY=max(20,resolution*(Fonte_Standard[1]+4))
44         self.id_up=self.canvas.bind("<F11>", self.page_up)
45         self.id_down=self.canvas.bind("<F12>", self.page_down)
46         self.id_um=self.canvas.bind("<Key-Left>", self.mot_up)
47         self.id_dm=self.canvas.bind("<Key-Right>", self.mot_down)
48         self.id_s=self.canvas.bind("<1>", self.canvas_select)             
49         self.tree = self
50         self.command = command
51         self.rmenu=rmenu
52         self.appli = appli
53         self.parent = None
54         self.racine = self
55         self.node_selected = None
56         self.build_children()
57
58     def canvas_select(self,event):
59         self.canvas.focus_set()
60
61     def page_up(self,event):
62         event.widget.yview_scroll(-1, "page")
63
64     def page_down(self,event):
65         event.widget.yview_scroll(1, "page")
66    
67     def unit_up(self,event):
68         event.widget.yview_scroll(-1, "unit")
69
70     def unit_down(self,event):
71         event.widget.yview_scroll(1, "unit")              
72
73     def mot_down(self,event):
74         self.select_next(None)
75         self.canvas.focus_set()
76
77     def mot_down_force(self):
78         self.select_next(None)
79         self.canvas.focus_set()
80
81     def mot_up(self,event):
82         self.node_selected.select_mot_previous()
83         self.canvas.focus_set()
84
85     def mot_up_force(self):
86         self.node_selected.select_mot_prev()
87         self.canvas.focus_set()
88
89     def deplieReplieNode(self):
90         self.node_selected.deplieReplieNode()
91
92     def build_children(self):
93         """ Construit la liste des enfants de self """
94         self.children = []
95         child = self.item.itemNode(self,self.item,self.command,self.rmenu)
96         self.children.append(child)
97         child.state='expanded'
98
99     def draw(self):
100         """ Dessine l'arbre """
101         lasty = 8
102         x = 5
103         for child in self.children:
104             child.draw(x,lasty)
105             lasty = child.lasty + 15
106         self.children[0].select()
107         self.resizescrollregion()
108
109     def deselectall(self):
110         """ déselectionne tous les éléments de l'arbre """
111         if self.node_selected :
112             self.node_selected.deselect()
113             
114     def update(self):
115         """ Update tous les éléments de l'arbre """
116         for child in self.children:
117             child.update()
118
119     def supprime(self):
120         """ supprime tous les éléments de l'arbre """
121         #print "supprime",self
122         self.canvas.unbind("<F11>",self.id_up)
123         self.canvas.unbind("<F12>",self.id_down)
124         self.canvas.unbind("<Key-Left>",self.id_um)
125         self.canvas.unbind("<Key-Right>",self.id_dm)
126         self.canvas.unbind("<1>",self.id_s)             
127         self.tree = None
128         self.racine = None
129         self.node_selected = None
130         self.item = None
131         self.scrolledcanvas = None
132         self.canvas = None
133         self.command = None
134         self.rmenu=None
135         for child in self.children:
136             child.supprime()
137         self.children=[]
138
139     def update_valid(self) :
140         """Cette methode a pour but de mettre a jour la validite du noeud
141            et de propager la demande de mise à jour à son parent
142         """
143         pass
144
145     def resizescrollregion(self):
146         x0,y0,x1,y1=self.canvas.bbox(ALL)
147         # On ajoute une marge approximativement de la moitié du canvas
148         y1=y1+self.canvas.winfo_height()/2
149         self.canvas.configure(scrollregion = (x0,y0,x1,y1))
150
151     def select_next(self,event):
152         self.node_selected.select_next()
153         self.canvas.focus_set()
154
155     def select_previous(self,event):
156         self.node_selected.select_previous()
157
158     def see(self,items):
159         x1, y1, x2, y2=apply(self.canvas.bbox, items)
160         while x2 > self.canvas.canvasx(0)+self.canvas.winfo_width():
161             old=self.canvas.canvasx(0)
162             self.canvas.xview_scroll( 1, 'units')
163             # avoid endless loop if we can't scroll
164             if old == self.canvas.canvasx(0):
165                 break
166         while y2 > self.canvas.canvasy(0)+self.canvas.winfo_height():
167             old=self.canvas.canvasy(0)
168             self.canvas.yview_scroll( 1, 'units')
169             if old == self.canvas.canvasy(0):
170                 break
171         # done in this order to ensure upper-left of object is visible
172         while x1 < self.canvas.canvasx(0):
173             old=self.canvas.canvasx(0)
174             self.canvas.xview_scroll( -1, 'units')
175             if old == self.canvas.canvasx(0):
176                 break
177         while y1 < self.canvas.canvasy(0):
178             old=self.canvas.canvasy(0)
179             self.canvas.yview_scroll( -1, 'units')
180             if old == self.canvas.canvasy(0):
181                 break
182
183     #def __del__(self):
184     #   print "__del__",self
185
186  
187 class Node :
188     def __init__(self,parent,item,command=None,rmenu=None):
189         self.parent = parent
190         self.item = item
191         self.command = command
192         self.rmenu=rmenu
193         self.tree = self.parent.tree
194         self.appli = self.parent.appli
195         self.canvas = self.parent.canvas
196         self.init()
197         self.connect()
198
199     def init(self):
200         self.state='collapsed'
201         self.displayed = 0
202         self.selected = 0
203         self.x = self.y  =None
204         self.lasty = 0
205         self.children = None
206         self.id = []
207         if self.parent is self.tree:
208            self.racine=self
209         else:
210            self.racine = self.parent.racine
211            
212     def connect(self):
213         self.item.connect("add",self.onAdd,())
214         self.item.connect("supp",self.onSupp,())
215         self.item.connect("valid",self.onValid,())
216
217     #def __del__(self):
218     #    print "__del__",self
219
220     def force_select(self):
221         if self.selected:
222            # le noeud est selectionné. On force la reconstruction du panel associé
223            if self.command:apply(self.command,(None,))
224            self.select()
225
226     def onValid(self):
227         #print "onValid : l'item a changé de validité ",self.item,self.item.object,self.item.object.isvalid()
228         self.update_node_valid()
229         self.update_node_label()
230         self.update_node_texte()
231         if self.selected and self.command:
232            self.command(self)
233
234     def onAdd(self,objet):
235         #print "onAdd : un objet a été ajouté aux fils de l'item ",self.item.object,objet
236         self.expand_node()
237         old_nodes=self.children
238         self.update_nodes()
239         self.redraw_children(old_nodes)
240         self.force_select()
241
242     def onSupp(self,objet):
243         #print "onSupp : un objet a été supprimé des fils de l'item ",self.item.object,objet
244         self.expand_node()
245         old_nodes=self.children
246         self.update_nodes()
247         self.redraw_children(old_nodes)
248         self.force_select()
249
250     def update_nodes(self):
251         #print "update_nodes",self
252         newnodes=[]
253         inodes=iter(self.children)
254         sublist=self.item._GetSubList()
255         iliste=iter(sublist)
256
257         while(1):
258            old_item=item=None
259            for node in inodes:
260               old_item=node.item
261               if old_item in sublist:break
262               #print "item supprime",old_item
263            for item in iliste:
264               if item is old_item:break
265               #print "item ajoute",item
266               child = item.itemNode(self,item,self.command,self.rmenu)
267               newnodes.append(child)
268
269            if old_item is None and item is None:break
270            if old_item is item:
271               #print "item conserve",item
272               newnodes.append(node)
273
274         self.children=newnodes
275         self.connect()
276
277     def supprime(self):
278         #print "supprime",self
279         self.efface_node()
280         self.racine = None
281         self.command = None
282         self.rmenu=None
283         if not self.children : return
284         for child in self.children:
285             child.supprime()
286         self.children=None
287
288     def redraw_children(self,old_nodes):
289         #print "redraw_children",old_nodes
290         #print self.children
291         y = self.y + self.tree.DDY
292         x = self.x + 15
293         supp_nodes=[]
294
295         inodes=iter(old_nodes)
296         iliste=iter(self.children)
297         # on parcourt la liste des anciens noeuds (node)
298         # et la liste des nouveaux noeuds (new_node) en parallele (iterateurs)
299
300         while(1):
301            new_node=node=None
302            for node in inodes:
303               #print "ancien noeud",node
304               if node in self.children:break # ancien noeud toujours present
305               #print "noeud supprime",node,node.item.GetLabelText()[0]
306               dy=node.y-node.lasty -self.tree.DDY
307               #print "deplacer noeuds",y,dy
308               node.move_nodes(y,dy)
309               node.supprime()
310               #supp_nodes.append(node)
311
312            for new_node in iliste:
313               #print "nouveau noeud",new_node
314               if new_node in old_nodes: break # nouveau noeud deja present
315               #print "noeud ajoute",new_node,new_node.item.GetLabelText()[0]
316               y=self.draw_node(new_node,x,y)
317
318            if node is None and new_node is None : break
319
320            if node is new_node: # ancien noeud
321               #print "noeud conserve",node
322               node.update_node_label()
323               y=y+node.lasty-node.y +self.tree.DDY
324
325         self.racine.update_coords()
326         self.canvas.delete('line')
327         self.racine.trace_ligne()
328         self.tree.resizescrollregion()
329         # Mettre à 1 pour verifier les cycles entre objets node
330         #withCyclops=0
331         #if withCyclops:
332            #from Misc import Cyclops
333            #z = Cyclops.CycleFinder()
334            #print supp_nodes
335            #for o in supp_nodes:
336              #z.register(o)
337            #del supp_nodes
338            #del o
339            #z.find_cycles()
340            #z.show_stats()
341            #z.show_cycles()
342
343     def tag_move_nodes(self,y):
344         """ Marque pour deplacement tous les noeuds au dela de l'ordonnée y """
345         #print "tag_move_nodes",y
346         self.canvas.dtag(ALL,'move')
347         # on marque tous les ids au dela de y
348         x0, y0, x1, y1 = self.canvas.bbox(ALL)
349         if y > y1: # pas d'objet a deplacer
350            return
351         self.canvas.addtag_overlapping('move',x0,y,x1,y1)
352
353     def move_nodes(self,y,dy):
354         """ Déplace de l'incrément dy les noeuds au dela de l'ordonnée y """
355         #print "move_nodes",y,dy
356         self.tag_move_nodes(y)
357         # on déplace tous les items de dy
358         self.canvas.move('move',0,dy)
359
360     def draw_node(self,new_node,x,y):
361         """ Dessine le noeud new_node en x,y en deplacant les noeuds existants
362             en y et au dela
363             Retourne la position du premier des noeuds deplaces
364         """
365         #print "draw_node",new_node,x,y
366         self.tag_move_nodes(y)
367         #if new_node.item.isactif():
368            #new_node.state = 'expanded'
369         new_node.state = 'expanded'
370         new_node.draw(x,y)
371         dy=(new_node.get_nb_children()+1)*self.tree.DDY
372         #print "deplacer noeuds",y,dy
373         self.canvas.move('move',0,dy)
374         return new_node.lasty+self.tree.DDY
375
376     def build_children(self):
377         """ Construit la liste des enfants de self """
378         self.children = []
379         sublist = self.item._GetSubList()
380         if not sublist : return
381         for item in sublist :
382             child = item.itemNode(self,item,self.command,self.rmenu)
383             self.children.append(child)
384             
385     #-----------------------------------------------
386     # Méthodes de sélection/déselection d'un noeud
387     #-----------------------------------------------
388     
389     def select(self, event=None):
390         """
391         Rend le noeud courant (self) sélectionné et déselectionne
392         tous les autres
393         """
394         #print "SELECT",self
395         if not self.children : self.build_children()
396         self.tree.deselectall()
397         self.selected = 1
398         self.tree.node_selected = self
399         if self.command:apply(self.command,(self,))
400         self.highlight()
401         self.make_visible()
402
403     def deselect(self, event=None):
404         """ Déselectionne self """
405         self.selected = 0
406         if self.displayed == 1 : self.dehighlight()
407             
408     def make_visible(self):
409         """ Rend l'objet self visible cad déplace le scroll pour que self 
410             soit dans la fenêtre de visu
411         """
412         lchild=self.last_child()
413         self.tree.see((self.image_id,lchild.image_id))
414         
415     def select_next(self,ind=0):
416         """ on doit chercher à sélectionner dans l'ordre:
417             - son premier fils s'il est affiché
418             - son frère cadet s'il existe
419             - son oncle (benjamin de son père)
420             - ... appel récursif ...
421         """
422         if self.state=='expanded' and len(self.children) > ind:
423             self.children[ind].select()
424         else :
425             index = self.parent.children.index(self) + 1
426             try :
427               if isinstance(self.parent,TREE) :
428                 try:
429                     self.children[ind].select()
430                 except:
431                     self.children[0].select()
432             except :
433               if self.parent is self.tree:
434                 pass
435               else :
436                 self.parent.select_next(index)
437
438     def select_mot_prev(self):
439         index = self.parent.children.index(self) - 1
440         try :
441            if index > -1  :
442               self.parent.children[index].select()
443               if self.parent.children[index].state=="expanded":
444                  print len(self.parent.children[index].children)
445                  if len(self.parent.children[index].children)!=0 :
446                     max=len(self.parent.children[index].children) - 1
447                     self.parent.children[index].children[max].select()
448                  else :
449                     self.parent.children[index].select()
450               else :
451                  self.parent.children[index].select()
452            elif self.parent is self.tree:
453               pass
454            else :
455               self.parent.select()
456         except:
457             if self.parent is self.tree:
458                pass
459             else :
460                self.parent.select_previous()
461
462         
463     def select_mot_previous(self):
464         index = self.parent.children.index(self) - 1
465         try :
466             if index > -1  :
467                self.parent.children[index].select()
468             elif self.parent is self.tree:
469                pass
470             else :
471                self.parent.select()
472         except:
473             if self.parent is self.tree:
474                pass
475             else :
476                self.parent.select_previous()
477
478     def select_previous(self):
479         """ on doit d'abord sélectionner(dans l'ordre) :
480              - son frère aîné
481              - son père
482         """
483         index = self.parent.children.index(self) - 1
484         try :
485             self.parent.children[index].select()
486         except:
487             #self.parent.select()
488             if self.parent is self.tree:
489                pass
490             else :
491                self.parent.select_previous()
492
493     def popup(self,event=None):
494         """
495             Declenche le traitement associé au clic droit de la souris
496             sur l'icone du Node
497         """
498         if not self.rmenu:return
499         apply(self.rmenu,(self,event))
500
501     #-----------------------------------------------
502     # Méthodes de recherche d'informations
503     #-----------------------------------------------
504     def geticonimage(self,name=None):
505         """
506         Retourne l'image qui doit être associée à self
507         """
508         if not name :
509             name = self.item.GetIconName()
510         if not name or name == 'aucune' :
511             return None
512         return images.get_image(name)
513
514     def get_nb_children(self):
515         """ Retourne le nombre d'enfants affichés de self """
516         nb = 0
517         if self.state =='collapsed' :  return nb
518         for child in self.children :
519             nb = nb + 1 + child.get_nb_children()
520         return nb
521
522     def get_liste_id(self):
523         """ Retourne la liste de tous les id (filiation comprise) de self """
524         liste = self.id
525         for child in self.children:
526             liste.extend(child.get_liste_id())
527         return liste
528
529     def get_node_fils(self,name) :
530         """ Retourne le fils de self de nom name s'il existe"""
531         for child in self.children:
532             if child.item.get_nom() == name: return child
533         return None
534
535     #-----------------------------------------------
536     # Méthodes d'affichage d'un noeud
537     #-----------------------------------------------
538     def draw(self,x,y):
539         """ Permet de tracer le noeud self """
540         # le début du noeud est en x,y
541         self.x = x
542         self.y = y
543         self.lasty = y
544         self.id=[]
545         # choix de l'icone à afficher : + ou -
546         if self.item.IsExpandable():
547             if self.state == 'expanded':
548                 iconname = "minusnode"
549                 callback = self.collapse
550             else:
551                 iconname = "plusnode"
552                 callback = self.expand
553             image = self.geticonimage(name=iconname)
554             self.icone_id = self.canvas.create_image(self.x, self.y, image=image)
555             self.callback_id=self.canvas.tag_bind(self.icone_id, "<1>", callback)
556             self.id.append(self.icone_id)
557         # création de la ligne horizontale
558         self.ligne_id = self.canvas.create_line(self.x,self.y,self.x+10,self.y)
559         self.id.append(self.ligne_id)
560         self.canvas.tag_lower(self.ligne_id)
561         # affichage de l'icone (carre ,rond, ovale ...) de couleur
562         image = self.geticonimage()
563         if image != None :
564             self.image_id = self.canvas.create_image(self.x+15,self.y,image = image)
565             self.select_id2=self.canvas.tag_bind(self.image_id,"<1>",self.select)
566             self.popup_id2=self.canvas.tag_bind(self.image_id,"<3>",self.popup)
567             self.id.append(self.image_id)
568         else:
569             self.image_id = None
570         # affichage du texte : nom de l'objet (ETAPE ou MOT-CLE) et sa valeur
571         self.drawtext()
572         self.displayed = 1
573         if self.state == 'expanded' :
574             if not self.children : self.build_children()
575             if len(self.children) > 0:
576                 self.drawchildren()
577                 self.lasty = self.children[-1].lasty
578    
579     def drawchildren(self):
580         """ Dessine les enfants de self """
581         y = self.y + self.tree.DDY
582         x = self.x + 15
583         for child in self.children:
584             child.draw(x,y)
585             nb = child.get_nb_children()
586             y = y + self.tree.DDY*(nb+1)
587         self.trace_ligne()
588
589     def drawtext(self):
590         """ Affiche les deux zones de texte après l'icône de couleur de l'objet """
591         if self.image_id != None :
592             textx = self.x + 30
593         else:
594             textx = self.x + 15
595         texty = self.y
596         # nom,fonte et couleur de l'objet du noeud à afficher
597         labeltext,fonte,couleur = self.item.GetLabelText()
598         if labeltext    == ''   : labeltext = '   '
599         if fonte        == None : fonte = Fonte_Standard
600         if couleur      == None : couleur = 'black'
601         # création du widget label
602         self.label = Label(self.canvas,
603                            text = labeltext,
604                            fg = couleur,
605                            bg = 'gray95',
606                            font=fonte)
607         self.label_id = self.canvas.create_window(textx,texty,window=self.label,anchor='w')
608         self.id.append(self.label_id)
609         # bindings sur le widget label
610         self.select_id=self.label.bind("<1>", self.select)
611         self.popup_id=self.label.bind("<3>", self.popup)
612         self.enter_id=self.label.bind("<Enter>",self.enter)
613         self.leave_id=self.label.bind("<Leave>",self.leave)
614         # valeur de cet objet à afficher
615         x0, y0, x1, y1 = self.canvas.bbox(self.label_id)
616         textx = max(x1, 200) + 10
617         text = self.item.GetText() or " "
618         self.text = Label(self.canvas, text=text,
619                             bd=0, padx=2, pady=2,background='gray95',
620                             font=fonte)
621         if self.selected:
622             self.highlight()
623         else:
624             self.dehighlight()
625         self.text_id = self.canvas.create_window(textx, texty,anchor="w", window=self.text)
626         self.id.append(self.text_id)
627         
628     def highlight(self,event=None):
629         """ Met en surbrillance self"""
630         if hasattr(self,'label'):
631             self.label.configure(fg='white',bg='#00008b')
632         if (hasattr(self.item,'get_nom') and hasattr( self.appli, 'salome')) :
633             if self.item.get_nom() == "AFFE_CARA_ELEM":
634                self.item.rmenu_specs=[("View3D", "visu_3D")]
635                self.tree.rmenu
636               
637             
638     def dehighlight(self,event=None):
639         """ Rétablit l'affichage normal de self"""
640         if hasattr(self,'label'):
641             self.label.configure(fg='black',bg='gray95')
642
643     def enter(self,event=None):
644         """ Met en surbrillance self et affiche le fr de l'objet """
645         self.highlight()
646         fr = self.item.get_fr()
647         self.appli.affiche_infos(fr)
648         
649     def leave(self,event=None):
650         """ Rétablit l'affichage normal de self et efface le fr de l'objet """
651         if not self.selected :
652             self.dehighlight()
653         self.appli.affiche_infos('')
654
655     def collapse_children(self):
656         """ Collapse récursivement tous les descendants de self """
657         if not self.children : return
658         for child in self.children:
659             child.state='collapsed'
660             child.collapse_children()
661
662     def deplieReplieNode(self):           
663         if self.state == 'expanded':
664            self.collapse()
665         else :
666            self.expand_node()
667
668     def collapse(self,event = None):
669         """ Collapse self et descendants et retrace self """
670         nb = self.get_nb_children()
671         self.state = 'collapsed'
672         self.collapse_children()
673         self.redraw(-nb)
674         self.select()
675    
676     def expand_node(self,event = None):
677         """ Expanse self et le retrace """
678         if self.state == 'expanded':return
679         #if not self.item.isactif() : return
680         if not self.children : self.build_children()
681         self.state = 'expanded'
682         nb = self.get_nb_children()
683         self.redraw(nb)
684
685     def expand(self,event = None):
686         """ Expanse self et le retrace """
687         self.expand_node()
688         self.select()
689
690     def redraw(self,nb):
691         """ Redessine self :  nb est le décalage à introduire
692             en dessous de self pour le redessiner """
693         # nb = nombre d'items de décalage
694         self.move(self.tree.DDY*nb)
695         # on efface self et on le redessine
696         self.efface()
697         self.draw(self.x,self.y)
698         # Il n'est pas nécessaire d'appeler update
699         # il suffit d'updater les coordonnees et de retracer les lignes
700         self.racine.update_coords()
701         self.racine.trace_ligne()
702         self.update_valid()
703         self.tree.resizescrollregion()
704         
705     def update_coords(self):
706         """ Permet d'updater les coordonnes de self et de tous ses enfants"""
707         if self.displayed == 0 : return
708         if self.image_id != None :
709             coords = self.canvas.coords(self.image_id)
710             self.x = coords[0]-15
711         else:
712             coords = self.canvas.coords(self.label_id)
713             self.x = coords[0]-15
714         self.y = coords[1]
715         self.lasty = self.y
716         if self.state == 'expanded' :
717             for child in self.children:
718                 if child.displayed != 0:
719                     child.update_coords()
720                     self.lasty = child.lasty
721
722     def update_icone(self):
723         """ Met à jour les icônes de tous les noeuds : teste la validité de l'objet
724         Cette méthode est très lente, trop !!"""
725         if self.image_id != None :
726             image = self.geticonimage()
727             self.canvas.itemconfig(self.image_id,image=image)
728         if self.state == 'expanded':
729             for child in self.children:
730                 if child.displayed != 0:
731                     child.update_icone()
732
733     def update_label_texte(self):
734         """ Met a jour le label du noeud et celui de tous ses fils ouverts """
735         self.update_node_label()
736         if self.state == 'expanded' :
737             for child in self.children:
738                 if child.displayed != 0 : child.update_label_texte()
739
740     def update_texte(self):
741         """ Met à jour les noms des SD et valeurs des mots-clés """
742         self.update_node_texte()
743         if self.state == 'expanded' :
744             for child in self.children:
745                 if child.displayed != 0 : child.update_texte()
746         
747     def update_node_label(self):
748         """ Met a jour le label du noeud """
749         if self.displayed == 0 : return
750         # nom,fonte et couleur de l'objet du noeud à afficher
751         labeltext,fonte,couleur = self.item.GetLabelText()
752         if labeltext    == ''   : labeltext = '   '
753         if fonte        == None : fonte = Fonte_Standard
754         if couleur      == None : couleur = 'black'
755         self.label.configure(text=labeltext,font=fonte)
756
757     def update_node_texte(self):
758         """ Met à jour les noms des SD et valeurs des mots-clés """
759         if self.displayed == 0 : return
760         text = self.item.GetText()
761         if text == None : text = ''
762         self.text.configure(text=text)
763
764     def update_node_valid(self) :
765         """Cette methode remet a jour la validite du noeud (icone)
766            Elle appelle isvalid
767         """
768         if self.displayed == 0 : return
769         if self.image_id != None :
770             image = self.geticonimage()
771             self.canvas.itemconfig(self.image_id,image=image)
772
773     def update_valid(self) :
774         """Cette methode a pour but de mettre a jour la validite du noeud
775            et de propager la demande de mise à jour à son parent
776         """
777         self.update_node_valid()
778         self.parent.update_valid()
779
780     def update(self,event=None) :
781         """ Classe Node :
782             Cette méthode est appelée pour demander l update d un noeud 
783             d'un jeu de commandes
784             Cette demande est transmise au noeud racine (le JDC) qui update
785             tout l arbre représentant le jeu de commandes
786             Pendant cette mise à jour, on appelle la méthode isvalid qui
787             fera l update de tous les objets déclarés modifiés lors des
788             actions précédentes
789             La métode isvalid est en général appelée par l intermédiaire de
790             update_icone -> geticonimage -> GetIconName
791         """
792         #print "update",self
793         #traceback.print_stack()
794         self.racine.update_coords()
795         self.racine.trace_ligne()
796         self.racine.update_icone()
797         self.racine.update_texte()
798         self.racine.update_label_texte()
799         self.tree.resizescrollregion()
800
801     def efface_node(self):
802         if self.displayed != 0:
803            self.label.unbind("<1>", self.select_id)
804            self.label.unbind("<3>", self.popup_id)
805            self.label.unbind("<Enter>",self.enter_id)
806            self.label.unbind("<Leave>",self.leave_id)
807            self.canvas.tag_unbind(self.image_id,"<1>",self.select_id2)
808            self.canvas.tag_unbind(self.image_id,"<3>",self.popup_id2)
809            if self.item.IsExpandable():
810               self.canvas.tag_unbind(self.icone_id, "<1>", self.callback_id)
811            self.label.destroy()
812            self.text.destroy()
813
814         for id in self.id :
815             self.canvas.delete(id)
816         self.id=[]
817         self.label_id=None
818         self.text_id=None
819         self.image_id=None
820         self.icone_id=None
821         self.label=None
822         self.text=None
823         self.displayed=0
824
825     def efface(self):
826         """ Efface du canvas les id associés à self : cad les siens et ceux
827             de ses enfants """
828         self.efface_node()
829         if not self.children : return
830         for child in self.children:
831             child.efface()
832
833     def move(self,dy):
834         """ Déplace de l'incrément dy tous les id en dessous de self """
835         # il faut marquer tous les suivants de self
836         bbox1 = self.canvas.bbox(ALL)
837         self.canvas.dtag(ALL,'move')
838         self.canvas.delete('line')
839         try:
840             self.canvas.addtag_overlapping('move',bbox1[0],self.y +10,bbox1[2],bbox1[3])
841         except:
842             print "Erreur dans move :"
843             print self
844             print self.item
845             print self.item.getObject()
846             print self.item.getObject().definition.label
847             print 'y=',self.y
848             print 'dy=',dy
849         # on déplace tous les items de dy
850         self.canvas.move('move',0,dy)
851
852     def trace_ligne(self):
853         """ Dessine les lignes verticales entre frères et entre père et premier fils"""
854         if self.state=='collapsed' : return
855         if len(self.children)==0 : return
856         # on est bien dans le cas d'un noeud expansé avec enfants ...
857         # il faut rechercher l'ordonnée du dernier fils de self
858         y_end = self.children[-1].y
859         ligne = self.canvas.create_line(self.x+15,self.y,self.x+15,y_end,tags='line')
860         self.canvas.tag_lower(ligne)
861         for child in self.children :
862             try:
863                 child.trace_ligne()
864             except:
865                 print "Erreur dans trace_ligne :"
866                 print child
867                 print child.item.getObject()
868
869     def last_child(self):
870         lchild=self
871         if self.state == 'expanded' and self.children:
872            lchild= self.children[-1].last_child()
873         return lchild
874
875     #------------------------------------------------------------------
876     # Méthodes de création et destruction de noeuds
877     # Certaines de ces méthodes peuvent être appelées depuis l'externe
878     #------------------------------------------------------------------
879     def append_brother(self,name,pos='after',retour='non'):
880         """
881         Permet d'ajouter un objet frère à l'objet associé au noeud self
882         par défaut on l'ajoute immédiatement après 
883         Méthode externe
884         """
885         # on veut ajouter le frère de nom name directement avant ou après self
886         index = self.parent.children.index(self)
887         if pos == 'before':
888             index = index
889         elif pos == 'after':
890             index = index +1
891         else:
892             print str(pos)," n'est pas un index valide pour append_brother"
893             return 0
894         return self.parent.append_child(name,pos=index)
895
896     def append_child(self,name,pos=None,verif='oui',retour='non'):
897         """
898            Methode pour ajouter un objet fils à l'objet associé au noeud self.
899            On peut l'ajouter en début de liste (pos='first'), en fin (pos='last')
900            ou en position intermédiaire.
901            Si pos vaut None, on le place à la position du catalogue.
902         """
903         #print "append_child",self,self.children
904         if pos == 'first':
905             index = 0
906         elif pos == 'last':
907             index = len(self.children)
908         elif type(pos) == types.IntType :
909             # position fixee
910             index = pos
911         elif type(pos) == types.InstanceType:
912             # pos est un item. Il faut inserer name apres pos
913             index = self.item.get_index(pos) +1
914         elif type(name) == types.InstanceType:
915             index = self.item.get_index_child(name.nom)
916         else:
917             index = self.item.get_index_child(name)
918         obj=self.item.additem(name,index)
919         #print obj
920         if obj is None:obj=0
921         if obj == 0:return 0
922         #print "append_child",index,self.children
923         child=self.children[index]
924         child.select()
925         return child
926
927     def delete(self):
928         """ 
929             Méthode externe pour la destruction de l'objet associé au noeud
930             La mise à jour des noeuds est faite par onSupp sur notification
931         """
932         index = self.parent.children.index(self) - 1 
933         if index < 0 : index =0
934
935         parent=self.parent
936         ret=parent.item.suppitem(self.item)
937         if ret == 0:return
938
939         brothers=parent.children
940         if brothers:
941            toselect=brothers[index]
942         else:
943            toselect=parent
944         toselect.select()
945