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