]> git.saurik.com Git - wxWidgets.git/blob - wxPython/src/_app_ex.py
Updated manual version
[wxWidgets.git] / wxPython / src / _app_ex.py
1
2 #----------------------------------------------------------------------
3
4 class 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         self.frame.Bind(wx.EVT_CLOSE, 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         
73 class 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         
131         wx.PyApp.__init__(self)
132
133         # make sure we can create a GUI
134         if not self.IsDisplayAvailable():
135             
136             if wx.Platform == "__WXMAC__":
137                 msg = """This program needs access to the screen.
138 Please run with 'pythonw', not 'python', and only when you are logged
139 in on the main display of your Mac."""
140                 
141             elif wx.Platform == "__WXGTK__":
142                 msg ="Unable to access the X Display, is $DISPLAY set properly?"
143
144             else:
145                 msg = "Unable to create GUI"
146                 # TODO: more description is needed for wxMSW...
147
148             raise SystemExit(msg)
149         
150         # This has to be done before OnInit
151         self.SetUseBestVisual(useBestVisual)
152
153         # Set the default handler for SIGINT.  This fixes a problem
154         # where if Ctrl-C is pressed in the console that started this
155         # app then it will not appear to do anything, (not even send
156         # KeyboardInterrupt???)  but will later segfault on exit.  By
157         # setting the default handler then the app will exit, as
158         # expected (depending on platform.)
159         if clearSigInt:
160             try:
161                 import signal
162                 signal.signal(signal.SIGINT, signal.SIG_DFL)
163             except:
164                 pass
165
166         # Save and redirect the stdio to a window?
167         self.stdioWin = None
168         self.saveStdio = (_sys.stdout, _sys.stderr)
169         if redirect:
170             self.RedirectStdio(filename)
171
172         # Use Python's install prefix as the default  
173         wx.StandardPaths.Get().SetInstallPrefix(_sys.prefix)
174
175         # This finishes the initialization of wxWindows and then calls
176         # the OnInit that should be present in the derived class
177         self._BootstrapApp()
178
179
180     def OnPreInit(self):
181         """
182         Things that must be done after _BootstrapApp has done its
183         thing, but would be nice if they were already done by the time
184         that OnInit is called.
185         """
186         wx.StockGDI._initStockObjects()
187         
188
189     def __del__(self, destroy=wx.PyApp.__del__):
190         self.RestoreStdio()  # Just in case the MainLoop was overridden
191         destroy(self)
192
193     def Destroy(self):
194         self.this.own(False)
195         wx.PyApp.Destroy(self)
196
197     def SetTopWindow(self, frame):
198         """Set the \"main\" top level window"""
199         if self.stdioWin:
200             self.stdioWin.SetParent(frame)
201         wx.PyApp.SetTopWindow(self, frame)
202
203
204     def MainLoop(self):
205         """Execute the main GUI event loop"""
206         wx.PyApp.MainLoop(self)
207         self.RestoreStdio()
208
209
210     def RedirectStdio(self, filename=None):
211         """Redirect sys.stdout and sys.stderr to a file or a popup window."""
212         if filename:
213             _sys.stdout = _sys.stderr = open(filename, 'a')
214         else:
215             self.stdioWin = self.outputWindowClass()
216             _sys.stdout = _sys.stderr = self.stdioWin
217
218
219     def RestoreStdio(self):
220         try:
221             _sys.stdout, _sys.stderr = self.saveStdio
222         except:
223             pass
224
225
226     def SetOutputWindowAttributes(self, title=None, pos=None, size=None):
227         """
228         Set the title, position and/or size of the output window if
229         the stdio has been redirected.  This should be called before
230         any output would cause the output window to be created.
231         """
232         if self.stdioWin:
233             if title is not None:
234                 self.stdioWin.title = title
235             if pos is not None:
236                 self.stdioWin.pos = pos
237             if size is not None:
238                 self.stdioWin.size = size
239             
240
241
242
243 # change from wx.PyApp_XX to wx.App_XX
244 App_GetMacSupportPCMenuShortcuts = _core_.PyApp_GetMacSupportPCMenuShortcuts
245 App_GetMacAboutMenuItemId        = _core_.PyApp_GetMacAboutMenuItemId
246 App_GetMacPreferencesMenuItemId  = _core_.PyApp_GetMacPreferencesMenuItemId
247 App_GetMacExitMenuItemId         = _core_.PyApp_GetMacExitMenuItemId
248 App_GetMacHelpMenuTitleName      = _core_.PyApp_GetMacHelpMenuTitleName
249 App_SetMacSupportPCMenuShortcuts = _core_.PyApp_SetMacSupportPCMenuShortcuts
250 App_SetMacAboutMenuItemId        = _core_.PyApp_SetMacAboutMenuItemId
251 App_SetMacPreferencesMenuItemId  = _core_.PyApp_SetMacPreferencesMenuItemId
252 App_SetMacExitMenuItemId         = _core_.PyApp_SetMacExitMenuItemId
253 App_SetMacHelpMenuTitleName      = _core_.PyApp_SetMacHelpMenuTitleName
254 App_GetComCtl32Version           = _core_.PyApp_GetComCtl32Version
255
256 #----------------------------------------------------------------------------
257
258 class PySimpleApp(wx.App):
259     """
260     A simple application class.  You can just create one of these and
261     then then make your top level windows later, and not have to worry
262     about OnInit.  For example::
263
264         app = wx.PySimpleApp()
265         frame = wx.Frame(None, title='Hello World')
266         frame.Show()
267         app.MainLoop()
268
269     :see: `wx.App` 
270     """
271
272     def __init__(self, redirect=False, filename=None,
273                  useBestVisual=False, clearSigInt=True):
274         """
275         :see: `wx.App.__init__`
276         """
277         wx.App.__init__(self, redirect, filename, useBestVisual, clearSigInt)
278         
279     def OnInit(self):
280         return True
281
282
283
284 # Is anybody using this one?
285 class PyWidgetTester(wx.App):
286     def __init__(self, size = (250, 100)):
287         self.size = size
288         wx.App.__init__(self, 0)
289
290     def OnInit(self):
291         self.frame = wx.Frame(None, -1, "Widget Tester", pos=(0,0), size=self.size)
292         self.SetTopWindow(self.frame)
293         return True
294
295     def SetWidget(self, widgetClass, *args, **kwargs):
296         w = widgetClass(self.frame, *args, **kwargs)
297         self.frame.Show(True)
298
299 #----------------------------------------------------------------------------
300 # DO NOT hold any other references to this object.  This is how we
301 # know when to cleanup system resources that wxWidgets is holding.  When
302 # the sys module is unloaded, the refcount on sys.__wxPythonCleanup
303 # goes to zero and it calls the wx.App_CleanUp function.
304
305 class __wxPyCleanup:
306     def __init__(self):
307         self.cleanup = _core_.App_CleanUp
308     def __del__(self):
309         self.cleanup()
310
311 _sys.__wxPythonCleanup = __wxPyCleanup()
312
313 ## # another possible solution, but it gets called too early...
314 ## import atexit
315 ## atexit.register(_core_.wxApp_CleanUp)
316
317
318 #----------------------------------------------------------------------------