]> git.saurik.com Git - wxWidgets.git/blob - wxPython/src/_core_ex.py
Tweaks to work around wxMac bugs
[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 wxWindows.
23
24 from __version__ import *
25 __version__ = VERSION_STRING
26
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:
30 import warnings
31 warnings.warn("wxPython/wxWindows 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 _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
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
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 def __init__(self, millis, callable, *args, **kwargs):
135 self.millis = millis
136 self.callable = callable
137 self.SetArgs(*args, **kwargs)
138 self.runCount = 0
139 self.running = False
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)
161 self.running = True
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
208 self.running = False
209 self.result = self.callable(*self.args, **self.kwargs)
210 self.hasRun = True
211 if not self.running:
212 # if it wasn't restarted, then cleanup
213 wx.CallAfter(self.Stop)
214
215
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
225 class __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
241
242 #----------------------------------------------------------------------------
243 #----------------------------------------------------------------------------
244
245 # Import other modules in this package that should show up in the
246 # "core" wx namespace
247 from _gdi import *
248 from _windows import *
249 from _controls import *
250 from _misc import *
251
252
253 # Fixup the stock objects since they can't be used yet. (They will be
254 # restored in wx.PyApp.OnInit.)
255 _core_._wxPyFixStockObjects()
256
257 #----------------------------------------------------------------------------
258 #----------------------------------------------------------------------------