]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/py/crust.py
guarding against calls in the destruction sequence of a window
[wxWidgets.git] / wxPython / wx / py / crust.py
1 """Crust combines the shell and filling into one control."""
2
3 __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
4 __cvsid__ = "$Id$"
5 __revision__ = "$Revision$"[11:-2]
6
7 import wx
8
9 import os
10 import pprint
11 import sys
12
13 import dispatcher
14 import editwindow
15 from filling import Filling
16 import frame
17 from shell import Shell
18 from version import VERSION
19
20
21 class Crust(wx.SplitterWindow):
22 """Crust based on SplitterWindow."""
23
24 name = 'Crust'
25 revision = __revision__
26
27 def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
28 size=wx.DefaultSize, style=wx.SP_3D,
29 name='Crust Window', rootObject=None, rootLabel=None,
30 rootIsNamespace=True, intro='', locals=None,
31 InterpClass=None, *args, **kwds):
32 """Create Crust instance."""
33 wx.SplitterWindow.__init__(self, parent, id, pos, size, style, name)
34 self.shell = Shell(parent=self, introText=intro,
35 locals=locals, InterpClass=InterpClass,
36 *args, **kwds)
37 self.editor = self.shell
38 if rootObject is None:
39 rootObject = self.shell.interp.locals
40 self.notebook = wx.Notebook(parent=self, id=-1)
41 self.shell.interp.locals['notebook'] = self.notebook
42 self.filling = Filling(parent=self.notebook,
43 rootObject=rootObject,
44 rootLabel=rootLabel,
45 rootIsNamespace=rootIsNamespace)
46 # Add 'filling' to the interpreter's locals.
47 self.shell.interp.locals['filling'] = self.filling
48 self.notebook.AddPage(page=self.filling, text='Namespace', select=True)
49 self.display = Display(parent=self.notebook)
50 self.notebook.AddPage(page=self.display, text='Display')
51 # Add 'pp' (pretty print) to the interpreter's locals.
52 self.shell.interp.locals['pp'] = self.display.setItem
53 self.calltip = Calltip(parent=self.notebook)
54 self.notebook.AddPage(page=self.calltip, text='Calltip')
55 self.sessionlisting = SessionListing(parent=self.notebook)
56 self.notebook.AddPage(page=self.sessionlisting, text='Session')
57 self.dispatcherlisting = DispatcherListing(parent=self.notebook)
58 self.notebook.AddPage(page=self.dispatcherlisting, text='Dispatcher')
59 ## from wxd import wx_
60 ## self.wxdocs = Filling(parent=self.notebook,
61 ## rootObject=wx_,
62 ## rootLabel='wx',
63 ## rootIsNamespace=False,
64 ## static=True)
65 ## self.notebook.AddPage(page=self.wxdocs, text='wxPython Docs')
66 ## from wxd import stc_
67 ## self.stcdocs = Filling(parent=self.notebook,
68 ## rootObject=stc_.StyledTextCtrl,
69 ## rootLabel='StyledTextCtrl',
70 ## rootIsNamespace=False,
71 ## static=True)
72 ## self.notebook.AddPage(page=self.stcdocs, text='StyledTextCtrl Docs')
73 self.SplitHorizontally(self.shell, self.notebook, 300)
74 self.SetMinimumPaneSize(1)
75
76
77 class Display(editwindow.EditWindow):
78 """STC used to display an object using Pretty Print."""
79
80 def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
81 size=wx.DefaultSize,
82 style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER,
83 static=False):
84 """Create Display instance."""
85 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
86 # Configure various defaults and user preferences.
87 self.SetReadOnly(True)
88 self.SetWrapMode(False)
89 if not static:
90 dispatcher.connect(receiver=self.push, signal='Interpreter.push')
91
92 def push(self, command, more):
93 """Receiver for Interpreter.push signal."""
94 self.Refresh()
95
96 def Refresh(self):
97 if not hasattr(self, "item"):
98 return
99 self.SetReadOnly(False)
100 text = pprint.pformat(self.item)
101 self.SetText(text)
102 self.SetReadOnly(True)
103
104 def setItem(self, item):
105 """Set item to pretty print in the notebook Display tab."""
106 self.item = item
107 self.Refresh()
108
109
110 class Calltip(wx.TextCtrl):
111 """Text control containing the most recent shell calltip."""
112
113 def __init__(self, parent=None, id=-1):
114 style = (wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH2)
115 wx.TextCtrl.__init__(self, parent, id, style=style)
116 self.SetBackgroundColour(wx.Colour(255, 255, 232))
117 dispatcher.connect(receiver=self.display, signal='Shell.calltip')
118
119 def display(self, calltip):
120 """Receiver for Shell.calltip signal."""
121 ## self.SetValue(calltip) # Caused refresh problem on Windows.
122 self.Clear()
123 self.AppendText(calltip)
124
125
126 class SessionListing(wx.TextCtrl):
127 """Text control containing all commands for session."""
128
129 def __init__(self, parent=None, id=-1):
130 style = (wx.TE_MULTILINE | wx.TE_READONLY |
131 wx.TE_RICH2 | wx.TE_DONTWRAP)
132 wx.TextCtrl.__init__(self, parent, id, style=style)
133 dispatcher.connect(receiver=self.push, signal='Interpreter.push')
134
135 def push(self, command, more):
136 """Receiver for Interpreter.push signal."""
137 if command and not more:
138 self.SetInsertionPointEnd()
139 start, end = self.GetSelection()
140 if start != end:
141 self.SetSelection(0, 0)
142 self.AppendText(command + '\n')
143
144
145 class DispatcherListing(wx.TextCtrl):
146 """Text control containing all dispatches for session."""
147
148 def __init__(self, parent=None, id=-1):
149 style = (wx.TE_MULTILINE | wx.TE_READONLY |
150 wx.TE_RICH2 | wx.TE_DONTWRAP)
151 wx.TextCtrl.__init__(self, parent, id, style=style)
152 dispatcher.connect(receiver=self.spy)
153
154 def spy(self, signal, sender):
155 """Receiver for Any signal from Any sender."""
156 text = '%r from %s' % (signal, sender)
157 self.SetInsertionPointEnd()
158 start, end = self.GetSelection()
159 if start != end:
160 self.SetSelection(0, 0)
161 self.AppendText(text + '\n')
162
163
164 class CrustFrame(frame.Frame):
165 """Frame containing all the PyCrust components."""
166
167 name = 'CrustFrame'
168 revision = __revision__
169
170 def __init__(self, parent=None, id=-1, title='PyCrust',
171 pos=wx.DefaultPosition, size=wx.DefaultSize,
172 style=wx.DEFAULT_FRAME_STYLE,
173 rootObject=None, rootLabel=None, rootIsNamespace=True,
174 locals=None, InterpClass=None, *args, **kwds):
175 """Create CrustFrame instance."""
176 frame.Frame.__init__(self, parent, id, title, pos, size, style)
177 intro = 'PyCrust %s - The Flakiest Python Shell' % VERSION
178 intro += '\nSponsored by Orbtech - '
179 intro += 'Your source for Python programming expertise.'
180 self.SetStatusText(intro.replace('\n', ', '))
181 self.crust = Crust(parent=self, intro=intro,
182 rootObject=rootObject,
183 rootLabel=rootLabel,
184 rootIsNamespace=rootIsNamespace,
185 locals=locals,
186 InterpClass=InterpClass, *args, **kwds)
187 self.shell = self.crust.shell
188 # Override the filling so that status messages go to the status bar.
189 self.crust.filling.tree.setStatusText = self.SetStatusText
190 # Override the shell so that status messages go to the status bar.
191 self.shell.setStatusText = self.SetStatusText
192 # Fix a problem with the sash shrinking to nothing.
193 self.crust.filling.SetSashPosition(200)
194 # Set focus to the shell editor.
195 self.shell.SetFocus()
196
197 def OnClose(self, event):
198 """Event handler for closing."""
199 self.crust.shell.destroy()
200 self.Destroy()
201
202 def OnAbout(self, event):
203 """Display an About window."""
204 title = 'About PyCrust'
205 text = 'PyCrust %s\n\n' % VERSION + \
206 'Yet another Python shell, only flakier.\n\n' + \
207 'Half-baked by Patrick K. O\'Brien,\n' + \
208 'the other half is still in the oven.\n\n' + \
209 'Shell Revision: %s\n' % self.shell.revision + \
210 'Interpreter Revision: %s\n\n' % self.shell.interp.revision + \
211 'Platform: %s\n' % sys.platform + \
212 'Python Version: %s\n' % sys.version.split()[0] + \
213 'wxPython Version: %s\n' % wx.VERSION_STRING + \
214 ('\t(%s)\n' % ", ".join(wx.PlatformInfo[1:]))
215 dialog = wx.MessageDialog(self, text, title,
216 wx.OK | wx.ICON_INFORMATION)
217 dialog.ShowModal()
218 dialog.Destroy()