]> git.saurik.com Git - wxWidgets.git/blob - wxPython/src/_core_ex.py
Applied patch [ 1171467 ] Fix for DocManager not checking OnNewDocument's return...
[wxWidgets.git] / wxPython / src / _core_ex.py
1 #----------------------------------------------------------------------------
2
3 # Use Python's bool constants if available, make some if not
4 try:
5 True
6 except NameError:
7 __builtins__.True = 1==1
8 __builtins__.False = 1==0
9 def bool(value): return not not value
10 __builtins__.bool = bool
11
12
13
14 # workarounds for bad wxRTTI names
15 __wxPyPtrTypeMap['wxGauge95'] = 'wxGauge'
16 __wxPyPtrTypeMap['wxSlider95'] = 'wxSlider'
17 __wxPyPtrTypeMap['wxStatusBar95'] = 'wxStatusBar'
18
19
20 #----------------------------------------------------------------------------
21 # Load version numbers from __version__... Ensure that major and minor
22 # versions are the same for both wxPython and wxWidgets.
23
24 from __version__ import *
25 __version__ = VERSION_STRING
26
27 assert MAJOR_VERSION == _core_.MAJOR_VERSION, "wxPython/wxWidgets version mismatch"
28 assert MINOR_VERSION == _core_.MINOR_VERSION, "wxPython/wxWidgets version mismatch"
29 if RELEASE_VERSION != _core_.RELEASE_VERSION:
30 import warnings
31 warnings.warn("wxPython/wxWidgets release number mismatch")
32
33 #----------------------------------------------------------------------------
34
35 # Set the default string<-->unicode conversion encoding from the
36 # locale. This encoding is used when string or unicode objects need
37 # to be converted in order to pass them to wxWidgets. Please be aware
38 # that the default encoding within the same locale may be slightly
39 # different on different platforms. For example, please see
40 # http://www.alanwood.net/demos/charsetdiffs.html for differences
41 # between the common latin/roman encodings.
42
43 default = _sys.getdefaultencoding()
44 if default == 'ascii':
45 import locale
46 import codecs
47 try:
48 default = locale.getdefaultlocale()[1]
49 codecs.lookup(default)
50 except (ValueError, LookupError):
51 default = _sys.getdefaultencoding()
52 del locale
53 del codecs
54 if default:
55 wx.SetDefaultPyEncoding(default)
56 del default
57
58 #----------------------------------------------------------------------------
59
60 class PyDeadObjectError(AttributeError):
61 pass
62
63 class _wxPyDeadObject(object):
64 """
65 Instances of wx objects that are OOR capable will have their __class__
66 changed to this class when the C++ object is deleted. This should help
67 prevent crashes due to referencing a bogus C++ pointer.
68 """
69 reprStr = "wxPython wrapper for DELETED %s object! (The C++ object no longer exists.)"
70 attrStr = "The C++ part of the %s object has been deleted, attribute access no longer allowed."
71
72 def __repr__(self):
73 if not hasattr(self, "_name"):
74 self._name = "[unknown]"
75 return self.reprStr % self._name
76
77 def __getattr__(self, *args):
78 if not hasattr(self, "_name"):
79 self._name = "[unknown]"
80 raise PyDeadObjectError(self.attrStr % self._name)
81
82 def __nonzero__(self):
83 return 0
84
85
86
87 class PyUnbornObjectError(AttributeError):
88 pass
89
90 class _wxPyUnbornObject(object):
91 """
92 Some stock objects are created when the wx._core module is
93 imported, but their C++ instance is not created until the wx.App
94 object is created and initialized. These object instances will
95 temporarily have their __class__ changed to this class so an
96 exception will be raised if they are used before the C++ instance
97 is ready.
98 """
99
100 reprStr = "wxPython wrapper for UNBORN object! (The C++ object is not initialized yet.)"
101 attrStr = "The C++ part of this object has not been initialized, attribute access not allowed."
102
103 def __repr__(self):
104 #if not hasattr(self, "_name"):
105 # self._name = "[unknown]"
106 return self.reprStr #% self._name
107
108 def __getattr__(self, *args):
109 #if not hasattr(self, "_name"):
110 # self._name = "[unknown]"
111 raise PyUnbornObjectError(self.attrStr) # % self._name )
112
113 def __nonzero__(self):
114 return 0
115
116
117 #----------------------------------------------------------------------------
118
119 def CallAfter(callable, *args, **kw):
120 """
121 Call the specified function after the current and pending event
122 handlers have been completed. This is also good for making GUI
123 method calls from non-GUI threads. Any extra positional or
124 keyword args are passed on to the callable when it is called.
125
126 :see: `wx.FutureCall`
127 """
128 app = wx.GetApp()
129 assert app is not None, 'No wx.App created yet'
130
131 if not hasattr(app, "_CallAfterId"):
132 app._CallAfterId = wx.NewEventType()
133 app.Connect(-1, -1, app._CallAfterId,
134 lambda event: event.callable(*event.args, **event.kw) )
135 evt = wx.PyEvent()
136 evt.SetEventType(app._CallAfterId)
137 evt.callable = callable
138 evt.args = args
139 evt.kw = kw
140 wx.PostEvent(app, evt)
141
142 #----------------------------------------------------------------------------
143
144
145 class FutureCall:
146 """
147 A convenience class for `wx.Timer`, that calls the given callable
148 object once after the given amount of milliseconds, passing any
149 positional or keyword args. The return value of the callable is
150 availbale after it has been run with the `GetResult` method.
151
152 If you don't need to get the return value or restart the timer
153 then there is no need to hold a reference to this object. It will
154 hold a reference to itself while the timer is running (the timer
155 has a reference to self.Notify) but the cycle will be broken when
156 the timer completes, automatically cleaning up the wx.FutureCall
157 object.
158
159 :see: `wx.CallAfter`
160 """
161 def __init__(self, millis, callable, *args, **kwargs):
162 self.millis = millis
163 self.callable = callable
164 self.SetArgs(*args, **kwargs)
165 self.runCount = 0
166 self.running = False
167 self.hasRun = False
168 self.result = None
169 self.timer = None
170 self.Start()
171
172 def __del__(self):
173 self.Stop()
174
175
176 def Start(self, millis=None, *args, **kwargs):
177 """
178 (Re)start the timer
179 """
180 self.hasRun = False
181 if millis is not None:
182 self.millis = millis
183 if args or kwargs:
184 self.SetArgs(*args, **kwargs)
185 self.Stop()
186 self.timer = wx.PyTimer(self.Notify)
187 self.timer.Start(self.millis, wx.TIMER_ONE_SHOT)
188 self.running = True
189 Restart = Start
190
191
192 def Stop(self):
193 """
194 Stop and destroy the timer.
195 """
196 if self.timer is not None:
197 self.timer.Stop()
198 self.timer = None
199
200
201 def GetInterval(self):
202 if self.timer is not None:
203 return self.timer.GetInterval()
204 else:
205 return 0
206
207
208 def IsRunning(self):
209 return self.timer is not None and self.timer.IsRunning()
210
211
212 def SetArgs(self, *args, **kwargs):
213 """
214 (Re)set the args passed to the callable object. This is
215 useful in conjunction with Restart if you want to schedule a
216 new call to the same callable object but with different
217 parameters.
218 """
219 self.args = args
220 self.kwargs = kwargs
221
222
223 def HasRun(self):
224 return self.hasRun
225
226 def GetResult(self):
227 return self.result
228
229 def Notify(self):
230 """
231 The timer has expired so call the callable.
232 """
233 if self.callable and getattr(self.callable, 'im_self', True):
234 self.runCount += 1
235 self.running = False
236 self.result = self.callable(*self.args, **self.kwargs)
237 self.hasRun = True
238 if not self.running:
239 # if it wasn't restarted, then cleanup
240 wx.CallAfter(self.Stop)
241
242
243
244 #----------------------------------------------------------------------------
245 # Control which items in this module should be documented by epydoc.
246 # We allow only classes and functions, which will help reduce the size
247 # of the docs by filtering out the zillions of constants, EVT objects,
248 # and etc that don't make much sense by themselves, but are instead
249 # documented (or will be) as part of the classes/functions/methods
250 # where they should be used.
251
252 class __DocFilter:
253 """
254 A filter for epydoc that only allows non-Ptr classes and
255 fucntions, in order to reduce the clutter in the API docs.
256 """
257 def __init__(self, globals):
258 self._globals = globals
259
260 def __call__(self, name):
261 import types
262 obj = self._globals.get(name, None)
263 if type(obj) not in [type, types.ClassType, types.FunctionType, types.BuiltinFunctionType]:
264 return False
265 if name.startswith('_') or name.endswith('Ptr') or name.startswith('EVT'):
266 return False
267 return True
268
269 #----------------------------------------------------------------------------
270 #----------------------------------------------------------------------------
271
272 # Import other modules in this package that should show up in the
273 # "core" wx namespace
274 from _gdi import *
275 from _windows import *
276 from _controls import *
277 from _misc import *
278
279
280 # Fixup the stock objects since they can't be used yet. (They will be
281 # restored in wx.PyApp.OnInit.)
282 _core_._wxPyFixStockObjects()
283
284 #----------------------------------------------------------------------------
285 #----------------------------------------------------------------------------