don't discard width padding
[naja.git] / naja / widgets / text.py
1 import pygame
2
3 from naja.constants import FONT, FONT_SIZE, EIGHT_BIT_SCALE
4 from naja.widgets.base import Widget
5 from naja.resources import resources
6 from naja.utils import convert_colour
7
8
9 class TextWidget(Widget):
10
11     def __init__(self, pos, text, size=None, fontname=None, fontsize=None,
12                  colour=None):
13         super(TextWidget, self).__init__(pos, size)
14
15         self.text = text
16         self.fontname = fontname or FONT
17         self.fontsize = (fontsize or FONT_SIZE) // EIGHT_BIT_SCALE
18         self.colour = convert_colour(colour or (0, 0, 0))
19
20     def render_line(self, text):
21         text_surf = self.font.render(text, True, self.colour)
22         text_rect = text_surf.get_rect()
23         return pygame.transform.scale(
24             text_surf, (text_rect.width * EIGHT_BIT_SCALE,
25                         text_rect.height * EIGHT_BIT_SCALE))
26
27     def prepare(self):
28         self.font = resources.get_font(self.fontname, self.fontsize)
29         self.surface = self.render_line(self.text)
30         self.size = self.surface.get_rect().size
31
32     def draw(self, surface):
33         surface.blit(self.surface, self.pos)
34
35
36 class TextBoxWidget(TextWidget):
37     def __init__(self, *args, **kwargs):
38         self.padding = kwargs.pop('padding', 5)
39         self.border = kwargs.pop('border', 2)
40         self.bg_colour = convert_colour(kwargs.pop('bg_colour',
41                                                    (255, 255, 255, 192)))
42         self.border_colour = convert_colour(kwargs.pop('border_colour',
43                                                        (0, 0, 0)))
44         self.box_width = kwargs.pop('box_width', 0)
45
46         super(TextBoxWidget, self).__init__(*args, **kwargs)
47
48     def lines(self):
49         if self.box_width != 0:
50             return self._wrapped_lines()
51         else:
52             return self.text.splitlines()
53
54     def _wrapped_lines(self):
55         def words_fit(words):
56             words_line = ' '.join(words)
57             width = self.font.size(words_line)[0]
58             if width < self.box_width:
59                 return True
60             elif len(words) == 1:
61                 Exception("Word %r too long for box." % (words[0],))
62             return False
63
64         for line in self.text.splitlines():
65             current_words = []
66             for word in line.split():
67                 current_words.append(word)
68                 if words_fit(current_words):
69                     continue
70                 else:
71                     yield ' '.join(current_words[:-1])
72                     current_words = current_words[-1:]
73             if current_words and words_fit(current_words):
74                 yield ' '.join(current_words)
75
76     def prepare(self):
77         self.font = resources.get_font(self.fontname, self.fontsize)
78         rendered_lines = []
79         width, height = self.padding, self.padding
80         for line in self.lines():
81             line_surface = self.render_line(line)
82             line_rect = line_surface.get_rect()
83             rendered_lines.append(line_surface)
84             width = max(width, line_rect.width + self.padding)
85             height += line_rect.height
86
87         self.surface = pygame.surface.Surface((width, height),
88                                               pygame.locals.SRCALPHA)
89         self.surface.fill(self.bg_colour)
90         self.size = self.surface.get_rect().size
91
92         x, y = self.padding, self.padding
93         for line_surface in rendered_lines:
94             self.surface.blit(line_surface, (x, y))
95             y += line_surface.get_rect().height
96
97     def draw(self, surface):
98         surface.blit(self.surface, self.rect)