]> git.saurik.com Git - wxWidgets.git/blame - wxPython/src/_core_ex.py
wx.lib.masked: Patch from Will Sadkin. Includes Unicode fixes, plus
[wxWidgets.git] / wxPython / src / _core_ex.py
CommitLineData
d14a1e28
RD
1#----------------------------------------------------------------------------
2
322913ce 3# Use Python's bool constants if available, make some if not
d14a1e28
RD
4try:
5 True
6except NameError:
322913ce
RD
7 __builtins__.True = 1==1
8 __builtins__.False = 1==0
c19bd0a3
RD
9 def bool(value): return not not value
10 __builtins__.bool = bool
d14a1e28 11
d14a1e28
RD
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
611190df 22# versions are the same for both wxPython and wxWidgets.
d14a1e28
RD
23
24from __version__ import *
25__version__ = VERSION_STRING
26
611190df
RD
27assert MAJOR_VERSION == _core_.MAJOR_VERSION, "wxPython/wxWidgets version mismatch"
28assert MINOR_VERSION == _core_.MINOR_VERSION, "wxPython/wxWidgets version mismatch"
54f9ee45 29if RELEASE_VERSION != _core_.RELEASE_VERSION:
d14a1e28 30 import warnings
611190df 31 warnings.warn("wxPython/wxWidgets release number mismatch")
d14a1e28 32
a47418db
RD
33
34def version():
35 """Returns a string containing version and port info"""
36 ctype = wx.USE_UNICODE and 'unicode' or 'ansi'
37 if wx.Platform == '__WXMSW__':
38 port = 'msw'
39 elif wx.Platform == '__WXMAC__':
40 port = 'mac'
41 elif wx.Platform == '__WXGTK__':
42 port = 'gtk'
43 if 'gtk2' in wx.PlatformInfo:
44 port = 'gtk2'
45 else:
46 port = '?'
47
48 return "%s (%s-%s)" % (wx.VERSION_STRING, port, ctype)
49
50
d14a1e28
RD
51#----------------------------------------------------------------------------
52
ac3b7152
RD
53# Set wxPython's default string<-->unicode conversion encoding from
54# the locale, but only if Python's default hasn't been changed. (We
55# assume that if the user has customized it already then that is the
56# encoding we need to use as well.)
57#
58# The encoding selected here is used when string or unicode objects
59# need to be converted in order to pass them to wxWidgets. Please be
60# aware that the default encoding within the same locale may be
61# slightly different on different platforms. For example, please see
669e06d7
RD
62# http://www.alanwood.net/demos/charsetdiffs.html for differences
63# between the common latin/roman encodings.
dd898dd8
RD
64
65default = _sys.getdefaultencoding()
66if default == 'ascii':
67 import locale
68 import codecs
69 try:
70 default = locale.getdefaultlocale()[1]
71 codecs.lookup(default)
bbf07386 72 except (ValueError, LookupError, TypeError):
dd898dd8
RD
73 default = _sys.getdefaultencoding()
74 del locale
75 del codecs
4293f847
RD
76if default:
77 wx.SetDefaultPyEncoding(default)
78del default
4293f847
RD
79
80#----------------------------------------------------------------------------
81
d14a1e28
RD
82class PyDeadObjectError(AttributeError):
83 pass
84
d14a1e28
RD
85class _wxPyDeadObject(object):
86 """
87 Instances of wx objects that are OOR capable will have their __class__
88 changed to this class when the C++ object is deleted. This should help
89 prevent crashes due to referencing a bogus C++ pointer.
90 """
91 reprStr = "wxPython wrapper for DELETED %s object! (The C++ object no longer exists.)"
92 attrStr = "The C++ part of the %s object has been deleted, attribute access no longer allowed."
93
9e58eb56 94 def __repr__(self):
d14a1e28
RD
95 if not hasattr(self, "_name"):
96 self._name = "[unknown]"
97 return self.reprStr % self._name
98
9e58eb56 99 def __getattr__(self, *args):
d14a1e28
RD
100 if not hasattr(self, "_name"):
101 self._name = "[unknown]"
9e58eb56
RD
102 raise PyDeadObjectError(self.attrStr % self._name)
103
104 def __nonzero__(self):
105 return 0
106
107
108
109class PyUnbornObjectError(AttributeError):
110 pass
111
112class _wxPyUnbornObject(object):
113 """
54f9ee45 114 Some stock objects are created when the wx._core module is
9e58eb56
RD
115 imported, but their C++ instance is not created until the wx.App
116 object is created and initialized. These object instances will
117 temporarily have their __class__ changed to this class so an
118 exception will be raised if they are used before the C++ instance
119 is ready.
120 """
121
122 reprStr = "wxPython wrapper for UNBORN object! (The C++ object is not initialized yet.)"
123 attrStr = "The C++ part of this object has not been initialized, attribute access not allowed."
124
125 def __repr__(self):
126 #if not hasattr(self, "_name"):
127 # self._name = "[unknown]"
128 return self.reprStr #% self._name
129
130 def __getattr__(self, *args):
131 #if not hasattr(self, "_name"):
132 # self._name = "[unknown]"
133 raise PyUnbornObjectError(self.attrStr) # % self._name )
d14a1e28
RD
134
135 def __nonzero__(self):
136 return 0
137
138
139#----------------------------------------------------------------------------
d14a1e28
RD
140
141def CallAfter(callable, *args, **kw):
142 """
143 Call the specified function after the current and pending event
144 handlers have been completed. This is also good for making GUI
61863841
RD
145 method calls from non-GUI threads. Any extra positional or
146 keyword args are passed on to the callable when it is called.
147
8feec28c 148 :see: `wx.CallLater`
d14a1e28
RD
149 """
150 app = wx.GetApp()
2148e701 151 assert app is not None, 'No wx.App created yet'
d14a1e28 152
b0cafb91
RD
153 if not hasattr(app, "_CallAfterId"):
154 app._CallAfterId = wx.NewEventType()
155 app.Connect(-1, -1, app._CallAfterId,
156 lambda event: event.callable(*event.args, **event.kw) )
d14a1e28 157 evt = wx.PyEvent()
b0cafb91 158 evt.SetEventType(app._CallAfterId)
d14a1e28
RD
159 evt.callable = callable
160 evt.args = args
161 evt.kw = kw
162 wx.PostEvent(app, evt)
163
d14a1e28
RD
164#----------------------------------------------------------------------------
165
166
8feec28c 167class CallLater:
d14a1e28 168 """
a3c9f064 169 A convenience class for `wx.Timer`, that calls the given callable
d14a1e28
RD
170 object once after the given amount of milliseconds, passing any
171 positional or keyword args. The return value of the callable is
61863841 172 availbale after it has been run with the `GetResult` method.
d14a1e28
RD
173
174 If you don't need to get the return value or restart the timer
175 then there is no need to hold a reference to this object. It will
176 hold a reference to itself while the timer is running (the timer
177 has a reference to self.Notify) but the cycle will be broken when
8feec28c 178 the timer completes, automatically cleaning up the wx.CallLater
d14a1e28 179 object.
61863841
RD
180
181 :see: `wx.CallAfter`
d14a1e28
RD
182 """
183 def __init__(self, millis, callable, *args, **kwargs):
184 self.millis = millis
185 self.callable = callable
186 self.SetArgs(*args, **kwargs)
187 self.runCount = 0
66065839 188 self.running = False
d14a1e28
RD
189 self.hasRun = False
190 self.result = None
191 self.timer = None
192 self.Start()
193
194 def __del__(self):
195 self.Stop()
196
197
198 def Start(self, millis=None, *args, **kwargs):
199 """
200 (Re)start the timer
201 """
202 self.hasRun = False
203 if millis is not None:
204 self.millis = millis
205 if args or kwargs:
206 self.SetArgs(*args, **kwargs)
207 self.Stop()
208 self.timer = wx.PyTimer(self.Notify)
209 self.timer.Start(self.millis, wx.TIMER_ONE_SHOT)
66065839 210 self.running = True
d14a1e28
RD
211 Restart = Start
212
213
214 def Stop(self):
215 """
216 Stop and destroy the timer.
217 """
218 if self.timer is not None:
219 self.timer.Stop()
220 self.timer = None
221
222
223 def GetInterval(self):
224 if self.timer is not None:
225 return self.timer.GetInterval()
226 else:
227 return 0
228
229
230 def IsRunning(self):
231 return self.timer is not None and self.timer.IsRunning()
232
233
234 def SetArgs(self, *args, **kwargs):
235 """
236 (Re)set the args passed to the callable object. This is
237 useful in conjunction with Restart if you want to schedule a
238 new call to the same callable object but with different
239 parameters.
240 """
241 self.args = args
242 self.kwargs = kwargs
243
244
245 def HasRun(self):
246 return self.hasRun
247
248 def GetResult(self):
249 return self.result
250
251 def Notify(self):
252 """
253 The timer has expired so call the callable.
254 """
255 if self.callable and getattr(self.callable, 'im_self', True):
256 self.runCount += 1
66065839 257 self.running = False
d14a1e28
RD
258 self.result = self.callable(*self.args, **self.kwargs)
259 self.hasRun = True
66065839
RD
260 if not self.running:
261 # if it wasn't restarted, then cleanup
262 wx.CallAfter(self.Stop)
d14a1e28 263
42e2bbb9
RD
264 Interval = property(GetInterval)
265 Result = property(GetResult)
d14a1e28 266
5b29df3f 267
8feec28c 268class FutureCall(CallLater):
846c181b 269 """A compatibility alias for `CallLater`."""
8feec28c 270
5b29df3f
RD
271#----------------------------------------------------------------------------
272# Control which items in this module should be documented by epydoc.
273# We allow only classes and functions, which will help reduce the size
274# of the docs by filtering out the zillions of constants, EVT objects,
275# and etc that don't make much sense by themselves, but are instead
276# documented (or will be) as part of the classes/functions/methods
277# where they should be used.
278
99109c0f
RD
279class __DocFilter:
280 """
281 A filter for epydoc that only allows non-Ptr classes and
955e46d2 282 functions, in order to reduce the clutter in the API docs.
99109c0f
RD
283 """
284 def __init__(self, globals):
285 self._globals = globals
286
287 def __call__(self, name):
288 import types
289 obj = self._globals.get(name, None)
a8ec3708
RD
290
291 # only document classes and function
99109c0f
RD
292 if type(obj) not in [type, types.ClassType, types.FunctionType, types.BuiltinFunctionType]:
293 return False
a8ec3708
RD
294
295 # skip other things that are private or will be documented as part of somethign else
ace78e27 296 if name.startswith('_') or name.startswith('EVT') or name.endswith('_swigregister') or name.endswith('Ptr') :
99109c0f 297 return False
a8ec3708
RD
298
299 # skip functions that are duplicates of static functions in a class
300 if name.find('_') != -1:
301 cls = self._globals.get(name.split('_')[0], None)
302 methname = name.split('_')[1]
303 if hasattr(cls, methname) and type(getattr(cls, methname)) is types.FunctionType:
304 return False
305
99109c0f 306 return True
5b29df3f 307
d14a1e28
RD
308#----------------------------------------------------------------------------
309#----------------------------------------------------------------------------
310
311# Import other modules in this package that should show up in the
312# "core" wx namespace
54f9ee45
RD
313from _gdi import *
314from _windows import *
315from _controls import *
316from _misc import *
d14a1e28
RD
317
318#----------------------------------------------------------------------------
319#----------------------------------------------------------------------------