diff --git a/example_config.json b/example_config.json index 46a3e21..ee98407 100644 --- a/example_config.json +++ b/example_config.json @@ -1,10 +1,10 @@ { "actions": [ { - "label": "example 1", + "label": "example 1\nMultiline!", "action_type": "MSG", "action_param": "1", - "action_message": "Doing example 1" + "action_message": "Doing example 1\nwith\nmultiple\nlines" }, { "label": "example 2", diff --git a/menu.py b/menu.py index daaaedb..de52855 100644 --- a/menu.py +++ b/menu.py @@ -34,18 +34,40 @@ class Action(TypedDict): action_message: Optional[str] +class MultilineText: + VMARGIN = 10 + + def __init__(self, text: str, font: pygame.freetype.Font): + self.lines = text.splitlines() + self.font = font + self.all_rects = list(map(self.font.get_rect, self.lines)) + self.width = max(map(lambda r: r.width, self.all_rects)) + self.height = sum(map(lambda r: r.height + self.VMARGIN, self.all_rects)) + + def get_rect(self) -> pygame.Rect: + return pygame.Rect(0, 0, self.width, self.height) + + def render_to(self, screen: pygame.Surface, pos: pygame.Rect, fgcolor: pygame.Color): + current_top = pos.top + for line, rect in zip(self.lines, self.all_rects): + self.font.render_to(screen, + pygame.Rect(pos.left, current_top, rect.width, rect.height), + line, fgcolor="black") + current_top += rect.top + self.VMARGIN + + class Button: PRESS_OFFSET = 2 HOVER_ANIMATION_STEPS = 5 def __init__(self, position: pygame.Rect, text: str, theme: Dict, cbk: Callable[[], None]): + font = pygame.freetype.SysFont(name=theme["btn_font_face"], size=int(theme["btn_font_size"])) self.position: pygame.Rect self.set_position(position) - self.text = text + self.label = MultilineText(text, font) self.theme = theme self.cbk = cbk - self.font = pygame.freetype.SysFont(name=theme["btn_font_face"], size=int(theme["btn_font_size"])) - text_rect = self.font.get_rect(self.text) + text_rect = self.label.get_rect() self.text_pos = pygame.Rect((self.position.left + (self.position.width - text_rect.width)/2), (self.position.top + (self.position.height - text_rect.height)/2), text_rect.width, text_rect.height) @@ -88,7 +110,7 @@ class Button: def draw(self, screen: pygame.Surface): pygame.draw.rect(screen, self.get_bg_color(), self.get_position(), 0) - self.font.render_to(screen, self.get_text_pos(), self.text, fgcolor=self.theme["btn_text_color"]) + self.label.render_to(screen, self.get_text_pos(), self.theme["btn_text_color"]) def pos_is_inside(self, pos: Tuple) -> bool: return (self.position.left < pos[0] and (self.position.left + self.position.width) > pos[0]) and \ @@ -102,9 +124,9 @@ class Button: class MessageBoard(IBoard): def __init__(self, screen_rect: pygame.Rect, text: str, theme: Dict): - self.text = text - self.font = pygame.freetype.SysFont(name=theme["message_font_face"], size=int(theme["message_font_size"])) - text_rect = self.font.get_rect(self.text) + font = pygame.freetype.SysFont(name=theme["message_font_face"], size=int(theme["message_font_size"])) + self.label = MultilineText(text, font) + text_rect = self.label.get_rect() self.text_pos = pygame.Rect((screen_rect.left + (screen_rect.width - text_rect.width)/2), (screen_rect.top + (screen_rect.height - text_rect.height)/2), text_rect.width, text_rect.height) @@ -117,7 +139,7 @@ class MessageBoard(IBoard): def draw(self, screen: pygame.Surface, force_redraw: bool): if not self.was_drawn_already or force_redraw: screen.fill(self.theme["message_bg_color"]) - self.font.render_to(screen, self.text_pos, self.text, fgcolor=self.theme["message_text_color"]) + self.label.render_to(screen, self.text_pos, fgcolor=self.theme["message_text_color"]) self.was_drawn_already = True