IronForce is a decentralized network, Degeon is a messenger built on it
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
3.9 KiB

from __future__ import annotations
import typing
import pygame
import degeon_core as dc
from dataclasses import dataclass, field
from abc import ABC
# Configuration variables and loading
pygame.init()
font = pygame.font.Font('CRC35.otf', 25)
FPS = 30
RED = 0xFF0000
BLUE = 0x0000FF
YELLOW = 0xFFC91F
GREEN = 0x00FF00
MAGENTA = 0xFF03B8
CYAN = 0x00FFCC
BLACK = 0x000
WHITE = 0xFFFFFF
DARK_BLUE = 0x282e46
GREY = 0x383e4F
COLORS = [RED, BLUE, YELLOW, GREEN, MAGENTA, CYAN]
WIDTH = 900
HEIGHT = 700
@dataclass
class ChatSelector:
"""
The widget with the list of chats.
It's a dataclass, it should be initialized using the `from_chats` classmethod
Attributes:
chats (List[dc.Chat]): list of all chats, where each chat is a native Rust struct Chat
active_chat (int): the index of the current selected chat
hovered_chat (int or None): the index of the current hovered chat
width (int): the width of this widget
height (int): the height of this widget
chat_height (int): height of one chat
"""
chats: typing.List['dc.Chat'] = field(default_factory=list)
active_chat: int = 0
hovered_chat: typing.Optional[int] = None
width: int = WIDTH // 3
height: int = HEIGHT
chat_height: int = HEIGHT // 10
def render(self) -> pygame.Surface:
"""
Creates a pygame surface and draws the list of chats on it
:return: the surface with the chat selector
"""
surface: pygame.Surface = pygame.Surface((self.width, self.chat_height * len(self.chats)))
for i, chat in enumerate(self.chats):
bg_color, text_color = DARK_BLUE, WHITE
if i == self.hovered_chat:
bg_color = GREY
if i == self.active_chat:
bg_color = BLUE
title_surface: pygame.Surface = font.render(chat.profile.name, True, text_color)
pygame.draw.rect(surface, bg_color, (0, i * self.chat_height + 1, self.width, self.chat_height - 2))
surface.blit(title_surface, (i * self.chat_height + 10))
return surface
def process_event(self, event: pygame.event.Event):
"""
Process a click: select the necessary chat if this click is in the widget
:param event: pygame event
"""
if event.type == pygame.MOUSEBUTTONUP and event.pos[0] < self.width:
self.active_chat = event.pos[1] // self.chat_height
self.hovered_chat = None
if event.type == pygame.MOUSEMOTION:
if 0 < event.pos[0] < self.width \
and 0 < event.pos[1] < min(self.height, len(self.chats) * self.chat_height) - 2:
self.hovered_chat = event.pos[1] // self.chat_height
else:
self.hovered_chat = None
@classmethod
def from_chats(cls, chats: typing.List['dc.Chat'], **kwargs) -> ChatSelector:
return cls(chats, **kwargs)
@dataclass
class ActiveChat:
"""
The widget with the current chat
Attributes:
:param chat (dc.Chat): the chat (Rust Chat type)
"""
chat: 'dc.Chat'
@dataclass
class Degeon:
"""
The main class with everything connected to the app: the data, the
Attributes
"""
core: 'dc.Degeon'
chat_selector: ChatSelector
has_profile_popup_opened: bool = False
has_no_peers_popup: bool = False
@classmethod
def new(cls) -> Degeon:
"""
Create a new default instance with settings from file
:return: a Degeon instance
"""
pass # todo
def render(self, screen: pygame.Surface):
"""
Render everything on the screen
:param screen: the main screen
"""
chats_surface = self.chat_selector.render()
screen.blit(chats_surface, (0, 0))
def tick(self):
"""
Handle incoming messages, update chats, create no_peers popup if necessary
"""
pass # todo