From ff5e99ceb01b3b7c0ba189647dbb1de5931f67db Mon Sep 17 00:00:00 2001 From: ennucore Date: Sun, 12 Dec 2021 06:57:04 +0300 Subject: [PATCH] Rendering messages in interface --- degeon_py/active_chat.py | 22 ++++++++++++++++++++- degeon_py/config.py | 5 +++++ degeon_py/message.py | 42 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 degeon_py/message.py diff --git a/degeon_py/active_chat.py b/degeon_py/active_chat.py index 30874f4..7d82732 100644 --- a/degeon_py/active_chat.py +++ b/degeon_py/active_chat.py @@ -1,11 +1,15 @@ from __future__ import annotations +import typing from dataclasses import dataclass import pygame -from config import HEIGHT, WIDTH, CHAT_SELECTOR_WIDTH, DARKER_BLUE, CHAT_PREVIEW_HEIGHT, BLUE, WHITE, font, DARK_BLUE +from config import HEIGHT, WIDTH, CHAT_SELECTOR_WIDTH, DARKER_BLUE, CHAT_PREVIEW_HEIGHT, BLUE, WHITE, font, DARK_BLUE, \ + MESSAGE_HEIGHT import degeon_core as dc +from message import Message + @dataclass class ActiveChat: @@ -35,6 +39,15 @@ class ActiveChat: """ return cls(chat=chat, **kwargs) + def get_messages(self) -> typing.Iterable[Message]: + """ + Get an iterator over all messages in this chat in the backwards order + This function creates a python `message.Message` object from rust instances + :return: an iterator of `message.Message` objects + """ + for msg in reversed(self.chat.messages): + yield Message(text=msg.get_content_py().text, is_from_me=False) + def get_header(self) -> pygame.Surface: """ Render a pygame surface with the header. @@ -56,6 +69,13 @@ class ActiveChat: surface: pygame.Surface = pygame.Surface((self.width, self.height)) surface.fill(DARKER_BLUE) + # Render messages + # This is the y0 for the last message + last_message_y = self.height - 60 + for i, message in zip(range(30), self.get_messages()): + msg_surface = message.render() + surface.blit(msg_surface, (0, last_message_y - (MESSAGE_HEIGHT + 30) * (i + 1))) + # Render header header = self.get_header() surface.blit(header, (0, 10)) return surface diff --git a/degeon_py/config.py b/degeon_py/config.py index 091c688..48e871e 100644 --- a/degeon_py/config.py +++ b/degeon_py/config.py @@ -2,9 +2,12 @@ import pygame pygame.init() + +# Fontss font = pygame.font.Font('CRC35.otf', 25) font_large = pygame.font.Font('CRC35.otf', 35) +# Colors used in the app RED = 0xFF0000 BLUE = 0x0000FF YELLOW = 0xFFC91F @@ -18,9 +21,11 @@ DARK_BLUE = 0x282e46 DARKER_BLUE = 0x202033 GREY = 0x383e4F +# Geometrical parameters WIDTH = 1000 HEIGHT = 800 CHAT_PREVIEW_HEIGHT = 80 CHAT_SELECTOR_WIDTH = WIDTH // 3 +MESSAGE_HEIGHT = 60 FPS = 30 diff --git a/degeon_py/message.py b/degeon_py/message.py new file mode 100644 index 0000000..b3ba57a --- /dev/null +++ b/degeon_py/message.py @@ -0,0 +1,42 @@ +from __future__ import annotations + +from dataclasses import dataclass + +import pygame + +from config import WIDTH, CHAT_SELECTOR_WIDTH, MESSAGE_HEIGHT, font, BLUE, DARK_BLUE, WHITE, DARKER_BLUE + + +@dataclass +class Message: + """ + The message (for now, it consists only of text) + + Attributes: + :param text (str): the message text + :param is_from_me (bool): False if the message is not from the current user + :param chat_width (int): the width of the active chat widget + """ + text: str + is_from_me: bool + chat_width: int = WIDTH - CHAT_SELECTOR_WIDTH - 10 + height: int = MESSAGE_HEIGHT + + def render(self) -> pygame.Surface: + """ + Creates a surface with a rectangle and the message text written on it + :return: the surface with rendered message + """ + surface = pygame.Surface((self.chat_width, self.height)) + surface.fill(DARKER_BLUE) + bg_color = BLUE * self.is_from_me + DARK_BLUE * (not self.is_from_me) + text_surface: pygame.Surface = font.render(self.text, True, WHITE) + padding = 5 + # Size of the scaled text surface + blit_height = self.height - padding * 2 + blit_width = round(text_surface.get_width() * blit_height / text_surface.get_height()) + x = 0 if not self.is_from_me else self.chat_width - blit_width - padding * 2 + pygame.draw.rect(surface, bg_color, (x, 0, blit_width + padding * 2, self.height)) + text_surface = pygame.transform.smoothscale(text_surface, (blit_width, blit_height)) + surface.blit(text_surface, (x + padding, padding)) + return surface