X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f91cd3896917fc386a1f7ede095c6cdf5fcdf7e6..8bf5d46efb26ab22575ca9bc0d0ca5d32d6b77a3:/utils/wxPython/tests/pytree.py diff --git a/utils/wxPython/tests/pytree.py b/utils/wxPython/tests/pytree.py new file mode 100644 index 0000000000..10deb1859d --- /dev/null +++ b/utils/wxPython/tests/pytree.py @@ -0,0 +1,203 @@ +""" +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 +import string # Don't use it, but it's fun expanding :-) + +#---------------------------------------------------------------------- + +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 + + + 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() + 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): + split = wx.wxSplitterWindow(nb, -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) + text.SetBackgroundColour(wxNamedColour("LIGHT BLUE")) + tree.SetBackgroundColour(wxNamedColour("LIGHT BLUE")) + + return split + + + +#---------------------------------------------------------------------- +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__ + wx.wxFrame.__init__(self, wx.NULL, -1, "PyTreeItemData Test", + 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() + +