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()

Reply via email to