]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/py/crust.py
Compile fixes for Panther
[wxWidgets.git] / wxPython / wx / py / crust.py
CommitLineData
d14a1e28 1"""Crust combines the shell and filling into one control."""
1fded56b 2
d14a1e28
RD
3__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
4__cvsid__ = "$Id$"
5__revision__ = "$Revision$"[11:-2]
1fded56b 6
d14a1e28
RD
7import wx
8
9import os
10import pprint
02b800ce 11import re
d14a1e28
RD
12import sys
13
14import dispatcher
15import editwindow
16from filling import Filling
17import frame
18from shell import Shell
19from version import VERSION
20
d14a1e28
RD
21
22class Crust(wx.SplitterWindow):
23 """Crust based on SplitterWindow."""
24
25 name = 'Crust'
26 revision = __revision__
02b800ce 27 sashoffset = 300
d14a1e28 28
02b800ce
RD
29 def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
30 size=wx.DefaultSize, style=wx.SP_3D|wx.SP_LIVE_UPDATE,
d14a1e28 31 name='Crust Window', rootObject=None, rootLabel=None,
02b800ce
RD
32 rootIsNamespace=True, intro='', locals=None,
33 InterpClass=None,
34 startupScript=None, execStartupScript=True,
35 *args, **kwds):
d14a1e28
RD
36 """Create Crust instance."""
37 wx.SplitterWindow.__init__(self, parent, id, pos, size, style, name)
f365323f
VZ
38
39 # Turn off the tab-traversal style that is automatically
40 # turned on by wx.SplitterWindow. We do this because on
41 # Windows the event for Ctrl-Enter is stolen and used as a
42 # navigation key, but the Shell window uses it to insert lines.
43 style = self.GetWindowStyle()
44 self.SetWindowStyle(style & ~wx.TAB_TRAVERSAL)
45
02b800ce
RD
46 self.shell = Shell(parent=self, introText=intro,
47 locals=locals, InterpClass=InterpClass,
48 startupScript=startupScript,
49 execStartupScript=execStartupScript,
d14a1e28
RD
50 *args, **kwds)
51 self.editor = self.shell
52 if rootObject is None:
53 rootObject = self.shell.interp.locals
54 self.notebook = wx.Notebook(parent=self, id=-1)
55 self.shell.interp.locals['notebook'] = self.notebook
02b800ce
RD
56 self.filling = Filling(parent=self.notebook,
57 rootObject=rootObject,
58 rootLabel=rootLabel,
d14a1e28
RD
59 rootIsNamespace=rootIsNamespace)
60 # Add 'filling' to the interpreter's locals.
61 self.shell.interp.locals['filling'] = self.filling
62 self.notebook.AddPage(page=self.filling, text='Namespace', select=True)
02b800ce 63
d14a1e28
RD
64 self.display = Display(parent=self.notebook)
65 self.notebook.AddPage(page=self.display, text='Display')
66 # Add 'pp' (pretty print) to the interpreter's locals.
67 self.shell.interp.locals['pp'] = self.display.setItem
02b800ce
RD
68 self.display.nbTab = self.notebook.GetPageCount()-1
69
d14a1e28
RD
70 self.calltip = Calltip(parent=self.notebook)
71 self.notebook.AddPage(page=self.calltip, text='Calltip')
02b800ce 72
d14a1e28 73 self.sessionlisting = SessionListing(parent=self.notebook)
e773f79b 74 self.notebook.AddPage(page=self.sessionlisting, text='History')
02b800ce 75
d14a1e28
RD
76 self.dispatcherlisting = DispatcherListing(parent=self.notebook)
77 self.notebook.AddPage(page=self.dispatcherlisting, text='Dispatcher')
02b800ce
RD
78
79 self.SplitHorizontally(self.shell, self.notebook, -self.sashoffset)
80 self.SetMinimumPaneSize(100)
81
82 self.Bind(wx.EVT_SIZE, self.SplitterOnSize)
83 self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnChanged)
84
85
86 def OnChanged(self, event):
87 """update sash offset from the bottom of the window"""
88 self.sashoffset = self.GetSize().height - event.GetSashPosition()
89 event.Skip()
90
91
92 # Make the splitter expand the top window when resized
93 def SplitterOnSize(self, event):
94 splitter = event.GetEventObject()
95 sz = splitter.GetSize()
96 splitter.SetSashPosition(sz.height - self.sashoffset, True)
97 event.Skip()
98
99
100 def LoadSettings(self, config):
101 self.shell.LoadSettings(config)
102 self.filling.LoadSettings(config)
103
104 pos = config.ReadInt('Sash/CrustPos', 400)
105 wx.CallAfter(self.SetSashPosition, pos)
106 def _updateSashPosValue():
107 sz = self.GetSize()
108 self.sashoffset = sz.height - self.GetSashPosition()
109 wx.CallAfter(_updateSashPosValue)
110 zoom = config.ReadInt('View/Zoom/Display', -99)
111 if zoom != -99:
112 self.display.SetZoom(zoom)
113
114
115 def SaveSettings(self, config):
116 self.shell.SaveSettings(config)
117 self.filling.SaveSettings(config)
118
119 config.WriteInt('Sash/CrustPos', self.GetSashPosition())
120 config.WriteInt('View/Zoom/Display', self.display.GetZoom())
121
122
123
d14a1e28
RD
124
125
126class Display(editwindow.EditWindow):
127 """STC used to display an object using Pretty Print."""
128
129 def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
130 size=wx.DefaultSize,
131 style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER,
132 static=False):
133 """Create Display instance."""
134 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
135 # Configure various defaults and user preferences.
136 self.SetReadOnly(True)
137 self.SetWrapMode(False)
138 if not static:
139 dispatcher.connect(receiver=self.push, signal='Interpreter.push')
140
141 def push(self, command, more):
142 """Receiver for Interpreter.push signal."""
143 self.Refresh()
144
145 def Refresh(self):
146 if not hasattr(self, "item"):
147 return
148 self.SetReadOnly(False)
149 text = pprint.pformat(self.item)
150 self.SetText(text)
151 self.SetReadOnly(True)
152
153 def setItem(self, item):
154 """Set item to pretty print in the notebook Display tab."""
155 self.item = item
156 self.Refresh()
02b800ce
RD
157 if self.GetParent().GetSelection() != self.nbTab:
158 focus = wx.Window.FindFocus()
159 self.GetParent().SetSelection(self.nbTab)
160 wx.CallAfter(focus.SetFocus)
161
d14a1e28 162
02b800ce 163# TODO: Switch this to a editwindow.EditWindow
d14a1e28
RD
164class Calltip(wx.TextCtrl):
165 """Text control containing the most recent shell calltip."""
166
167 def __init__(self, parent=None, id=-1):
65d005e4
PB
168 style = (wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH2)
169 wx.TextCtrl.__init__(self, parent, id, style=style)
02b800ce 170 self.SetBackgroundColour(wx.Colour(255, 255, 208))
d14a1e28
RD
171 dispatcher.connect(receiver=self.display, signal='Shell.calltip')
172
e773f79b
RD
173 df = self.GetFont()
174 font = wx.Font(df.GetPointSize(), wx.TELETYPE, wx.NORMAL, wx.NORMAL)
175 self.SetFont(font)
176
d14a1e28
RD
177 def display(self, calltip):
178 """Receiver for Shell.calltip signal."""
07b87e8d
PB
179 ## self.SetValue(calltip) # Caused refresh problem on Windows.
180 self.Clear()
181 self.AppendText(calltip)
d14a1e28
RD
182
183
02b800ce 184# TODO: Switch this to a editwindow.EditWindow
d14a1e28
RD
185class SessionListing(wx.TextCtrl):
186 """Text control containing all commands for session."""
187
188 def __init__(self, parent=None, id=-1):
65d005e4
PB
189 style = (wx.TE_MULTILINE | wx.TE_READONLY |
190 wx.TE_RICH2 | wx.TE_DONTWRAP)
191 wx.TextCtrl.__init__(self, parent, id, style=style)
e773f79b
RD
192 dispatcher.connect(receiver=self.addHistory, signal="Shell.addHistory")
193 dispatcher.connect(receiver=self.clearHistory, signal="Shell.clearHistory")
194 dispatcher.connect(receiver=self.loadHistory, signal="Shell.loadHistory")
195
196 df = self.GetFont()
197 font = wx.Font(df.GetPointSize(), wx.TELETYPE, wx.NORMAL, wx.NORMAL)
198 self.SetFont(font)
199
200 def loadHistory(self, history):
201 # preload the existing history, if any
202 hist = history[:]
203 hist.reverse()
204 self.SetValue('\n'.join(hist) + '\n')
205 self.SetInsertionPointEnd()
d14a1e28 206
e773f79b
RD
207 def addHistory(self, command):
208 if command:
d14a1e28 209 self.SetInsertionPointEnd()
d14a1e28
RD
210 self.AppendText(command + '\n')
211
e773f79b
RD
212 def clearHistory(self):
213 self.SetValue("")
214
d14a1e28
RD
215
216class DispatcherListing(wx.TextCtrl):
217 """Text control containing all dispatches for session."""
218
219 def __init__(self, parent=None, id=-1):
65d005e4
PB
220 style = (wx.TE_MULTILINE | wx.TE_READONLY |
221 wx.TE_RICH2 | wx.TE_DONTWRAP)
222 wx.TextCtrl.__init__(self, parent, id, style=style)
d14a1e28
RD
223 dispatcher.connect(receiver=self.spy)
224
e773f79b
RD
225 df = self.GetFont()
226 font = wx.Font(df.GetPointSize(), wx.TELETYPE, wx.NORMAL, wx.NORMAL)
227 self.SetFont(font)
228
d14a1e28
RD
229 def spy(self, signal, sender):
230 """Receiver for Any signal from Any sender."""
231 text = '%r from %s' % (signal, sender)
232 self.SetInsertionPointEnd()
233 start, end = self.GetSelection()
234 if start != end:
235 self.SetSelection(0, 0)
236 self.AppendText(text + '\n')
237
238
02b800ce
RD
239
240class CrustFrame(frame.Frame, frame.ShellFrameMixin):
d14a1e28
RD
241 """Frame containing all the PyCrust components."""
242
243 name = 'CrustFrame'
244 revision = __revision__
245
02b800ce 246
d14a1e28
RD
247 def __init__(self, parent=None, id=-1, title='PyCrust',
248 pos=wx.DefaultPosition, size=wx.DefaultSize,
249 style=wx.DEFAULT_FRAME_STYLE,
250 rootObject=None, rootLabel=None, rootIsNamespace=True,
02b800ce
RD
251 locals=None, InterpClass=None,
252 config=None, dataDir=None,
253 *args, **kwds):
d14a1e28
RD
254 """Create CrustFrame instance."""
255 frame.Frame.__init__(self, parent, id, title, pos, size, style)
02b800ce
RD
256 frame.ShellFrameMixin.__init__(self, config, dataDir)
257
258 if size == wx.DefaultSize:
259 self.SetSize((800, 600))
260
d14a1e28 261 intro = 'PyCrust %s - The Flakiest Python Shell' % VERSION
d14a1e28
RD
262 self.SetStatusText(intro.replace('\n', ', '))
263 self.crust = Crust(parent=self, intro=intro,
264 rootObject=rootObject,
265 rootLabel=rootLabel,
266 rootIsNamespace=rootIsNamespace,
267 locals=locals,
02b800ce
RD
268 InterpClass=InterpClass,
269 startupScript=self.startupScript,
270 execStartupScript=self.execStartupScript,
271 *args, **kwds)
d14a1e28 272 self.shell = self.crust.shell
02b800ce 273
d14a1e28
RD
274 # Override the filling so that status messages go to the status bar.
275 self.crust.filling.tree.setStatusText = self.SetStatusText
02b800ce 276
d14a1e28
RD
277 # Override the shell so that status messages go to the status bar.
278 self.shell.setStatusText = self.SetStatusText
02b800ce 279
d14a1e28 280 self.shell.SetFocus()
02b800ce
RD
281 self.LoadSettings()
282
d14a1e28
RD
283
284 def OnClose(self, event):
285 """Event handler for closing."""
02b800ce 286 self.SaveSettings()
d14a1e28
RD
287 self.crust.shell.destroy()
288 self.Destroy()
289
02b800ce 290
d14a1e28
RD
291 def OnAbout(self, event):
292 """Display an About window."""
293 title = 'About PyCrust'
294 text = 'PyCrust %s\n\n' % VERSION + \
295 'Yet another Python shell, only flakier.\n\n' + \
296 'Half-baked by Patrick K. O\'Brien,\n' + \
297 'the other half is still in the oven.\n\n' + \
298 'Shell Revision: %s\n' % self.shell.revision + \
299 'Interpreter Revision: %s\n\n' % self.shell.interp.revision + \
f2f8a5fc 300 'Platform: %s\n' % sys.platform + \
d14a1e28
RD
301 'Python Version: %s\n' % sys.version.split()[0] + \
302 'wxPython Version: %s\n' % wx.VERSION_STRING + \
02b800ce 303 ('\t(%s)\n' % ", ".join(wx.PlatformInfo[1:]))
d14a1e28
RD
304 dialog = wx.MessageDialog(self, text, title,
305 wx.OK | wx.ICON_INFORMATION)
306 dialog.ShowModal()
307 dialog.Destroy()
02b800ce
RD
308
309
4617be08
RD
310 def OnHelp(self, event):
311 """Show a help dialog."""
312 frame.ShellFrameMixin.OnHelp(self, event)
313
02b800ce
RD
314
315 def LoadSettings(self):
316 if self.config is not None:
317 frame.ShellFrameMixin.LoadSettings(self)
318 frame.Frame.LoadSettings(self, self.config)
319 self.crust.LoadSettings(self.config)
320
321
c0ab3f7f 322 def SaveSettings(self, force=False):
02b800ce
RD
323 if self.config is not None:
324 frame.ShellFrameMixin.SaveSettings(self)
c0ab3f7f 325 if self.autoSaveSettings or force:
02b800ce
RD
326 frame.Frame.SaveSettings(self, self.config)
327 self.crust.SaveSettings(self.config)
328
329
330 def DoSaveSettings(self):
331 if self.config is not None:
c0ab3f7f 332 self.SaveSettings(force=True)
02b800ce
RD
333 self.config.Flush()
334
335
336