5 - reparse when source changed (maybe just a button would be OK?)
6 (or recheck on window popup)
7 - add popup menu with more options (e.g. doc strings, base classes, imports)
8 - show function argument list? (have to do pattern matching on source)
9 - should the classes and methods lists also be in the module's menu bar?
10 - add base classes to class browser tree
18 from WindowList
import ListedToplevel
19 from TreeWidget
import TreeNode
, TreeItem
, ScrolledCanvas
20 from configHandler
import idleConf
24 def __init__(self
, flist
, name
, path
):
25 # XXX This API should change, if the file doesn't end in ".py"
26 # XXX the code here is bogus!
28 self
.file = os
.path
.join(path
[0], self
.name
+ ".py")
31 def close(self
, event
=None):
35 def init(self
, flist
):
38 pyclbr
._modules
.clear()
40 self
.top
= top
= ListedToplevel(flist
.root
)
41 top
.protocol("WM_DELETE_WINDOW", self
.close
)
42 top
.bind("<Escape>", self
.close
)
45 # create scrolled canvas
46 theme
= idleConf
.GetOption('main','Theme','name')
47 background
= idleConf
.GetHighlight(theme
, 'normal')['background']
48 sc
= ScrolledCanvas(top
, bg
=background
, highlightthickness
=0, takefocus
=1)
49 sc
.frame
.pack(expand
=1, fill
="both")
50 item
= self
.rootnode()
51 self
.node
= node
= TreeNode(sc
.canvas
, None, item
)
56 self
.top
.wm_title("Class Browser - " + self
.name
)
57 self
.top
.wm_iconname("Class Browser")
60 return ModuleBrowserTreeItem(self
.file)
62 class ModuleBrowserTreeItem(TreeItem
):
64 def __init__(self
, file):
68 return os
.path
.basename(self
.file)
70 def GetIconName(self
):
75 for name
in self
.listclasses():
76 item
= ClassBrowserTreeItem(name
, self
.classes
, self
.file)
80 def OnDoubleClick(self
):
81 if os
.path
.normcase(self
.file[-3:]) != ".py":
83 if not os
.path
.exists(self
.file):
85 PyShell
.flist
.open(self
.file)
87 def IsExpandable(self
):
88 return os
.path
.normcase(self
.file[-3:]) == ".py"
90 def listclasses(self
):
91 dir, file = os
.path
.split(self
.file)
92 name
, ext
= os
.path
.splitext(file)
93 if os
.path
.normcase(ext
) != ".py":
96 dict = pyclbr
.readmodule_ex(name
, [dir] + sys
.path
)
97 except ImportError, msg
:
101 for key
, cl
in dict.items():
102 if cl
.module
== name
:
104 if hasattr(cl
, 'super') and cl
.super:
107 if type(sup
) is type(''):
111 if sup
.module
!= cl
.module
:
112 sname
= "%s.%s" % (sup
.module
, sname
)
114 s
= s
+ "(%s)" % ", ".join(supers
)
115 items
.append((cl
.lineno
, s
))
119 for item
, s
in items
:
123 class ClassBrowserTreeItem(TreeItem
):
125 def __init__(self
, name
, classes
, file):
127 self
.classes
= classes
130 self
.cl
= self
.classes
[self
.name
]
131 except (IndexError, KeyError):
133 self
.isfunction
= isinstance(self
.cl
, pyclbr
.Function
)
137 return "def " + self
.name
+ "(...)"
139 return "class " + self
.name
141 def GetIconName(self
):
147 def IsExpandable(self
):
150 return not not self
.cl
.methods
151 except AttributeError:
154 def GetSubList(self
):
158 for name
in self
.listmethods():
159 item
= MethodBrowserTreeItem(name
, self
.cl
, self
.file)
163 def OnDoubleClick(self
):
164 if not os
.path
.exists(self
.file):
166 edit
= PyShell
.flist
.open(self
.file)
167 if hasattr(self
.cl
, 'lineno'):
168 lineno
= self
.cl
.lineno
169 edit
.gotoline(lineno
)
171 def listmethods(self
):
175 for name
, lineno
in self
.cl
.methods
.items():
176 items
.append((lineno
, name
))
179 for item
, name
in items
:
183 class MethodBrowserTreeItem(TreeItem
):
185 def __init__(self
, name
, cl
, file):
191 return "def " + self
.name
+ "(...)"
193 def GetIconName(self
):
194 return "python" # XXX
196 def IsExpandable(self
):
199 def OnDoubleClick(self
):
200 if not os
.path
.exists(self
.file):
202 edit
= PyShell
.flist
.open(self
.file)
203 edit
.gotoline(self
.cl
.methods
[self
.name
])
214 dir, file = os
.path
.split(file)
215 name
= os
.path
.splitext(file)[0]
216 ClassBrowser(PyShell
.flist
, name
, [dir])
217 if sys
.stdin
is sys
.__stdin
__:
220 if __name__
== "__main__":