]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wxPython/lib/PyCrust/filling.py
9a846b4def2776ed72f9242e81fb24c0d694a46c
1 """PyCrust Filling is the gui tree control through which a user can
2 navigate the local namespace or any object."""
4 __author__
= "Patrick K. O'Brien <pobrien@orbtech.com>"
6 __revision__
= "$Revision$"[11:-2]
8 from wxPython
import wx
9 from wxPython
import stc
10 from version
import VERSION
24 COMMONTYPES
= [getattr(types
, t
) for t
in dir(types
) \
25 if not t
.startswith('_') \
26 and t
not in ('ClassType', 'InstanceType', 'ModuleType')]
28 DOCTYPES
= ('BuiltinFunctionType', 'BuiltinMethodType', 'ClassType',
29 'FunctionType', 'GeneratorType', 'InstanceType',
30 'LambdaType', 'MethodType', 'ModuleType',
31 'UnboundMethodType', 'method-wrapper')
33 SIMPLETYPES
= [getattr(types
, t
) for t
in dir(types
) \
34 if not t
.startswith('_') and t
not in DOCTYPES
]
37 COMMONTYPES
.append(type(''.__repr
__)) # Method-wrapper in version 2.2.x.
38 except AttributeError:
42 class FillingTree(wx
.wxTreeCtrl
):
43 """PyCrust FillingTree based on wxTreeCtrl."""
45 name
= 'PyCrust Filling Tree'
46 revision
= __revision__
48 def __init__(self
, parent
, id=-1, pos
=wx
.wxDefaultPosition
,
49 size
=wx
.wxDefaultSize
, style
=wx
.wxTR_DEFAULT_STYLE
,
50 rootObject
=None, rootLabel
=None, rootIsNamespace
=0,
52 """Create a PyCrust FillingTree instance."""
53 wx
.wxTreeCtrl
.__init
__(self
, parent
, id, pos
, size
, style
)
54 self
.rootIsNamespace
= rootIsNamespace
56 if rootObject
is None:
57 rootObject
= __main__
.__dict
__
58 self
.rootIsNamespace
= 1
59 if rootObject
is __main__
.__dict
__ and rootLabel
is None:
60 rootLabel
= 'locals()'
62 rootLabel
= 'Ingredients'
63 rootData
= wx
.wxTreeItemData(rootObject
)
64 self
.item
= self
.root
= self
.AddRoot(rootLabel
, -1, -1, rootData
)
65 self
.SetItemHasChildren(self
.root
, self
.hasChildren(rootObject
))
66 wx
.EVT_TREE_ITEM_EXPANDING(self
, self
.GetId(), self
.OnItemExpanding
)
67 wx
.EVT_TREE_ITEM_COLLAPSED(self
, self
.GetId(), self
.OnItemCollapsed
)
68 wx
.EVT_TREE_SEL_CHANGED(self
, self
.GetId(), self
.OnSelChanged
)
69 wx
.EVT_TREE_ITEM_ACTIVATED(self
, self
.GetId(), self
.OnItemActivated
)
71 dispatcher
.connect(receiver
=self
.push
, signal
='Interpreter.push')
73 def push(self
, command
, more
):
74 """Receiver for Interpreter.push signal."""
77 def OnItemExpanding(self
, event
):
78 """Add children to the item."""
79 busy
= wx
.wxBusyCursor()
80 item
= event
.GetItem()
81 if self
.IsExpanded(item
):
83 self
.addChildren(item
)
84 # self.SelectItem(item)
86 def OnItemCollapsed(self
, event
):
87 """Remove all children from the item."""
88 busy
= wx
.wxBusyCursor()
89 item
= event
.GetItem()
90 # self.CollapseAndReset(item)
91 # self.DeleteChildren(item)
92 # self.SelectItem(item)
94 def OnSelChanged(self
, event
):
95 """Display information about the item."""
96 busy
= wx
.wxBusyCursor()
97 self
.item
= event
.GetItem()
100 def OnItemActivated(self
, event
):
101 """Launch a DirFrame."""
102 item
= event
.GetItem()
103 text
= self
.getFullName(item
)
104 obj
= self
.GetPyData(item
)
105 frame
= FillingFrame(parent
=self
, size
=(600, 100), rootObject
=obj
,
106 rootLabel
=text
, rootIsNamespace
=False)
109 def hasChildren(self
, obj
):
110 """Return true if object has children."""
111 if self
.getChildren(obj
):
116 def getChildren(self
, obj
):
117 """Return dictionary with attributes or contents of object."""
118 busy
= wx
.wxBusyCursor()
120 if otype
is types
.DictType \
121 or str(otype
)[17:23] == 'BTrees' and hasattr(obj
, 'keys'):
124 if otype
is types
.ListType
or otype
is types
.TupleType
:
125 for n
in range(len(obj
)):
126 key
= '[' + str(n
) + ']'
128 if otype
not in COMMONTYPES
:
129 for key
in introspect
.getAttributeNames(obj
):
130 # Believe it or not, some attributes can disappear,
131 # such as the exc_traceback attribute of the sys
132 # module. So this is nested in a try block.
134 d
[key
] = getattr(obj
, key
)
139 def addChildren(self
, item
):
140 self
.DeleteChildren(item
)
141 obj
= self
.GetPyData(item
)
142 children
= self
.getChildren(obj
)
145 keys
= children
.keys()
146 keys
.sort(lambda x
, y
: cmp(x
.lower(), y
.lower()))
149 # Show string dictionary items with single quotes, except
150 # for the first level of items, if they represent a
152 if type(obj
) is types
.DictType \
153 and type(key
) is types
.StringType \
154 and (item
!= self
.root \
155 or (item
== self
.root
and not self
.rootIsNamespace
)):
157 child
= children
[key
]
158 data
= wx
.wxTreeItemData(child
)
159 branch
= self
.AppendItem(parent
=item
, text
=itemtext
, data
=data
)
160 self
.SetItemHasChildren(branch
, self
.hasChildren(child
))
164 if self
.IsExpanded(item
):
165 self
.addChildren(item
)
167 obj
= self
.GetPyData(item
)
168 if obj
is None: # Windows bug fix.
170 self
.SetItemHasChildren(item
, self
.hasChildren(obj
))
173 text
+= self
.getFullName(item
)
174 text
+= '\n\nType: ' + str(otype
)
179 if otype
is types
.StringType
or otype
is types
.UnicodeType
:
181 text
+= '\n\nValue: ' + value
182 if otype
not in SIMPLETYPES
:
184 text
+= '\n\nDocstring:\n\n"""' + \
185 inspect
.getdoc(obj
).strip() + '"""'
188 if otype
is types
.InstanceType
:
190 text
+= '\n\nClass Definition:\n\n' + \
191 inspect
.getsource(obj
.__class
__)
196 text
+= '\n\nSource Code:\n\n' + \
197 inspect
.getsource(obj
)
202 def getFullName(self
, item
, partial
=''):
203 """Return a syntactically proper name for item."""
204 name
= self
.GetItemText(item
)
207 if item
!= self
.root
:
208 parent
= self
.GetItemParent(item
)
209 obj
= self
.GetPyData(parent
)
210 # Apply dictionary syntax to dictionary items, except the root
211 # and first level children of a namepace.
212 if (type(obj
) is types
.DictType \
213 or str(type(obj
))[17:23] == 'BTrees' \
214 and hasattr(obj
, 'keys')) \
215 and ((item
!= self
.root
and parent
!= self
.root
) \
216 or (parent
== self
.root
and not self
.rootIsNamespace
)):
217 name
= '[' + name
+ ']'
218 # Apply dot syntax to multipart names.
220 if partial
[0] == '[':
223 name
+= '.' + partial
224 # Repeat for everything but the root item
225 # and first level children of a namespace.
226 if (item
!= self
.root
and parent
!= self
.root
) \
227 or (parent
== self
.root
and not self
.rootIsNamespace
):
228 name
= self
.getFullName(parent
, partial
=name
)
231 def setText(self
, text
):
232 """Display information about the current selection."""
234 # This method will likely be replaced by the enclosing app to
235 # do something more interesting, like write to a text control.
238 def setStatusText(self
, text
):
239 """Display status information."""
241 # This method will likely be replaced by the enclosing app to
242 # do something more interesting, like write to a status bar.
246 if wx
.wxPlatform
== '__WXMSW__':
247 faces
= { 'times' : 'Times New Roman',
248 'mono' : 'Courier New',
249 'helv' : 'Lucida Console',
250 'lucida' : 'Lucida Console',
251 'other' : 'Comic Sans MS',
254 'backcol': '#FFFFFF',
257 faces
= { 'times' : 'Times',
259 'helv' : 'Helvetica',
260 'other' : 'new century schoolbook',
263 'backcol': '#FFFFFF',
267 class FillingText(stc
.wxStyledTextCtrl
):
268 """PyCrust FillingText based on wxStyledTextCtrl."""
270 name
= 'PyCrust Filling Text'
271 revision
= __revision__
273 def __init__(self
, parent
, id=-1, pos
=wx
.wxDefaultPosition
,
274 size
=wx
.wxDefaultSize
, style
=wx
.wxCLIP_CHILDREN
,
276 """Create a PyCrust FillingText instance."""
277 stc
.wxStyledTextCtrl
.__init
__(self
, parent
, id, pos
, size
, style
)
278 # Configure various defaults and user preferences.
280 dispatcher
.connect(receiver
=self
.fontsizer
, signal
='FontIncrease')
281 dispatcher
.connect(receiver
=self
.fontsizer
, signal
='FontDecrease')
282 dispatcher
.connect(receiver
=self
.fontsizer
, signal
='FontDefault')
284 dispatcher
.connect(receiver
=self
.push
, signal
='Interpreter.push')
286 def push(self
, command
, more
):
287 """Receiver for Interpreter.push signal."""
290 def fontsizer(self
, signal
):
291 """Receiver for Font* signals."""
292 size
= self
.GetZoom()
293 if signal
== 'FontIncrease':
295 elif signal
== 'FontDecrease':
297 elif signal
== 'FontDefault':
302 """Configure shell based on user preferences."""
303 self
.SetMarginWidth(1, 0)
305 self
.SetLexer(stc
.wxSTC_LEX_PYTHON
)
306 self
.SetKeyWords(0, ' '.join(keyword
.kwlist
))
308 self
.setStyles(faces
)
309 self
.SetViewWhiteSpace(0)
315 except AttributeError:
318 def setStyles(self
, faces
):
319 """Configure font size, typeface and color for lexer."""
322 self
.StyleSetSpec(stc
.wxSTC_STYLE_DEFAULT
,
323 "face:%(mono)s,size:%(size)d" % faces
)
328 self
.StyleSetSpec(stc
.wxSTC_STYLE_LINENUMBER
,
329 "back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % faces
)
330 self
.StyleSetSpec(stc
.wxSTC_STYLE_CONTROLCHAR
,
331 "face:%(mono)s" % faces
)
332 self
.StyleSetSpec(stc
.wxSTC_STYLE_BRACELIGHT
,
333 "fore:#0000FF,back:#FFFF88")
334 self
.StyleSetSpec(stc
.wxSTC_STYLE_BRACEBAD
,
335 "fore:#FF0000,back:#FFFF88")
338 self
.StyleSetSpec(stc
.wxSTC_P_DEFAULT
,
339 "face:%(mono)s" % faces
)
340 self
.StyleSetSpec(stc
.wxSTC_P_COMMENTLINE
,
341 "fore:#007F00,face:%(mono)s" % faces
)
342 self
.StyleSetSpec(stc
.wxSTC_P_NUMBER
,
344 self
.StyleSetSpec(stc
.wxSTC_P_STRING
,
345 "fore:#7F007F,face:%(mono)s" % faces
)
346 self
.StyleSetSpec(stc
.wxSTC_P_CHARACTER
,
347 "fore:#7F007F,face:%(mono)s" % faces
)
348 self
.StyleSetSpec(stc
.wxSTC_P_WORD
,
350 self
.StyleSetSpec(stc
.wxSTC_P_TRIPLE
,
352 self
.StyleSetSpec(stc
.wxSTC_P_TRIPLEDOUBLE
,
353 "fore:#000033,back:#FFFFE8")
354 self
.StyleSetSpec(stc
.wxSTC_P_CLASSNAME
,
356 self
.StyleSetSpec(stc
.wxSTC_P_DEFNAME
,
358 self
.StyleSetSpec(stc
.wxSTC_P_OPERATOR
,
360 self
.StyleSetSpec(stc
.wxSTC_P_IDENTIFIER
,
362 self
.StyleSetSpec(stc
.wxSTC_P_COMMENTBLOCK
,
364 self
.StyleSetSpec(stc
.wxSTC_P_STRINGEOL
,
365 "fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces
)
367 def SetText(self
, *args
, **kwds
):
369 stc
.wxStyledTextCtrl
.SetText(self
, *args
, **kwds
)
373 class Filling(wx
.wxSplitterWindow
):
374 """PyCrust Filling based on wxSplitterWindow."""
376 name
= 'PyCrust Filling'
377 revision
= __revision__
379 def __init__(self
, parent
, id=-1, pos
=wx
.wxDefaultPosition
,
380 size
=wx
.wxDefaultSize
, style
=wx
.wxSP_3D
,
381 name
='Filling Window', rootObject
=None,
382 rootLabel
=None, rootIsNamespace
=0, static
=False):
383 """Create a PyCrust Filling instance."""
384 wx
.wxSplitterWindow
.__init
__(self
, parent
, id, pos
, size
, style
, name
)
385 self
.tree
= FillingTree(parent
=self
, rootObject
=rootObject
,
387 rootIsNamespace
=rootIsNamespace
,
389 self
.text
= FillingText(parent
=self
, static
=static
)
390 self
.SplitVertically(self
.tree
, self
.text
, 200)
391 self
.SetMinimumPaneSize(1)
392 # Override the filling so that descriptions go to FillingText.
393 self
.tree
.setText
= self
.text
.SetText
394 # Display the root item.
395 ## self.tree.SelectItem(self.tree.root)
399 class FillingFrame(wx
.wxFrame
):
400 """Frame containing the PyCrust filling, or namespace tree component."""
402 name
= 'PyCrust Filling Frame'
403 revision
= __revision__
405 def __init__(self
, parent
=None, id=-1, title
='PyFilling',
406 pos
=wx
.wxDefaultPosition
, size
=wx
.wxDefaultSize
,
407 style
=wx
.wxDEFAULT_FRAME_STYLE
, rootObject
=None,
408 rootLabel
=None, rootIsNamespace
=0, static
=False):
409 """Create a PyCrust FillingFrame instance."""
410 wx
.wxFrame
.__init
__(self
, parent
, id, title
, pos
, size
, style
)
411 intro
= 'PyFilling - The Tastiest Namespace Inspector'
412 self
.CreateStatusBar()
413 self
.SetStatusText(intro
)
415 self
.SetIcon(images
.getPyCrustIcon())
416 self
.filling
= Filling(parent
=self
, rootObject
=rootObject
,
418 rootIsNamespace
=rootIsNamespace
,
420 # Override so that status messages go to the status bar.
421 self
.filling
.tree
.setStatusText
= self
.SetStatusText
425 """PyFilling standalone application."""
428 wx
.wxInitAllImageHandlers()
429 self
.fillingFrame
= FillingFrame()
430 self
.fillingFrame
.Show(True)
431 self
.SetTopWindow(self
.fillingFrame
)