From e6fae1cbcad8c3bc58925cd14badfcbbcb05893c Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Thu, 15 Oct 1998 23:27:08 +0000 Subject: [PATCH] Generalized the scrolled list which is the base for the class and method browser into a separate class in its own module. --- Tools/idle/ClassBrowser.py | 209 ++++++++++++++----------------------- Tools/idle/ScrolledList.py | 128 +++++++++++++++++++++++ 2 files changed, 207 insertions(+), 130 deletions(-) create mode 100644 Tools/idle/ScrolledList.py diff --git a/Tools/idle/ClassBrowser.py b/Tools/idle/ClassBrowser.py index 8db037aff64..ffbf5089e4f 100644 --- a/Tools/idle/ClassBrowser.py +++ b/Tools/idle/ClassBrowser.py @@ -9,11 +9,15 @@ XXX TO DO: """ +import os import string import pyclbr from Tkinter import * import tkMessageBox +from ScrolledList import ScrolledList + + class ClassBrowser: def __init__(self, flist, name): @@ -32,44 +36,62 @@ class ClassBrowser: self.root = root self.top = top = Toplevel(root) self.top.protocol("WM_DELETE_WINDOW", self.close) + top.wm_title("Class browser") 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(leftframe, - text="Classes in module %s" % name, - borderwidth=2, relief="groove") + self.helplabel = Label(leftframe, text="Module %s" % name, + relief="groove", borderwidth=2) self.helplabel.pack(fill="x") # Create top frame, with scrollbar and listbox - 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=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("", self.click_event) - self.listbox.bind("", self.double_click_event) - ##self.listbox.bind("", self.popup_event) - self.listbox.bind("", self.up_event) - self.listbox.bind("", self.down_event) + self.classviewer = ClassViewer( + self.leftframe, self.flist, self) # Load the classes - self.loadclasses(dict, name) + self.load_classes(dict, name) def close(self): + self.classviewer = None + self.methodviewer = None self.top.destroy() - def loadclasses(self, dict, module): + def load_classes(self, dict, module): + self.classviewer.load_classes(dict, module) + if self.botframe: + self.botframe.destroy() + self.botframe = None + self.methodviewer = None + + botframe = None + methodhelplabel = None + methodviewer = None + + def show_methods(self, cl): + if not self.botframe: + self.botframe = Frame(self.top) + self.botframe.pack(side="right", expand=1, fill="both") + self.methodhelplabel = Label(self.botframe, + relief="groove", borderwidth=2) + self.methodhelplabel.pack(fill="x") + self.methodviewer = MethodViewer(self.botframe, self.flist) + self.methodhelplabel.config(text="Class %s" % cl.name) + self.methodviewer.load_methods(cl) + + +class ClassViewer(ScrolledList): + + def __init__(self, master, flist, browser): + ScrolledList.__init__(self, master) + self.flist = flist + self.browser = browser + + def load_classes(self, dict, module): + self.clear() + self.dict = dict items = [] for key, value in dict.items(): if value.module == module: items.append((value.lineno, key, value)) items.sort() - l = self.listbox for lineno, key, value in items: s = key if value.super: @@ -80,133 +102,60 @@ class ClassBrowser: name = "%s.%s" % (sup.module, name) super.append(name) s = s + "(%s)" % string.join(super, ", ") - l.insert("end", s) - l.focus_set() - l.selection_clear(0, "end") - if self.botframe: - self.botframe.destroy() - self.botframe = None - self.methodviewer = None + self.append(s) + + def getname(self, index): + name = self.listbox.get(index) + i = string.find(name, '(') + if i >= 0: + name = name[:i] + return name - def click_event(self, event): - self.listbox.activate("@%d,%d" % (event.x, event.y)) - index = self.listbox.index("active") + def getclass(self, index): + return self.dict[self.getname(index)] + + def on_select(self, index): self.show_methods(index) - def double_click_event(self, event): - self.listbox.activate("@%d,%d" % (event.x, event.y)) - index = self.listbox.index("active") + def on_double(self, index): 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) + cl = self.getclass(index) + self.browser.show_methods(cl) -class MethodViewer: + def show_source(self, index): + cl = self.getclass(index) + if os.path.isfile(cl.file): + edit = self.flist.open(cl.file) + edit.gotoline(cl.lineno) + + +class MethodViewer(ScrolledList): - # XXX There's a pattern emerging here... - - def __init__(self, frame, flist): - self.frame = frame + def __init__(self, master, flist): + ScrolledList.__init__(self, master) 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("", self.click_event) - self.listbox.bind("", self.double_click_event) - ##self.listbox.bind("", self.popup_event) - self.listbox.bind("", self.up_event) - self.listbox.bind("", self.down_event) classinfo = None - def loadmethods(self, cl): + def load_methods(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") + self.clear() items = [] for name, lineno in cl.methods.items(): items.append((lineno, name)) items.sort() for item, name in items: - l.insert("end", name) + self.append(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 on_double(self, index): + self.show_source(self.get(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]) - + def show_source(self, name): + if os.path.isfile(self.classinfo.file): + edit = self.flist.open(self.classinfo.file) + edit.gotoline(self.classinfo.methods[name]) diff --git a/Tools/idle/ScrolledList.py b/Tools/idle/ScrolledList.py new file mode 100644 index 00000000000..703cd0c3a31 --- /dev/null +++ b/Tools/idle/ScrolledList.py @@ -0,0 +1,128 @@ +from Tkinter import * + +class ScrolledList: + + def __init__(self, master, **options): + # Create top frame, with scrollbar and listbox + self.master = master + self.frame = frame = Frame(master) + self.frame.pack(fill="both", expand=1) + self.vbar = vbar = Scrollbar(frame, name="vbar") + self.vbar.pack(side="right", fill="y") + self.listbox = listbox = Listbox(frame, exportselection=0) + if options: + listbox.configure(options) + listbox.pack(expand=1, fill="both") + # Tie listbox and scrollbar together + vbar["command"] = listbox.yview + listbox["yscrollcommand"] = vbar.set + # Bind events to the list box + listbox.bind("", self.click_event) + listbox.bind("", self.double_click_event) + listbox.bind("", self.popup_event) + listbox.bind("", self.up_event) + listbox.bind("", self.down_event) + # Set the focus + listbox.focus_set() + + def clear(self): + self.listbox.delete(0, "end") + + def append(self, item): + self.listbox.insert("end", str(item)) + + def get(self, index): + return self.listbox.get(index) + + def click_event(self, event): + self.listbox.activate("@%d,%d" % (event.x, event.y)) + index = self.listbox.index("active") + self.select(index) + self.on_select(index) + return "break" + + def double_click_event(self, event): + index = self.listbox.index("active") + self.select(index) + self.on_double(index) + return "break" + + menu = None + + def popup_event(self, event): + if not self.menu: + self.make_menu() + menu = self.menu + self.listbox.activate("@%d,%d" % (event.x, event.y)) + index = self.listbox.index("active") + self.select(index) + menu.tk_popup(event.x_root, event.y_root) + + def make_menu(self): + menu = Menu(self.listbox, tearoff=0) + self.menu = menu + self.fill_menu() + + def up_event(self, event): + index = self.listbox.index("active") + if self.listbox.selection_includes(index): + index = index - 1 + else: + index = self.listbox.size() - 1 + if index < 0: + self.listbox.bell() + else: + self.select(index) + self.on_select(index) + return "break" + + def down_event(self, event): + index = self.listbox.index("active") + if self.listbox.selection_includes(index): + index = index + 1 + else: + index = 0 + if index >= self.listbox.size(): + self.listbox.bell() + else: + self.select(index) + self.on_select(index) + return "break" + + def select(self, index): + self.listbox.focus_set() + self.listbox.activate(index) + self.listbox.selection_clear(0, "end") + self.listbox.selection_set(index) + self.listbox.see(index) + + # Methods to override for specific actions + + def fill_menu(self): + pass + + def on_select(self, index): + pass + + def on_double(self, index): + pass + + +def test(): + root = Tk() + root.protocol("WM_DELETE_WINDOW", root.destroy) + class MyScrolledList(ScrolledList): + def fill_menu(self): self.menu.add_command(label="pass") + def on_select(self, index): print "select", self.get(index) + def on_double(self, index): print "double", self.get(index) + s = MyScrolledList(root) + for i in range(30): + s.append("item %02d" % i) + return root + +def main(): + root = test() + root.mainloop() + +if __name__ == '__main__': + main()