# HG changeset patch # User Neil Muller # Date 1329080804 -7200 # Node ID fa168b5e2624e9ba4f7246593ac64b4040531d02 # Parent 36d7f7e9650e64b3e4f4f97122ccb35523394d15 The return of the message dialog (and there was much rejoicing) diff -r 36d7f7e9650e -r fa168b5e2624 pyntnclick/gamescreen.py --- a/pyntnclick/gamescreen.py Sun Feb 12 21:47:06 2012 +0200 +++ b/pyntnclick/gamescreen.py Sun Feb 12 23:06:44 2012 +0200 @@ -11,7 +11,7 @@ from pyntnclick.engine import Screen from pyntnclick.state import handle_result from pyntnclick.widgets.base import Container, ModalStackContainer -from pyntnclick.widgets.text import TextButton, LabelWidget +from pyntnclick.widgets.text import TextButton, ModalWrappedTextLabel from pyntnclick.widgets.imagebutton import ImageButtonWidget # XXX: Need a way to get at the constants. @@ -151,6 +151,7 @@ self.detail = DetailWindow(rect, gd, screen) self.add_callback(MOUSEBUTTONDOWN, self.mouse_down) self.add_callback(MOUSEMOTION, self.mouse_move) + self._message_queue = [] def draw(self, surface): self.game.current_scene.draw(surface, self) @@ -170,6 +171,9 @@ else: self.game.current_scene.draw_description(surface) + def queue_widget(self, widget): + self._message_queue.append(widget) + def mouse_down(self, event, widget): if self.game.current_detail: return self.detail.mouse_down(event, widget) @@ -188,6 +192,11 @@ # of what happens result = self.game.check_enter_leave(self.screen) handle_result(result, self) + if self._message_queue: + # Only add a message if we're at the top + if self.screen.modal_magic.is_top(self.screen.inner_container): + widget = self._message_queue.pop(0) + self.screen.modal_magic.add(widget) if self.game.current_detail: self.game.current_detail.animate() else: @@ -200,10 +209,8 @@ self.game.current_scene.mouse_move(event.pos) self.game.old_pos = event.pos - def show_message(self, message, style=None): + def show_message(self, message): # Display the message as a modal dialog - # self.screen.modal_magic.add(LabelWidget((50, 50), self.gd, message)) - print message # XXX: MessageDialog(self.screen, message, 60, style=style).present() # queue a redraw to show updated state # XXX: self.invalidate() @@ -212,6 +219,13 @@ # self.subwidgets[0]._mouse_move(mouse.get_pos()) # else: # self._mouse_move(mouse.get_pos()) + rect = Rect((0, 0), (1, 1)) + widget = ModalWrappedTextLabel(rect, self.gd, message, + max_width=self.gd.constants.screen[0] - 100) + widget.rect.center = self.rect.center + # We abuse animate so we can queue multiple results + # according + self.queue_widget(widget) def show_detail(self, detail): self.clear_detail() @@ -286,10 +300,9 @@ self.game.highlight_override = False self.game.current_detail.mouse_move(self.global_to_local(pos)) - def show_message(self, message, style=None): - # self.parent.show_message(message, style) + def show_message(self, message): + self.parent.show_message(message) # self.invalidate() - print message class ToolBar(Container): diff -r 36d7f7e9650e -r fa168b5e2624 pyntnclick/state.py --- a/pyntnclick/state.py Sun Feb 12 21:47:06 2012 +0200 +++ b/pyntnclick/state.py Sun Feb 12 23:06:44 2012 +0200 @@ -37,7 +37,7 @@ """Helper function to do the right thing with a result object""" self.play_sound(scene_widget) if self.message: - scene_widget.show_message(self.message, self.style) + scene_widget.show_message(self.message) if self.detail_view: scene_widget.show_detail(self.detail_view) if (self.close_detail diff -r 36d7f7e9650e -r fa168b5e2624 pyntnclick/widgets/base.py --- a/pyntnclick/widgets/base.py Sun Feb 12 21:47:06 2012 +0200 +++ b/pyntnclick/widgets/base.py Sun Feb 12 23:06:44 2012 +0200 @@ -139,6 +139,11 @@ if super(Container, self).event(ev): return True + def is_top(self, widget): + if self.children: + return self.children[-1] is widget + return False + def draw(self, surface): obscure = pygame.Surface(self.rect.size, SRCALPHA) obscure.fill(self.obscure_color) diff -r 36d7f7e9650e -r fa168b5e2624 pyntnclick/widgets/text.py --- a/pyntnclick/widgets/text.py Sun Feb 12 21:47:06 2012 +0200 +++ b/pyntnclick/widgets/text.py Sun Feb 12 23:06:44 2012 +0200 @@ -1,5 +1,8 @@ +from textwrap import wrap + import pygame from pygame.constants import SRCALPHA +from pygame.locals import MOUSEBUTTONDOWN from pyntnclick.widgets.base import Widget, Button, convert_color @@ -96,3 +99,78 @@ def draw(self, surface): super(TextButton, self).draw(surface) + + +class WrappedTextLabel(LabelWidget): + """A Label Widget that wraps the text to a given maximum width""" + + def __init__(self, rect, gd, *args, **kwargs): + self.max_width = kwargs.pop('max_width', gd.constants.screen[0] - 50) + self._wrap_width = None + self._text_lines = None + super(WrappedTextLabel, self).__init__(rect, gd, *args, **kwargs) + self.prepare() + + def prepare(self): + if self._wrap_width is None: + # Start without wrapping + self._wrap_width = len(self.text) + 1 + self._text_lines = [self.text] + + self.font = self.resource.get_font(self.fontname, self.fontsize) + self.color = convert_color(self.color) + self._render() + self.text_rect = self.surface.get_rect() + width, height = self.surface.get_rect().size + while width > self.max_width: + # Very simplistic approach + self._wrap_width = self._wrap_width / 2 + self._text_lines = wrap(self.text, self._wrap_width) + self._render() + width, height = self.surface.get_rect().size + self.rect.width = max(self.rect.width, width) + self.rect.height = max(self.rect.height, height) + + self.rect.width += 2 * self.padding + self.rect.height += 2 * self.padding + new_surface = pygame.Surface(self.rect.size) + new_surface = new_surface.convert_alpha() + new_surface.fill(self.bg_color) + new_surface.blit(self.surface, self.surface.get_rect().move( + (self.padding, self.padding))) + if self.border: + pygame.draw.rect(new_surface, self.border_color, + new_surface.get_rect(), + self.border) + self.surface = new_surface + + def _render(self): + surfaces = [] + width = 0 + height = 0 + for line in self._text_lines: + line_surf = self.font.render(line, True, self.color, + self.bg_color) + surfaces.append(line_surf) + width = max(line_surf.get_rect().width, width) + height += line_surf.get_rect().height + self.surface = pygame.Surface((width, height)) + self.surface.fill(self.bg_color) + height = 0 + for line_surf in surfaces: + rect = pygame.Rect((0, height), (line_surf.get_rect().size)) + self.surface.blit(line_surf, rect) + height += line_surf.get_rect().height + + +class ModalWrappedTextLabel(WrappedTextLabel): + """A WrappedTextLabel that removes itself when a mouse + click occurs""" + def __init__(self, rect, gd, *args, **kwargs): + super(ModalWrappedTextLabel, self).__init__(rect, gd, *args, **kwargs) + self.add_callback(MOUSEBUTTONDOWN, self.close) + + def close(self, ev, widget): + if self.parent: + self.parent.remove(self) + return True