diff options
Diffstat (limited to 'Tools/idle/ClassBrowser.py')
-rw-r--r-- | Tools/idle/ClassBrowser.py | 164 |
1 files changed, 153 insertions, 11 deletions
diff --git a/Tools/idle/ClassBrowser.py b/Tools/idle/ClassBrowser.py index 289d6f6..8db037a 100644 --- a/Tools/idle/ClassBrowser.py +++ b/Tools/idle/ClassBrowser.py @@ -1,10 +1,23 @@ -from Tkinter import * +"""Primitive class browser. + +XXX TO DO: + +- generalize the scrolling listbox with some behavior into a base class +- 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? + +""" + import string import pyclbr +from Tkinter import * +import tkMessageBox class ClassBrowser: - def __init__(self, root, name): + def __init__(self, flist, name): + root = flist.root try: dict = pyclbr.readmodule(name) except ImportError, msg: @@ -14,20 +27,26 @@ class ClassBrowser: tkMessageBox.showerror("Nothing to browse", "Module %s defines no classes" % name, parent=root) return + self.flist = flist + self.dict = dict self.root = root self.top = top = Toplevel(root) + self.top.protocol("WM_DELETE_WINDOW", self.close) + self.leftframe = leftframe = Frame(top) + self.leftframe.pack(side="left", fill="both", expand=1) + top.wm_title("Class browser") # Create help label - self.helplabel = Label(top, + self.helplabel = Label(leftframe, text="Classes in module %s" % name, borderwidth=2, relief="groove") self.helplabel.pack(fill="x") # Create top frame, with scrollbar and listbox - self.topframe = Frame(top) + self.topframe = Frame(leftframe) self.topframe.pack(fill="both", expand=1) self.vbar = Scrollbar(self.topframe, name="vbar") self.vbar.pack(side="right", fill="y") self.listbox = Listbox(self.topframe, exportselection=0, - takefocus=1, width=60) + takefocus=1, width=30) self.listbox.pack(expand=1, fill="both") # Tie listbox and scrollbar together self.vbar["command"] = self.listbox.yview @@ -39,13 +58,19 @@ class ClassBrowser: self.listbox.bind("<Key-Up>", self.up_event) self.listbox.bind("<Key-Down>", self.down_event) # Load the classes - self.loadclasses(dict) + self.loadclasses(dict, name) + + def close(self): + self.top.destroy() - def loadclasses(self, dict): - items = dict.items() + def loadclasses(self, dict, module): + items = [] + for key, value in dict.items(): + if value.module == module: + items.append((value.lineno, key, value)) items.sort() l = self.listbox - for key, value in items: + for lineno, key, value in items: s = key if value.super: super = [] @@ -55,16 +80,133 @@ class ClassBrowser: name = "%s.%s" % (sup.module, name) super.append(name) s = s + "(%s)" % string.join(super, ", ") - l.insert(END, s) + l.insert("end", s) + l.focus_set() + l.selection_clear(0, "end") + if self.botframe: + self.botframe.destroy() + self.botframe = None + self.methodviewer = None def click_event(self, event): - pass + self.listbox.activate("@%d,%d" % (event.x, event.y)) + index = self.listbox.index("active") + self.show_methods(index) def double_click_event(self, event): + self.listbox.activate("@%d,%d" % (event.x, event.y)) + index = self.listbox.index("active") + self.show_source(index) + + def up_event(self, event): + index = self.listbox.index("active") - 1 + if index < 0: + self.top.bell() + return "break" + self.show_methods(index) + return "break" + + def down_event(self, event): + index = self.listbox.index("active") + 1 + if index >= self.listbox.index("end"): + self.top.bell() + return "break" + self.show_methods(index) + return "break" + + def show_source(self, index): + name = self.listbox.get(index) + i = string.find(name, '(') + if i >= 0: + name = name[:i] + cl = self.dict[name] + edit = self.flist.open(cl.file) + edit.gotoline(cl.lineno) + + botframe = None + methodviewer = None + + def show_methods(self, index): + self.listbox.selection_clear(0, "end") + self.listbox.selection_set(index) + self.listbox.activate(index) + self.listbox.see(index) + self.listbox.focus_set() + name = self.listbox.get(index) + i = string.find(name, '(') + if i >= 0: + name = name[:i] + cl = self.dict[name] + if not self.botframe: + self.botframe = Frame(self.top) + self.botframe.pack(expand=1, fill="both") + if not self.methodviewer: + self.methodviewer = MethodViewer(self.botframe, self.flist) + self.methodviewer.loadmethods(cl) + +class MethodViewer: + + # XXX There's a pattern emerging here... + + def __init__(self, frame, flist): + self.frame = frame + self.flist = flist + # Create help label + self.helplabel = Label(frame, + text="Methods", borderwidth=2, relief="groove") + self.helplabel.pack(fill="x") + # Create top frame, with scrollbar and listbox + self.topframe = Frame(frame) + self.topframe.pack(fill="both", expand=1) + self.vbar = Scrollbar(self.topframe, name="vbar") + self.vbar.pack(side="right", fill="y") + self.listbox = Listbox(self.topframe, exportselection=0, + takefocus=1, width=30) + self.listbox.pack(expand=1, fill="both") + # Tie listbox and scrollbar together + self.vbar["command"] = self.listbox.yview + self.listbox["yscrollcommand"] = self.vbar.set + # Bind events to the list box + self.listbox.bind("<ButtonRelease-1>", self.click_event) + self.listbox.bind("<Double-ButtonRelease-1>", self.double_click_event) + ##self.listbox.bind("<ButtonPress-3>", self.popup_event) + self.listbox.bind("<Key-Up>", self.up_event) + self.listbox.bind("<Key-Down>", self.down_event) + + classinfo = None + + def loadmethods(self, cl): + self.classinfo = cl + self.helplabel.config(text="Methods of class %s" % cl.name) + l = self.listbox + l.delete(0, "end") + l.selection_clear(0, "end") + items = [] + for name, lineno in cl.methods.items(): + items.append((lineno, name)) + items.sort() + for item, name in items: + l.insert("end", name) + + def click_event(self, event): pass + def double_click_event(self, event): + self.listbox.activate("@%d,%d" % (event.x, event.y)) + index = self.listbox.index("active") + self.show_source(index) + def up_event(self, event): pass def down_event(self, event): pass + + def show_source(self, index): + name = self.listbox.get(index) + i = string.find(name, '(') + if i >= 0: + name = name[:i] + edit = self.flist.open(self.classinfo.file) + edit.gotoline(self.classinfo.methods[name]) + |