Skip to content

Commit

Permalink
Back button refactor (#258)
Browse files Browse the repository at this point in the history
Back button which is always at the same place and visible when needed.
  • Loading branch information
soerface authored Dec 3, 2024
1 parent f3383b3 commit d3c012f
Show file tree
Hide file tree
Showing 33 changed files with 567 additions and 298 deletions.
18 changes: 14 additions & 4 deletions drinks_touch/config.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import enum
import os
from datetime import timedelta
from pathlib import Path
Expand All @@ -21,10 +22,19 @@
"yes",
]

COLORS = {
"infragelb": (246, 198, 0, 255),
"disabled": (50, 50, 50, 255),
}
_INFRAGELB = (246, 198, 0, 255)


class Color(enum.Enum):
PRIMARY = _INFRAGELB
DISABLED = (50, 50, 50, 255)
ERROR = (255, 0, 0, 255)
SUCCESS = (0, 255, 0, 255)
BLACK = (0, 0, 0, 255)
BACKGROUND = (30, 30, 26, 255)
NAVBAR_BACKGROUND = (5, 5, 5, 255)
BUTTON_BACKGROUND = (0, 0, 0, 255)


if bn := os.environ.get("BUILD_NUMBER"):
BUILD_NUMBER = bn
Expand Down
55 changes: 26 additions & 29 deletions drinks_touch/elements/base_elm.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from pygame import Surface


class BaseElm(object):
class BaseElm:
def __init__(
self,
children: list["BaseElm"] | None = None,
Expand Down Expand Up @@ -77,39 +77,36 @@ def screen_pos(self):
def box(self):
return self.screen_pos + (self.width, self.height)

def events(self, events, pos=None):
for event in events:
consumed = "consumed" in event.dict and event.consumed
if pos is None and hasattr(event, "pos"):
pos = event.pos
if pos is None:
continue
collides = self.collides_with(pos)
if collides:
transformed_pos = (
pos[0] - self.screen_pos[0],
pos[1] - self.screen_pos[1],
)
else:
transformed_pos = None
def event(self, event, pos=None):
if pos is None and hasattr(event, "pos"):
pos = event.pos
if pos is None:
return
collides = self.collides_with(pos)
transformed_pos = (
pos[0] - self.screen_pos[0],
pos[1] - self.screen_pos[1],
)

for child in self.children:
child.events(events, transformed_pos)
for child in self.children:
if hasattr(event, "consumed") and event.consumed:
return
child.event(event, transformed_pos)

if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
if collides:
self.focus = True
else:
self.focus = False
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
if collides:
self.focus = True
event.consumed = True
else:
self.focus = False

elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:
if not hasattr(self, "on_click"):
continue
elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:

if not consumed and self.focus and collides:
if self.focus and collides:
if hasattr(self, "on_click"):
self.on_click(*transformed_pos)
event.consumed = True
self.focus = False
event.consumed = True
self.focus = False

@property
def visible(self):
Expand Down
17 changes: 13 additions & 4 deletions drinks_touch/elements/button.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from config import FONTS, COLORS
from config import FONTS, Color
from .base_elm import BaseElm

import contextlib
Expand All @@ -14,7 +14,7 @@ def __init__(
font=FONTS["monospace"],
size=30,
text=None,
color=COLORS["infragelb"],
color=Color.PRIMARY,
on_click=None,
force_width=None,
force_height=None,
Expand Down Expand Up @@ -45,6 +45,13 @@ def __init__(
)
self.inner = inner

def __repr__(self):
if hasattr(self.inner, "text"):
text = self.inner.text
else:
text = str(self.inner)
return f"<Button {text}>"

def render(self, *args, **kwargs) -> pygame.Surface:
inner = self.inner.render(*args, **kwargs)

Expand All @@ -58,11 +65,13 @@ def render(self, *args, **kwargs) -> pygame.Surface:

surface = pygame.Surface(size, pygame.SRCALPHA)
if self.focus:
surface.fill(tuple(c * 0.7 for c in self.color), (0, 0, *size))
surface.fill(tuple(c * 0.7 for c in self.color.value), (0, 0, *size))
else:
surface.fill(Color.BUTTON_BACKGROUND.value, (0, 0, *size))

if inner is not None:
surface.blit(inner, (self.padding_left, self.padding_top))
pygame.draw.rect(surface, self.color, (0, 0, *size), 1)
pygame.draw.rect(surface, self.color.value, (0, 0, *size), 1)
return surface

def on_click(self, x, y):
Expand Down
5 changes: 5 additions & 0 deletions drinks_touch/elements/hbox.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pygame

from config import Color
from elements.base_elm import BaseElm


Expand All @@ -25,6 +26,10 @@ def render(self, *args, **kwargs) -> pygame.Surface:
element_surface = element.render(*args, **kwargs)
surface.blit(element_surface, element.pos)
x += element.width + self.gap
if self.focus:
pygame.draw.rect(
surface, Color.PRIMARY.value, (0, 0, self.width, self.height), 1
)
return surface

@property
Expand Down
4 changes: 2 additions & 2 deletions drinks_touch/elements/icons/base.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import pygame

from config import COLORS
from config import Color
from elements.base_elm import BaseElm


class BaseIcon(BaseElm):
SIZE = 24
COLOR = COLORS["infragelb"]
COLOR = Color.PRIMARY

def __init__(self, pos=None, width=None, height=None):
super().__init__(pos=pos)
Expand Down
8 changes: 4 additions & 4 deletions drinks_touch/elements/icons/refresh.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class RefreshIcon(BaseIcon):
def draw(self, surface):
pygame.draw.arc(
surface,
self.COLOR,
self.COLOR.value,
(0, 0, self.width, self.height),
math.pi * 0.2,
math.pi * 0.8,
Expand All @@ -20,7 +20,7 @@ def draw(self, surface):

pygame.draw.arc(
surface,
self.COLOR,
self.COLOR.value,
(0, 0, self.width, self.height),
math.pi * 1.2,
math.pi * 1.8,
Expand All @@ -29,7 +29,7 @@ def draw(self, surface):

pygame.draw.polygon(
surface,
self.COLOR,
self.COLOR.value,
[
(self.width * 0.6, self.height * 0.4),
(self.width * 0.95, self.height * 0.4),
Expand All @@ -39,7 +39,7 @@ def draw(self, surface):

pygame.draw.polygon(
surface,
self.COLOR,
self.COLOR.value,
[
(self.width * 0.4, self.height * 0.6),
(self.width * 0.05, self.height * 0.6),
Expand Down
26 changes: 23 additions & 3 deletions drinks_touch/elements/icons/svg.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,38 @@
import io

import pygame

from config import Color
from .base import BaseIcon


def load_and_scale_svg(filename, scale):
svg_string = open(filename, "rt").read()
start = svg_string.find("<svg")
if start > 0:
svg_string = (
svg_string[: start + 4]
+ f' transform="scale({scale})"'
+ svg_string[start + 4 :]
)
return pygame.image.load(io.BytesIO(svg_string.encode()))


class SvgIcon(BaseIcon):

def __init__(self, path, pos=None, color=None, width=None, height=None):
def __init__(
self, path, pos=None, color: Color | None = None, width=None, height=None
):
"""
If one of width or height is set and the other is None, the other
will be calculated to keep the aspect ratio.
"""
super().__init__(pos=pos)
self.path = path
image = pygame.image.load(self.path).convert_alpha()
# image = load_and_scale_svg(self.path, 2)
if color:
image.fill(color, special_flags=pygame.BLEND_RGBA_MIN)
image.fill(color.value, special_flags=pygame.BLEND_RGBA_MIN)

if width and height is None:
aspect_ratio = image.get_width() / image.get_height()
Expand All @@ -24,11 +42,13 @@ def __init__(self, path, pos=None, color=None, width=None, height=None):
width = int(height / aspect_ratio)

if width and height:
self.image = pygame.transform.scale(image, (width, height))
self.image = pygame.transform.smoothscale(image, (width, height))
self.width = width
self.height = height
else:
self.image = image
self.width = image.get_width()
self.height = image.get_height()

def draw(self, surface):
surface.blit(self.image, (0, 0))
4 changes: 1 addition & 3 deletions drinks_touch/elements/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@


class Image(BaseElm):
def __init__(
self, src="drinks_touch/resources/images/test.jpg", size=None, *args, **kwargs
):
def __init__(self, src, size=None, *args, **kwargs):
self.src = src
self.size = size
self.img = pygame.image.load(self.src).convert_alpha()
Expand Down
5 changes: 3 additions & 2 deletions drinks_touch/elements/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def __init__(
text="<Label>",
font=config.FONTS["sans serif"],
size=35,
color=config.COLORS["infragelb"],
color: config.Color = config.Color.PRIMARY,
bg_color=None,
border_color=None,
border_width=0,
Expand All @@ -27,6 +27,7 @@ def __init__(
*args,
**kwargs,
):
assert isinstance(color, config.Color)
self.size = size
self.max_width = max_width
self.text = text
Expand Down Expand Up @@ -76,7 +77,7 @@ def _render_background(self, area: pygame.Rect) -> pygame.Surface | None:
return surface

def _build_text(self):
elm = self.font.render(self.text, 1, self.color)
elm = self.font.render(self.text, 1, self.color.value)
cutx = 0
pos = self.pos
if self.align_right:
Expand Down
4 changes: 2 additions & 2 deletions drinks_touch/elements/progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def __init__(
children: list["BaseElm"] | None = None,
pos=None,
size=50,
color=config.COLORS["infragelb"],
color=config.Color.PRIMARY,
tick=None,
speed=1 / 4.0, # 4 secs
on_elapsed=None,
Expand Down Expand Up @@ -66,7 +66,7 @@ def render(self, dt) -> pygame.Surface:
end = start + self.value * 2 * math.pi
pygame.draw.arc(
surface,
self.color,
self.color.value,
(0, 0, self.width, self.height),
start,
end,
Expand Down
Loading

0 comments on commit d3c012f

Please sign in to comment.