mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +00:00 
			
		
		
		
	Much improved, much left to do.
This commit is contained in:
		
							parent
							
								
									e73d702344
								
							
						
					
					
						commit
						7f5c9ef5fd
					
				
					 1 changed files with 153 additions and 11 deletions
				
			
		| 
						 | 
					@ -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 string
 | 
				
			||||||
import pyclbr
 | 
					import pyclbr
 | 
				
			||||||
 | 
					from Tkinter import *
 | 
				
			||||||
 | 
					import tkMessageBox
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ClassBrowser:
 | 
					class ClassBrowser:
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    def __init__(self, root, name):
 | 
					    def __init__(self, flist, name):
 | 
				
			||||||
 | 
					        root = flist.root
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            dict = pyclbr.readmodule(name)
 | 
					            dict = pyclbr.readmodule(name)
 | 
				
			||||||
        except ImportError, msg:
 | 
					        except ImportError, msg:
 | 
				
			||||||
| 
						 | 
					@ -14,20 +27,26 @@ class ClassBrowser:
 | 
				
			||||||
            tkMessageBox.showerror("Nothing to browse",
 | 
					            tkMessageBox.showerror("Nothing to browse",
 | 
				
			||||||
                "Module %s defines no classes" % name, parent=root)
 | 
					                "Module %s defines no classes" % name, parent=root)
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					        self.flist = flist
 | 
				
			||||||
 | 
					        self.dict = dict
 | 
				
			||||||
        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.leftframe = leftframe = Frame(top)
 | 
				
			||||||
 | 
					        self.leftframe.pack(side="left", fill="both", expand=1)
 | 
				
			||||||
 | 
					        top.wm_title("Class browser")
 | 
				
			||||||
        # Create help label
 | 
					        # Create help label
 | 
				
			||||||
        self.helplabel = Label(top,
 | 
					        self.helplabel = Label(leftframe,
 | 
				
			||||||
            text="Classes in module %s" % name,
 | 
					            text="Classes in module %s" % name,
 | 
				
			||||||
            borderwidth=2, relief="groove")
 | 
					            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(top)
 | 
					        self.topframe = Frame(leftframe)
 | 
				
			||||||
        self.topframe.pack(fill="both", expand=1)
 | 
					        self.topframe.pack(fill="both", expand=1)
 | 
				
			||||||
        self.vbar = Scrollbar(self.topframe, name="vbar")
 | 
					        self.vbar = Scrollbar(self.topframe, name="vbar")
 | 
				
			||||||
        self.vbar.pack(side="right", fill="y")
 | 
					        self.vbar.pack(side="right", fill="y")
 | 
				
			||||||
        self.listbox = Listbox(self.topframe, exportselection=0, 
 | 
					        self.listbox = Listbox(self.topframe, exportselection=0, 
 | 
				
			||||||
                               takefocus=1, width=60)
 | 
					                               takefocus=1, width=30)
 | 
				
			||||||
        self.listbox.pack(expand=1, fill="both")
 | 
					        self.listbox.pack(expand=1, fill="both")
 | 
				
			||||||
        # Tie listbox and scrollbar together
 | 
					        # Tie listbox and scrollbar together
 | 
				
			||||||
        self.vbar["command"] = self.listbox.yview
 | 
					        self.vbar["command"] = self.listbox.yview
 | 
				
			||||||
| 
						 | 
					@ -39,13 +58,19 @@ class ClassBrowser:
 | 
				
			||||||
        self.listbox.bind("<Key-Up>", self.up_event)
 | 
					        self.listbox.bind("<Key-Up>", self.up_event)
 | 
				
			||||||
        self.listbox.bind("<Key-Down>", self.down_event)
 | 
					        self.listbox.bind("<Key-Down>", self.down_event)
 | 
				
			||||||
        # Load the classes
 | 
					        # Load the classes
 | 
				
			||||||
        self.loadclasses(dict)
 | 
					        self.loadclasses(dict, name)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    def loadclasses(self, dict):
 | 
					    def close(self):
 | 
				
			||||||
        items = dict.items()
 | 
					        self.top.destroy()
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    def loadclasses(self, dict, module):
 | 
				
			||||||
 | 
					        items = []
 | 
				
			||||||
 | 
					        for key, value in dict.items():
 | 
				
			||||||
 | 
					            if value.module == module:
 | 
				
			||||||
 | 
					                items.append((value.lineno, key, value))
 | 
				
			||||||
        items.sort()
 | 
					        items.sort()
 | 
				
			||||||
        l = self.listbox
 | 
					        l = self.listbox
 | 
				
			||||||
        for key, value in items:
 | 
					        for lineno, key, value in items:
 | 
				
			||||||
            s = key
 | 
					            s = key
 | 
				
			||||||
            if value.super:
 | 
					            if value.super:
 | 
				
			||||||
                super = []
 | 
					                super = []
 | 
				
			||||||
| 
						 | 
					@ -55,16 +80,133 @@ 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)
 | 
					            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):
 | 
				
			||||||
 | 
					        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):
 | 
					    def click_event(self, event):
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    def double_click_event(self, event):
 | 
					    def double_click_event(self, event):
 | 
				
			||||||
        pass
 | 
					        self.listbox.activate("@%d,%d" % (event.x, event.y))
 | 
				
			||||||
 | 
					        index = self.listbox.index("active")
 | 
				
			||||||
 | 
					        self.show_source(index)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    def up_event(self, event):
 | 
					    def up_event(self, event):
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    def down_event(self, event):
 | 
					    def down_event(self, event):
 | 
				
			||||||
        pass
 | 
					        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])
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue