]> git.saurik.com Git - wxWidgets.git/blame_incremental - wxPython/src/_app_ex.py
Version
[wxWidgets.git] / wxPython / src / _app_ex.py
... / ...
CommitLineData
1
2#----------------------------------------------------------------------
3
4class PyOnDemandOutputWindow:
5 """
6 A class that can be used for redirecting Python's stdout and
7 stderr streams. It will do nothing until something is wrriten to
8 the stream at which point it will create a Frame with a text area
9 and write the text there.
10 """
11 def __init__(self, title = "wxPython: stdout/stderr"):
12 self.frame = None
13 self.title = title
14 self.pos = wx.DefaultPosition
15 self.size = (450, 300)
16 self.parent = None
17
18 def SetParent(self, parent):
19 """Set the window to be used as the popup Frame's parent."""
20 self.parent = parent
21
22
23 def CreateOutputWindow(self, st):
24 self.frame = wx.Frame(self.parent, -1, self.title, self.pos, self.size,
25 style=wx.DEFAULT_FRAME_STYLE)
26 self.text = wx.TextCtrl(self.frame, -1, "",
27 style=wx.TE_MULTILINE|wx.TE_READONLY)
28 self.text.AppendText(st)
29 self.frame.Show(True)
30 EVT_CLOSE(self.frame, self.OnCloseWindow)
31
32
33 def OnCloseWindow(self, event):
34 if self.frame is not None:
35 self.frame.Destroy()
36 self.frame = None
37 self.text = None
38
39
40 # These methods provide the file-like output behaviour.
41 def write(self, text):
42 """
43 Create the output window if needed and write the string to it.
44 If not called in the context of the gui thread then uses
45 CallAfter to do the work there.
46 """
47 if self.frame is None:
48 if not wx.Thread_IsMain():
49 wx.CallAfter(self.CreateOutputWindow, text)
50 else:
51 self.CreateOutputWindow(text)
52 else:
53 if not wx.Thread_IsMain():
54 wx.CallAfter(self.text.AppendText, text)
55 else:
56 self.text.AppendText(text)
57
58
59 def close(self):
60 if self.frame is not None:
61 wx.CallAfter(self.frame.Close)
62
63
64 def flush(self):
65 pass
66
67
68
69#----------------------------------------------------------------------
70
71_defRedirect = (wx.Platform == '__WXMSW__' or wx.Platform == '__WXMAC__')
72
73class App(wx.PyApp):
74 """
75 The ``wx.App`` class represents the application and is used to:
76
77 * bootstrap the wxPython system and initialize the underlying
78 gui toolkit
79 * set and get application-wide properties
80 * implement the windowing system main message or event loop,
81 and to dispatch events to window instances
82 * etc.
83
84 Every application must have a ``wx.App`` instance, and all
85 creation of UI objects should be delayed until after the
86 ``wx.App`` object has been created in order to ensure that the gui
87 platform and wxWidgets have been fully initialized.
88
89 Normally you would derive from this class and implement an
90 ``OnInit`` method that creates a frame and then calls
91 ``self.SetTopWindow(frame)``.
92
93 :see: `wx.PySimpleApp` for a simpler app class that can be used
94 directly.
95 """
96
97 outputWindowClass = PyOnDemandOutputWindow
98
99 def __init__(self, redirect=_defRedirect, filename=None,
100 useBestVisual=False, clearSigInt=True):
101 """
102 Construct a ``wx.App`` object.
103
104 :param redirect: Should ``sys.stdout`` and ``sys.stderr`` be
105 redirected? Defaults to True on Windows and Mac, False
106 otherwise. If `filename` is None then output will be
107 redirected to a window that pops up as needed. (You can
108 control what kind of window is created for the output by
109 resetting the class variable ``outputWindowClass`` to a
110 class of your choosing.)
111
112 :param filename: The name of a file to redirect output to, if
113 redirect is True.
114
115 :param useBestVisual: Should the app try to use the best
116 available visual provided by the system (only relevant on
117 systems that have more than one visual.) This parameter
118 must be used instead of calling `SetUseBestVisual` later
119 on because it must be set before the underlying GUI
120 toolkit is initialized.
121
122 :param clearSigInt: Should SIGINT be cleared? This allows the
123 app to terminate upon a Ctrl-C in the console like other
124 GUI apps will.
125
126 :note: You should override OnInit to do applicaition
127 initialization to ensure that the system, toolkit and
128 wxWidgets are fully initialized.
129 """
130 wx.PyApp.__init__(self)
131
132 if wx.Platform == "__WXMAC__":
133 try:
134 import MacOS
135 if not MacOS.WMAvailable():
136 print """\
137This program needs access to the screen. Please run with 'pythonw',
138not 'python', and only when you are logged in on the main display of
139your Mac."""
140 _sys.exit(1)
141 except SystemExit:
142 raise
143 except:
144 pass
145
146 # This has to be done before OnInit
147 self.SetUseBestVisual(useBestVisual)
148
149 # Set the default handler for SIGINT. This fixes a problem
150 # where if Ctrl-C is pressed in the console that started this
151 # app then it will not appear to do anything, (not even send
152 # KeyboardInterrupt???) but will later segfault on exit. By
153 # setting the default handler then the app will exit, as
154 # expected (depending on platform.)
155 if clearSigInt:
156 try:
157 import signal
158 signal.signal(signal.SIGINT, signal.SIG_DFL)
159 except:
160 pass
161
162 # Save and redirect the stdio to a window?
163 self.stdioWin = None
164 self.saveStdio = (_sys.stdout, _sys.stderr)
165 if redirect:
166 self.RedirectStdio(filename)
167
168 # Use Python's install prefix as the default
169 wx.StandardPaths.Get().SetInstallPrefix(_sys.prefix)
170
171 # This finishes the initialization of wxWindows and then calls
172 # the OnInit that should be present in the derived class
173 self._BootstrapApp()
174
175
176 def __del__(self):
177 try:
178 self.RestoreStdio() # Just in case the MainLoop was overridden
179 except:
180 pass
181
182
183 def SetTopWindow(self, frame):
184 """Set the \"main\" top level window"""
185 if self.stdioWin:
186 self.stdioWin.SetParent(frame)
187 wx.PyApp.SetTopWindow(self, frame)
188
189
190 def MainLoop(self):
191 """Execute the main GUI event loop"""
192 wx.PyApp.MainLoop(self)
193 self.RestoreStdio()
194
195
196 def RedirectStdio(self, filename=None):
197 """Redirect sys.stdout and sys.stderr to a file or a popup window."""
198 if filename:
199 _sys.stdout = _sys.stderr = open(filename, 'a')
200 else:
201 self.stdioWin = self.outputWindowClass()
202 _sys.stdout = _sys.stderr = self.stdioWin
203
204
205 def RestoreStdio(self):
206 _sys.stdout, _sys.stderr = self.saveStdio
207
208
209 def SetOutputWindowAttributes(self, title=None, pos=None, size=None):
210 """
211 Set the title, position and/or size of the output window if
212 the stdio has been redirected. This should be called before
213 any output would cause the output window to be created.
214 """
215 if self.stdioWin:
216 if title is not None:
217 self.stdioWin.title = title
218 if pos is not None:
219 self.stdioWin.pos = pos
220 if size is not None:
221 self.stdioWin.size = size
222
223
224
225
226# change from wx.PyApp_XX to wx.App_XX
227App_GetMacSupportPCMenuShortcuts = _core_.PyApp_GetMacSupportPCMenuShortcuts
228App_GetMacAboutMenuItemId = _core_.PyApp_GetMacAboutMenuItemId
229App_GetMacPreferencesMenuItemId = _core_.PyApp_GetMacPreferencesMenuItemId
230App_GetMacExitMenuItemId = _core_.PyApp_GetMacExitMenuItemId
231App_GetMacHelpMenuTitleName = _core_.PyApp_GetMacHelpMenuTitleName
232App_SetMacSupportPCMenuShortcuts = _core_.PyApp_SetMacSupportPCMenuShortcuts
233App_SetMacAboutMenuItemId = _core_.PyApp_SetMacAboutMenuItemId
234App_SetMacPreferencesMenuItemId = _core_.PyApp_SetMacPreferencesMenuItemId
235App_SetMacExitMenuItemId = _core_.PyApp_SetMacExitMenuItemId
236App_SetMacHelpMenuTitleName = _core_.PyApp_SetMacHelpMenuTitleName
237App_GetComCtl32Version = _core_.PyApp_GetComCtl32Version
238
239#----------------------------------------------------------------------------
240
241class PySimpleApp(wx.App):
242 """
243 A simple application class. You can just create one of these and
244 then then make your top level windows later, and not have to worry
245 about OnInit. For example::
246
247 app = wx.PySimpleApp()
248 frame = wx.Frame(None, title='Hello World')
249 frame.Show()
250 app.MainLoop()
251
252 :see: `wx.App`
253 """
254
255 def __init__(self, redirect=False, filename=None,
256 useBestVisual=False, clearSigInt=True):
257 """
258 :see: `wx.App.__init__`
259 """
260 wx.App.__init__(self, redirect, filename, useBestVisual, clearSigInt)
261
262 def OnInit(self):
263 return True
264
265
266
267# Is anybody using this one?
268class PyWidgetTester(wx.App):
269 def __init__(self, size = (250, 100)):
270 self.size = size
271 wx.App.__init__(self, 0)
272
273 def OnInit(self):
274 self.frame = wx.Frame(None, -1, "Widget Tester", pos=(0,0), size=self.size)
275 self.SetTopWindow(self.frame)
276 return True
277
278 def SetWidget(self, widgetClass, *args, **kwargs):
279 w = widgetClass(self.frame, *args, **kwargs)
280 self.frame.Show(True)
281
282#----------------------------------------------------------------------------
283# DO NOT hold any other references to this object. This is how we
284# know when to cleanup system resources that wxWidgets is holding. When
285# the sys module is unloaded, the refcount on sys.__wxPythonCleanup
286# goes to zero and it calls the wx.App_CleanUp function.
287
288class __wxPyCleanup:
289 def __init__(self):
290 self.cleanup = _core_.App_CleanUp
291 def __del__(self):
292 self.cleanup()
293
294_sys.__wxPythonCleanup = __wxPyCleanup()
295
296## # another possible solution, but it gets called too early...
297## import atexit
298## atexit.register(_core_.wxApp_CleanUp)
299
300
301#----------------------------------------------------------------------------