1999-04-30 03:29:54 +00:00
|
|
|
"""
|
|
|
|
Hello, and welcome to this test of the wxTreeItemData
|
|
|
|
class.
|
|
|
|
|
|
|
|
The wxTreeItemData class can be used to associate a python
|
|
|
|
object with a wxTreeCtrl item. In this sample, its use is
|
|
|
|
demonstrated via a tree control that shows the contents of a
|
|
|
|
python namespace according to the standard dir()
|
|
|
|
command. Every item in the tree has its label taken from the
|
|
|
|
dir() output, and 'behind it' a reference to the python
|
|
|
|
object is stored in a wxTreeItemData object.
|
|
|
|
|
|
|
|
As you may have guessed by now, this sample automatically
|
|
|
|
displays '__doc__' strings if the selected python object
|
|
|
|
happens to have one. Please expand the pyTree object to
|
|
|
|
learn more about the implementation.
|
|
|
|
|
|
|
|
Version 1.0, April 4 1999.
|
|
|
|
Harm van der Heijden (H.v.d.Heijden@phys.tue.nl)
|
|
|
|
|
|
|
|
P.S. Check out the string module. It's imported in this
|
|
|
|
sample not because it's used, but because it's so
|
|
|
|
beautifully documented...
|
|
|
|
"""
|
|
|
|
|
|
|
|
from wxPython import wx
|
2001-04-09 19:36:36 +00:00
|
|
|
import sys, string # Don't use it, but it's fun expanding :-)
|
1999-04-30 03:29:54 +00:00
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
|
|
|
def _getindent(line):
|
|
|
|
"""Returns the indentation level of the given line."""
|
|
|
|
indent = 0
|
|
|
|
for c in line:
|
|
|
|
if c == ' ': indent = indent + 1
|
|
|
|
elif c == '\t': indent = indent + 8
|
|
|
|
else: break
|
|
|
|
return indent
|
|
|
|
|
|
|
|
def _sourcefinder(func):
|
|
|
|
"""Given a func_code object, this function tries to find and return
|
|
|
|
the python source code of the function."""
|
|
|
|
try:
|
|
|
|
f = open(func.co_filename,"r")
|
|
|
|
except:
|
|
|
|
return "(could not open file %s)" % (func.co_filename,)
|
|
|
|
|
|
|
|
for i in range(func.co_firstlineno):
|
|
|
|
line = f.readline()
|
|
|
|
ind = _getindent(line)
|
|
|
|
msg = ""
|
|
|
|
while line:
|
|
|
|
msg = msg + line
|
|
|
|
line = f.readline()
|
|
|
|
# the following should be <= ind, but then we get
|
|
|
|
# confused by multiline docstrings. Using == works most of
|
|
|
|
# the time... but not always!
|
|
|
|
if _getindent(line) == ind: break
|
|
|
|
return msg
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
|
|
|
class pyTree(wx.wxTreeCtrl):
|
|
|
|
"""
|
|
|
|
This wxTreeCtrl derivative displays a tree view of a Python namespace.
|
|
|
|
Anything from which the dir() command returns a non-empty list is a branch
|
|
|
|
in this tree.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, parent, id, root):
|
|
|
|
"""
|
|
|
|
Initialize function; because we insert branches into the tree
|
|
|
|
as needed, we use the ITEM_EXPANDING event handler. The
|
|
|
|
ITEM_COLLAPSED handler removes the stuff afterwards. The
|
|
|
|
SEL_CHANGED handler attempts to display interesting
|
|
|
|
information about the selected object.
|
|
|
|
"""
|
|
|
|
wx.wxTreeCtrl.__init__(self, parent, id)
|
|
|
|
self.root = self.AddRoot(str(root), -1, -1, wx.wxTreeItemData(root))
|
|
|
|
if dir(root):
|
|
|
|
self.SetItemHasChildren(self.root, wx.TRUE)
|
|
|
|
wx.EVT_TREE_ITEM_EXPANDING(self, self.GetId(), self.OnItemExpanding)
|
|
|
|
wx.EVT_TREE_ITEM_COLLAPSED(self, self.GetId(), self.OnItemCollapsed)
|
|
|
|
wx.EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
|
|
|
|
self.output = None
|
2001-05-18 21:59:59 +00:00
|
|
|
self.Expand(self.root)
|
1999-04-30 03:29:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
def SetOutput(self, output):
|
|
|
|
"""
|
|
|
|
Set output function (accepts single string). Used to display string
|
|
|
|
representation of the selected object by OnSelChanged.
|
|
|
|
"""
|
|
|
|
self.output = output
|
|
|
|
|
|
|
|
|
|
|
|
def OnItemExpanding(self,event):
|
|
|
|
"""
|
|
|
|
The real workhorse of this class. First we retrieve the object
|
|
|
|
(parent) belonging to the branch that is to be expanded. This
|
|
|
|
is done by calling GetPyData(parent), which is a short-cut for
|
|
|
|
GetPyItemData(parent).Get().
|
|
|
|
|
|
|
|
Then we get the dir() list of that object. For each item in
|
|
|
|
this list, a tree item is created with associated
|
|
|
|
wxTreeItemData referencing the child object. We get this
|
|
|
|
object using child = getattr(parent, item).
|
|
|
|
|
|
|
|
Finally, we check wether the child returns a non-empty dir()
|
|
|
|
list. If so, it is labeled as 'having children', so that it
|
|
|
|
may be expanded. When it actually is expanded, this function
|
|
|
|
will again figure out what the offspring is.
|
|
|
|
"""
|
|
|
|
item = event.GetItem()
|
2001-05-18 21:59:59 +00:00
|
|
|
if self.IsExpanded(item): # This event can happen twice in the self.Expand call
|
|
|
|
return
|
1999-04-30 03:29:54 +00:00
|
|
|
obj = self.GetPyData( item )
|
|
|
|
lst = dir(obj)
|
|
|
|
for key in lst:
|
|
|
|
new_obj = getattr(obj,key)
|
|
|
|
new_item = self.AppendItem( item, key, -1, -1,
|
|
|
|
wx.wxTreeItemData(new_obj) )
|
|
|
|
if dir(new_obj):
|
|
|
|
self.SetItemHasChildren(new_item, wx.TRUE)
|
|
|
|
|
|
|
|
def OnItemCollapsed(self, event):
|
|
|
|
"""
|
|
|
|
We need to remove all children here, otherwise we'll see all
|
|
|
|
that old rubbish again after the next expansion.
|
|
|
|
"""
|
|
|
|
item = event.GetItem()
|
|
|
|
self.DeleteChildren(item)
|
|
|
|
|
|
|
|
def OnSelChanged(self, event):
|
|
|
|
"""
|
|
|
|
If an output function is defined, we try to print some
|
|
|
|
informative, interesting and thought-provoking stuff to it.
|
|
|
|
If it has a __doc__ string, we print it. If it's a function or
|
|
|
|
unbound class method, we attempt to find the python source.
|
|
|
|
"""
|
|
|
|
if not self.output:
|
|
|
|
return
|
|
|
|
obj = self.GetPyData( event.GetItem() )
|
|
|
|
msg = str(obj)
|
|
|
|
if hasattr(obj, '__doc__'):
|
|
|
|
msg = msg+"\n\nDocumentation string:\n\n%s" % ( getattr(obj, '__doc__'),)
|
|
|
|
# Is it a function?
|
|
|
|
func = None
|
|
|
|
if hasattr(obj, "func_code"): # normal function
|
|
|
|
func = getattr(obj, "func_code")
|
|
|
|
elif hasattr(obj, "im_func"): # unbound class method
|
|
|
|
func = getattr(getattr(obj, "im_func"), "func_code")
|
|
|
|
if func: # if we found one, let's try to print the source
|
|
|
|
msg = msg+"\n\nFunction source:\n\n" + _sourcefinder(func)
|
|
|
|
|
|
|
|
apply(self.output, (msg,))
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
|
|
|
overview = __doc__
|
|
|
|
|
|
|
|
def runTest(frame, nb, log):
|
|
|
|
"""
|
|
|
|
This method is used by the wxPython Demo Framework for integrating
|
|
|
|
this demo with the rest.
|
|
|
|
"""
|
2001-04-09 19:36:36 +00:00
|
|
|
#thisModule = __import__(__name__, globals())
|
|
|
|
thisModule = sys.modules[__name__]
|
1999-04-30 03:29:54 +00:00
|
|
|
win = wx.wxFrame(frame, -1, "PyTreeItemData Test")
|
|
|
|
split = wx.wxSplitterWindow(win, -1)
|
|
|
|
tree = pyTree(split, -1, thisModule)
|
|
|
|
text = wx.wxTextCtrl(split, -1, "", wx.wxDefaultPosition,
|
|
|
|
wx.wxDefaultSize, wx.wxTE_MULTILINE)
|
|
|
|
split.SplitVertically(tree, text, 200)
|
|
|
|
tree.SetOutput(text.SetValue)
|
|
|
|
tree.SelectItem(tree.root)
|
|
|
|
win.SetSize(wx.wxSize(800,500))
|
|
|
|
frame.otherWin = win
|
|
|
|
win.Show(1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
|
|
|
class MyFrame(wx.wxFrame):
|
|
|
|
"""Very standard Frame class. Nothing special here!"""
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
"""Make a splitter window; left a tree, right a textctrl. Wow."""
|
|
|
|
import __main__
|
2001-05-18 21:59:59 +00:00
|
|
|
wx.wxFrame.__init__(self, None, -1, "PyTreeItemData Test",
|
1999-04-30 03:29:54 +00:00
|
|
|
wx.wxDefaultPosition, wx.wxSize(800,500))
|
|
|
|
split = wx.wxSplitterWindow(self, -1)
|
|
|
|
tree = pyTree(split, -1, __main__)
|
|
|
|
text = wx.wxTextCtrl(split, -1, "", wx.wxDefaultPosition,
|
|
|
|
wx.wxDefaultSize, wx.wxTE_MULTILINE)
|
|
|
|
split.SplitVertically(tree, text, 200)
|
|
|
|
tree.SetOutput(text.SetValue)
|
|
|
|
tree.SelectItem(tree.root)
|
|
|
|
|
|
|
|
class MyApp(wx.wxApp):
|
|
|
|
"""This class is even less interesting than MyFrame."""
|
|
|
|
|
|
|
|
def OnInit(self):
|
|
|
|
"""OnInit. Boring, boring, boring!"""
|
|
|
|
frame = MyFrame()
|
|
|
|
frame.Show(wx.TRUE)
|
|
|
|
self.SetTopWindow(frame)
|
|
|
|
return wx.TRUE
|
|
|
|
|
|
|
|
app = MyApp(0)
|
|
|
|
app.MainLoop()
|
|
|
|
|
|
|
|
|