]> git.saurik.com Git - wxWidgets.git/blame - wxPython/demo/pyTree.py
The bug is no longer there, but leave the workaround in place for
[wxWidgets.git] / wxPython / demo / pyTree.py
CommitLineData
cf694132
RD
1"""
2Hello, and welcome to this test of the wxTreeItemData
3class.
4
5The wxTreeItemData class can be used to associate a python
6object with a wxTreeCtrl item. In this sample, its use is
7demonstrated via a tree control that shows the contents of a
8python namespace according to the standard dir()
9command. Every item in the tree has its label taken from the
10dir() output, and 'behind it' a reference to the python
11object is stored in a wxTreeItemData object.
12
13As you may have guessed by now, this sample automatically
14displays '__doc__' strings if the selected python object
15happens to have one. Please expand the pyTree object to
16learn more about the implementation.
17
18Version 1.0, April 4 1999.
19Harm van der Heijden (H.v.d.Heijden@phys.tue.nl)
20
21P.S. Check out the string module. It's imported in this
22sample not because it's used, but because it's so
23beautifully documented...
24"""
25
8fa876ca
RD
26import string # Used for demo purposes, nothing more. :-)
27import sys
28
29import wx
cf694132
RD
30
31#----------------------------------------------------------------------
32
33def _getindent(line):
34 """Returns the indentation level of the given line."""
35 indent = 0
36 for c in line:
37 if c == ' ': indent = indent + 1
38 elif c == '\t': indent = indent + 8
39 else: break
40 return indent
41
42def _sourcefinder(func):
43 """Given a func_code object, this function tries to find and return
44 the python source code of the function."""
45 try:
46 f = open(func.co_filename,"r")
47 except:
48 return "(could not open file %s)" % (func.co_filename,)
49
50 for i in range(func.co_firstlineno):
51 line = f.readline()
8fa876ca 52
cf694132
RD
53 ind = _getindent(line)
54 msg = ""
8fa876ca 55
cf694132
RD
56 while line:
57 msg = msg + line
58 line = f.readline()
59 # the following should be <= ind, but then we get
60 # confused by multiline docstrings. Using == works most of
61 # the time... but not always!
62 if _getindent(line) == ind: break
8fa876ca 63
cf694132
RD
64 return msg
65
66#----------------------------------------------------------------------
67
8fa876ca 68class pyTree(wx.TreeCtrl):
cf694132 69 """
8fa876ca 70 This wx.TreeCtrl derivative displays a tree view of a Python namespace.
cf694132
RD
71 Anything from which the dir() command returns a non-empty list is a branch
72 in this tree.
73 """
74
75 def __init__(self, parent, id, root):
76 """
77 Initialize function; because we insert branches into the tree
78 as needed, we use the ITEM_EXPANDING event handler. The
79 ITEM_COLLAPSED handler removes the stuff afterwards. The
80 SEL_CHANGED handler attempts to display interesting
81 information about the selected object.
82 """
8fa876ca
RD
83 wx.TreeCtrl.__init__(self, parent, id)
84 self.root = self.AddRoot(str(root), -1, -1, wx.TreeItemData(root))
85
cf694132 86 if dir(root):
8fa876ca
RD
87 self.SetItemHasChildren(self.root, True)
88
89 self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpanding, id=self.GetId())
90 self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, id=self.GetId())
91 self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=self.GetId())
92
cf694132 93 self.output = None
493f1553 94 self.Expand(self.root)
cf694132
RD
95
96
97 def SetOutput(self, output):
98 """
99 Set output function (accepts single string). Used to display string
100 representation of the selected object by OnSelChanged.
101 """
102 self.output = output
103
104
105 def OnItemExpanding(self,event):
106 """
107 The real workhorse of this class. First we retrieve the object
108 (parent) belonging to the branch that is to be expanded. This
109 is done by calling GetPyData(parent), which is a short-cut for
110 GetPyItemData(parent).Get().
111
112 Then we get the dir() list of that object. For each item in
113 this list, a tree item is created with associated
114 wxTreeItemData referencing the child object. We get this
115 object using child = getattr(parent, item).
116
117 Finally, we check wether the child returns a non-empty dir()
118 list. If so, it is labeled as 'having children', so that it
119 may be expanded. When it actually is expanded, this function
120 will again figure out what the offspring is.
121 """
122 item = event.GetItem()
8fa876ca 123
493f1553
RD
124 if self.IsExpanded(item): # This event can happen twice in the self.Expand call
125 return
8fa876ca 126
cf694132
RD
127 obj = self.GetPyData( item )
128 lst = dir(obj)
8fa876ca 129
cf694132
RD
130 for key in lst:
131 new_obj = getattr(obj,key)
132 new_item = self.AppendItem( item, key, -1, -1,
8fa876ca
RD
133 wx.TreeItemData(new_obj) )
134
cf694132 135 if dir(new_obj):
8fa876ca 136 self.SetItemHasChildren(new_item, True)
cf694132
RD
137
138 def OnItemCollapsed(self, event):
139 """
140 We need to remove all children here, otherwise we'll see all
141 that old rubbish again after the next expansion.
142 """
143 item = event.GetItem()
144 self.DeleteChildren(item)
145
146 def OnSelChanged(self, event):
147 """
148 If an output function is defined, we try to print some
149 informative, interesting and thought-provoking stuff to it.
150 If it has a __doc__ string, we print it. If it's a function or
151 unbound class method, we attempt to find the python source.
152 """
153 if not self.output:
154 return
8fa876ca 155
cf694132
RD
156 obj = self.GetPyData( event.GetItem() )
157 msg = str(obj)
8fa876ca 158
cf694132
RD
159 if hasattr(obj, '__doc__'):
160 msg = msg+"\n\nDocumentation string:\n\n%s" % ( getattr(obj, '__doc__'),)
8fa876ca 161
cf694132
RD
162 # Is it a function?
163 func = None
8fa876ca 164
cf694132
RD
165 if hasattr(obj, "func_code"): # normal function
166 func = getattr(obj, "func_code")
8fa876ca 167
cf694132
RD
168 elif hasattr(obj, "im_func"): # unbound class method
169 func = getattr(getattr(obj, "im_func"), "func_code")
8fa876ca 170
cf694132
RD
171 if func: # if we found one, let's try to print the source
172 msg = msg+"\n\nFunction source:\n\n" + _sourcefinder(func)
173
174 apply(self.output, (msg,))
175
176#----------------------------------------------------------------------
177
178overview = __doc__
179
180def runTest(frame, nb, log):
181 """
182 This method is used by the wxPython Demo Framework for integrating
183 this demo with the rest.
184 """
96bfd053 185 thisModule = sys.modules[__name__]
8fa876ca
RD
186 win = wx.Frame(frame, -1, "PyTreeItemData Test")
187 split = wx.SplitterWindow(win, -1)
cf694132 188 tree = pyTree(split, -1, thisModule)
8fa876ca 189 text = wx.TextCtrl(split, -1, "", style=wx.TE_MULTILINE)
cf694132
RD
190 split.SplitVertically(tree, text, 200)
191 tree.SetOutput(text.SetValue)
192 tree.SelectItem(tree.root)
8fa876ca 193 win.SetSize((800,500))
cf694132
RD
194 frame.otherWin = win
195 win.Show(1)
196
197
198
199#----------------------------------------------------------------------
200if __name__ == '__main__':
201
8fa876ca 202 class MyFrame(wx.Frame):
cf694132
RD
203 """Very standard Frame class. Nothing special here!"""
204
205 def __init__(self):
206 """Make a splitter window; left a tree, right a textctrl. Wow."""
207 import __main__
8fa876ca
RD
208 wx.Frame.__init__(self, None, -1, "PyTreeItemData Test", size=(800,500))
209 split = wx.SplitterWindow(self, -1)
cf694132 210 tree = pyTree(split, -1, __main__)
8fa876ca 211 text = wx.TextCtrl(split, -1, "", style=wx.TE_MULTILINE)
cf694132
RD
212 split.SplitVertically(tree, text, 200)
213 tree.SetOutput(text.SetValue)
214 tree.SelectItem(tree.root)
215
8fa876ca 216 class MyApp(wx.App):
cf694132
RD
217 """This class is even less interesting than MyFrame."""
218
219 def OnInit(self):
220 """OnInit. Boring, boring, boring!"""
221 frame = MyFrame()
8fa876ca 222 frame.Show(True)
cf694132 223 self.SetTopWindow(frame)
8fa876ca 224 return True
cf694132 225
8fa876ca 226 app = MyApp(False)
cf694132
RD
227 app.MainLoop()
228
229