Browse Source

Name input in the python interface

master
Lev 3 years ago
parent
commit
a2c5059646
  1. 5
      degeon_py/active_chat.py
  2. 1
      degeon_py/config.py
  3. 40
      degeon_py/degeon.py
  4. 2
      degeon_py/input_field.py
  5. 24
      degeon_py/message.py
  6. 7
      degeon_py/utils.py

5
degeon_py/active_chat.py

@ -26,7 +26,7 @@ class ActiveChat:
:param header_height (int): height of the header (the title)
"""
chat: dc.Chat
input_field: TextField = field(default_factory=lambda: TextField())
input_field: TextField = field(default_factory=lambda: TextField(placeholder='New message'))
send_button: Button = field(default_factory=lambda: Button(height=CHAT_PREVIEW_HEIGHT, width=100, text='Send',
top_left=(WIDTH - 112, HEIGHT - 85)))
height: int = HEIGHT
@ -79,7 +79,8 @@ class ActiveChat:
last_message_y = self.height - MESSAGE_HEIGHT * 2
for i, message in zip(range(30), self.get_messages(core)):
msg_surface = message.render()
surface.blit(msg_surface, (0, last_message_y - (MESSAGE_HEIGHT + 30) * (i + 1)))
last_message_y -= msg_surface.get_height() + 30
surface.blit(msg_surface, (0, last_message_y - 30))
# Render header
header = self.get_header()
surface.blit(header, (0, 10))

1
degeon_py/config.py

@ -4,6 +4,7 @@ import pygame
pygame.init()
# Fonts
font_medium = pygame.font.Font('CRC35.otf', 25)
font = pygame.font.Font('CRC35.otf', 32)
font_large = pygame.font.Font('CRC35.otf', 50)

40
degeon_py/degeon.py

@ -4,12 +4,15 @@ from dataclasses import dataclass, field
import typing
import pygame
from button import Button
from chat_selector import ChatSelector
from active_chat import ActiveChat
from config import FPS, DARKER_BLUE, font, WHITE, WIDTH, CHAT_SELECTOR_WIDTH, HEIGHT
import degeon_core as dc
from input_field import TextField
@dataclass
class Degeon:
@ -22,9 +25,13 @@ class Degeon:
:param active_chat (typing.Optional[ActiveChat]): current chat widget
:param fps (int): FPS rate
"""
core: 'dc.Degeon'
core: typing.Optional[dc.Degeon]
chat_selector: ChatSelector
active_chat: typing.Optional[ActiveChat] = None
name_input_field: TextField = field(
default_factory=lambda: TextField(placeholder='Name', top_left_corner=(WIDTH // 5, HEIGHT // 3)))
name_input_button: Button = field(default_factory=lambda: Button(text='Done', width=200, height=100,
top_left=(round(2 * WIDTH / 5), 2 * HEIGHT // 3)))
has_profile_popup_opened: bool = False
has_no_peers_popup: bool = False
clock: pygame.time.Clock = field(default_factory=pygame.time.Clock)
@ -36,15 +43,34 @@ class Degeon:
Create a new default instance with settings from file
:return: a Degeon instance
"""
if dc.is_data_available():
core: dc.Degeon = dc.new_degeon()
else:
# core: dc.Degeon = dc.new_degeon_with_name(input('Enter name: '))
core = None
chat_selector = ChatSelector()
return cls(core=core, chat_selector=chat_selector)
def register(self, name: str):
"""
Create new rust-Degeon instance with name
:param name: user's name
"""
self.core = dc.new_degeon_with_name(name)
self.chat_selector.chats = self.core.chats
def render(self, screen: pygame.Surface):
"""
Render everything on the screen
:param screen: the main screen
"""
if self.core is None:
screen.fill(DARKER_BLUE)
button_surface: pygame.Surface = self.name_input_button.render()
screen.blit(button_surface, self.name_input_button.top_left)
name_field_surface: pygame.Surface = self.name_input_field.render()
screen.blit(name_field_surface, self.name_input_field.top_left_corner)
return
chats_surface = self.chat_selector.render()
screen.blit(chats_surface, (0, 0))
if self.active_chat is not None:
@ -59,6 +85,8 @@ class Degeon:
"""
Do all the necessary Rust work
"""
if self.core is None:
return
while self.core.message_queue_len():
self.core.handling_loop_iteration()
@ -66,12 +94,15 @@ class Degeon:
"""
Handle incoming messages, update chats, create no_peers popup if necessary
"""
if self.core is None:
return
# process events in core
self.process_core_messages()
if self.core is not None:
self.chat_selector.chats = self.core.chats
if 0 <= self.chat_selector.active_chat < len(self.chat_selector.chats) and self.active_chat is None:
self.active_chat = ActiveChat.new(self.chat_selector.chats[self.chat_selector.active_chat])
if self.active_chat is not None:
if self.active_chat is not None and self.core is not None:
self.active_chat.chat = self.core.chats[self.chat_selector.active_chat]
def process_event(self, event: pygame.event.Event):
@ -79,6 +110,11 @@ class Degeon:
Process an event
:param event: pygame event
"""
if self.core is None:
self.name_input_field.process_event(event)
if self.name_input_button.process_event(event):
self.register(self.name_input_field.value)
return
if self.chat_selector.process_event(event):
if 0 <= self.chat_selector.active_chat < len(self.chat_selector.chats):
self.active_chat = ActiveChat.new(self.chat_selector.chats[self.chat_selector.active_chat])

2
degeon_py/input_field.py

@ -32,7 +32,7 @@ class TextField:
padding = 5
pygame.draw.rect(surface, DARKER_BLUE, (padding, padding, self.width - padding * 2, self.height - padding * 2))
if not self.value and self.placeholder:
placeholder_text: pygame.Surface = font.render(self.placeholder, True, GREY)
placeholder_text: pygame.Surface = font.render(self.placeholder, True, (GREY + WHITE) // 2)
surface.blit(
placeholder_text,
(

24
degeon_py/message.py

@ -4,7 +4,8 @@ from dataclasses import dataclass
import pygame
from config import WIDTH, CHAT_SELECTOR_WIDTH, MESSAGE_HEIGHT, font, BLUE, DARK_BLUE, WHITE, DARKER_BLUE
from config import WIDTH, CHAT_SELECTOR_WIDTH, MESSAGE_HEIGHT, font_medium, BLUE, DARK_BLUE, WHITE, DARKER_BLUE
from utils import render_text
@dataclass
@ -27,16 +28,21 @@ class Message:
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 = pygame.Surface((self.chat_width, self.height * 10))
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
padding = 7
# Size of the scaled text surface
blit_height: int = self.height - padding * 2
blit_width: int = round(text_surface.get_width() * blit_height / text_surface.get_height())
blit_width: int = self.chat_width // 2
x: int = 0 if not self.is_from_me else self.chat_width - blit_width - padding * 3.5
pygame.draw.rect(surface, bg_color, (x, 0, blit_width + padding * 2, self.height))
text_surface: pygame.Surface = pygame.transform.smoothscale(text_surface, (blit_width, blit_height))
surface.blit(text_surface, (x + padding, padding))
return surface
pygame.draw.rect(surface, bg_color, (x, 0, blit_width + padding * 2, self.height * 10))
text_surface: pygame.Surface = pygame.Surface((blit_width, blit_height * 10))
text_surface.fill(bg_color)
text_height = render_text(text_surface, (0, 0), font_medium, self.text, WHITE)
# text_surface = pygame.transform.chop(text_surface, (0, 0, blit_width, text_height))
surface.blit(text_surface, (x + padding, padding, blit_width, text_height))
new_surface = pygame.Surface((self.chat_width, text_height + 2 * padding))
new_surface.fill(bg_color)
new_surface.blit(surface, (0, 0, new_surface.get_width(), new_surface.get_height()))
return new_surface

7
degeon_py/utils.py

@ -16,11 +16,11 @@ def get_word_length(ft, word: str):
def render_text(surface, position: typing.Tuple[int, int], font: pygame.font, text: str, c=pygame.Color('black'),
cursor_position: Optional[int] = None):
cursor_position: Optional[int] = None) -> int:
"""Render text with hyphenation"""
if len(text) == 0:
return None
if len(list(filter(bool, text.split()))) == 0:
return 0
need_cursor = cursor_position is not None
lines = [word.split() for word in text.splitlines()]
@ -48,3 +48,4 @@ def render_text(surface, position: typing.Tuple[int, int], font: pygame.font, te
x += w + space_size
y += h
x = position[0]
return y

Loading…
Cancel
Save