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