##// END OF EJS Templates
Added code for the GLUT interactive session
Nicolas Rougier -
Show More
@@ -1,29 +1,30 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Extra capabilities for IPython
3 Extra capabilities for IPython
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2009 The IPython Development Team
7 # Copyright (C) 2008-2009 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 from IPython.lib.inputhook import (
17 from IPython.lib.inputhook import (
18 enable_wx, disable_wx,
18 enable_wx, disable_wx,
19 enable_gtk, disable_gtk,
19 enable_gtk, disable_gtk,
20 enable_qt4, disable_qt4,
20 enable_qt4, disable_qt4,
21 enable_tk, disable_tk,
21 enable_tk, disable_tk,
22 enable_glut, disable_glut,
22 enable_pyglet, disable_pyglet,
23 enable_pyglet, disable_pyglet,
23 set_inputhook, clear_inputhook,
24 set_inputhook, clear_inputhook,
24 current_gui
25 current_gui
25 )
26 )
26
27
27 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
28 # Code
29 # Code
29 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
@@ -1,382 +1,521 b''
1 # coding: utf-8
1 # coding: utf-8
2 """
2 """
3 Inputhook management for GUI event loop integration.
3 Inputhook management for GUI event loop integration.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2009 The IPython Development Team
7 # Copyright (C) 2008-2009 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 import ctypes
17 import ctypes
18 import sys
18 import sys
19 import warnings
19 import warnings
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Constants
22 # Constants
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 # Constants for identifying the GUI toolkits.
25 # Constants for identifying the GUI toolkits.
26 GUI_WX = 'wx'
26 GUI_WX = 'wx'
27 GUI_QT = 'qt'
27 GUI_QT = 'qt'
28 GUI_QT4 = 'qt4'
28 GUI_QT4 = 'qt4'
29 GUI_GTK = 'gtk'
29 GUI_GTK = 'gtk'
30 GUI_TK = 'tk'
30 GUI_TK = 'tk'
31 GUI_OSX = 'osx'
31 GUI_OSX = 'osx'
32 GUI_GLUT = 'glut'
32 GUI_PYGLET = 'pyglet'
33 GUI_PYGLET = 'pyglet'
33
34
34 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
35 # Utility classes
36 # Utility classes
36 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
37
38
38
39
39 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
40 # Main InputHookManager class
41 # Main InputHookManager class
41 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
42
43
43
44
44 class InputHookManager(object):
45 class InputHookManager(object):
45 """Manage PyOS_InputHook for different GUI toolkits.
46 """Manage PyOS_InputHook for different GUI toolkits.
46
47
47 This class installs various hooks under ``PyOSInputHook`` to handle
48 This class installs various hooks under ``PyOSInputHook`` to handle
48 GUI event loop integration.
49 GUI event loop integration.
49 """
50 """
50
51
51 def __init__(self):
52 def __init__(self):
52 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
53 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
53 self._apps = {}
54 self._apps = {}
54 self._reset()
55 self._reset()
55
56
56 def _reset(self):
57 def _reset(self):
57 self._callback_pyfunctype = None
58 self._callback_pyfunctype = None
58 self._callback = None
59 self._callback = None
59 self._installed = False
60 self._installed = False
60 self._current_gui = None
61 self._current_gui = None
61
62
62 def get_pyos_inputhook(self):
63 def get_pyos_inputhook(self):
63 """Return the current PyOS_InputHook as a ctypes.c_void_p."""
64 """Return the current PyOS_InputHook as a ctypes.c_void_p."""
64 return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
65 return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
65
66
66 def get_pyos_inputhook_as_func(self):
67 def get_pyos_inputhook_as_func(self):
67 """Return the current PyOS_InputHook as a ctypes.PYFUNCYPE."""
68 """Return the current PyOS_InputHook as a ctypes.PYFUNCYPE."""
68 return self.PYFUNC.in_dll(ctypes.pythonapi,"PyOS_InputHook")
69 return self.PYFUNC.in_dll(ctypes.pythonapi,"PyOS_InputHook")
69
70
70 def set_inputhook(self, callback):
71 def set_inputhook(self, callback):
71 """Set PyOS_InputHook to callback and return the previous one."""
72 """Set PyOS_InputHook to callback and return the previous one."""
72 self._callback = callback
73 self._callback = callback
73 self._callback_pyfunctype = self.PYFUNC(callback)
74 self._callback_pyfunctype = self.PYFUNC(callback)
74 pyos_inputhook_ptr = self.get_pyos_inputhook()
75 pyos_inputhook_ptr = self.get_pyos_inputhook()
75 original = self.get_pyos_inputhook_as_func()
76 original = self.get_pyos_inputhook_as_func()
76 pyos_inputhook_ptr.value = \
77 pyos_inputhook_ptr.value = \
77 ctypes.cast(self._callback_pyfunctype, ctypes.c_void_p).value
78 ctypes.cast(self._callback_pyfunctype, ctypes.c_void_p).value
78 self._installed = True
79 self._installed = True
79 return original
80 return original
80
81
81 def clear_inputhook(self, app=None):
82 def clear_inputhook(self, app=None):
82 """Set PyOS_InputHook to NULL and return the previous one.
83 """Set PyOS_InputHook to NULL and return the previous one.
83
84
84 Parameters
85 Parameters
85 ----------
86 ----------
86 app : optional, ignored
87 app : optional, ignored
87 This parameter is allowed only so that clear_inputhook() can be
88 This parameter is allowed only so that clear_inputhook() can be
88 called with a similar interface as all the ``enable_*`` methods. But
89 called with a similar interface as all the ``enable_*`` methods. But
89 the actual value of the parameter is ignored. This uniform interface
90 the actual value of the parameter is ignored. This uniform interface
90 makes it easier to have user-level entry points in the main IPython
91 makes it easier to have user-level entry points in the main IPython
91 app like :meth:`enable_gui`."""
92 app like :meth:`enable_gui`."""
92 pyos_inputhook_ptr = self.get_pyos_inputhook()
93 pyos_inputhook_ptr = self.get_pyos_inputhook()
93 original = self.get_pyos_inputhook_as_func()
94 original = self.get_pyos_inputhook_as_func()
94 pyos_inputhook_ptr.value = ctypes.c_void_p(None).value
95 pyos_inputhook_ptr.value = ctypes.c_void_p(None).value
95 self._reset()
96 self._reset()
96 return original
97 return original
97
98
98 def clear_app_refs(self, gui=None):
99 def clear_app_refs(self, gui=None):
99 """Clear IPython's internal reference to an application instance.
100 """Clear IPython's internal reference to an application instance.
100
101
101 Whenever we create an app for a user on qt4 or wx, we hold a
102 Whenever we create an app for a user on qt4 or wx, we hold a
102 reference to the app. This is needed because in some cases bad things
103 reference to the app. This is needed because in some cases bad things
103 can happen if a user doesn't hold a reference themselves. This
104 can happen if a user doesn't hold a reference themselves. This
104 method is provided to clear the references we are holding.
105 method is provided to clear the references we are holding.
105
106
106 Parameters
107 Parameters
107 ----------
108 ----------
108 gui : None or str
109 gui : None or str
109 If None, clear all app references. If ('wx', 'qt4') clear
110 If None, clear all app references. If ('wx', 'qt4') clear
110 the app for that toolkit. References are not held for gtk or tk
111 the app for that toolkit. References are not held for gtk or tk
111 as those toolkits don't have the notion of an app.
112 as those toolkits don't have the notion of an app.
112 """
113 """
113 if gui is None:
114 if gui is None:
114 self._apps = {}
115 self._apps = {}
115 elif self._apps.has_key(gui):
116 elif self._apps.has_key(gui):
116 del self._apps[gui]
117 del self._apps[gui]
117
118
118 def enable_wx(self, app=None):
119 def enable_wx(self, app=None):
119 """Enable event loop integration with wxPython.
120 """Enable event loop integration with wxPython.
120
121
121 Parameters
122 Parameters
122 ----------
123 ----------
123 app : WX Application, optional.
124 app : WX Application, optional.
124 Running application to use. If not given, we probe WX for an
125 Running application to use. If not given, we probe WX for an
125 existing application object, and create a new one if none is found.
126 existing application object, and create a new one if none is found.
126
127
127 Notes
128 Notes
128 -----
129 -----
129 This methods sets the ``PyOS_InputHook`` for wxPython, which allows
130 This methods sets the ``PyOS_InputHook`` for wxPython, which allows
130 the wxPython to integrate with terminal based applications like
131 the wxPython to integrate with terminal based applications like
131 IPython.
132 IPython.
132
133
133 If ``app`` is not given we probe for an existing one, and return it if
134 If ``app`` is not given we probe for an existing one, and return it if
134 found. If no existing app is found, we create an :class:`wx.App` as
135 found. If no existing app is found, we create an :class:`wx.App` as
135 follows::
136 follows::
136
137
137 import wx
138 import wx
138 app = wx.App(redirect=False, clearSigInt=False)
139 app = wx.App(redirect=False, clearSigInt=False)
139 """
140 """
140 from IPython.lib.inputhookwx import inputhook_wx
141 from IPython.lib.inputhookwx import inputhook_wx
141 self.set_inputhook(inputhook_wx)
142 self.set_inputhook(inputhook_wx)
142 self._current_gui = GUI_WX
143 self._current_gui = GUI_WX
143 import wx
144 import wx
144 if app is None:
145 if app is None:
145 app = wx.GetApp()
146 app = wx.GetApp()
146 if app is None:
147 if app is None:
147 app = wx.App(redirect=False, clearSigInt=False)
148 app = wx.App(redirect=False, clearSigInt=False)
148 app._in_event_loop = True
149 app._in_event_loop = True
149 self._apps[GUI_WX] = app
150 self._apps[GUI_WX] = app
150 return app
151 return app
151
152
152 def disable_wx(self):
153 def disable_wx(self):
153 """Disable event loop integration with wxPython.
154 """Disable event loop integration with wxPython.
154
155
155 This merely sets PyOS_InputHook to NULL.
156 This merely sets PyOS_InputHook to NULL.
156 """
157 """
157 if self._apps.has_key(GUI_WX):
158 if self._apps.has_key(GUI_WX):
158 self._apps[GUI_WX]._in_event_loop = False
159 self._apps[GUI_WX]._in_event_loop = False
159 self.clear_inputhook()
160 self.clear_inputhook()
160
161
161 def enable_qt4(self, app=None):
162 def enable_qt4(self, app=None):
162 """Enable event loop integration with PyQt4.
163 """Enable event loop integration with PyQt4.
163
164
164 Parameters
165 Parameters
165 ----------
166 ----------
166 app : Qt Application, optional.
167 app : Qt Application, optional.
167 Running application to use. If not given, we probe Qt for an
168 Running application to use. If not given, we probe Qt for an
168 existing application object, and create a new one if none is found.
169 existing application object, and create a new one if none is found.
169
170
170 Notes
171 Notes
171 -----
172 -----
172 This methods sets the PyOS_InputHook for PyQt4, which allows
173 This methods sets the PyOS_InputHook for PyQt4, which allows
173 the PyQt4 to integrate with terminal based applications like
174 the PyQt4 to integrate with terminal based applications like
174 IPython.
175 IPython.
175
176
176 If ``app`` is not given we probe for an existing one, and return it if
177 If ``app`` is not given we probe for an existing one, and return it if
177 found. If no existing app is found, we create an :class:`QApplication`
178 found. If no existing app is found, we create an :class:`QApplication`
178 as follows::
179 as follows::
179
180
180 from PyQt4 import QtCore
181 from PyQt4 import QtCore
181 app = QtGui.QApplication(sys.argv)
182 app = QtGui.QApplication(sys.argv)
182 """
183 """
183 from IPython.external.qt_for_kernel import QtCore, QtGui
184 from IPython.external.qt_for_kernel import QtCore, QtGui
184
185
185 if 'pyreadline' in sys.modules:
186 if 'pyreadline' in sys.modules:
186 # see IPython GitHub Issue #281 for more info on this issue
187 # see IPython GitHub Issue #281 for more info on this issue
187 # Similar intermittent behavior has been reported on OSX,
188 # Similar intermittent behavior has been reported on OSX,
188 # but not consistently reproducible
189 # but not consistently reproducible
189 warnings.warn("""PyReadline's inputhook can conflict with Qt, causing delays
190 warnings.warn("""PyReadline's inputhook can conflict with Qt, causing delays
190 in interactive input. If you do see this issue, we recommend using another GUI
191 in interactive input. If you do see this issue, we recommend using another GUI
191 toolkit if you can, or disable readline with the configuration option
192 toolkit if you can, or disable readline with the configuration option
192 'TerminalInteractiveShell.readline_use=False', specified in a config file or
193 'TerminalInteractiveShell.readline_use=False', specified in a config file or
193 at the command-line""",
194 at the command-line""",
194 RuntimeWarning)
195 RuntimeWarning)
195
196
196 # PyQt4 has had this since 4.3.1. In version 4.2, PyOS_InputHook
197 # PyQt4 has had this since 4.3.1. In version 4.2, PyOS_InputHook
197 # was set when QtCore was imported, but if it ever got removed,
198 # was set when QtCore was imported, but if it ever got removed,
198 # you couldn't reset it. For earlier versions we can
199 # you couldn't reset it. For earlier versions we can
199 # probably implement a ctypes version.
200 # probably implement a ctypes version.
200 try:
201 try:
201 QtCore.pyqtRestoreInputHook()
202 QtCore.pyqtRestoreInputHook()
202 except AttributeError:
203 except AttributeError:
203 pass
204 pass
204
205
205 self._current_gui = GUI_QT4
206 self._current_gui = GUI_QT4
206 if app is None:
207 if app is None:
207 app = QtCore.QCoreApplication.instance()
208 app = QtCore.QCoreApplication.instance()
208 if app is None:
209 if app is None:
209 app = QtGui.QApplication([" "])
210 app = QtGui.QApplication([" "])
210 app._in_event_loop = True
211 app._in_event_loop = True
211 self._apps[GUI_QT4] = app
212 self._apps[GUI_QT4] = app
212 return app
213 return app
213
214
214 def disable_qt4(self):
215 def disable_qt4(self):
215 """Disable event loop integration with PyQt4.
216 """Disable event loop integration with PyQt4.
216
217
217 This merely sets PyOS_InputHook to NULL.
218 This merely sets PyOS_InputHook to NULL.
218 """
219 """
219 if self._apps.has_key(GUI_QT4):
220 if self._apps.has_key(GUI_QT4):
220 self._apps[GUI_QT4]._in_event_loop = False
221 self._apps[GUI_QT4]._in_event_loop = False
221 self.clear_inputhook()
222 self.clear_inputhook()
222
223
223 def enable_gtk(self, app=None):
224 def enable_gtk(self, app=None):
224 """Enable event loop integration with PyGTK.
225 """Enable event loop integration with PyGTK.
225
226
226 Parameters
227 Parameters
227 ----------
228 ----------
228 app : ignored
229 app : ignored
229 Ignored, it's only a placeholder to keep the call signature of all
230 Ignored, it's only a placeholder to keep the call signature of all
230 gui activation methods consistent, which simplifies the logic of
231 gui activation methods consistent, which simplifies the logic of
231 supporting magics.
232 supporting magics.
232
233
233 Notes
234 Notes
234 -----
235 -----
235 This methods sets the PyOS_InputHook for PyGTK, which allows
236 This methods sets the PyOS_InputHook for PyGTK, which allows
236 the PyGTK to integrate with terminal based applications like
237 the PyGTK to integrate with terminal based applications like
237 IPython.
238 IPython.
238 """
239 """
239 import gtk
240 import gtk
240 try:
241 try:
241 gtk.set_interactive(True)
242 gtk.set_interactive(True)
242 self._current_gui = GUI_GTK
243 self._current_gui = GUI_GTK
243 except AttributeError:
244 except AttributeError:
244 # For older versions of gtk, use our own ctypes version
245 # For older versions of gtk, use our own ctypes version
245 from IPython.lib.inputhookgtk import inputhook_gtk
246 from IPython.lib.inputhookgtk import inputhook_gtk
246 self.set_inputhook(inputhook_gtk)
247 self.set_inputhook(inputhook_gtk)
247 self._current_gui = GUI_GTK
248 self._current_gui = GUI_GTK
248
249
249 def disable_gtk(self):
250 def disable_gtk(self):
250 """Disable event loop integration with PyGTK.
251 """Disable event loop integration with PyGTK.
251
252
252 This merely sets PyOS_InputHook to NULL.
253 This merely sets PyOS_InputHook to NULL.
253 """
254 """
254 self.clear_inputhook()
255 self.clear_inputhook()
255
256
256 def enable_tk(self, app=None):
257 def enable_tk(self, app=None):
257 """Enable event loop integration with Tk.
258 """Enable event loop integration with Tk.
258
259
259 Parameters
260 Parameters
260 ----------
261 ----------
261 app : toplevel :class:`Tkinter.Tk` widget, optional.
262 app : toplevel :class:`Tkinter.Tk` widget, optional.
262 Running toplevel widget to use. If not given, we probe Tk for an
263 Running toplevel widget to use. If not given, we probe Tk for an
263 existing one, and create a new one if none is found.
264 existing one, and create a new one if none is found.
264
265
265 Notes
266 Notes
266 -----
267 -----
267 If you have already created a :class:`Tkinter.Tk` object, the only
268 If you have already created a :class:`Tkinter.Tk` object, the only
268 thing done by this method is to register with the
269 thing done by this method is to register with the
269 :class:`InputHookManager`, since creating that object automatically
270 :class:`InputHookManager`, since creating that object automatically
270 sets ``PyOS_InputHook``.
271 sets ``PyOS_InputHook``.
271 """
272 """
272 self._current_gui = GUI_TK
273 self._current_gui = GUI_TK
273 if app is None:
274 if app is None:
274 import Tkinter
275 import Tkinter
275 app = Tkinter.Tk()
276 app = Tkinter.Tk()
276 app.withdraw()
277 app.withdraw()
277 self._apps[GUI_TK] = app
278 self._apps[GUI_TK] = app
278 return app
279 return app
279
280
280 def disable_tk(self):
281 def disable_tk(self):
281 """Disable event loop integration with Tkinter.
282 """Disable event loop integration with Tkinter.
282
283
283 This merely sets PyOS_InputHook to NULL.
284 This merely sets PyOS_InputHook to NULL.
284 """
285 """
285 self.clear_inputhook()
286 self.clear_inputhook()
286
287
287
288
289 <<<<<<< HEAD
288
290
289 def enable_pyglet(self, app=None):
291 def enable_pyglet(self, app=None):
290 """Enable event loop integration with pyglet.
292 """Enable event loop integration with pyglet.
293 =======
294 def enable_glut(self, app=None):
295 """Enable event loop integration with GLUT.
296 >>>>>>> Added code for the GLUT interactive session
291
297
292 Parameters
298 Parameters
293 ----------
299 ----------
294 app : ignored
300 app : ignored
295 Ignored, it's only a placeholder to keep the call signature of all
301 Ignored, it's only a placeholder to keep the call signature of all
296 gui activation methods consistent, which simplifies the logic of
302 gui activation methods consistent, which simplifies the logic of
297 supporting magics.
303 supporting magics.
298
304
299 Notes
305 Notes
300 -----
306 -----
307 <<<<<<< HEAD
301 This methods sets the ``PyOS_InputHook`` for pyglet, which allows
308 This methods sets the ``PyOS_InputHook`` for pyglet, which allows
302 pyglet to integrate with terminal based applications like
309 pyglet to integrate with terminal based applications like
303 IPython.
310 IPython.
304
311
305 """
312 """
306 import pyglet
313 import pyglet
307 from IPython.lib.inputhookpyglet import inputhook_pyglet
314 from IPython.lib.inputhookpyglet import inputhook_pyglet
308 self.set_inputhook(inputhook_pyglet)
315 self.set_inputhook(inputhook_pyglet)
309 self._current_gui = GUI_PYGLET
316 self._current_gui = GUI_PYGLET
310 return app
317 return app
311
318
312 def disable_pyglet(self):
319 def disable_pyglet(self):
313 """Disable event loop integration with pyglet.
320 """Disable event loop integration with pyglet.
314
321
315 This merely sets PyOS_InputHook to NULL.
322 This merely sets PyOS_InputHook to NULL.
316 """
323 """
324 =======
325 This methods sets the PyOS_InputHook for GLUT, which allows
326 the GLUT to integrate with terminal based applications like
327 IPython.
328
329 GLUT is a quite old library and it is difficult to ensure proper
330 integration within IPython since original GLUT does not allow to handle
331 events one by one. Instead, it requires for the mainloop to be entered
332 and never returned (there is not event a function to exit he
333 mainloop). Fortunately, there are alternatives such as freeglut
334 (avaialble for linux and windows) and the OSX implementation gives
335 access to a glutCheckLoop() function that blocks itself until a new
336 event is received. This means we have to setup a default timer to
337 ensure we got at least one event that will unblock the function.
338
339 Furthermore, it is not possible to install these handlers wihtout a
340 window being first created. We choose to make this window visible for
341 the user to realize that it does not need to create a new one (or this
342 will bring troubles). But, display mode options are then set here and
343 it won't be possible for the user to change them without modifying the
344 code or this has to be made availble via IPython options system.
345
346 Script integration
347 ------------------
348
349 ::
350
351 interactive = False
352 if glut.glutGetWindow() > 0:
353 interactive = True
354 else:
355 glut.glutInit(sys.argv)
356 glut.glutInitDisplayMode( glut.GLUT_DOUBLE |
357 glut.GLUT_RGBA |
358 glut.GLUT_DEPTH )
359 ...
360 if not interactive:
361 glut.glutMainLoop()
362 """
363 import OpenGL.GLUT as glut
364 import OpenGL.platform as platform
365
366 def timer_none(fps):
367 ''' Dummy timer function '''
368 pass
369
370 def display():
371 ''' Dummy display function '''
372 pass
373
374 def timer(fps):
375 # We should normally set the active window to 1 and post a
376 # redisplay for each window. The problem is that we do not know
377 # how much active windows we have and there is no function in glut
378 # to get that number.
379 # glut.glutSetWindow(1)
380 glut.glutTimerFunc( int(1000.0/fps), timer, fps)
381 glut.glutPostRedisplay()
382
383 glutMainLoopEvent = None
384 if sys.platform == 'darwin':
385 try:
386 glutCheckLoop = platform.createBaseFunction(
387 'glutCheckLoop', dll=platform.GLUT, resultType=None,
388 argTypes=[],
389 doc='glutCheckLoop( ) -> None',
390 argNames=(),
391 )
392 except AttributeError:
393 raise RuntimeError,\
394 'Your glut implementation does not allow interactive sessions' \
395 'Consider installing freeglut.'
396 glutMainLoopEvent = glutCheckLoop
397 elif glut.HAVE_FREEGLUT:
398 glutMainLoopEvent = glut.glutMainLoopEvent
399 else:
400 raise RuntimeError,\
401 'Your glut implementation does not allow interactive sessions. ' \
402 'Consider installing freeglut.'
403
404 def inputhook_glut():
405 """ Process pending GLUT events only. """
406 # We need to protect against a user pressing Control-C when IPython is
407 # idle and this is running. We trap KeyboardInterrupt and pass.
408 try:
409 glutMainLoopEvent()
410 except KeyboardInterrupt:
411 pass
412 return 0
413
414 # Frame per second : 60
415 # Should be probably an IPython option
416 fps = 60
417 if not self._apps.has_key(GUI_GLUT):
418 glut.glutInit(sys.argv)
419
420 # Display mode shoudl be also an Ipython option since user won't be able
421 # to change it later
422 glut.glutInitDisplayMode(glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH)
423 glut.glutCreateWindow(sys.argv[0])
424 glut.glutReshapeWindow(1,1)
425 glut.glutHideWindow()
426 glut.glutDisplayFunc(display)
427 glut.glutTimerFunc( int(1000.0/fps), timer, fps)
428 else:
429 glut.glutDisplayFunc(display)
430 glut.glutTimerFunc( int(1000.0/fps), timer, fps)
431
432 self.set_inputhook(inputhook_glut)
433 self._current_gui = GUI_GLUT
434 self._apps[GUI_GLUT] = True
435
436
437 def disable_glut(self):
438 """Disable event loop integration with glut.
439
440 This sets PyOS_InputHook to NULL and set the display function to a
441 dummy one and set the timer to a dummy timer that will be triggered
442 very far in the future.
443 """
444 glut.HideWindow()
445 glut.glutTimerFunc( sys.maxint-1, null_timer_none, 0)
446 >>>>>>> Added code for the GLUT interactive session
317 self.clear_inputhook()
447 self.clear_inputhook()
318
448
319
449
320 def current_gui(self):
450 def current_gui(self):
321 """Return a string indicating the currently active GUI or None."""
451 """Return a string indicating the currently active GUI or None."""
322 return self._current_gui
452 return self._current_gui
323
453
324 inputhook_manager = InputHookManager()
454 inputhook_manager = InputHookManager()
325
455
326 enable_wx = inputhook_manager.enable_wx
456 enable_wx = inputhook_manager.enable_wx
327 disable_wx = inputhook_manager.disable_wx
457 disable_wx = inputhook_manager.disable_wx
328 enable_qt4 = inputhook_manager.enable_qt4
458 enable_qt4 = inputhook_manager.enable_qt4
329 disable_qt4 = inputhook_manager.disable_qt4
459 disable_qt4 = inputhook_manager.disable_qt4
330 enable_gtk = inputhook_manager.enable_gtk
460 enable_gtk = inputhook_manager.enable_gtk
331 disable_gtk = inputhook_manager.disable_gtk
461 disable_gtk = inputhook_manager.disable_gtk
332 enable_tk = inputhook_manager.enable_tk
462 enable_tk = inputhook_manager.enable_tk
333 disable_tk = inputhook_manager.disable_tk
463 disable_tk = inputhook_manager.disable_tk
464 <<<<<<< HEAD
334 enable_pyglet = inputhook_manager.enable_pyglet
465 enable_pyglet = inputhook_manager.enable_pyglet
335 disable_pyglet = inputhook_manager.disable_pyglet
466 disable_pyglet = inputhook_manager.disable_pyglet
467 =======
468 enable_glut = inputhook_manager.enable_glut
469 disable_glut = inputhook_manager.disable_glut
470 >>>>>>> Added code for the GLUT interactive session
336 clear_inputhook = inputhook_manager.clear_inputhook
471 clear_inputhook = inputhook_manager.clear_inputhook
337 set_inputhook = inputhook_manager.set_inputhook
472 set_inputhook = inputhook_manager.set_inputhook
338 current_gui = inputhook_manager.current_gui
473 current_gui = inputhook_manager.current_gui
339 clear_app_refs = inputhook_manager.clear_app_refs
474 clear_app_refs = inputhook_manager.clear_app_refs
340
475
341
476
342 # Convenience function to switch amongst them
477 # Convenience function to switch amongst them
343 def enable_gui(gui=None, app=None):
478 def enable_gui(gui=None, app=None):
344 """Switch amongst GUI input hooks by name.
479 """Switch amongst GUI input hooks by name.
345
480
346 This is just a utility wrapper around the methods of the InputHookManager
481 This is just a utility wrapper around the methods of the InputHookManager
347 object.
482 object.
348
483
349 Parameters
484 Parameters
350 ----------
485 ----------
351 gui : optional, string or None
486 gui : optional, string or None
352 If None, clears input hook, otherwise it must be one of the recognized
487 If None, clears input hook, otherwise it must be one of the recognized
353 GUI names (see ``GUI_*`` constants in module).
488 GUI names (see ``GUI_*`` constants in module).
354
489
355 app : optional, existing application object.
490 app : optional, existing application object.
356 For toolkits that have the concept of a global app, you can supply an
491 For toolkits that have the concept of a global app, you can supply an
357 existing one. If not given, the toolkit will be probed for one, and if
492 existing one. If not given, the toolkit will be probed for one, and if
358 none is found, a new one will be created. Note that GTK does not have
493 none is found, a new one will be created. Note that GTK does not have
359 this concept, and passing an app if `gui`=="GTK" will raise an error.
494 this concept, and passing an app if `gui`=="GTK" will raise an error.
360
495
361 Returns
496 Returns
362 -------
497 -------
363 The output of the underlying gui switch routine, typically the actual
498 The output of the underlying gui switch routine, typically the actual
364 PyOS_InputHook wrapper object or the GUI toolkit app created, if there was
499 PyOS_InputHook wrapper object or the GUI toolkit app created, if there was
365 one.
500 one.
366 """
501 """
367 guis = {None: clear_inputhook,
502 guis = {None: clear_inputhook,
368 GUI_OSX: lambda app=False: None,
503 GUI_OSX: lambda app=False: None,
369 GUI_TK: enable_tk,
504 GUI_TK: enable_tk,
370 GUI_GTK: enable_gtk,
505 GUI_GTK: enable_gtk,
371 GUI_WX: enable_wx,
506 GUI_WX: enable_wx,
372 GUI_QT: enable_qt4, # qt3 not supported
507 GUI_QT: enable_qt4, # qt3 not supported
373 GUI_QT4: enable_qt4,
508 GUI_QT4: enable_qt4,
509 <<<<<<< HEAD
374 GUI_PYGLET: enable_pyglet,
510 GUI_PYGLET: enable_pyglet,
375 }
511 }
512 =======
513 GUI_GLUT: enable_glut}
514 >>>>>>> Added code for the GLUT interactive session
376 try:
515 try:
377 gui_hook = guis[gui]
516 gui_hook = guis[gui]
378 except KeyError:
517 except KeyError:
379 e = "Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys())
518 e = "Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys())
380 raise ValueError(e)
519 raise ValueError(e)
381 return gui_hook(app)
520 return gui_hook(app)
382
521
General Comments 0
You need to be logged in to leave comments. Login now