python-2.5.2/win32/Lib/idlelib/ClassBrowser.py
changeset 0 ae805ac0140d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python-2.5.2/win32/Lib/idlelib/ClassBrowser.py	Fri Apr 03 17:19:34 2009 +0100
@@ -0,0 +1,221 @@
+"""Class browser.
+
+XXX TO DO:
+
+- reparse when source changed (maybe just a button would be OK?)
+    (or recheck on window popup)
+- add popup menu with more options (e.g. doc strings, base classes, imports)
+- show function argument list? (have to do pattern matching on source)
+- should the classes and methods lists also be in the module's menu bar?
+- add base classes to class browser tree
+"""
+
+import os
+import sys
+import pyclbr
+
+import PyShell
+from WindowList import ListedToplevel
+from TreeWidget import TreeNode, TreeItem, ScrolledCanvas
+from configHandler import idleConf
+
+class ClassBrowser:
+
+    def __init__(self, flist, name, path):
+        # XXX This API should change, if the file doesn't end in ".py"
+        # XXX the code here is bogus!
+        self.name = name
+        self.file = os.path.join(path[0], self.name + ".py")
+        self.init(flist)
+
+    def close(self, event=None):
+        self.top.destroy()
+        self.node.destroy()
+
+    def init(self, flist):
+        self.flist = flist
+        # reset pyclbr
+        pyclbr._modules.clear()
+        # create top
+        self.top = top = ListedToplevel(flist.root)
+        top.protocol("WM_DELETE_WINDOW", self.close)
+        top.bind("<Escape>", self.close)
+        self.settitle()
+        top.focus_set()
+        # create scrolled canvas
+        theme = idleConf.GetOption('main','Theme','name')
+        background = idleConf.GetHighlight(theme, 'normal')['background']
+        sc = ScrolledCanvas(top, bg=background, highlightthickness=0, takefocus=1)
+        sc.frame.pack(expand=1, fill="both")
+        item = self.rootnode()
+        self.node = node = TreeNode(sc.canvas, None, item)
+        node.update()
+        node.expand()
+
+    def settitle(self):
+        self.top.wm_title("Class Browser - " + self.name)
+        self.top.wm_iconname("Class Browser")
+
+    def rootnode(self):
+        return ModuleBrowserTreeItem(self.file)
+
+class ModuleBrowserTreeItem(TreeItem):
+
+    def __init__(self, file):
+        self.file = file
+
+    def GetText(self):
+        return os.path.basename(self.file)
+
+    def GetIconName(self):
+        return "python"
+
+    def GetSubList(self):
+        sublist = []
+        for name in self.listclasses():
+            item = ClassBrowserTreeItem(name, self.classes, self.file)
+            sublist.append(item)
+        return sublist
+
+    def OnDoubleClick(self):
+        if os.path.normcase(self.file[-3:]) != ".py":
+            return
+        if not os.path.exists(self.file):
+            return
+        PyShell.flist.open(self.file)
+
+    def IsExpandable(self):
+        return os.path.normcase(self.file[-3:]) == ".py"
+
+    def listclasses(self):
+        dir, file = os.path.split(self.file)
+        name, ext = os.path.splitext(file)
+        if os.path.normcase(ext) != ".py":
+            return []
+        try:
+            dict = pyclbr.readmodule_ex(name, [dir] + sys.path)
+        except ImportError, msg:
+            return []
+        items = []
+        self.classes = {}
+        for key, cl in dict.items():
+            if cl.module == name:
+                s = key
+                if hasattr(cl, 'super') and cl.super:
+                    supers = []
+                    for sup in cl.super:
+                        if type(sup) is type(''):
+                            sname = sup
+                        else:
+                            sname = sup.name
+                            if sup.module != cl.module:
+                                sname = "%s.%s" % (sup.module, sname)
+                        supers.append(sname)
+                    s = s + "(%s)" % ", ".join(supers)
+                items.append((cl.lineno, s))
+                self.classes[s] = cl
+        items.sort()
+        list = []
+        for item, s in items:
+            list.append(s)
+        return list
+
+class ClassBrowserTreeItem(TreeItem):
+
+    def __init__(self, name, classes, file):
+        self.name = name
+        self.classes = classes
+        self.file = file
+        try:
+            self.cl = self.classes[self.name]
+        except (IndexError, KeyError):
+            self.cl = None
+        self.isfunction = isinstance(self.cl, pyclbr.Function)
+
+    def GetText(self):
+        if self.isfunction:
+            return "def " + self.name + "(...)"
+        else:
+            return "class " + self.name
+
+    def GetIconName(self):
+        if self.isfunction:
+            return "python"
+        else:
+            return "folder"
+
+    def IsExpandable(self):
+        if self.cl:
+            try:
+                return not not self.cl.methods
+            except AttributeError:
+                return False
+
+    def GetSubList(self):
+        if not self.cl:
+            return []
+        sublist = []
+        for name in self.listmethods():
+            item = MethodBrowserTreeItem(name, self.cl, self.file)
+            sublist.append(item)
+        return sublist
+
+    def OnDoubleClick(self):
+        if not os.path.exists(self.file):
+            return
+        edit = PyShell.flist.open(self.file)
+        if hasattr(self.cl, 'lineno'):
+            lineno = self.cl.lineno
+            edit.gotoline(lineno)
+
+    def listmethods(self):
+        if not self.cl:
+            return []
+        items = []
+        for name, lineno in self.cl.methods.items():
+            items.append((lineno, name))
+        items.sort()
+        list = []
+        for item, name in items:
+            list.append(name)
+        return list
+
+class MethodBrowserTreeItem(TreeItem):
+
+    def __init__(self, name, cl, file):
+        self.name = name
+        self.cl = cl
+        self.file = file
+
+    def GetText(self):
+        return "def " + self.name + "(...)"
+
+    def GetIconName(self):
+        return "python" # XXX
+
+    def IsExpandable(self):
+        return 0
+
+    def OnDoubleClick(self):
+        if not os.path.exists(self.file):
+            return
+        edit = PyShell.flist.open(self.file)
+        edit.gotoline(self.cl.methods[self.name])
+
+def main():
+    try:
+        file = __file__
+    except NameError:
+        file = sys.argv[0]
+        if sys.argv[1:]:
+            file = sys.argv[1]
+        else:
+            file = sys.argv[0]
+    dir, file = os.path.split(file)
+    name = os.path.splitext(file)[0]
+    ClassBrowser(PyShell.flist, name, [dir])
+    if sys.stdin is sys.__stdin__:
+        mainloop()
+
+if __name__ == "__main__":
+    main()