Projekt_Sztuczna_Inteligencja/ui/text_box.py

183 lines
6.7 KiB
Python

import pygame
from math import floor
class TextBox:
# constructor that can be used to set parameters of TextBox instance
def __init__(
self,
position,
dimensions,
text="",
box_color=(200, 200, 200),
font=pygame.font.get_default_font(),
font_color=(0, 0, 0),
font_size=None,
is_visible=True,
fit_text=True,
outline=True,
irregular_outline=False,
outline_additional_pixel=False,
outline_hover_inclusive=True,
outline_thickness=None,
outline_color=(50, 50, 50)
):
# extracting and setting values
smaller_dimension = min(dimensions)
width, height = dimensions
# counting default outline thickness
default_outline_thickness = max(1, floor((2 * smaller_dimension + width + height) / 200))
# setting attributes
self.position = position
self.dimensions = dimensions
self.text = text
self.box_color = get_fixed_rgb(box_color)
self.font_color = get_fixed_rgb(font_color)
self.font_size = _return_value_or_default(font_size, floor(smaller_dimension / 2))
self.font = pygame.font.SysFont(font, self.font_size)
self.is_visible = is_visible
self.fit_text = fit_text
self.outline = outline
self.irregular_outline = irregular_outline
self.outline_additional_pixel = outline_additional_pixel
self.outline_hover_inclusive = outline_hover_inclusive
self.outline_thickness = _return_value_or_default(outline_thickness, default_outline_thickness)
self.outline_color = get_fixed_rgb(outline_color)
# rendering text to get it's width and height
rendered_text = self.font.render(text, True, (0, 0, 0))
# if text is out of bounds and fit_text=True - resizing text to fit the box
if self.fit_text and rendered_text.get_width() > self.dimensions[0]:
self.font_size = floor(self.font_size / (rendered_text.get_width() / width + 0.1))
self.font = pygame.font.SysFont(font, self.font_size)
# draws the TextBox
def draw(self, window, *args, **kwargs):
# if is_visible=True drawing the TextBox
if self.is_visible:
# extracting and setting values from attributes
box_x, box_y = self.position
width, height = self.dimensions
# if outline=True - drawing an outline
if self.outline:
padding = self.outline_thickness - self.irregular_outline / 2 + self.outline_additional_pixel
outline_coordinates = (box_x - padding, box_y - padding, width + 2 * padding, height + 2 * padding)
pygame.draw.rect(window, self.outline_color, outline_coordinates)
# drawing the box
pygame.draw.rect(window, self.box_color, (box_x, box_y, width, height))
# rendering text and counting it's coordinates
rendered_text = self.font.render(self.text, True, self.font_color)
rendered_text_x = box_x + width/2 - rendered_text.get_width()/2
rendered_text_y = box_y + height/2 - rendered_text.get_height()/2
# drawing the box on the coordinates
window.blit(rendered_text, (rendered_text_x, rendered_text_y))
# checks if a position is over the InputBox and returns True or False
def is_over(self, position):
mouse_x, mouse_y = position
if not self.outline_hover_inclusive:
button_x, button_y = self.position
width, height = self.dimensions
else:
padding = self.outline_thickness
button_x, button_y = self.position
width, height = self.dimensions
button_x, button_y = button_x - padding, button_y - padding
width, height = width + 2 * padding, height + 2 * padding
return button_x <= mouse_x <= (button_x + width) and button_y <= mouse_y <= (button_y + height)
# returns text value
def get_text(self):
return self.text
# sets chosen coordinates
def set_coordinates(self, position=None, dimensions=None, outline_thickness=None):
if position is not None:
self.position = position
if dimensions is not None:
self.dimensions = dimensions
if outline_thickness is not None:
self.outline_thickness = outline_thickness
# sets the TextBox's text
def set_text(self, text):
if text is not None:
self.text = text
# sets chosen font attributes
def set_font(self, font=None, font_size=None):
if font_size is not None:
self.font_size = font_size
# rendering text to get it's width and height
rendered_text = self.font.render(self.text, True, (0, 0, 0))
# if text is out of bounds and fit_text=True - resizing text to fit the box
if self.fit_text and rendered_text.get_width() > self.dimensions[0]:
self.font_size = floor(self.font_size / (rendered_text.get_width() / self.dimensions[0] + 0.1))
self.font = pygame.font.SysFont(font, self.font_size)
if font is not None:
self.font = pygame.font.SysFont(font, self.font_size)
# sets chosen color attributes
def set_colors(self, box_color=None, font_color=None, outline_color=None):
if box_color is not None:
self.box_color = get_fixed_rgb(box_color)
if font_color is not None:
self.font_color = get_fixed_rgb(font_color)
if outline_color is not None:
self.outline_color = outline_color
# sets chosen flags
def set_flags(
self,
is_visible=None,
outline=None,
irregular_outline=None,
outline_additional_pixel=None,
outline_hover_inclusive=None
):
if is_visible is not None:
self.is_visible = is_visible
if outline is not None:
self.outline = outline
if irregular_outline is not None:
self.irregular_outline = irregular_outline
if outline_additional_pixel is not None:
self.outline_additional_pixel = outline_additional_pixel
if outline_hover_inclusive is not None:
self.outline_hover_inclusive = outline_hover_inclusive
# returns values that are not out of range
def get_fixed_rgb(x):
r, g, b = x
r, g, b = max(0, min(255, floor(r))), max(0, min(255, floor(g))), max(0, min(255, floor(b)))
return tuple((r, g, b))
# returns value or default depending on if passed value is None or not
def _return_value_or_default(value, default):
return default if value is None else value