| 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 | |
| 35 | class PyDeadObjectError(AttributeError): |
| 36 | pass |
| 37 | |
| 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 | |
| 47 | def __repr__(self): |
| 48 | if not hasattr(self, "_name"): |
| 49 | self._name = "[unknown]" |
| 50 | return self.reprStr % self._name |
| 51 | |
| 52 | def __getattr__(self, *args): |
| 53 | if not hasattr(self, "_name"): |
| 54 | self._name = "[unknown]" |
| 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 | """ |
| 67 | Some stock objects are created when the wx._core module is |
| 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 ) |
| 87 | |
| 88 | def __nonzero__(self): |
| 89 | return 0 |
| 90 | |
| 91 | |
| 92 | #---------------------------------------------------------------------------- |
| 93 | |
| 94 | def CallAfter(callable, *args, **kw): |
| 95 | """ |
| 96 | Call the specified function after the current and pending event |
| 97 | handlers have been completed. This is also good for making GUI |
| 98 | method calls from non-GUI threads. Any extra positional or |
| 99 | keyword args are passed on to the callable when it is called. |
| 100 | |
| 101 | :see: `wx.FutureCall` |
| 102 | """ |
| 103 | app = wx.GetApp() |
| 104 | assert app is not None, 'No wx.App created yet' |
| 105 | |
| 106 | if not hasattr(app, "_CallAfterId"): |
| 107 | app._CallAfterId = wx.NewEventType() |
| 108 | app.Connect(-1, -1, app._CallAfterId, |
| 109 | lambda event: event.callable(*event.args, **event.kw) ) |
| 110 | evt = wx.PyEvent() |
| 111 | evt.SetEventType(app._CallAfterId) |
| 112 | evt.callable = callable |
| 113 | evt.args = args |
| 114 | evt.kw = kw |
| 115 | wx.PostEvent(app, evt) |
| 116 | |
| 117 | #---------------------------------------------------------------------------- |
| 118 | |
| 119 | |
| 120 | class FutureCall: |
| 121 | """ |
| 122 | A convenience class for `wx.Timer`, that calls the given callable |
| 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 | :see: `wx.CallAfter` |
| 135 | """ |
| 136 | def __init__(self, millis, callable, *args, **kwargs): |
| 137 | self.millis = millis |
| 138 | self.callable = callable |
| 139 | self.SetArgs(*args, **kwargs) |
| 140 | self.runCount = 0 |
| 141 | self.running = False |
| 142 | self.hasRun = False |
| 143 | self.result = None |
| 144 | self.timer = None |
| 145 | self.Start() |
| 146 | |
| 147 | def __del__(self): |
| 148 | self.Stop() |
| 149 | |
| 150 | |
| 151 | def Start(self, millis=None, *args, **kwargs): |
| 152 | """ |
| 153 | (Re)start the timer |
| 154 | """ |
| 155 | self.hasRun = False |
| 156 | if millis is not None: |
| 157 | self.millis = millis |
| 158 | if args or kwargs: |
| 159 | self.SetArgs(*args, **kwargs) |
| 160 | self.Stop() |
| 161 | self.timer = wx.PyTimer(self.Notify) |
| 162 | self.timer.Start(self.millis, wx.TIMER_ONE_SHOT) |
| 163 | self.running = True |
| 164 | Restart = Start |
| 165 | |
| 166 | |
| 167 | def Stop(self): |
| 168 | """ |
| 169 | Stop and destroy the timer. |
| 170 | """ |
| 171 | if self.timer is not None: |
| 172 | self.timer.Stop() |
| 173 | self.timer = None |
| 174 | |
| 175 | |
| 176 | def GetInterval(self): |
| 177 | if self.timer is not None: |
| 178 | return self.timer.GetInterval() |
| 179 | else: |
| 180 | return 0 |
| 181 | |
| 182 | |
| 183 | def IsRunning(self): |
| 184 | return self.timer is not None and self.timer.IsRunning() |
| 185 | |
| 186 | |
| 187 | def SetArgs(self, *args, **kwargs): |
| 188 | """ |
| 189 | (Re)set the args passed to the callable object. This is |
| 190 | useful in conjunction with Restart if you want to schedule a |
| 191 | new call to the same callable object but with different |
| 192 | parameters. |
| 193 | """ |
| 194 | self.args = args |
| 195 | self.kwargs = kwargs |
| 196 | |
| 197 | |
| 198 | def HasRun(self): |
| 199 | return self.hasRun |
| 200 | |
| 201 | def GetResult(self): |
| 202 | return self.result |
| 203 | |
| 204 | def Notify(self): |
| 205 | """ |
| 206 | The timer has expired so call the callable. |
| 207 | """ |
| 208 | if self.callable and getattr(self.callable, 'im_self', True): |
| 209 | self.runCount += 1 |
| 210 | self.running = False |
| 211 | self.result = self.callable(*self.args, **self.kwargs) |
| 212 | self.hasRun = True |
| 213 | if not self.running: |
| 214 | # if it wasn't restarted, then cleanup |
| 215 | wx.CallAfter(self.Stop) |
| 216 | |
| 217 | |
| 218 | |
| 219 | #---------------------------------------------------------------------------- |
| 220 | # Control which items in this module should be documented by epydoc. |
| 221 | # We allow only classes and functions, which will help reduce the size |
| 222 | # of the docs by filtering out the zillions of constants, EVT objects, |
| 223 | # and etc that don't make much sense by themselves, but are instead |
| 224 | # documented (or will be) as part of the classes/functions/methods |
| 225 | # where they should be used. |
| 226 | |
| 227 | class __DocFilter: |
| 228 | """ |
| 229 | A filter for epydoc that only allows non-Ptr classes and |
| 230 | fucntions, in order to reduce the clutter in the API docs. |
| 231 | """ |
| 232 | def __init__(self, globals): |
| 233 | self._globals = globals |
| 234 | |
| 235 | def __call__(self, name): |
| 236 | import types |
| 237 | obj = self._globals.get(name, None) |
| 238 | if type(obj) not in [type, types.ClassType, types.FunctionType, types.BuiltinFunctionType]: |
| 239 | return False |
| 240 | if name.startswith('_') or name.endswith('Ptr') or name.startswith('EVT'): |
| 241 | return False |
| 242 | return True |
| 243 | |
| 244 | #---------------------------------------------------------------------------- |
| 245 | #---------------------------------------------------------------------------- |
| 246 | |
| 247 | # Import other modules in this package that should show up in the |
| 248 | # "core" wx namespace |
| 249 | from _gdi import * |
| 250 | from _windows import * |
| 251 | from _controls import * |
| 252 | from _misc import * |
| 253 | |
| 254 | |
| 255 | # Fixup the stock objects since they can't be used yet. (They will be |
| 256 | # restored in wx.PyApp.OnInit.) |
| 257 | _core_._wxPyFixStockObjects() |
| 258 | |
| 259 | #---------------------------------------------------------------------------- |
| 260 | #---------------------------------------------------------------------------- |