]> git.saurik.com Git - wxWidgets.git/blob - wxPython/src/_core_ex.py
Finally fixed control scrolling
[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 def 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
51 #----------------------------------------------------------------------------
52
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
62 # http://www.alanwood.net/demos/charsetdiffs.html for differences
63 # between the common latin/roman encodings.
64
65 default = _sys.getdefaultencoding()
66 if default == 'ascii':
67 import locale
68 import codecs
69 try:
70 if hasattr(locale, 'getpreferredencoding'):
71 default = locale.getpreferredencoding()
72 else:
73 default = locale.getdefaultlocale()[1]
74 codecs.lookup(default)
75 except (ValueError, LookupError, TypeError):
76 default = _sys.getdefaultencoding()
77 del locale
78 del codecs
79 if default:
80 wx.SetDefaultPyEncoding(default)
81 del default
82
83 #----------------------------------------------------------------------------
84
85 class PyDeadObjectError(AttributeError):
86 pass
87
88 class _wxPyDeadObject(object):
89 """
90 Instances of wx objects that are OOR capable will have their __class__
91 changed to this class when the C++ object is deleted. This should help
92 prevent crashes due to referencing a bogus C++ pointer.
93 """
94 reprStr = "wxPython wrapper for DELETED %s object! (The C++ object no longer exists.)"
95 attrStr = "The C++ part of the %s object has been deleted, attribute access no longer allowed."
96
97 def __repr__(self):
98 if not hasattr(self, "_name"):
99 self._name = "[unknown]"
100 return self.reprStr % self._name
101
102 def __getattr__(self, *args):
103 if not hasattr(self, "_name"):
104 self._name = "[unknown]"
105 raise PyDeadObjectError(self.attrStr % self._name)
106
107 def __nonzero__(self):
108 return 0
109
110
111
112 class PyUnbornObjectError(AttributeError):
113 pass
114
115 class _wxPyUnbornObject(object):
116 """
117 Some stock objects are created when the wx._core module is
118 imported, but their C++ instance is not created until the wx.App
119 object is created and initialized. These object instances will
120 temporarily have their __class__ changed to this class so an
121 exception will be raised if they are used before the C++ instance
122 is ready.
123 """
124
125 reprStr = "wxPython wrapper for UNBORN object! (The C++ object is not initialized yet.)"
126 attrStr = "The C++ part of this object has not been initialized, attribute access not allowed."
127
128 def __repr__(self):
129 #if not hasattr(self, "_name"):
130 # self._name = "[unknown]"
131 return self.reprStr #% self._name
132
133 def __getattr__(self, *args):
134 #if not hasattr(self, "_name"):
135 # self._name = "[unknown]"
136 raise PyUnbornObjectError(self.attrStr) # % self._name )
137
138 def __nonzero__(self):
139 return 0
140
141
142 #----------------------------------------------------------------------------
143
144 def CallAfter(callable, *args, **kw):
145 """
146 Call the specified function after the current and pending event
147 handlers have been completed. This is also good for making GUI
148 method calls from non-GUI threads. Any extra positional or
149 keyword args are passed on to the callable when it is called.
150
151 :see: `wx.CallLater`
152 """
153 app = wx.GetApp()
154 assert app is not None, 'No wx.App created yet'
155
156 if not hasattr(app, "_CallAfterId"):
157 app._CallAfterId = wx.NewEventType()
158 app.Connect(-1, -1, app._CallAfterId,
159 lambda event: event.callable(*event.args, **event.kw) )
160 evt = wx.PyEvent()
161 evt.SetEventType(app._CallAfterId)
162 evt.callable = callable
163 evt.args = args
164 evt.kw = kw
165 wx.PostEvent(app, evt)
166
167 #----------------------------------------------------------------------------
168
169
170 class CallLater:
171 """
172 A convenience class for `wx.Timer`, that calls the given callable
173 object once after the given amount of milliseconds, passing any
174 positional or keyword args. The return value of the callable is
175 availbale after it has been run with the `GetResult` method.
176
177 If you don't need to get the return value or restart the timer
178 then there is no need to hold a reference to this object. It will
179 hold a reference to itself while the timer is running (the timer
180 has a reference to self.Notify) but the cycle will be broken when
181 the timer completes, automatically cleaning up the wx.CallLater
182 object.
183
184 :see: `wx.CallAfter`
185 """
186 def __init__(self, millis, callable, *args, **kwargs):
187 self.millis = millis
188 self.callable = callable
189 self.SetArgs(*args, **kwargs)
190 self.runCount = 0
191 self.running = False
192 self.hasRun = False
193 self.result = None
194 self.timer = None
195 self.Start()
196
197 def __del__(self):
198 self.Stop()
199
200
201 def Start(self, millis=None, *args, **kwargs):
202 """
203 (Re)start the timer
204 """
205 self.hasRun = False
206 if millis is not None:
207 self.millis = millis
208 if args or kwargs:
209 self.SetArgs(*args, **kwargs)
210 self.Stop()
211 self.timer = wx.PyTimer(self.Notify)
212 self.timer.Start(self.millis, wx.TIMER_ONE_SHOT)
213 self.running = True
214 Restart = Start
215
216
217 def Stop(self):
218 """
219 Stop and destroy the timer.
220 """
221 if self.timer is not None:
222 self.timer.Stop()
223 self.timer = None
224
225
226 def GetInterval(self):
227 if self.timer is not None:
228 return self.timer.GetInterval()
229 else:
230 return 0
231
232
233 def IsRunning(self):
234 return self.timer is not None and self.timer.IsRunning()
235
236
237 def SetArgs(self, *args, **kwargs):
238 """
239 (Re)set the args passed to the callable object. This is
240 useful in conjunction with Restart if you want to schedule a
241 new call to the same callable object but with different
242 parameters.
243 """
244 self.args = args
245 self.kwargs = kwargs
246
247
248 def HasRun(self):
249 return self.hasRun
250
251 def GetResult(self):
252 return self.result
253
254 def Notify(self):
255 """
256 The timer has expired so call the callable.
257 """
258 if self.callable and getattr(self.callable, 'im_self', True):
259 self.runCount += 1
260 self.running = False
261 self.result = self.callable(*self.args, **self.kwargs)
262 self.hasRun = True
263 if not self.running:
264 # if it wasn't restarted, then cleanup
265 wx.CallAfter(self.Stop)
266
267 Interval = property(GetInterval)
268 Result = property(GetResult)
269
270
271 class FutureCall(CallLater):
272 """A compatibility alias for `CallLater`."""
273
274 #----------------------------------------------------------------------------
275 # Control which items in this module should be documented by epydoc.
276 # We allow only classes and functions, which will help reduce the size
277 # of the docs by filtering out the zillions of constants, EVT objects,
278 # and etc that don't make much sense by themselves, but are instead
279 # documented (or will be) as part of the classes/functions/methods
280 # where they should be used.
281
282 class __DocFilter:
283 """
284 A filter for epydoc that only allows non-Ptr classes and
285 functions, in order to reduce the clutter in the API docs.
286 """
287 def __init__(self, globals):
288 self._globals = globals
289
290 def __call__(self, name):
291 import types
292 obj = self._globals.get(name, None)
293
294 # only document classes and function
295 if type(obj) not in [type, types.ClassType, types.FunctionType, types.BuiltinFunctionType]:
296 return False
297
298 # skip other things that are private or will be documented as part of somethign else
299 if name.startswith('_') or name.startswith('EVT') or name.endswith('_swigregister') or name.endswith('Ptr') :
300 return False
301
302 # skip functions that are duplicates of static functions in a class
303 if name.find('_') != -1:
304 cls = self._globals.get(name.split('_')[0], None)
305 methname = name.split('_')[1]
306 if hasattr(cls, methname) and type(getattr(cls, methname)) is types.FunctionType:
307 return False
308
309 return True
310
311 #----------------------------------------------------------------------------
312 #----------------------------------------------------------------------------
313
314 # Import other modules in this package that should show up in the
315 # "core" wx namespace
316 from _gdi import *
317 from _windows import *
318 from _controls import *
319 from _misc import *
320
321 #----------------------------------------------------------------------------
322 #----------------------------------------------------------------------------