Hi
I have been trying to write a modal win lately. Any idea how it could be
done better? Should a ModalWindow class have a show_modal(...) method?
Or maybe some events shouldn't be forwarded... not sure. It should work
on any platform since it doesn't use any platform specific code. Let me
know if you have any trouble on a certain platform.
The example opens a window, press 'M' for another modal window or press
'R' for a window that redirects its events to a single function. You can
open hierarchical modal windows.
Any feedback appreciated.
~DR0ID
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"pyglet-users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/pyglet-users?hl=en
-~----------~----~----~----~------~----~------~--~---
#!/usr/bin/python
# -*- coding: utf-8 -*-
__version__ = '$Id: modalwin.py 118 2009-03-12 23:00:25Z DR0ID $'
import pyglet
from pyglet.event import EventDispatcher
from pyglet.event import EVENT_HANDLED
from pyglet.window import key
gwin = pyglet.window.Window()
@gwin.event
def on_key_press(symbol, mod):
#print 'keypress', symbol, mod
if symbol == key.M:
print TestModalWin().set_visible()
elif symbol == key.R:
print TestRedirectedWin()
#-------------------------------------------------------------------------------
class Redirector(object):
class _TypeRedirect(object):
def __init__(self, win, a_event_type, a_other_handler):
self._type = a_event_type
self._other_handler = a_other_handler
self._win = win
def __call__(self, *args, **kwargs):
return self._other_handler(self._win, self._type, *args, **kwargs)
def __init__(self, win, event_types, handler=None):
self.update(win, event_types)
self._handler = handler
def handle(self, win, event_type, *args, **kwargs):
if self._handler:
return self._handler(win, event_type, *args, **kwargs)
# prevent further propagation
return EVENT_HANDLED
def update(self, win, event_types):
for event_type in event_types:
if hasattr(self, event_type):
# should not happen that this instance has an attribut named
# like the event_type, if it does it has to be an instance of
# self._TypeRedirect otherwise it is an error and you need to
# rename either event or the attribute
# replace the old _TypeRedirector with new one
assert(isinstance(getattr(self, event_type),
self._TypeRedirect))
setattr(self, event_type, self._TypeRedirect(win, event_type,
self.handle))
#-------------------------------------------------------------------------------
class RedirectedWindow(pyglet.window.Window):
def __init__(self, *args, **kwargs):
super(RedirectedWindow, self).__init__(*args, **kwargs)
# XXX: make redirected event_types configurable?
r = Redirector(self, list(self.event_types), self.on_redirected_event)
self.push_handlers(r)
def on_redirected_event(self, source_win, event_type, *args, **kwargs):
pass
#return EVENT_HANDLED
#-------------------------------------------------------------------------------
class TestRedirectedWin(RedirectedWindow):
def __init__(self, *args, **kwargs):
super(TestRedirectedWin, self).__init__(*args, **kwargs)
self.set_caption(str(id(self)))
def on_redirected_event(self, source_win, event_type, *args, **kwargs):
if event_type not in ['on_draw', 'on_mouse_motion', 'on_expose']:
print id(self), 'got from', id(source_win), 'redirected revent',
event_type, args, kwargs
if event_type == 'on_close':
self.close()
return EVENT_HANDLED
#-------------------------------------------------------------------------------
class ModalWindow(pyglet.window.Window):
def __init__(self, visible=False, *args, **kwargs):
super(ModalWindow, self).__init__( visible=visible, *args, **kwargs)
def set_visible(self, visible=True):
if visible:
# apply changes only once!
if not self.visible:
self.register_event_type('on_redirected_event')
event_types = list(self.event_types) #XXX: maybe make event
list configurable?
#event_types.remove('on_expose')
for win in pyglet.app.windows:
if win is not self:
r = Redirector(win, event_types,
self.on_redirected_event)
win.push_handlers(r)
self.push_handlers(self)
super(ModalWindow, self).set_visible(True)
else:
# apply changes only once!
if self.visible:
super(ModalWindow, self).set_visible(False)
for win in pyglet.app.windows:
#if win is not self:
print "poping handlers from", id(win)
win.pop_handlers()
# XXX: Maybe better to use a 'show_modal' method?? (and a 'end_modal' method??)
# def show_modal(self):
# if not self.visible:
# self.register_event_type('on_redirected_event')
# #self._win_redirector = WindowRedirector(self,
self.on_redirected_event)
# event_types = list(self.event_types)
# #event_types.remove('on_expose')
# for win in pyglet.app.windows:
# if win is not self:
# r = Redirector(win, event_types, self.on_redirected_event)
# win.push_handlers(r)
# self.push_handlers(self)
# self.set_visible()
def close(self):
self.set_visible(False)
super(ModalWindow, self).close()
def on_redirected_event(self, source_win, event_type, *args, **kwargs):
pass
#-------------------------------------------------------------------------------
class TestModalWin(ModalWindow):
def __init__(self, *args, **kwargs):
super(TestModalWin, self).__init__(*args, **kwargs)
self.set_caption(str(id(self)))
def on_redirected_event(self, source_win, event_type, *args, **kwargs):
if event_type not in ['on_draw', 'on_mouse_motion', 'on_expose']:
print id(self), 'got from', id(source_win), 'revent', event_type,
args, kwargs
self.activate()
if event_type not in ['on_activate']:
return EVENT_HANDLED
def on_key_press(self, symbol, mod):
if symbol == key.M:
print TestModalWin().set_visible()
elif symbol == key.R:
print TestRedirectedWin()
elif symbol == key.C:
print self.event_types
elif symbol == key.ESCAPE:
self.close()
elif symbol == key.N:
print "num win:", len(pyglet.app.windows)
return EVENT_HANDLED
#-------------------------------------------------------------------------------
if __name__ == '__main__':
pyglet.app.run()