diff pyntnclick/widgets/text.py @ 679:fa168b5e2624 pyntnclick

The return of the message dialog (and there was much rejoicing)
author Neil Muller <neil@dip.sun.ac.za>
date Sun, 12 Feb 2012 23:06:44 +0200
parents fe7023750b20
children 6892d36dad75
line wrap: on
line diff
--- 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