Generalized the scrolled list which is the base for the class and

method browser into a separate class in its own module.
This commit is contained in:
Guido van Rossum 1998-10-15 23:27:08 +00:00
parent 341d1fe18e
commit e6fae1cbca
2 changed files with 207 additions and 130 deletions

View File

@ -9,11 +9,15 @@ XXX TO DO:
""" """
import os
import string import string
import pyclbr import pyclbr
from Tkinter import * from Tkinter import *
import tkMessageBox import tkMessageBox
from ScrolledList import ScrolledList
class ClassBrowser: class ClassBrowser:
def __init__(self, flist, name): def __init__(self, flist, name):
@ -32,44 +36,62 @@ class ClassBrowser:
self.root = root self.root = root
self.top = top = Toplevel(root) self.top = top = Toplevel(root)
self.top.protocol("WM_DELETE_WINDOW", self.close) self.top.protocol("WM_DELETE_WINDOW", self.close)
top.wm_title("Class browser")
self.leftframe = leftframe = Frame(top) self.leftframe = leftframe = Frame(top)
self.leftframe.pack(side="left", fill="both", expand=1) self.leftframe.pack(side="left", fill="both", expand=1)
top.wm_title("Class browser")
# Create help label # Create help label
self.helplabel = Label(leftframe, self.helplabel = Label(leftframe, text="Module %s" % name,
text="Classes in module %s" % name, relief="groove", borderwidth=2)
borderwidth=2, relief="groove")
self.helplabel.pack(fill="x") self.helplabel.pack(fill="x")
# Create top frame, with scrollbar and listbox # Create top frame, with scrollbar and listbox
self.topframe = Frame(leftframe) self.classviewer = ClassViewer(
self.topframe.pack(fill="both", expand=1) self.leftframe, self.flist, self)
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)
# Load the classes # Load the classes
self.loadclasses(dict, name) self.load_classes(dict, name)
def close(self): def close(self):
self.classviewer = None
self.methodviewer = None
self.top.destroy() 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 = [] items = []
for key, value in dict.items(): for key, value in dict.items():
if value.module == module: if value.module == module:
items.append((value.lineno, key, value)) items.append((value.lineno, key, value))
items.sort() items.sort()
l = self.listbox
for lineno, key, value in items: for lineno, key, value in items:
s = key s = key
if value.super: if value.super:
@ -80,133 +102,60 @@ class ClassBrowser:
name = "%s.%s" % (sup.module, name) name = "%s.%s" % (sup.module, name)
super.append(name) super.append(name)
s = s + "(%s)" % string.join(super, ", ") s = s + "(%s)" % string.join(super, ", ")
l.insert("end", s) self.append(s)
l.focus_set()
l.selection_clear(0, "end") def getname(self, index):
if self.botframe: name = self.listbox.get(index)
self.botframe.destroy() i = string.find(name, '(')
self.botframe = None if i >= 0:
self.methodviewer = None name = name[:i]
return name
def click_event(self, event): def getclass(self, index):
self.listbox.activate("@%d,%d" % (event.x, event.y)) return self.dict[self.getname(index)]
index = self.listbox.index("active")
def on_select(self, index):
self.show_methods(index) self.show_methods(index)
def double_click_event(self, event): def on_double(self, index):
self.listbox.activate("@%d,%d" % (event.x, event.y))
index = self.listbox.index("active")
self.show_source(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): def show_methods(self, index):
self.listbox.selection_clear(0, "end") cl = self.getclass(index)
self.listbox.selection_set(index) self.browser.show_methods(cl)
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: 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, master, flist):
ScrolledList.__init__(self, master)
def __init__(self, frame, flist):
self.frame = frame
self.flist = flist 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 classinfo = None
def loadmethods(self, cl): def load_methods(self, cl):
self.classinfo = cl self.classinfo = cl
self.helplabel.config(text="Methods of class %s" % cl.name) self.clear()
l = self.listbox
l.delete(0, "end")
l.selection_clear(0, "end")
items = [] items = []
for name, lineno in cl.methods.items(): for name, lineno in cl.methods.items():
items.append((lineno, name)) items.append((lineno, name))
items.sort() items.sort()
for item, name in items: for item, name in items:
l.insert("end", name) self.append(name)
def click_event(self, event): def click_event(self, event):
pass pass
def double_click_event(self, event): def on_double(self, index):
self.listbox.activate("@%d,%d" % (event.x, event.y)) self.show_source(self.get(index))
index = self.listbox.index("active")
self.show_source(index)
def up_event(self, event): def show_source(self, name):
pass if os.path.isfile(self.classinfo.file):
edit = self.flist.open(self.classinfo.file)
def down_event(self, event): edit.gotoline(self.classinfo.methods[name])
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])

128
Tools/idle/ScrolledList.py Normal file
View File

@ -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("<ButtonRelease-1>", self.click_event)
listbox.bind("<Double-ButtonRelease-1>", self.double_click_event)
listbox.bind("<ButtonPress-3>", self.popup_event)
listbox.bind("<Key-Up>", self.up_event)
listbox.bind("<Key-Down>", 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()