]>
Commit | Line | Data |
---|---|---|
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() |