Salome HOME
Modif V6_4_°
[tools/eficas.git] / Pmw / Pmw_1_2 / contrib / TreeBrowser.py
1 #
2 #  FILE: TreeBrowser.py
3 #
4 #  DESCRIPTION:
5 #    This file provides a generic hierarchical tree browser widget.
6 #
7 #  AUTHOR:  Steve Kinneberg <skinneberg@mvista.com>,
8 #           MontaVista Software, Inc. <source@mvista.com>
9 #
10 #  Copyright 2001 MontaVista Software Inc.
11 #
12 #  This program is free software; you can redistribute  it and/or modify it
13 #  under  the terms of  the GNU General  Public License as published by the
14 #  Free Software Foundation;  either version 2 of the  License, or (at your
15 #  option) any later version.
16 #
17 #  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
18 #  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
19 #  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
20 #  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
21 #  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 #  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
23 #  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 #  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
25 #  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 #  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #
28 #  You should have received a copy of the  GNU General Public License along
29 #  with this program; if not, write  to the Free Software Foundation, Inc.,
30 #  675 Mass Ave, Cambridge, MA 02139, USA.
31 #
32
33
34 import types
35 import Tkinter
36 import Pmw
37
38
39 class _Branching:
40     def __init__(self):
41         # List of branch names
42         self._nodeNames = []
43
44         # Map from branch name to branch info
45         #   branch      Either _LeafNode or _BranchNode widget of the branch
46         #   nodetype    Either 'TreeNode' or 'LeafNode'
47         self._nodeAttrs = {}
48
49     def addbranch(self, branchName = None, **kw):
50         kw['indent'] = self['indent']
51         return apply(self._insertnode,
52                      ('tree', branchName, len(self._nodeNames),
53                       self._treeRoot),
54                      kw)
55
56     def addleaf(self, leafName = None, **kw):
57         return apply(self._insertnode,
58                      ('leaf', leafName, len(self._nodeNames),
59                       self._treeRoot),
60                      kw)
61
62     def insertbranch(self, branchName = None, before = 0, **kw):
63         kw['indent'] = self['indent']
64         return apply(self._insertnode,
65                      ('tree', branchName, before, self._treeRoot),
66                      kw)
67     
68     def insertleaf(self, leafName = None, before = 0, **kw):
69         return apply(self._insertnode,
70                      ('leaf', leafName, before, self._treeRoot),
71                      kw)
72
73     def _insertnode(self, type, nodeName, before, treeRoot, **kw):
74         if 'selectbackground' not in kw.keys():
75             kw['selectbackground'] = self['selectbackground']
76
77         if 'selectforeground' not in kw.keys():
78             kw['selectforeground'] = self['selectforeground']
79
80         if 'background' not in kw.keys():
81             kw['background'] = self['background']
82
83         if 'foreground' not in kw.keys():
84             kw['foreground'] = self['foreground']
85
86         if nodeName == None:
87             nodeName = self._nodeName + ".%d" % (len(self._nodeNames) + 1)
88         
89         if self._nodeAttrs.has_key(nodeName):
90             msg = 'Node "%s" already exists.' % nodeName
91             raise ValueError, msg
92
93         # Do this early to catch bad <before> spec before creating any items.
94         beforeIndex = self.index(before, 1)
95         attributes = {}
96
97         last = (beforeIndex == len(self._nodeNames))
98         if last and len(self._nodeNames) > 0:
99             # set the previous node to not last
100             self._nodeAttrs[self._nodeNames[-1]]['branch']._setlast(0)
101             
102         if(type == 'tree'):
103             node = apply(self.createcomponent, ('branch%d'%len(self._nodeNames),
104                                                 (), None,
105                                                 _BranchNode,
106                                                 self._branchFrame,
107                                                 nodeName,
108                                                 treeRoot,
109                                                 self,
110                                                 last,
111                                                 ), kw)
112             attributes['nodetype'] = 'TreeNode'
113         else:
114             node = apply(self.createcomponent, ('leaf%d'%len(self._nodeNames),
115                                                 (), None,
116                                                 _LeafNode,
117                                                 self._branchFrame,
118                                                 nodeName,
119                                                 treeRoot,
120                                                 self,
121                                                 last,
122                                                 ), kw)
123             attributes['nodetype'] = 'LeafNode'
124
125         if len(self._nodeNames) == beforeIndex:
126             node.pack(anchor='w')
127         else:
128             bname = self._nodeNames[beforeIndex]
129             battrs = self._nodeAttrs[bname]
130             node.pack(anchor='w', before=battrs['branch'])
131
132         attributes['branch'] = node
133
134         self._nodeAttrs[nodeName] = attributes
135         self._nodeNames.insert(beforeIndex, nodeName)
136         self._sizechange()
137         return node
138
139     def delete(self, *nodes):
140         curSel = self._treeRoot.curselection()[0]
141         for node in nodes:
142             index = self.index(node)
143             name = self._nodeNames.pop(index)
144             dnode = self._nodeAttrs[name]['branch']
145             del self._nodeAttrs[name]
146             if dnode == curSel:
147                 self._treeRoot._unhightlightnode(dnode)
148             dnode.destroy()
149         self._sizechange()
150
151     def destroy(self):
152         for node in len(self._nodeNames):
153             self.delete(node)
154         Pmw.MegaWidget.destroy(self)
155
156     def index(self, index, forInsert = 0):
157         if isinstance(index, _LeafNode):
158             index = index._nodeName
159         listLength = len(self._nodeNames)
160         if type(index) == types.IntType:
161             if forInsert and index <= listLength:
162                 return index
163             elif not forInsert and index < listLength:
164                 return index
165             else:
166                 raise ValueError, 'index "%s" is out of range' % index
167         elif type(index) == types.StringType:
168             if index in self._nodeNames:
169                 return self._nodeNames.index(index)
170             raise ValueError, 'bad branch or leaf name: %s' % index
171         elif index is Pmw.END:
172             if forInsert:
173                 return listLength
174             elif listLength > 0:
175                 return listLength - 1
176             else:
177                 raise ValueError, 'TreeNode has no branches'
178         #elif index is Pmw.SELECT:
179         #    if listLength == 0:
180         #       raise ValueError, 'TreeNode has no branches'
181         #    return self._pageNames.index(self.getcurselection())
182         else:
183             validValues = 'a name, a number, Pmw.END, Pmw.SELECT, or a reference to a TreeBrowser Leaf or Branch'
184             raise ValueError, \
185                 'bad index "%s": must be %s' % (index, validValues)
186
187     def getnodenames(self):
188         return self._nodeNames
189
190     def getnode(self, node):
191         nodeName = self._nodeNames[self.index(node)]
192         return self._nodeAttrs[nodeName]['branch']
193
194
195 class _LeafNode(Pmw.MegaWidget):
196     
197     def __init__(self, parent, nodeName, treeRoot, parentnode, last = 1, **kw):
198         colors = Pmw.Color.getdefaultpalette(parent)
199         
200         self._nodeName = nodeName
201         self._treeRoot = treeRoot
202         self._parentNode = parentnode
203
204         self._last = last
205         # Define the megawidget options.
206         INITOPT = Pmw.INITOPT
207         optiondefs = (
208             ('selectbackground', colors['selectBackground'], INITOPT),
209             ('selectforeground', colors['selectForeground'], INITOPT),
210             ('background',       colors['background'],       INITOPT),
211             ('foreground',       colors['foreground'],       INITOPT),
212             ('selectcommand',    None,                       None),
213             ('deselectcommand',  None,                       None),
214             ('labelpos',         'e',                        INITOPT),
215             ('labelmargin',      0,                          INITOPT),
216             ('label',            None,                       None),
217         )
218         self.defineoptions(kw, optiondefs)
219
220         # Initialise the base class (after defining the options).
221         Pmw.MegaWidget.__init__(self, parent)
222
223         # Create the components
224         interior = self._hull
225
226
227         labelpos = self['labelpos']
228
229         if self['label'] == None:
230             self._labelWidget = self.createcomponent('labelwidget',
231                                                      (), None,
232                                                      Pmw.LabeledWidget,
233                                                      (interior,),
234                                                      #background = self['background'],
235                                                      #foreground = self['foreground'],
236                                                      )
237         else:
238             self._labelWidget = self.createcomponent('labelwidget',
239                                                      (), None,
240                                                      Pmw.LabeledWidget,
241                                                      (interior,),
242                                                      label_background = self['background'],
243                                                      label_foreground = self['foreground'],
244                                                      labelpos = labelpos,
245                                                      labelmargin = self['labelmargin'],
246                                                      label_text = self['label'],
247                                                      )
248             self._labelWidget.component('label').bind('<ButtonRelease-1>',
249                                                       self._selectevent)
250
251         self._labelWidget.grid(column = 1, row = 0, sticky = 'w')
252
253         self._labelWidget.update()
254
255         self._labelheight = self._labelWidget.winfo_height()
256
257         self._lineCanvas = self.createcomponent('linecanvas',
258                                                 (), None,
259                                                 Tkinter.Canvas,
260                                                 (interior,),
261                                                 width = self._labelheight,
262                                                 height = self._labelheight,
263                                                 )
264         self._lineCanvas.grid( column = 0, row = 0, sticky = 'news')
265         self._lineCanvas.update()
266
267         cw = int(self._lineCanvas['width'])
268         ch = int(self._lineCanvas['height'])
269
270         self._lineCanvas.create_line(cw/2, ch/2, cw, ch/2, tag='hline')
271         if last:
272             self._lineCanvas.create_line(cw/2, 0, cw/2, ch/2, tag='vline')
273         else:
274             self._lineCanvas.create_line(cw/2, 0, cw/2, ch, tag='vline')
275
276         # Check keywords and initialise options.
277         self.initialiseoptions()
278
279
280     def interior(self):
281         return self._labelWidget.interior()
282
283     def select(self):
284         self._highlight()
285
286     def getname(self):
287         return self._nodeName
288
289     def getlabel(self):
290         return self['label']
291     
292     def _selectevent(self, event):
293         self._highlight()
294
295     def _highlight(self):
296         self._treeRoot._highlightnode(self)
297         #self._subHull.configure(background = self._selectbg, relief = 'raised')
298         if self['label'] != None:
299             self._labelWidget.configure(label_background = self['selectbackground'])
300             self._labelWidget.configure(label_foreground = self['selectforeground'])
301         #self._viewButton.configure(background = self._selectbg)
302         cmd = self['selectcommand']
303         if callable(cmd):
304             cmd(self)
305
306     def _unhighlight(self):
307         #self._subHull.configure(background = self._bg, relief = 'flat')
308         if self['label'] != None:
309             self._labelWidget.configure(label_background = self['background'])
310             self._labelWidget.configure(label_foreground = self['foreground'])
311         #self._viewButton.configure(background = self._bg)
312         cmd = self['deselectcommand']
313         if callable(cmd):
314             cmd(self)
315
316     def _setlast(self, last):
317         self._last = last
318
319         cw = int(self._lineCanvas['width'])
320         ch = int(self._lineCanvas['height'])
321
322         if last:
323             self._lineCanvas.create_line(cw/2, 0, cw/2, ch/2, tag='vline')
324         else:
325             self._lineCanvas.create_line(cw/2, 0, cw/2, ch, tag='vline')
326         
327
328 class _BranchNode(_LeafNode, _Branching): #Pmw.MegaWidget):
329
330     def __init__(self, parent, nodeName, treeRoot, parentnode, last = 1, **kw):
331         # Define the megawidget options.
332         INITOPT = Pmw.INITOPT
333         optiondefs = (
334             ('view',            'collapsed', None),
335             ('expandcommand',   None,        None),
336             ('collapsecommand', None,        None),
337             ('indent',          0,           INITOPT)
338         )
339         self.defineoptions(kw, optiondefs)
340
341         # Initialise the base class (after defining the options).
342         apply(_LeafNode.__init__,
343               (self, parent, nodeName, treeRoot, parentnode, last),
344               kw)
345         _Branching.__init__(self)
346
347         # Create the components
348         interior = self._hull
349
350         # Create the expand/collapse button
351         self._viewButton = self.createcomponent('viewbutton', (), None,
352                                                 Tkinter.Canvas,
353                                                 (interior,),
354                                                 background = self['background'],
355                                                 width = self._labelheight - 4,
356                                                 height = self._labelheight - 4,
357                                                 borderwidth = 2,
358                                                 relief = 'raised')
359
360         self._viewButton.grid(column = 0, row = 0, sticky='se')
361         self._viewButton.bind('<ButtonPress-1>', self._showbuttonpress)
362         self._viewButton.bind('<ButtonRelease-1>', self._toggleview)
363
364         # The label widget is already created by the base class, however
365         # we do need to make some slight modifications.
366         if self['label'] != None:
367             self._labelWidget.component('label').bind('<Double-1>',
368                                                       self._toggleview)
369         self._labelWidget.grid(column=1, row=0, columnspan = 3, sticky='sw')
370
371         # A line canvas is already created for us, we just need to make
372         # some slight modifications
373         self._lineCanvas.delete('hline')
374         self._lineCanvas.grid_forget()
375
376         
377         # Set the minsize of column 1 to control additional branch frame indentation
378         self.grid_columnconfigure(1, minsize = self['indent'])
379
380         # Create the branch frame that will contain all the branch/leaf nodes
381         self._branchFrame = self.createcomponent('frame', (), None,
382                                                  Tkinter.Frame, (interior,),
383                                                  #borderwidth=2,
384                                                  #relief='ridge',
385                                                  )
386         self.grid_columnconfigure(2,minsize=0, weight=1)
387         #self.grid_rowconfigure(0,minsize=0)
388
389         if(self['view'] == 'expanded'):
390             Pmw.drawarrow(self._viewButton,
391                           self['foreground'],
392                           'down', 'arrow')
393             self._branchFrame.grid(column = 2, row = 1, sticky='nw')
394             if not self._last:
395                 self._branchFrame.update()
396                 bh = self._branchFrame.winfo_height()
397                 self._lineCanvas.configure(height = bh)
398                 self._lineCanvas.grid(column = 0, row = 1, sticky='news')
399                 cw = int(self._lineCanvas['width'])
400                 ch = int(self._lineCanvas['height'])
401                 #self._lineCanvas.create_line(cw/2, 1, cw/2, ch, tag = 'vline')
402                 self._lineCanvas.coords('vline', cw/2, 1, cw/2, ch)
403         else:
404             Pmw.drawarrow(self._viewButton,
405                           self['foreground'],
406                           'right', 'arrow')
407             self._viewButton.configure(relief = 'raised')
408         
409
410         # Check keywords and initialise options.
411         self.initialiseoptions()
412
413
414
415     def _showbuttonpress(self, event):
416         self._viewButton.configure(relief = 'sunken')
417         
418     def _toggleview(self, event):
419         self._viewButton.configure(relief = 'sunken')
420         self.select()
421         if(self['view'] == 'expanded'):
422             self.collapsetree()
423         else:
424             self.expandtree()
425         self._viewButton.configure(relief = 'raised')
426         
427     def expandtree(self):
428         if(self['view'] == 'collapsed'):
429             cmd = self['expandcommand']
430             if cmd is not None:
431                 cmd(self)
432             self['view'] = 'expanded'
433             Pmw.drawarrow(self._viewButton,
434                           self['foreground'],
435                           'down', 'arrow')
436             self._branchFrame.grid(column = 2, row = 1, sticky='nw')
437             
438             if not self._last:
439                 self._branchFrame.update()
440                 bh = self._branchFrame.winfo_height()
441                 self._lineCanvas.configure(height = bh)
442                 self._lineCanvas.grid(column = 0, row = 1, sticky='news')
443                 cw = int(self._lineCanvas['width'])
444                 ch = int(self._lineCanvas['height'])
445                 #self._lineCanvas.create_line( cw/2, 1, cw/2, ch, tag = 'vline')
446                 self._lineCanvas.coords('vline', cw/2, 1, cw/2, ch)
447             self._parentNode._sizechange()
448         
449     def collapsetree(self):
450         if(self['view'] == 'expanded'):
451             cmd = self['collapsecommand']
452             if cmd is not None:
453                 cmd(self)
454             self['view'] = 'collapsed'
455             Pmw.drawarrow(self._viewButton,
456                           self['foreground'],
457                           'right', 'arrow')
458             self._branchFrame.grid_forget()
459             if not self._last:
460                 #self._lineCanvas.delete('vline')
461                 self._lineCanvas.grid_forget()
462             self._parentNode._sizechange()
463
464     def _setlast(self, last):
465         self._last = last
466         if self['view'] == 'expanded':
467             self._branchFrame.update()
468             bh = self._branchFrame.winfo_height()
469             self._lineCanvas.configure(height = bh)
470             cw = int(self._lineCanvas['width'])
471             ch = int(self._lineCanvas['height'])
472             self._lineCanvas.delete('vline')
473             if not last:
474                 self._lineCanvas.create_line(cw/2, 1, cw/2, ch, tag='vline')
475
476
477     def _sizechange(self):
478         if not self._last and self['view'] == 'expanded':
479             self._branchFrame.update()
480             bh = self._branchFrame.winfo_height()
481             self._lineCanvas.configure(height = bh)
482             if self._lineCanvas.coords('vline')[3] < bh:
483                 cw = int(self._lineCanvas['width'])
484                 ch = int(self._lineCanvas['height'])
485                 #self._lineCanvas.delete('vline')
486                 #self._lineCanvas.create_line(cw/2, 1, cw/2, ch, tag='vline')
487                 self._lineCanvas.coords('vline', cw/2, 1, cw/2, ch)
488         self._parentNode._sizechange()
489
490 class TreeBrowser(Pmw.MegaWidget, _Branching):
491
492     def __init__(self, parent = None, nodeName = '0', **kw):
493         colors = Pmw.Color.getdefaultpalette(parent)
494
495         # Define the megawidget options.
496         INITOPT = Pmw.INITOPT
497         optiondefs = (
498             ('indent',           0,                          INITOPT),
499             ('selectbackground', colors['selectBackground'], INITOPT),
500             ('selectforeground', colors['selectForeground'], INITOPT),
501             ('background',       colors['background'],       INITOPT),
502             ('foreground',       colors['foreground'],       INITOPT),
503             #('selectrelief',     'raised',       INITOPT),
504         )
505         
506         self.defineoptions(kw, optiondefs)
507
508         # Initialise the base class (after defining the options).
509         Pmw.MegaWidget.__init__(self, parent)
510         _Branching.__init__(self)
511
512         
513         # Create the components
514         interior = self._hull
515
516         browserFrame = self.createcomponent('frame', (), None,
517                                             Pmw.ScrolledFrame,
518                                             (interior,),
519                                             )
520         
521         browserFrame.pack(expand = 1, fill='both')
522
523         self._branchFrame = browserFrame.interior()
524
525         self._highlightedNode = None
526         self._treeRoot = self
527         self._nodeName = nodeName
528         # Check keywords and initialise options.
529         self.initialiseoptions()
530
531     def _highlightnode(self, newNode):
532         if self._highlightedNode != newNode:
533             if self._highlightedNode != None:
534                 self._highlightedNode._unhighlight()
535             self._highlightedNode = newNode
536
537     def _unhighlightnode(self):
538         if self._highlightedNode != None:
539             self._highlightedNode._unhighlight()
540             self._highlightedNode = None
541
542     def curselection(self):
543         retVal = None
544         if self._highlightedNode != None:
545             retVal = (self._highlightedNode,
546                       self._highlightedNode._nodeName,
547                       self._highlightedNode['label'])
548         return retVal
549
550     def getname(self):
551         return self._nodeName
552
553     # The top-level TreeBrowser widget only shows nodes in an expanded view
554     # but still provides collapsetree() and expandtree() methods so that users
555     # don't have to special case the top-level node
556
557     def collapsetree(self):
558         return
559
560     def expandtree(self):
561         return
562     
563     def _sizechange(self):
564         return
565
566 if __name__ == '__main__':
567
568     rootWin = Tkinter.Tk()
569
570     Pmw.initialise()
571
572     rootWin.title('TreeBrowser Demo')
573
574     # Create the hierarchical tree browser widget
575     treeBrowser = TreeBrowser(rootWin,
576                                           #selectbackground = "darkgreen",
577                                           #selectforeground = 'lightgreen',
578                                           #background = 'green',
579                                           #indent = 10,
580                                           )
581
582
583     def printselected(node):
584         selection = treeBrowser.curselection()
585         if selection != None:
586             print "Selected node name:", selection[1], "   label:", selection[2]
587
588
589     def printdeselected(node):
590         selection = treeBrowser.curselection()
591         if selection != None:
592             print "Deselected node name:", selection[1], "   label:", selection[2]
593
594     def printexpanded(node):
595         print "Expanded node name:", node.getname(), "   label:", node.getlabel()
596
597     def printcollapsed(node):
598         print "Collapsed node name:", node.getname(), "   label:", node.getlabel()
599
600
601
602     for i in range(3):
603         # Add a tree node to the top level
604         treeNodeLevel1 = treeBrowser.addbranch(label = 'TreeNode %d'%i,
605                                                selectcommand = printselected,
606                                                deselectcommand = printdeselected,
607                                                expandcommand = printexpanded,
608                                                collapsecommand = printcollapsed,
609                                                )
610         for j in range(3):
611             # Add a tree node to the second level
612             treeNodeLevel2 = treeNodeLevel1.addbranch(label = 'TreeNode %d.%d'%(i,j),
613                                                       #selectforeground = 'yellow',
614                                                       selectcommand = printselected,
615                                                       deselectcommand = printdeselected,
616                                                       expandcommand = printexpanded,
617                                                       collapsecommand = printcollapsed,
618                                                       )
619             if i == 0 and j == 1:
620                 dynamicTreeRootNode = treeNodeLevel1
621                 dynamicTreePosNode = treeNodeLevel2
622                 
623             for item in range((i+1)*(j+1)):
624                 # Add a leaf node to the third level
625                 leaf = treeNodeLevel2.addleaf(label = "Item %c"%(item+65),
626                                               #selectbackground = 'blue',
627                                               selectcommand = printselected,
628                                               deselectcommand = printdeselected)
629         for item in range(i+1):
630             # Add a leaf node to the top level
631             leaf = treeNodeLevel1.addleaf(label = "Item %c"%(item+65),
632                                           selectcommand = printselected,
633                                           deselectcommand = printdeselected)
634
635
636     treeNodeLevel1 = treeBrowser.addbranch(label = 'Check Button Label',
637                                            selectcommand = printselected,
638                                            deselectcommand = printdeselected,
639                                            expandcommand = printexpanded,
640                                            collapsecommand = printcollapsed,
641                                            )
642     checkButton = Tkinter.Checkbutton(treeNodeLevel1.interior(),
643                                       text = 'Da Check Button',
644                                       relief = 'ridge',
645                                       command = treeNodeLevel1.select)
646     checkButton.pack()
647
648     treeNodeLevel1.addleaf(label = 'Labeled Leaf',
649                            selectcommand = printselected,
650                            deselectcommand = printdeselected)
651     leaf = treeNodeLevel1.addleaf(label = 'Labeled Leaf w/ Checkbutton',
652                                   selectcommand = printselected,
653                                   deselectcommand = printdeselected)
654     checkButton = Tkinter.Checkbutton(leaf.interior(),
655                                       text = 'Da Check Button',
656                                       relief = 'ridge',
657                                       command = leaf.select)
658     checkButton.pack()
659
660
661     treeNodeLevel1 = treeBrowser.addbranch(selectcommand = printselected,
662                                            deselectcommand = printdeselected,
663                                            expandcommand = printexpanded,
664                                            collapsecommand = printcollapsed,
665                                            )
666     checkButton = Tkinter.Checkbutton(treeNodeLevel1.interior(),
667                                       text = 'Check Button with no label',
668                                       relief = 'ridge',
669                                       command = treeNodeLevel1.select)
670     checkButton.pack()
671
672     treeNodeLevel1 = treeBrowser.addbranch(label = 'Label',
673                                            selectcommand = printselected,
674                                            deselectcommand = printdeselected,
675                                            expandcommand = printexpanded,
676                                            collapsecommand = printcollapsed,
677                                            )
678
679     # setup dynamic tree node insertion and removal
680     class dynTree:
681         def __init__(self):
682             self.dyn = Tkinter.IntVar()
683             self.dtree = None
684
685             self.dLeaf = treeBrowser.addleaf(selectcommand = self.dynSelected,
686                                              deselectcommand = self.dynDeselected)
687             
688             self.dCheckButton = Tkinter.Checkbutton(self.dLeaf.interior(),
689                                                     text = 'Enable Dynamic Tree',
690                                                     variable = self.dyn,
691                                                     command = self.ChkBtnHandler)
692             self.dCheckButton.pack()
693
694             
695         def dynSelected(self, node):
696             self.dCheckButton.configure(background = self.dLeaf.configure('selectbackground')[4])
697             printselected(node)
698                 
699         def dynDeselected(self, node):
700             self.dCheckButton.configure(background = self.dLeaf.configure('background')[4])
701             printdeselected(node)
702                     
703         def ChkBtnHandler(self):
704             self.dLeaf.select()
705             if self.dyn.get() == 1:
706                 self.dtree = dynamicTreeRootNode.insertbranch(label = 'Dynamic Tree Node',
707                                                               selectcommand = printselected,
708                                                               deselectcommand = printdeselected,
709                                                               expandcommand = printexpanded,
710                                                               collapsecommand = printcollapsed,
711                                                               before = dynamicTreePosNode)
712                 self.dtree.addleaf(label = 'Dynamic Leaf 1',
713                                    selectcommand = printselected,
714                                    deselectcommand = printdeselected)
715                 self.dtree.addleaf(label = 'Dynamic Leaf 2',
716                                    selectcommand = printselected,
717                                    deselectcommand = printdeselected)
718             else:
719                 if self.dtree != None:
720                     dynamicTreeRootNode.delete(self.dtree)
721                     self.dtree = None
722
723
724     foo = dynTree()
725
726
727     treeBrowser.pack(expand = 1, fill='both')
728
729     exitButton = Tkinter.Button(rootWin, text="Quit", command=rootWin.quit)
730     exitButton.pack()
731
732     rootWin.mainloop()