This implements an iterable root-widget for Albow. Sometimes the monolithic ‘run’ is fine, sometimes you want your own main loop. This is basically Greg Ewings .run_modal() code, reorganized as multiple methods. The methods to call are .run_start() once, .process_input() when relevant events are available, and .draw_gui() at each frame (or when redrawing is necessary).
from albow import root
from pygame.locals import *
from pygame.event import Event
import pygame
class NewRootWidget(root.RootWidget):
def __init__(self, surface):
root.RootWidget.__init__(self, surface)
self._progen = None
self.bg_color = None
def run_modal(self, modal_widget):
#print 'new root widget'
self.run_start(modal_widget)
while True:
events = [pygame.event.wait()]
events.extend(pygame.event.get())
self.process_input(events)
if redraw:
self.draw_gui()
def run_start(self, modal_widget):
self._progen = self._input_process_generator(modal_widget)
self._progen.next()
def process_input(self, events):
"""process mouse and keyboard events.
@param events: a list or tuple of pygame events
@returns: True if any widgets need redrawing, otherwise False
"""
return self._progen.send(events)
def _input_process_generator(self, modal_widget):
is_modal = modal_widget is not None
modal_widget = modal_widget or self
old_top_widget = root.top_widget
root.top_widget = modal_widget
was_modal = modal_widget.is_modal
modal_widget.is_modal = True
# modal_widget.modal_result = None
if not modal_widget.focus_switch:
modal_widget.tab_to_first()
# mouse_widget = None
if root.clicked_widget:
root.clicked_widget = modal_widget
num_clicks = 0
last_click_time = 0
do_draw = True
events = []
while True:
for event in events:
type = event.type
if type == QUIT:
self.quit()
elif type == MOUSEBUTTONDOWN:
do_draw = True
t = root.get_ticks()
if t - last_click_time <= root.double_click_time:
num_clicks += 1
else:
num_clicks = 1
last_click_time = t
event.dict['num_clicks'] = num_clicks
root.add_modifiers(event)
mouse_widget = self.find_widget(event.pos)
if not mouse_widget.is_inside(modal_widget):
mouse_widget = modal_widget
root.clicked_widget = mouse_widget
root.last_mouse_event_handler = mouse_widget
root.last_mouse_event = event
mouse_widget.notify_attention_loss()
mouse_widget.handle_mouse('mouse_down', event)
elif type == MOUSEMOTION:
root.add_modifiers(event)
modal_widget.dispatch_key('mouse_delta', event)
mouse_widget = self.find_widget(event.pos)
root.last_mouse_event = event
if root.clicked_widget:
root.last_mouse_event_handler = mouse_widget
root.clicked_widget.handle_mouse('mouse_drag', event)
else:
if not mouse_widget.is_inside(modal_widget):
mouse_widget = modal_widget
root.last_mouse_event_handler = mouse_widget
mouse_widget.handle_mouse('mouse_move', event)
elif type == MOUSEBUTTONUP:
root.add_modifiers(event)
do_draw = True
#mouse_widget = self.find_widget(event.pos)
if root.clicked_widget:
root.last_mouse_event_handler = root.clicked_widget
root.last_mouse_event = event
root.clicked_widget = None
root.last_mouse_event_handler.handle_mouse('mouse_up', event)
elif type == KEYDOWN:
key = event.key
root.set_modifier(key, True)
do_draw = True
self.send_key(modal_widget, 'key_down', event)
if root.last_mouse_event_handler:
event.dict['pos'] = root.last_mouse_event.pos
event.dict['local'] = root.last_mouse_event.local
root.last_mouse_event_handler.setup_cursor(event)
elif type == KEYUP:
key = event.key
root.set_modifier(key, False)
do_draw = True
self.send_key(modal_widget, 'key_up', event)
if root.last_mouse_event_handler:
event.dict['pos'] = root.last_mouse_event.pos
event.dict['local'] = root.last_mouse_event.local
root.last_mouse_event_handler.setup_cursor(event)
elif type == root.MUSIC_END_EVENT:
self.music_end()
elif type == USEREVENT:
root.make_scheduled_calls()
if not is_modal:
do_draw = self.redraw_every_frame
if root.last_mouse_event_handler:
event.dict['pos'] = root.last_mouse_event.pos
event.dict['local'] = root.last_mouse_event.local
root.add_modifiers(event)
root.last_mouse_event_handler.setup_cursor(event)
self.begin_frame()
events = yield do_draw
modal_widget.is_modal = was_modal
root.top_widget = old_top_widget
root.clicked_widget = None
def draw_gui(self):
if self.is_gl:
self.gl_clear()
self.gl_draw_all(self, (0, 0))
else:
self.draw_all(self.surface)
pygame.display.flip()
Advertisement