]> git.saurik.com Git - wxWidgets.git/blame - wxPython/src/_core_ex.py
Some error recovery and other tweaks
[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
22# versions are the same for both wxPython and wxWindows.
23
24from __version__ import *
25__version__ = VERSION_STRING
26
54f9ee45
RD
27assert MAJOR_VERSION == _core_.MAJOR_VERSION, "wxPython/wxWindows version mismatch"
28assert MINOR_VERSION == _core_.MINOR_VERSION, "wxPython/wxWindows version mismatch"
29if RELEASE_VERSION != _core_.RELEASE_VERSION:
d14a1e28
RD
30 import warnings
31 warnings.warn("wxPython/wxWindows release number mismatch")
32
33#----------------------------------------------------------------------------
34
35class PyDeadObjectError(AttributeError):
36 pass
37
d14a1e28
RD
38class _wxPyDeadObject(object):
39 """
40 Instances of wx objects that are OOR capable will have their __class__
41 changed to this class when the C++ object is deleted. This should help
42 prevent crashes due to referencing a bogus C++ pointer.
43 """
44 reprStr = "wxPython wrapper for DELETED %s object! (The C++ object no longer exists.)"
45 attrStr = "The C++ part of the %s object has been deleted, attribute access no longer allowed."
46
9e58eb56 47 def __repr__(self):
d14a1e28
RD
48 if not hasattr(self, "_name"):
49 self._name = "[unknown]"
50 return self.reprStr % self._name
51
9e58eb56 52 def __getattr__(self, *args):
d14a1e28
RD
53 if not hasattr(self, "_name"):
54 self._name = "[unknown]"
9e58eb56
RD
55 raise PyDeadObjectError(self.attrStr % self._name)
56
57 def __nonzero__(self):
58 return 0
59
60
61
62class PyUnbornObjectError(AttributeError):
63 pass
64
65class _wxPyUnbornObject(object):
66 """
54f9ee45 67 Some stock objects are created when the wx._core module is
9e58eb56
RD
68 imported, but their C++ instance is not created until the wx.App
69 object is created and initialized. These object instances will
70 temporarily have their __class__ changed to this class so an
71 exception will be raised if they are used before the C++ instance
72 is ready.
73 """
74
75 reprStr = "wxPython wrapper for UNBORN object! (The C++ object is not initialized yet.)"
76 attrStr = "The C++ part of this object has not been initialized, attribute access not allowed."
77
78 def __repr__(self):
79 #if not hasattr(self, "_name"):
80 # self._name = "[unknown]"
81 return self.reprStr #% self._name
82
83 def __getattr__(self, *args):
84 #if not hasattr(self, "_name"):
85 # self._name = "[unknown]"
86 raise PyUnbornObjectError(self.attrStr) # % self._name )
d14a1e28
RD
87
88 def __nonzero__(self):
89 return 0
90
91
92#----------------------------------------------------------------------------
93_wxPyCallAfterId = None
94
95def CallAfter(callable, *args, **kw):
96 """
97 Call the specified function after the current and pending event
98 handlers have been completed. This is also good for making GUI
99 method calls from non-GUI threads.
100 """
101 app = wx.GetApp()
102 assert app, 'No wxApp created yet'
103
104 global _wxPyCallAfterId
105 if _wxPyCallAfterId is None:
106 _wxPyCallAfterId = wx.NewEventType()
107 app.Connect(-1, -1, _wxPyCallAfterId,
108 lambda event: event.callable(*event.args, **event.kw) )
109 evt = wx.PyEvent()
110 evt.SetEventType(_wxPyCallAfterId)
111 evt.callable = callable
112 evt.args = args
113 evt.kw = kw
114 wx.PostEvent(app, evt)
115
116
117#----------------------------------------------------------------------------
118
119
120class FutureCall:
121 """
66065839 122 A convenience class for wx.Timer, that calls the given callable
d14a1e28
RD
123 object once after the given amount of milliseconds, passing any
124 positional or keyword args. The return value of the callable is
125 availbale after it has been run with the GetResult method.
126
127 If you don't need to get the return value or restart the timer
128 then there is no need to hold a reference to this object. It will
129 hold a reference to itself while the timer is running (the timer
130 has a reference to self.Notify) but the cycle will be broken when
131 the timer completes, automatically cleaning up the wx.FutureCall
132 object.
133 """
134 def __init__(self, millis, callable, *args, **kwargs):
135 self.millis = millis
136 self.callable = callable
137 self.SetArgs(*args, **kwargs)
138 self.runCount = 0
66065839 139 self.running = False
d14a1e28
RD
140 self.hasRun = False
141 self.result = None
142 self.timer = None
143 self.Start()
144
145 def __del__(self):
146 self.Stop()
147
148
149 def Start(self, millis=None, *args, **kwargs):
150 """
151 (Re)start the timer
152 """
153 self.hasRun = False
154 if millis is not None:
155 self.millis = millis
156 if args or kwargs:
157 self.SetArgs(*args, **kwargs)
158 self.Stop()
159 self.timer = wx.PyTimer(self.Notify)
160 self.timer.Start(self.millis, wx.TIMER_ONE_SHOT)
66065839 161 self.running = True
d14a1e28
RD
162 Restart = Start
163
164
165 def Stop(self):
166 """
167 Stop and destroy the timer.
168 """
169 if self.timer is not None:
170 self.timer.Stop()
171 self.timer = None
172
173
174 def GetInterval(self):
175 if self.timer is not None:
176 return self.timer.GetInterval()
177 else:
178 return 0
179
180
181 def IsRunning(self):
182 return self.timer is not None and self.timer.IsRunning()
183
184
185 def SetArgs(self, *args, **kwargs):
186 """
187 (Re)set the args passed to the callable object. This is
188 useful in conjunction with Restart if you want to schedule a
189 new call to the same callable object but with different
190 parameters.
191 """
192 self.args = args
193 self.kwargs = kwargs
194
195
196 def HasRun(self):
197 return self.hasRun
198
199 def GetResult(self):
200 return self.result
201
202 def Notify(self):
203 """
204 The timer has expired so call the callable.
205 """
206 if self.callable and getattr(self.callable, 'im_self', True):
207 self.runCount += 1
66065839 208 self.running = False
d14a1e28
RD
209 self.result = self.callable(*self.args, **self.kwargs)
210 self.hasRun = True
66065839
RD
211 if not self.running:
212 # if it wasn't restarted, then cleanup
213 wx.CallAfter(self.Stop)
d14a1e28
RD
214
215
5b29df3f
RD
216
217#----------------------------------------------------------------------------
218# Control which items in this module should be documented by epydoc.
219# We allow only classes and functions, which will help reduce the size
220# of the docs by filtering out the zillions of constants, EVT objects,
221# and etc that don't make much sense by themselves, but are instead
222# documented (or will be) as part of the classes/functions/methods
223# where they should be used.
224
99109c0f
RD
225class __DocFilter:
226 """
227 A filter for epydoc that only allows non-Ptr classes and
228 fucntions, in order to reduce the clutter in the API docs.
229 """
230 def __init__(self, globals):
231 self._globals = globals
232
233 def __call__(self, name):
234 import types
235 obj = self._globals.get(name, None)
236 if type(obj) not in [type, types.ClassType, types.FunctionType, types.BuiltinFunctionType]:
237 return False
238 if name.startswith('_') or name.endswith('Ptr') or name.startswith('EVT'):
239 return False
240 return True
5b29df3f 241
d14a1e28
RD
242#----------------------------------------------------------------------------
243#----------------------------------------------------------------------------
244
245# Import other modules in this package that should show up in the
246# "core" wx namespace
54f9ee45
RD
247from _gdi import *
248from _windows import *
249from _controls import *
250from _misc import *
d14a1e28 251
9e58eb56
RD
252
253# Fixup the stock objects since they can't be used yet. (They will be
254# restored in wx.PyApp.OnInit.)
54f9ee45 255_core_._wxPyFixStockObjects()
9e58eb56 256
d14a1e28
RD
257#----------------------------------------------------------------------------
258#----------------------------------------------------------------------------