blob: 1224964c42e66868b12aede367a35d9d9753516a [file] [log] [blame]
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +00001"""Primitive class browser.
2
3XXX TO DO:
Guido van Rossum504b0bf1999-01-02 21:28:54 +00004
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +00005- generalize the scrolling listbox with some behavior into a base class
6- add popup menu with more options (e.g. doc strings, base classes, imports)
7- show function argument list (have to do pattern matching on source)
8- should the classes and methods lists also be in the module's menu bar?
9
10"""
11
Guido van Rossume6fae1c1998-10-15 23:27:08 +000012import os
Guido van Rossum439c4671998-10-13 03:59:57 +000013import string
14import pyclbr
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +000015from Tkinter import *
16import tkMessageBox
Guido van Rossum504b0bf1999-01-02 21:28:54 +000017from WindowList import ListedToplevel
Guido van Rossum439c4671998-10-13 03:59:57 +000018
Guido van Rossume6fae1c1998-10-15 23:27:08 +000019from ScrolledList import ScrolledList
20
21
Guido van Rossum439c4671998-10-13 03:59:57 +000022class ClassBrowser:
Guido van Rossum504b0bf1999-01-02 21:28:54 +000023
Guido van Rossum654387e1998-12-18 15:52:54 +000024 def __init__(self, flist, name, path=[]):
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +000025 root = flist.root
Guido van Rossum439c4671998-10-13 03:59:57 +000026 try:
Guido van Rossum654387e1998-12-18 15:52:54 +000027 dict = pyclbr.readmodule(name, path)
Guido van Rossum439c4671998-10-13 03:59:57 +000028 except ImportError, msg:
29 tkMessageBox.showerror("Import error", str(msg), parent=root)
30 return
31 if not dict:
32 tkMessageBox.showerror("Nothing to browse",
33 "Module %s defines no classes" % name, parent=root)
34 return
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +000035 self.flist = flist
36 self.dict = dict
Guido van Rossum439c4671998-10-13 03:59:57 +000037 self.root = root
Guido van Rossum504b0bf1999-01-02 21:28:54 +000038 self.top = top = ListedToplevel(root)
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +000039 self.top.protocol("WM_DELETE_WINDOW", self.close)
Guido van Rossum504b0bf1999-01-02 21:28:54 +000040 top.wm_title("Class Browser - " + name)
41 top.wm_iconname("ClBrowser")
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +000042 self.leftframe = leftframe = Frame(top)
43 self.leftframe.pack(side="left", fill="both", expand=1)
Guido van Rossum439c4671998-10-13 03:59:57 +000044 # Create help label
Guido van Rossume6fae1c1998-10-15 23:27:08 +000045 self.helplabel = Label(leftframe, text="Module %s" % name,
46 relief="groove", borderwidth=2)
Guido van Rossum439c4671998-10-13 03:59:57 +000047 self.helplabel.pack(fill="x")
48 # Create top frame, with scrollbar and listbox
Guido van Rossume6fae1c1998-10-15 23:27:08 +000049 self.classviewer = ClassViewer(
50 self.leftframe, self.flist, self)
Guido van Rossum439c4671998-10-13 03:59:57 +000051 # Load the classes
Guido van Rossume6fae1c1998-10-15 23:27:08 +000052 self.load_classes(dict, name)
Guido van Rossum504b0bf1999-01-02 21:28:54 +000053
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +000054 def close(self):
Guido van Rossume6fae1c1998-10-15 23:27:08 +000055 self.classviewer = None
56 self.methodviewer = None
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +000057 self.top.destroy()
Guido van Rossum504b0bf1999-01-02 21:28:54 +000058
Guido van Rossume6fae1c1998-10-15 23:27:08 +000059 def load_classes(self, dict, module):
60 self.classviewer.load_classes(dict, module)
61 if self.botframe:
62 self.botframe.destroy()
63 self.botframe = None
64 self.methodviewer = None
65
66 botframe = None
67 methodhelplabel = None
68 methodviewer = None
Guido van Rossum504b0bf1999-01-02 21:28:54 +000069
Guido van Rossume6fae1c1998-10-15 23:27:08 +000070 def show_methods(self, cl):
71 if not self.botframe:
72 self.botframe = Frame(self.top)
73 self.botframe.pack(side="right", expand=1, fill="both")
74 self.methodhelplabel = Label(self.botframe,
75 relief="groove", borderwidth=2)
76 self.methodhelplabel.pack(fill="x")
77 self.methodviewer = MethodViewer(self.botframe, self.flist)
78 self.methodhelplabel.config(text="Class %s" % cl.name)
79 self.methodviewer.load_methods(cl)
80
81
82class ClassViewer(ScrolledList):
Guido van Rossum504b0bf1999-01-02 21:28:54 +000083
Guido van Rossume6fae1c1998-10-15 23:27:08 +000084 def __init__(self, master, flist, browser):
85 ScrolledList.__init__(self, master)
86 self.flist = flist
87 self.browser = browser
Guido van Rossum504b0bf1999-01-02 21:28:54 +000088
Guido van Rossume6fae1c1998-10-15 23:27:08 +000089 def load_classes(self, dict, module):
90 self.clear()
91 self.dict = dict
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +000092 items = []
93 for key, value in dict.items():
94 if value.module == module:
95 items.append((value.lineno, key, value))
Guido van Rossum439c4671998-10-13 03:59:57 +000096 items.sort()
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +000097 for lineno, key, value in items:
Guido van Rossum439c4671998-10-13 03:59:57 +000098 s = key
99 if value.super:
100 super = []
101 for sup in value.super:
102 name = sup.name
103 if sup.module != value.module:
104 name = "%s.%s" % (sup.module, name)
105 super.append(name)
106 s = s + "(%s)" % string.join(super, ", ")
Guido van Rossume6fae1c1998-10-15 23:27:08 +0000107 self.append(s)
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000108
Guido van Rossume6fae1c1998-10-15 23:27:08 +0000109 def getname(self, index):
110 name = self.listbox.get(index)
111 i = string.find(name, '(')
112 if i >= 0:
113 name = name[:i]
114 return name
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +0000115
Guido van Rossume6fae1c1998-10-15 23:27:08 +0000116 def getclass(self, index):
117 return self.dict[self.getname(index)]
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000118
Guido van Rossume6fae1c1998-10-15 23:27:08 +0000119 def on_select(self, index):
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +0000120 self.show_methods(index)
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000121
Guido van Rossume6fae1c1998-10-15 23:27:08 +0000122 def on_double(self, index):
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +0000123 self.show_source(index)
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000124
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +0000125 def show_methods(self, index):
Guido van Rossume6fae1c1998-10-15 23:27:08 +0000126 cl = self.getclass(index)
127 self.browser.show_methods(cl)
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +0000128
Guido van Rossume6fae1c1998-10-15 23:27:08 +0000129 def show_source(self, index):
130 cl = self.getclass(index)
131 if os.path.isfile(cl.file):
132 edit = self.flist.open(cl.file)
133 edit.gotoline(cl.lineno)
134
135
136class MethodViewer(ScrolledList):
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000137
Guido van Rossume6fae1c1998-10-15 23:27:08 +0000138 def __init__(self, master, flist):
139 ScrolledList.__init__(self, master)
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +0000140 self.flist = flist
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000141
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +0000142 classinfo = None
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000143
Guido van Rossume6fae1c1998-10-15 23:27:08 +0000144 def load_methods(self, cl):
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +0000145 self.classinfo = cl
Guido van Rossume6fae1c1998-10-15 23:27:08 +0000146 self.clear()
Guido van Rossum7f5c9ef1998-10-13 16:31:03 +0000147 items = []
148 for name, lineno in cl.methods.items():
149 items.append((lineno, name))
150 items.sort()
151 for item, name in items:
Guido van Rossume6fae1c1998-10-15 23:27:08 +0000152 self.append(name)
Guido van Rossum439c4671998-10-13 03:59:57 +0000153
154 def click_event(self, event):
155 pass
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000156
Guido van Rossume6fae1c1998-10-15 23:27:08 +0000157 def on_double(self, index):
158 self.show_source(self.get(index))
Guido van Rossum504b0bf1999-01-02 21:28:54 +0000159
Guido van Rossume6fae1c1998-10-15 23:27:08 +0000160 def show_source(self, name):
161 if os.path.isfile(self.classinfo.file):
162 edit = self.flist.open(self.classinfo.file)
163 edit.gotoline(self.classinfo.methods[name])