]>
Commit | Line | Data |
---|---|---|
d14a1e28 RD |
1 | #---------------------------------------------------------------------------- |
2 | ||
322913ce | 3 | # Use Python's bool constants if available, make some if not |
d14a1e28 RD |
4 | try: |
5 | True | |
6 | except 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 | ||
24 | from __version__ import * | |
25 | __version__ = VERSION_STRING | |
26 | ||
54f9ee45 RD |
27 | assert MAJOR_VERSION == _core_.MAJOR_VERSION, "wxPython/wxWindows version mismatch" |
28 | assert MINOR_VERSION == _core_.MINOR_VERSION, "wxPython/wxWindows version mismatch" | |
29 | if RELEASE_VERSION != _core_.RELEASE_VERSION: | |
d14a1e28 RD |
30 | import warnings |
31 | warnings.warn("wxPython/wxWindows release number mismatch") | |
32 | ||
33 | #---------------------------------------------------------------------------- | |
34 | ||
35 | class PyDeadObjectError(AttributeError): | |
36 | pass | |
37 | ||
d14a1e28 RD |
38 | class _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 | ||
62 | class PyUnbornObjectError(AttributeError): | |
63 | pass | |
64 | ||
65 | class _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 | ||
95 | def 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 | |
61863841 RD |
99 | method calls from non-GUI threads. Any extra positional or |
100 | keyword args are passed on to the callable when it is called. | |
101 | ||
102 | :see: `wx.FutureCall` | |
d14a1e28 RD |
103 | """ |
104 | app = wx.GetApp() | |
2148e701 | 105 | assert app is not None, 'No wx.App created yet' |
d14a1e28 RD |
106 | |
107 | global _wxPyCallAfterId | |
108 | if _wxPyCallAfterId is None: | |
109 | _wxPyCallAfterId = wx.NewEventType() | |
110 | app.Connect(-1, -1, _wxPyCallAfterId, | |
111 | lambda event: event.callable(*event.args, **event.kw) ) | |
112 | evt = wx.PyEvent() | |
113 | evt.SetEventType(_wxPyCallAfterId) | |
114 | evt.callable = callable | |
115 | evt.args = args | |
116 | evt.kw = kw | |
117 | wx.PostEvent(app, evt) | |
118 | ||
119 | ||
120 | #---------------------------------------------------------------------------- | |
121 | ||
122 | ||
123 | class FutureCall: | |
124 | """ | |
66065839 | 125 | A convenience class for wx.Timer, that calls the given callable |
d14a1e28 RD |
126 | object once after the given amount of milliseconds, passing any |
127 | positional or keyword args. The return value of the callable is | |
61863841 | 128 | availbale after it has been run with the `GetResult` method. |
d14a1e28 RD |
129 | |
130 | If you don't need to get the return value or restart the timer | |
131 | then there is no need to hold a reference to this object. It will | |
132 | hold a reference to itself while the timer is running (the timer | |
133 | has a reference to self.Notify) but the cycle will be broken when | |
134 | the timer completes, automatically cleaning up the wx.FutureCall | |
135 | object. | |
61863841 RD |
136 | |
137 | :see: `wx.CallAfter` | |
d14a1e28 RD |
138 | """ |
139 | def __init__(self, millis, callable, *args, **kwargs): | |
140 | self.millis = millis | |
141 | self.callable = callable | |
142 | self.SetArgs(*args, **kwargs) | |
143 | self.runCount = 0 | |
66065839 | 144 | self.running = False |
d14a1e28 RD |
145 | self.hasRun = False |
146 | self.result = None | |
147 | self.timer = None | |
148 | self.Start() | |
149 | ||
150 | def __del__(self): | |
151 | self.Stop() | |
152 | ||
153 | ||
154 | def Start(self, millis=None, *args, **kwargs): | |
155 | """ | |
156 | (Re)start the timer | |
157 | """ | |
158 | self.hasRun = False | |
159 | if millis is not None: | |
160 | self.millis = millis | |
161 | if args or kwargs: | |
162 | self.SetArgs(*args, **kwargs) | |
163 | self.Stop() | |
164 | self.timer = wx.PyTimer(self.Notify) | |
165 | self.timer.Start(self.millis, wx.TIMER_ONE_SHOT) | |
66065839 | 166 | self.running = True |
d14a1e28 RD |
167 | Restart = Start |
168 | ||
169 | ||
170 | def Stop(self): | |
171 | """ | |
172 | Stop and destroy the timer. | |
173 | """ | |
174 | if self.timer is not None: | |
175 | self.timer.Stop() | |
176 | self.timer = None | |
177 | ||
178 | ||
179 | def GetInterval(self): | |
180 | if self.timer is not None: | |
181 | return self.timer.GetInterval() | |
182 | else: | |
183 | return 0 | |
184 | ||
185 | ||
186 | def IsRunning(self): | |
187 | return self.timer is not None and self.timer.IsRunning() | |
188 | ||
189 | ||
190 | def SetArgs(self, *args, **kwargs): | |
191 | """ | |
192 | (Re)set the args passed to the callable object. This is | |
193 | useful in conjunction with Restart if you want to schedule a | |
194 | new call to the same callable object but with different | |
195 | parameters. | |
196 | """ | |
197 | self.args = args | |
198 | self.kwargs = kwargs | |
199 | ||
200 | ||
201 | def HasRun(self): | |
202 | return self.hasRun | |
203 | ||
204 | def GetResult(self): | |
205 | return self.result | |
206 | ||
207 | def Notify(self): | |
208 | """ | |
209 | The timer has expired so call the callable. | |
210 | """ | |
211 | if self.callable and getattr(self.callable, 'im_self', True): | |
212 | self.runCount += 1 | |
66065839 | 213 | self.running = False |
d14a1e28 RD |
214 | self.result = self.callable(*self.args, **self.kwargs) |
215 | self.hasRun = True | |
66065839 RD |
216 | if not self.running: |
217 | # if it wasn't restarted, then cleanup | |
218 | wx.CallAfter(self.Stop) | |
d14a1e28 RD |
219 | |
220 | ||
5b29df3f RD |
221 | |
222 | #---------------------------------------------------------------------------- | |
223 | # Control which items in this module should be documented by epydoc. | |
224 | # We allow only classes and functions, which will help reduce the size | |
225 | # of the docs by filtering out the zillions of constants, EVT objects, | |
226 | # and etc that don't make much sense by themselves, but are instead | |
227 | # documented (or will be) as part of the classes/functions/methods | |
228 | # where they should be used. | |
229 | ||
99109c0f RD |
230 | class __DocFilter: |
231 | """ | |
232 | A filter for epydoc that only allows non-Ptr classes and | |
233 | fucntions, in order to reduce the clutter in the API docs. | |
234 | """ | |
235 | def __init__(self, globals): | |
236 | self._globals = globals | |
237 | ||
238 | def __call__(self, name): | |
239 | import types | |
240 | obj = self._globals.get(name, None) | |
241 | if type(obj) not in [type, types.ClassType, types.FunctionType, types.BuiltinFunctionType]: | |
242 | return False | |
243 | if name.startswith('_') or name.endswith('Ptr') or name.startswith('EVT'): | |
244 | return False | |
245 | return True | |
5b29df3f | 246 | |
d14a1e28 RD |
247 | #---------------------------------------------------------------------------- |
248 | #---------------------------------------------------------------------------- | |
249 | ||
250 | # Import other modules in this package that should show up in the | |
251 | # "core" wx namespace | |
54f9ee45 RD |
252 | from _gdi import * |
253 | from _windows import * | |
254 | from _controls import * | |
255 | from _misc import * | |
d14a1e28 | 256 | |
9e58eb56 RD |
257 | |
258 | # Fixup the stock objects since they can't be used yet. (They will be | |
259 | # restored in wx.PyApp.OnInit.) | |
54f9ee45 | 260 | _core_._wxPyFixStockObjects() |
9e58eb56 | 261 | |
d14a1e28 RD |
262 | #---------------------------------------------------------------------------- |
263 | #---------------------------------------------------------------------------- |