]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/py/filling.py
1 """Filling is the gui tree control through which a user can navigate
2 the local namespace or any object."""
4 __author__
= "Patrick K. O'Brien <pobrien@orbtech.com>"
6 __revision__
= "$Revision$"[11:-2]
17 from version
import VERSION
25 COMMONTYPES
= [getattr(types
, t
) for t
in dir(types
) \
26 if not t
.startswith('_') \
27 and t
not in ('ClassType', 'InstanceType', 'ModuleType')]
29 DOCTYPES
= ('BuiltinFunctionType', 'BuiltinMethodType', 'ClassType',
30 'FunctionType', 'GeneratorType', 'InstanceType',
31 'LambdaType', 'MethodType', 'ModuleType',
32 'UnboundMethodType', 'method-wrapper')
34 SIMPLETYPES
= [getattr(types
, t
) for t
in dir(types
) \
35 if not t
.startswith('_') and t
not in DOCTYPES
]
40 COMMONTYPES
.append(type(''.__repr
__)) # Method-wrapper in version 2.2.x.
41 except AttributeError:
45 class FillingTree(wx
.TreeCtrl
):
46 """FillingTree based on TreeCtrl."""
49 revision
= __revision__
51 def __init__(self
, parent
, id=-1, pos
=wx
.DefaultPosition
,
52 size
=wx
.DefaultSize
, style
=wx
.TR_DEFAULT_STYLE
,
53 rootObject
=None, rootLabel
=None, rootIsNamespace
=False,
55 """Create FillingTree instance."""
56 wx
.TreeCtrl
.__init
__(self
, parent
, id, pos
, size
, style
)
57 self
.rootIsNamespace
= rootIsNamespace
59 if rootObject
is None:
60 rootObject
= __main__
.__dict
__
61 self
.rootIsNamespace
= True
62 if rootObject
is __main__
.__dict
__ and rootLabel
is None:
63 rootLabel
= 'locals()'
65 rootLabel
= 'Ingredients'
66 rootData
= wx
.TreeItemData(rootObject
)
67 self
.item
= self
.root
= self
.AddRoot(rootLabel
, -1, -1, rootData
)
68 self
.SetItemHasChildren(self
.root
, self
.objHasChildren(rootObject
))
69 wx
.EVT_TREE_ITEM_EXPANDING(self
, self
.GetId(), self
.OnItemExpanding
)
70 wx
.EVT_TREE_ITEM_COLLAPSED(self
, self
.GetId(), self
.OnItemCollapsed
)
71 wx
.EVT_TREE_SEL_CHANGED(self
, self
.GetId(), self
.OnSelChanged
)
72 wx
.EVT_TREE_ITEM_ACTIVATED(self
, self
.GetId(), self
.OnItemActivated
)
74 dispatcher
.connect(receiver
=self
.push
, signal
='Interpreter.push')
76 def push(self
, command
, more
):
77 """Receiver for Interpreter.push signal."""
80 def OnItemExpanding(self
, event
):
81 """Add children to the item."""
82 busy
= wx
.BusyCursor()
83 item
= event
.GetItem()
84 if self
.IsExpanded(item
):
86 self
.addChildren(item
)
87 # self.SelectItem(item)
89 def OnItemCollapsed(self
, event
):
90 """Remove all children from the item."""
91 busy
= wx
.BusyCursor()
92 item
= event
.GetItem()
93 # self.CollapseAndReset(item)
94 # self.DeleteChildren(item)
95 # self.SelectItem(item)
97 def OnSelChanged(self
, event
):
98 """Display information about the item."""
99 busy
= wx
.BusyCursor()
100 self
.item
= event
.GetItem()
103 def OnItemActivated(self
, event
):
104 """Launch a DirFrame."""
105 item
= event
.GetItem()
106 text
= self
.getFullName(item
)
107 obj
= self
.GetPyData(item
)
108 frame
= FillingFrame(parent
=self
, size
=(600, 100), rootObject
=obj
,
109 rootLabel
=text
, rootIsNamespace
=False)
112 def objHasChildren(self
, obj
):
113 """Return true if object has children."""
114 if self
.objGetChildren(obj
):
119 def objGetChildren(self
, obj
):
120 """Return dictionary with attributes or contents of object."""
121 busy
= wx
.BusyCursor()
123 if otype
is types
.DictType \
124 or str(otype
)[17:23] == 'BTrees' and hasattr(obj
, 'keys'):
127 if otype
is types
.ListType
or otype
is types
.TupleType
:
128 for n
in range(len(obj
)):
129 key
= '[' + str(n
) + ']'
131 if otype
not in COMMONTYPES
:
132 for key
in introspect
.getAttributeNames(obj
):
133 # Believe it or not, some attributes can disappear,
134 # such as the exc_traceback attribute of the sys
135 # module. So this is nested in a try block.
137 d
[key
] = getattr(obj
, key
)
142 def addChildren(self
, item
):
143 self
.DeleteChildren(item
)
144 obj
= self
.GetPyData(item
)
145 children
= self
.objGetChildren(obj
)
148 keys
= children
.keys()
149 keys
.sort(lambda x
, y
: cmp(str(x
).lower(), str(y
).lower()))
152 # Show string dictionary items with single quotes, except
153 # for the first level of items, if they represent a
155 if type(obj
) is types
.DictType \
156 and type(key
) is types
.StringType \
157 and (item
!= self
.root \
158 or (item
== self
.root
and not self
.rootIsNamespace
)):
160 child
= children
[key
]
161 data
= wx
.TreeItemData(child
)
162 branch
= self
.AppendItem(parent
=item
, text
=itemtext
, data
=data
)
163 self
.SetItemHasChildren(branch
, self
.objHasChildren(child
))
167 if self
.IsExpanded(item
):
168 self
.addChildren(item
)
170 obj
= self
.GetPyData(item
)
171 if wx
.Platform
== '__WXMSW__':
172 if obj
is None: # Windows bug fix.
174 self
.SetItemHasChildren(item
, self
.objHasChildren(obj
))
177 text
+= self
.getFullName(item
)
178 text
+= '\n\nType: ' + str(otype
)
183 if otype
is types
.StringType
or otype
is types
.UnicodeType
:
185 text
+= '\n\nValue: ' + value
186 if otype
not in SIMPLETYPES
:
188 text
+= '\n\nDocstring:\n\n"""' + \
189 inspect
.getdoc(obj
).strip() + '"""'
192 if otype
is types
.InstanceType
:
194 text
+= '\n\nClass Definition:\n\n' + \
195 inspect
.getsource(obj
.__class
__)
200 text
+= '\n\nSource Code:\n\n' + \
201 inspect
.getsource(obj
)
206 def getFullName(self
, item
, partial
=''):
207 """Return a syntactically proper name for item."""
208 name
= self
.GetItemText(item
)
211 if item
!= self
.root
:
212 parent
= self
.GetItemParent(item
)
213 obj
= self
.GetPyData(parent
)
214 # Apply dictionary syntax to dictionary items, except the root
215 # and first level children of a namepace.
216 if (type(obj
) is types
.DictType \
217 or str(type(obj
))[17:23] == 'BTrees' \
218 and hasattr(obj
, 'keys')) \
219 and ((item
!= self
.root
and parent
!= self
.root
) \
220 or (parent
== self
.root
and not self
.rootIsNamespace
)):
221 name
= '[' + name
+ ']'
222 # Apply dot syntax to multipart names.
224 if partial
[0] == '[':
227 name
+= '.' + partial
228 # Repeat for everything but the root item
229 # and first level children of a namespace.
230 if (item
!= self
.root
and parent
!= self
.root
) \
231 or (parent
== self
.root
and not self
.rootIsNamespace
):
232 name
= self
.getFullName(parent
, partial
=name
)
235 def setText(self
, text
):
236 """Display information about the current selection."""
238 # This method will likely be replaced by the enclosing app to
239 # do something more interesting, like write to a text control.
242 def setStatusText(self
, text
):
243 """Display status information."""
245 # This method will likely be replaced by the enclosing app to
246 # do something more interesting, like write to a status bar.
250 class FillingText(editwindow
.EditWindow
):
251 """FillingText based on StyledTextCtrl."""
253 name
= 'Filling Text'
254 revision
= __revision__
256 def __init__(self
, parent
, id=-1, pos
=wx
.DefaultPosition
,
257 size
=wx
.DefaultSize
, style
=wx
.CLIP_CHILDREN
,
259 """Create FillingText instance."""
260 editwindow
.EditWindow
.__init
__(self
, parent
, id, pos
, size
, style
)
261 # Configure various defaults and user preferences.
262 self
.SetReadOnly(True)
263 self
.SetWrapMode(True)
264 self
.SetMarginWidth(1, 0)
266 dispatcher
.connect(receiver
=self
.push
, signal
='Interpreter.push')
268 def push(self
, command
, more
):
269 """Receiver for Interpreter.push signal."""
272 def SetText(self
, *args
, **kwds
):
273 self
.SetReadOnly(False)
274 editwindow
.EditWindow
.SetText(self
, *args
, **kwds
)
275 self
.SetReadOnly(True)
278 class Filling(wx
.SplitterWindow
):
279 """Filling based on wxSplitterWindow."""
282 revision
= __revision__
284 def __init__(self
, parent
, id=-1, pos
=wx
.DefaultPosition
,
285 size
=wx
.DefaultSize
, style
=wx
.SP_3D
,
286 name
='Filling Window', rootObject
=None,
287 rootLabel
=None, rootIsNamespace
=False, static
=False):
288 """Create a Filling instance."""
289 wx
.SplitterWindow
.__init
__(self
, parent
, id, pos
, size
, style
, name
)
290 self
.tree
= FillingTree(parent
=self
, rootObject
=rootObject
,
292 rootIsNamespace
=rootIsNamespace
,
294 self
.text
= FillingText(parent
=self
, static
=static
)
295 self
.SplitVertically(self
.tree
, self
.text
, 130)
296 self
.SetMinimumPaneSize(1)
297 # Override the filling so that descriptions go to FillingText.
298 self
.tree
.setText
= self
.text
.SetText
299 # Display the root item.
300 ## self.tree.SelectItem(self.tree.root)
304 class FillingFrame(wx
.Frame
):
305 """Frame containing the namespace tree component."""
307 name
= 'Filling Frame'
308 revision
= __revision__
310 def __init__(self
, parent
=None, id=-1, title
='PyFilling',
311 pos
=wx
.DefaultPosition
, size
=(600, 400),
312 style
=wx
.DEFAULT_FRAME_STYLE
, rootObject
=None,
313 rootLabel
=None, rootIsNamespace
=False, static
=False):
314 """Create FillingFrame instance."""
315 wx
.Frame
.__init
__(self
, parent
, id, title
, pos
, size
, style
)
316 intro
= 'PyFilling - The Tastiest Namespace Inspector'
317 self
.CreateStatusBar()
318 self
.SetStatusText(intro
)
320 self
.SetIcon(images
.getPyIcon())
321 self
.filling
= Filling(parent
=self
, rootObject
=rootObject
,
323 rootIsNamespace
=rootIsNamespace
,
325 # Override so that status messages go to the status bar.
326 self
.filling
.tree
.setStatusText
= self
.SetStatusText
330 """PyFilling standalone application."""
333 wx
.InitAllImageHandlers()
334 self
.fillingFrame
= FillingFrame()
335 self
.fillingFrame
.Show(True)
336 self
.SetTopWindow(self
.fillingFrame
)