diff --git a/testing/pygame_simple.py b/testing/pygame_simple.py index 7ed6a07..0cc4ff5 100644 --- a/testing/pygame_simple.py +++ b/testing/pygame_simple.py @@ -1,32 +1,48 @@ -import numpy as np import pygame -from pprint import pprint +import pygame_gui + pygame.init() -screen = pygame.display.set_mode((12, 1), pygame.RESIZABLE | pygame.SCALED) + +pygame.display.set_caption("Quick Start") +window_surface = pygame.display.set_mode((800, 600)) + +background = pygame.Surface((800, 600)) +background.fill(pygame.Color("#000000")) + +manager = pygame_gui.UIManager((800, 600)) + +hello_button = pygame_gui.elements.UIButton( + relative_rect=pygame.Rect((350, 275), (100, 50)), text="Say Hello", manager=manager +) + +text_box = pygame_gui.elements.ui_text_box.UITextBox( + html_text="This is an EARTHQUAKE", + relative_rect=pygame.Rect(0, 0, 200, 50), + manager=manager, +) + clock = pygame.time.Clock() -running = True +is_running = True -while running: +while is_running: + time_delta = clock.tick(60) / 1000.0 for event in pygame.event.get(): if event.type == pygame.QUIT: - running = False + is_running = False - screen.fill((128, 0, 0)) - screen.set_at((0, 0), (255, 0, 0)) - screen.set_at((4, 0), (0, 255, 0)) - screen.set_at((8, 0), (0, 0, 255)) + if event.type == pygame_gui.UI_BUTTON_PRESSED: + if event.ui_element == hello_button: + print("Hello World!") + text_box.set_active_effect( + pygame_gui.TEXT_EFFECT_BOUNCE, effect_tag="test" + ) - original = pygame.surfarray.pixels3d(screen) - reshaped = np.reshape(original, (4, 3, -1), order="F") + manager.process_events(event) - print("original", original.shape) - print("reshaped", reshaped.shape) - assert (original[0, 0] == reshaped[0, 0]).all() - assert (original[4, 0] == reshaped[0, 1]).all() - assert (original[8, 0] == reshaped[0, 2]).all() + manager.update(time_delta) - pygame.display.flip() - clock.tick(1) + window_surface.blit(background, (0, 0)) + manager.draw_ui(window_surface) -pygame.quit() + pygame.display.update() diff --git a/wideboy/scenes/default/__init__.py b/wideboy/scenes/default/__init__.py index d8a15af..4e34082 100644 --- a/wideboy/scenes/default/__init__.py +++ b/wideboy/scenes/default/__init__.py @@ -9,6 +9,7 @@ from wideboy.sprites.homeassistant.entity_row import ( HomeAssistantEntityRowSprite, HomeAssistantEntityTile, + HomeAssistantEntityTileOrientation, ) from wideboy.sprites.notification import NotificationSprite from wideboy.sprites.weather.animation import WeatherAnimationSprite @@ -169,9 +170,13 @@ def setup(self): self.hass_row_power = HomeAssistantEntityRowSprite( self, - Rect(512, 48, 128, 16), + Rect(700, 2, 128, 60), hass_row_power_entities, + min_size=(64, None), color_bg=Color(0, 0, 0, 196), + orientation=HomeAssistantEntityTileOrientation.VERTICAL, + font_size=11, + padding_bottom=2, ) self.group.add(self.hass_row_power) @@ -221,9 +226,9 @@ def update( events: list[Event], ) -> None: super().update(clock, delta, events) - self.hass_row_main.rect.topright = self.width - 128 - 3, 2 - self.hass_row_power.rect.topright = self.width - 128 - 3, 17 - self.hass_row_battery.rect.topright = self.width - 128 - 3, 32 + self.hass_row_main.rect.topright = self.width - 256 - 3, 2 + self.hass_row_power.rect.topright = self.width - 68, 4 + self.hass_row_battery.rect.topright = self.width - 256 - 3, 32 # Handle Events diff --git a/wideboy/scenes/default/tiles.py b/wideboy/scenes/default/tiles.py index 09184d2..2a86cf3 100644 --- a/wideboy/scenes/default/tiles.py +++ b/wideboy/scenes/default/tiles.py @@ -9,6 +9,7 @@ class TileStepsLouis(HomeAssistantEntityTile): + label_font_size = 12 icon = MaterialIcons.MDI_DIRECTIONS_WALK icon_color = Color(255, 0, 255, 255) @@ -164,7 +165,7 @@ class TileElectricityHourlyRate(HomeAssistantEntityTile): def process(self, state): value = state.get("sensor.electricity_hourly_rate", 0) self.visible = value > 0 - self.label = f"{value:.2f}" + self.label = f"£{value:.2f}" self.icon_color = ( Color(255, 64, 64, 255) if value > 0.50 else Color(64, 255, 64, 255) ) @@ -179,7 +180,7 @@ def process(self, state): "sensor.octopus_energy_electricity_current_accumulative_cost", 0 ) self.visible = value > 0 - self.label = f"{value:.2f}" + self.label = f"£{value:.2f}" self.icon_color = ( Color(255, 64, 64, 255) if value > 2.50 else Color(64, 255, 64, 255) ) diff --git a/wideboy/sprites/homeassistant/entity_row.py b/wideboy/sprites/homeassistant/entity_row.py index e8e6abc..1da3dbd 100644 --- a/wideboy/sprites/homeassistant/entity_row.py +++ b/wideboy/sprites/homeassistant/entity_row.py @@ -1,7 +1,8 @@ import logging import types +from enum import Enum from pygame import Clock, Color, Event, Rect, Surface, SRCALPHA -from typing import Optional, List, Set, Dict, Any, Union +from typing import Optional, List, Set, Dict, Any, Union, Tuple from wideboy.constants import ( EVENT_EPOCH_MINUTE, EVENT_HASS_STATESTREAM_UPDATE, @@ -18,65 +19,55 @@ logger = logging.getLogger("sprite.hass_entity_row") +class HomeAssistantEntityTileOrientation(Enum): + HORIZONTAL = 0 + VERTICAL = 1 + + class HomeAssistantEntityTile: visible: bool = True icon: int = MaterialIcons.MDI_DELETE icon_color: Color = Color(255, 255, 255, 255) label: str = "" label_color: Color = Color(255, 255, 255, 255) - - def set_options( - self, - visible: bool, - icon: int, - icon_color: Color, - label: str, - label_color: Color, - ) -> None: - self.visible = visible - self.icon = icon - self.icon_color = icon_color - self.label = label - self.label_color = label_color + label_font_size: Optional[int] = None def process(self, state) -> None: pass - def to_dict(self) -> dict: - return { - "visible": self.visible, - "icon": self.icon, - "icon_color": self.icon_color, - "label": self.label, - "label_color": self.label_color, - } - class HomeAssistantEntityRowSprite(BaseSprite): rect: Rect image: Surface + orientation: HomeAssistantEntityTileOrientation def __init__( self, scene: BaseScene, rect: Rect, entities: List[HomeAssistantEntityTile], + min_size: Tuple[Optional[int], Optional[int]] = (None, None), + orientation: HomeAssistantEntityTileOrientation = HomeAssistantEntityTileOrientation.HORIZONTAL, font_name: str = "fonts/bitstream-vera.ttf", - font_size: int = 12, + font_size: int = 10, color_fg: Color = Color(255, 255, 255, 255), color_bg: Color = Color(0, 0, 0, 255), color_outline: Optional[Color] = None, padding_right: int = 3, + padding_bottom: int = 0, show_all: bool = False, ) -> None: super().__init__(scene, rect) self.entities = entities + self.min_size = min_size + self.orientation = orientation self.font_name = font_name self.font_size = font_size self.color_fg = color_fg self.color_bg = color_bg self.color_outline = color_outline self.padding_right = padding_right + self.padding_bottom = padding_bottom self.show_all = show_all self.render() @@ -96,6 +87,12 @@ def update( self.render() def render(self) -> None: + if self.orientation == HomeAssistantEntityTileOrientation.HORIZONTAL: + self.render_horizontal() + elif self.orientation == HomeAssistantEntityTileOrientation.VERTICAL: + self.render_vertical() + + def render_horizontal(self) -> None: w, h = 1, 2 surfaces = [] for entity in self.entities: @@ -108,6 +105,7 @@ def render(self) -> None: icon_color=entity.icon_color, label_text=entity.label, label_color=entity.label_color, + label_font_size=entity.label_font_size or self.font_size, padding_right=self.padding_right, ) w += entity_surface.get_rect().width @@ -121,7 +119,44 @@ def render(self) -> None: for surface in surfaces: self.image.blit(surface, (x, 0)) x += surface.get_rect().width - self.rect.width = x + if self.min_size[0] is not None: + self.rect.width = self.min_size[0] + else: + self.rect.width = x + self.dirty = 1 + + def render_vertical(self) -> None: + w, h = 1, 1 + surfaces = [] + for entity in self.entities: + entity.process(self.scene.hass.state) + try: + if not entity.visible: + continue + entity_surface = render_hass_tile( + icon_codepoint=entity.icon, + icon_color=entity.icon_color, + label_text=entity.label, + label_color=entity.label_color, + label_font_size=entity.label_font_size or self.font_size, + padding_right=self.padding_right, + ) + h += entity_surface.get_rect().height - 3 + self.padding_bottom + w = max(w, entity_surface.get_rect().width) + surfaces.append(entity_surface) + except Exception as ex: + logger.warn(f"failed to render entity", exc_info=ex) + if self.min_size[0] is not None: + w = self.min_size[0] + if self.min_size[1] is not None: + h = self.min_size[1] + self.image = Surface((w, h), SRCALPHA) + self.image.fill(self.color_bg) + y = 0 + for surface in surfaces: + self.image.blit(surface, (0, y)) + y += surface.get_rect().height - 3 + self.padding_bottom + self.rect.height = y self.dirty = 1