############################################################################# ## This file is part of TunnelHack II. ## ##-------------------------------------------------------------------------## ## Copyright 2007-2008 Bryce Schroeder ## ## bryce.schroeder@gmail.com ## ## http://www.ferazelhosting.net/~bryce/ ## ##-------------------------------------------------------------------------## ## This program is free software: you can redistribute it and/or modify ## ## it under the terms of the GNU General Public License as published by ## ## the Free Software Foundation, either version 3 of the License, or ## ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## ## along with this program. If not, see . ## ############################################################################# from .interface import IObj from .g import g import pygame class ILabel(IObj): def init(self): font_res = g.resources.get('Font', self.p.get('font', 'Junicode')) width, height, size = self.p.w, self.p.h, self.p.get('size', 12) align, valign = self.p.get('align', 'left'), self.p.get('valign', 'top') font = font_res.pygame_font(size) lines = font_res.wrap_text(size, self.p.text, width * 16 - 5) height_mul = font.get_height() + 2 font_height = len(lines) * height_mul - 2 self.text_surf = pygame.Surface((width * 16, font_height), pygame.SRCALPHA, 32) self.text_surf.fill((0, 0, 0, 0)) for e, line in enumerate(lines): surf = font.render(line, 1, self.p.color) if align == 'left': x = 0 elif align == 'center': x = (width * 16 - surf.get_width()) // 2 elif align == 'right': x = width * 16 - surf.get_width() self.text_surf.blit(surf, (x, e * height_mul)) self.text_surf = self.text_surf.convert_alpha() if valign == 'top': self.base_y = 0 elif valign == 'middle': self.base_y = (height * 16 - font_height - 1) // 2 elif valign == 'bottom': self.base_y = height * 16 - font_height def render_self(self, theme, target, px, py): target.blit(self.text_surf, (px, py + self.base_y)) class ITextBox(IObj): text_transition_function = { (IObj.NORMAL, 'mouse' ): IObj.FOCUSED, (IObj.TOGGLED, 'mouse' ): IObj.CLICKED, (IObj.TOGGLED, 'click' ): IObj.NORMAL, (IObj.FOCUSED, 'unmouse'): IObj.NORMAL, (IObj.CLICKED, 'unmouse'): IObj.TOGGLED, (IObj.FOCUSED, 'click' ): IObj.CLICKED, (IObj.CLICKED, 'click' ): IObj.CLICKED } transition_function = { True: text_transition_function, False: text_transition_function } def init(self): self.text = unicode(self.p.get('text', '')) self.cursor = self.scrollpos = 0 font_res = g.resources.get('Font', self.p.get('font', 'Junicode')) self.font = font_res.pygame_font(self.p.get('size', 12)) self.update_text() def update_text(self): self.text_surf = self.font.render(self.text, 1, self.p.color) self.base_y = (self.p.h * 16 - self.text_surf.get_height()) // 2 self.dirty = True def update_scroll(self): curs_x = self.font.size(self.text[:self.cursor])[0] width = self.p.w * 12 self.scrollpos = max((curs_x - 8) // width * width, 0) def accept_key(self, unicode_str, key, mod): return (self.state in (self.TOGGLED, self.CLICKED) and self.window_focused) def handle_key(self, unicode_str, key, mod): if key == pygame.K_BACKSPACE: if self.cursor > 0: self.text = self.text[:self.cursor - 1] + self.text[self.cursor:] self.cursor -= 1 elif key == pygame.K_DELETE: if self.cursor < len(self.text): self.text = self.text[:self.cursor] + self.text[self.cursor + 1:] elif key == pygame.K_DOWN: self.cursor = len(self.text) elif key == pygame.K_UP: self.cursor = 0 elif key == pygame.K_LEFT: self.cursor = max(0, self.cursor - 1) elif key == pygame.K_RIGHT: self.cursor = min(len(self.text), self.cursor + 1) elif unicode_str.strip() or unicode_str == u' ': self.text = self.text[:self.cursor] + unicode_str + self.text[self.cursor:] self.cursor += 1 self.update_scroll() self.update_text() def handle_click(self, lx, ly): lx += self.scrollpos - 4 processed, lwidth = '', 0 for c in self.text: processed += c text_width = self.font.size(processed)[0] if lx <= text_width: if lx - lwidth < text_width - lx: self.cursor = len(processed) - 1 else: self.cursor = len(processed) break lwidth = text_width else: self.cursor = len(self.text) self.update_scroll() self.dirty = True def render_self(self, theme, target, px, py): width, height = self.p.w, self.p.h if width == 1 and height == 1: raise NotImplementedError('1x1 text boxes are not supported') elif width == 1: raise NotImplementedError('1xN text boxes are not implemented') elif height == 1: theme_blit = self.archon.theme.blit theme_blit((1 + 3 * self.state, 9), target, px, py) for x in xrange(1, width - 1): theme_blit((2 + 3 * self.state, 9), target, x * 16 + px, py) theme_blit( (3 + 3 * self.state, 9), target, (width - 1) * 16 + px, py) else: self.draw_rect((1, 13), target, px, py, width, height, True) target.blit(self.text_surf, (px + 4, py + self.base_y), (self.scrollpos, 0, width * 16 - 8, height * 16)) if self.state in (self.TOGGLED, self.CLICKED): curs_x, curs_h = self.font.size(self.text[:self.cursor]) target.fill((0, 0, 0), (px + 3 + curs_x - self.scrollpos, py + self.base_y, 1, curs_h))