]>
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 | |
d14a1e28 | 9 | |
d14a1e28 RD |
10 | |
11 | ||
12 | # workarounds for bad wxRTTI names | |
13 | __wxPyPtrTypeMap['wxGauge95'] = 'wxGauge' | |
14 | __wxPyPtrTypeMap['wxSlider95'] = 'wxSlider' | |
15 | __wxPyPtrTypeMap['wxStatusBar95'] = 'wxStatusBar' | |
16 | ||
17 | ||
18 | #---------------------------------------------------------------------------- | |
19 | # Load version numbers from __version__... Ensure that major and minor | |
20 | # versions are the same for both wxPython and wxWindows. | |
21 | ||
22 | from __version__ import * | |
23 | __version__ = VERSION_STRING | |
24 | ||
25 | assert MAJOR_VERSION == _core.MAJOR_VERSION, "wxPython/wxWindows version mismatch" | |
26 | assert MINOR_VERSION == _core.MINOR_VERSION, "wxPython/wxWindows version mismatch" | |
27 | if RELEASE_VERSION != _core.RELEASE_VERSION: | |
28 | import warnings | |
29 | warnings.warn("wxPython/wxWindows release number mismatch") | |
30 | ||
31 | #---------------------------------------------------------------------------- | |
32 | ||
33 | class PyDeadObjectError(AttributeError): | |
34 | pass | |
35 | ||
d14a1e28 RD |
36 | class _wxPyDeadObject(object): |
37 | """ | |
38 | Instances of wx objects that are OOR capable will have their __class__ | |
39 | changed to this class when the C++ object is deleted. This should help | |
40 | prevent crashes due to referencing a bogus C++ pointer. | |
41 | """ | |
42 | reprStr = "wxPython wrapper for DELETED %s object! (The C++ object no longer exists.)" | |
43 | attrStr = "The C++ part of the %s object has been deleted, attribute access no longer allowed." | |
44 | ||
9e58eb56 | 45 | def __repr__(self): |
d14a1e28 RD |
46 | if not hasattr(self, "_name"): |
47 | self._name = "[unknown]" | |
48 | return self.reprStr % self._name | |
49 | ||
9e58eb56 | 50 | def __getattr__(self, *args): |
d14a1e28 RD |
51 | if not hasattr(self, "_name"): |
52 | self._name = "[unknown]" | |
9e58eb56 RD |
53 | raise PyDeadObjectError(self.attrStr % self._name) |
54 | ||
55 | def __nonzero__(self): | |
56 | return 0 | |
57 | ||
58 | ||
59 | ||
60 | class PyUnbornObjectError(AttributeError): | |
61 | pass | |
62 | ||
63 | class _wxPyUnbornObject(object): | |
64 | """ | |
65 | Some stock objects are created when the wx.core module is | |
66 | imported, but their C++ instance is not created until the wx.App | |
67 | object is created and initialized. These object instances will | |
68 | temporarily have their __class__ changed to this class so an | |
69 | exception will be raised if they are used before the C++ instance | |
70 | is ready. | |
71 | """ | |
72 | ||
73 | reprStr = "wxPython wrapper for UNBORN object! (The C++ object is not initialized yet.)" | |
74 | attrStr = "The C++ part of this object has not been initialized, attribute access not allowed." | |
75 | ||
76 | def __repr__(self): | |
77 | #if not hasattr(self, "_name"): | |
78 | # self._name = "[unknown]" | |
79 | return self.reprStr #% self._name | |
80 | ||
81 | def __getattr__(self, *args): | |
82 | #if not hasattr(self, "_name"): | |
83 | # self._name = "[unknown]" | |
84 | raise PyUnbornObjectError(self.attrStr) # % self._name ) | |
d14a1e28 RD |
85 | |
86 | def __nonzero__(self): | |
87 | return 0 | |
88 | ||
89 | ||
90 | #---------------------------------------------------------------------------- | |
91 | _wxPyCallAfterId = None | |
92 | ||
93 | def CallAfter(callable, *args, **kw): | |
94 | """ | |
95 | Call the specified function after the current and pending event | |
96 | handlers have been completed. This is also good for making GUI | |
97 | method calls from non-GUI threads. | |
98 | """ | |
99 | app = wx.GetApp() | |
100 | assert app, 'No wxApp created yet' | |
101 | ||
102 | global _wxPyCallAfterId | |
103 | if _wxPyCallAfterId is None: | |
104 | _wxPyCallAfterId = wx.NewEventType() | |
105 | app.Connect(-1, -1, _wxPyCallAfterId, | |
106 | lambda event: event.callable(*event.args, **event.kw) ) | |
107 | evt = wx.PyEvent() | |
108 | evt.SetEventType(_wxPyCallAfterId) | |
109 | evt.callable = callable | |
110 | evt.args = args | |
111 | evt.kw = kw | |
112 | wx.PostEvent(app, evt) | |
113 | ||
114 | ||
115 | #---------------------------------------------------------------------------- | |
116 | ||
117 | ||
118 | class FutureCall: | |
119 | """ | |
66065839 | 120 | A convenience class for wx.Timer, that calls the given callable |
d14a1e28 RD |
121 | object once after the given amount of milliseconds, passing any |
122 | positional or keyword args. The return value of the callable is | |
123 | availbale after it has been run with the GetResult method. | |
124 | ||
125 | If you don't need to get the return value or restart the timer | |
126 | then there is no need to hold a reference to this object. It will | |
127 | hold a reference to itself while the timer is running (the timer | |
128 | has a reference to self.Notify) but the cycle will be broken when | |
129 | the timer completes, automatically cleaning up the wx.FutureCall | |
130 | object. | |
131 | """ | |
132 | def __init__(self, millis, callable, *args, **kwargs): | |
133 | self.millis = millis | |
134 | self.callable = callable | |
135 | self.SetArgs(*args, **kwargs) | |
136 | self.runCount = 0 | |
66065839 | 137 | self.running = False |
d14a1e28 RD |
138 | self.hasRun = False |
139 | self.result = None | |
140 | self.timer = None | |
141 | self.Start() | |
142 | ||
143 | def __del__(self): | |
144 | self.Stop() | |
145 | ||
146 | ||
147 | def Start(self, millis=None, *args, **kwargs): | |
148 | """ | |
149 | (Re)start the timer | |
150 | """ | |
151 | self.hasRun = False | |
152 | if millis is not None: | |
153 | self.millis = millis | |
154 | if args or kwargs: | |
155 | self.SetArgs(*args, **kwargs) | |
156 | self.Stop() | |
157 | self.timer = wx.PyTimer(self.Notify) | |
158 | self.timer.Start(self.millis, wx.TIMER_ONE_SHOT) | |
66065839 | 159 | self.running = True |
d14a1e28 RD |
160 | Restart = Start |
161 | ||
162 | ||
163 | def Stop(self): | |
164 | """ | |
165 | Stop and destroy the timer. | |
166 | """ | |
167 | if self.timer is not None: | |
168 | self.timer.Stop() | |
169 | self.timer = None | |
170 | ||
171 | ||
172 | def GetInterval(self): | |
173 | if self.timer is not None: | |
174 | return self.timer.GetInterval() | |
175 | else: | |
176 | return 0 | |
177 | ||
178 | ||
179 | def IsRunning(self): | |
180 | return self.timer is not None and self.timer.IsRunning() | |
181 | ||
182 | ||
183 | def SetArgs(self, *args, **kwargs): | |
184 | """ | |
185 | (Re)set the args passed to the callable object. This is | |
186 | useful in conjunction with Restart if you want to schedule a | |
187 | new call to the same callable object but with different | |
188 | parameters. | |
189 | """ | |
190 | self.args = args | |
191 | self.kwargs = kwargs | |
192 | ||
193 | ||
194 | def HasRun(self): | |
195 | return self.hasRun | |
196 | ||
197 | def GetResult(self): | |
198 | return self.result | |
199 | ||
200 | def Notify(self): | |
201 | """ | |
202 | The timer has expired so call the callable. | |
203 | """ | |
204 | if self.callable and getattr(self.callable, 'im_self', True): | |
205 | self.runCount += 1 | |
66065839 | 206 | self.running = False |
d14a1e28 RD |
207 | self.result = self.callable(*self.args, **self.kwargs) |
208 | self.hasRun = True | |
66065839 RD |
209 | if not self.running: |
210 | # if it wasn't restarted, then cleanup | |
211 | wx.CallAfter(self.Stop) | |
d14a1e28 RD |
212 | |
213 | ||
214 | #---------------------------------------------------------------------------- | |
215 | #---------------------------------------------------------------------------- | |
216 | ||
217 | # Import other modules in this package that should show up in the | |
218 | # "core" wx namespace | |
219 | from gdi import * | |
220 | from windows import * | |
221 | from controls import * | |
222 | from misc import * | |
223 | ||
9e58eb56 RD |
224 | |
225 | # Fixup the stock objects since they can't be used yet. (They will be | |
226 | # restored in wx.PyApp.OnInit.) | |
227 | _core._wxPyFixStockObjects() | |
228 | ||
d14a1e28 RD |
229 | #---------------------------------------------------------------------------- |
230 | #---------------------------------------------------------------------------- |