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