Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,6 @@ dmypy.json

# DS_Store
.DS_Store

# secret tests
tests/test.py
4 changes: 4 additions & 0 deletions guipy/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import pygame

pygame.init()
pygame.font.init()
21 changes: 17 additions & 4 deletions guipy/components/_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,29 @@

class Component:
def __init__(self, width, height):
"""
Component init. Should create a surface for the component
"""
self.width = width
self.height = height
self.root = pygame.Surface((width, height))

self.root = pygame.Surface((width, height)).convert_alpha()
def _draw(self):
"""
All the drawing
"""

def get_surf(self):
return self.root

def draw(self):
pass
def _collide(self, rel_mouse):
return 0 <= rel_mouse[0] < self.width and 0 <= rel_mouse[1] < self.height

def update(self, rel_mouse, events):
pass
"""
Update the component. Usually calls

:param rel_mouse: Mouse position relative to the component
:param events: Pygame event list
"""
self._draw()
117 changes: 117 additions & 0 deletions guipy/components/button.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import pygame
from guipy.components._component import Component
from guipy.utils import *


class Button(Component):
"""
Button component
"""

def __init__(self, width=None, height=None, font=None, text="Bruh"):
"""
Button init

:param width: button width in pixels, defaults to fit text
:param height: button height in pixels, defaults to fit text
:param font: pygame Font object to use
:param text: text to display on the button
"""
if font == None:
self.font = get_default_font()
else:
self.font = font

min_w, min_h = self.font.size(text)
if width == None:
width = min_w + 6
if height == None:
height = min_h

self.width = width
self.height = height
self.off_surf = pygame.Surface((self.width, self.height)).convert_alpha()
self.on_surf = pygame.Surface((self.width, self.height)).convert_alpha()

self.pressed = False

self.set_text(text)

self.cb = None

def get_val(self):
"""
Get current state
"""
return self.pressed

def set_callback(self, cb):
"""
Set the callback to be run when the button is released

:param cb: Callback function
"""
self.cb = cb
return self

def _draw(self):
text_surf = self.font.render(self.text, True, BLACK)

x, y = sub_vector((self.width, self.height), text_surf.get_size())
pos = (x // 2, y // 2)

self.off_surf.fill(TRANSPARENT)
surf = self.off_surf
pygame.draw.rect(surf, LIGHT_GREY, surf.get_rect())
pygame.draw.rect(surf, DARK_GREY, surf.get_rect(), 1)
surf.blit(text_surf, pos)

self.on_surf.fill(TRANSPARENT)
surf = self.on_surf
pygame.draw.rect(surf, GREY, surf.get_rect())
pygame.draw.rect(surf, DARK_GREY, surf.get_rect(), 1)
surf.blit(text_surf, pos)

def set_text(self, text):
"""
Sets the text on the button and redraws the surface

:param text:
"""
self.text = text
self._draw()
return self

def get_surf(self):
"""
Get the button's surface
"""
if self.pressed:
return self.on_surf
else:
return self.off_surf

def update(self, rel_mouse, events):
"""
Update the button

:param rel_mouse: Relative mouse position
:param events: Pygame Event list
"""
on_click = False
on_release = False
for event in events:
if event.type == pygame.MOUSEBUTTONDOWN:
on_click = True
if event.type == pygame.MOUSEBUTTONUP:
on_release = True

in_comp = self._collide(rel_mouse)

if on_click and in_comp:
self.pressed = True

if on_release and self.pressed:
if in_comp and self.cb != None:
self.cb(self)
self.pressed = False
139 changes: 139 additions & 0 deletions guipy/components/menu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import pygame
from guipy.components._component import Component
from guipy.utils import *


class Dropdown(Component):
"""
Dropdown menu component
"""

def __init__(self, width, font=None):
"""
Dropdown init

:param width: Menu width in pixels
:param font: pygame Font object to use
"""
if font == None:
self.font = get_default_font()
else:
self.font = font

self.height = self.font.get_linesize()
self.width = max(self.height, width)

self.open = False
self.value = None
self.highlighted = -1
self.options = []

self.cb = None

self._draw()

def set_callback(self, cb):
"""
Set the callback to be run when a new option is selected

:param cb: Callback function
"""
self.cb = cb
return self

def _draw(self):
w = self.width - self.height
n = len(self.options)
if self.open:
self.root = pygame.Surface(
(self.width, self.height * (n + 1))
).convert_alpha()
self.root.fill((200, 200, 200, 150))

for i in range(n):
y = (i + 1) * self.height
if i == self.highlighted:
box = pygame.Rect(0, y, self.width, self.height)
pygame.draw.rect(self.root, (170, 170, 170, 150), box)
text = self.font.render(str(self.options[i]), True, BLACK)
self.root.blit(text, (3, y))
else:
self.root = pygame.Surface((self.width, self.height)).convert_alpha()

box = pygame.Rect(0, 0, self.width, self.height)
pygame.draw.rect(self.root, WHITE, box)
if self.value != None:
text = self.font.render(str(self.value), True, BLACK)
self.root.blit(text, (3, 0))
arrow = pygame.Rect(self.width - self.height, 0, self.height, self.height)
pygame.draw.rect(self.root, GREY, arrow)
y = self.height // 2
x = y + w
if self.open:
pygame.draw.line(
self.root,
WHITE,
(x, y - self.height // 6),
(x - self.height // 3, y + self.height // 6),
2,
)
pygame.draw.line(
self.root,
WHITE,
(x, y - self.height // 6),
(x + self.height // 3, y + self.height // 6),
2,
)
else:
pygame.draw.line(
self.root,
WHITE,
(x, y + self.height // 6),
(x - self.height // 3, y - self.height // 6),
2,
)
pygame.draw.line(
self.root,
WHITE,
(x, y + self.height // 6),
(x + self.height // 3, y - self.height // 6),
2,
)
pygame.draw.rect(self.root, BLACK, self.root.get_rect(), 1)

def add(self, *options):
self.options += options
return self

def update(self, rel_mouse, events):
"""
Update the dropdown menu

:param rel_mouse: Relative mouse position
:param events: Pygame Event list
"""
on_click = False
for event in events:
if event.type == pygame.MOUSEBUTTONDOWN:
on_click = True

in_width = 0 <= rel_mouse[0] < self.width
index = rel_mouse[1] // self.height - 1

if self.open:
if 0 <= index < len(self.options) and in_width:
self.highlighted = index
if on_click:
self.value = self.options[index]
if not self.cb == None:
self.cb(self)
else:
self.highlighted = -1
if on_click:
self.open = False
self.highlighted = -1
self._draw()

else:
if on_click and in_width and index == -1:
self.open = True
Loading