]> git.saurik.com Git - wxWidgets.git/blame_incremental - wxPython/demo/pyTree.py
The great wxVScrolledWindow refactoring: allow using it both horizontal and
[wxWidgets.git] / wxPython / demo / pyTree.py
... / ...
CommitLineData
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
26import string # Used for demo purposes, nothing more. :-)
27import sys
28
29import wx
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()
52
53 ind = _getindent(line)
54 msg = ""
55
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
63
64 return msg
65
66#----------------------------------------------------------------------
67
68class pyTree(wx.TreeCtrl):
69 """
70 This wx.TreeCtrl derivative displays a tree view of a Python namespace.
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 """
83 wx.TreeCtrl.__init__(self, parent, id)
84 self.root = self.AddRoot(str(root), -1, -1, wx.TreeItemData(root))
85
86 if dir(root):
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
93 self.output = None
94 self.Expand(self.root)
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()
123
124 if self.IsExpanded(item): # This event can happen twice in the self.Expand call
125 return
126
127 obj = self.GetPyData( item )
128 lst = dir(obj)
129
130 for key in lst:
131 new_obj = getattr(obj,key)
132 new_item = self.AppendItem( item, key, -1, -1,
133 wx.TreeItemData(new_obj) )
134
135 if dir(new_obj):
136 self.SetItemHasChildren(new_item, True)
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
155
156 obj = self.GetPyData( event.GetItem() )
157 msg = str(obj)
158
159 if hasattr(obj, '__doc__'):
160 msg = msg+"\n\nDocumentation string:\n\n%s" % ( getattr(obj, '__doc__'),)
161
162 # Is it a function?
163 func = None
164
165 if hasattr(obj, "func_code"): # normal function
166 func = getattr(obj, "func_code")
167
168 elif hasattr(obj, "im_func"): # unbound class method
169 func = getattr(getattr(obj, "im_func"), "func_code")
170
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 """
185 thisModule = sys.modules[__name__]
186 win = wx.Frame(frame, -1, "PyTreeItemData Test")
187 split = wx.SplitterWindow(win, -1)
188 tree = pyTree(split, -1, thisModule)
189 text = wx.TextCtrl(split, -1, "", style=wx.TE_MULTILINE)
190 split.SplitVertically(tree, text, 200)
191 tree.SetOutput(text.SetValue)
192 tree.SelectItem(tree.root)
193 win.SetSize((800,500))
194 frame.otherWin = win
195 win.Show(1)
196
197
198
199#----------------------------------------------------------------------
200if __name__ == '__main__':
201
202 class MyFrame(wx.Frame):
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__
208 wx.Frame.__init__(self, None, -1, "PyTreeItemData Test", size=(800,500))
209 split = wx.SplitterWindow(self, -1)
210 tree = pyTree(split, -1, __main__)
211 text = wx.TextCtrl(split, -1, "", style=wx.TE_MULTILINE)
212 split.SplitVertically(tree, text, 200)
213 tree.SetOutput(text.SetValue)
214 tree.SelectItem(tree.root)
215
216 class MyApp(wx.App):
217 """This class is even less interesting than MyFrame."""
218
219 def OnInit(self):
220 """OnInit. Boring, boring, boring!"""
221 frame = MyFrame()
222 frame.Show(True)
223 self.SetTopWindow(frame)
224 return True
225
226 app = MyApp(False)
227 app.MainLoop()
228
229