From 94218d9136b8031ca9a5025da36b975c1084ebaa Mon Sep 17 00:00:00 2001 From: Maic Siemering Date: Fri, 26 Jul 2024 18:50:13 +0200 Subject: [PATCH 1/5] docs(gui): fix last old style docs --- arcade/gui/widgets/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arcade/gui/widgets/__init__.py b/arcade/gui/widgets/__init__.py index 6d4abb5fd..17cd874b1 100644 --- a/arcade/gui/widgets/__init__.py +++ b/arcade/gui/widgets/__init__.py @@ -523,8 +523,7 @@ class UIInteractiveWidget(UIWidget): size_hint: Tuple of floats (0.0-1.0), how much space of the parent should be requested size_hint_min: min width and height in pixel - size_hint_max: max width and height in pixel:param x: center x - of widget + size_hint_max: max width and height in pixel interaction_buttons: defines, which mouse buttons should trigger the interaction (default: left mouse button) style: not used From c97e5e4cf4c3cdb085c1290243dcc921f069f10e Mon Sep 17 00:00:00 2001 From: Maic Siemering Date: Sat, 27 Jul 2024 07:23:00 +0200 Subject: [PATCH 2/5] fix(gui): event propagation and further cleanup --- arcade/gui/surface.py | 5 ++++ arcade/gui/widgets/__init__.py | 46 +++++++++++++--------------------- arcade/gui/widgets/text.py | 14 +++++++++-- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/arcade/gui/surface.py b/arcade/gui/surface.py index 1f330b428..8ecb3a215 100644 --- a/arcade/gui/surface.py +++ b/arcade/gui/surface.py @@ -3,6 +3,7 @@ from contextlib import contextmanager from typing import Generator, Optional +from PIL import Image from typing_extensions import Self import arcade @@ -251,3 +252,7 @@ def resize(self, *, size: tuple[int, int], pixel_ratio: float) -> None: self.texture = self.ctx.texture(self.size_scaled, components=4) self.fbo = self.ctx.framebuffer(color_attachments=[self.texture]) self.fbo.clear() + + def to_image(self) -> Image.Image: + """Convert the surface to an PIL image""" + return self.ctx.get_framebuffer_image(self.fbo) diff --git a/arcade/gui/widgets/__init__.py b/arcade/gui/widgets/__init__.py index 17cd874b1..0f5ded063 100644 --- a/arcade/gui/widgets/__init__.py +++ b/arcade/gui/widgets/__init__.py @@ -526,7 +526,6 @@ class UIInteractiveWidget(UIWidget): size_hint_max: max width and height in pixel interaction_buttons: defines, which mouse buttons should trigger the interaction (default: left mouse button) - style: not used """ # States @@ -616,8 +615,9 @@ def on_click(self, event: UIOnClickEvent): class UIDummy(UIInteractiveWidget): - """Solid color widget used for testing & examples + """Solid color widget used for testing & examples. + Starts with a random color. It should not be subclassed for real-world usage. When clicked, it does the following: @@ -628,14 +628,13 @@ class UIDummy(UIInteractiveWidget): Args: x: x coordinate of bottom left y: y coordinate of bottom left - color: fill color for the widget width: width of widget height: height of widget size_hint: Tuple of floats (0.0-1.0), how much space of the parent should be requested size_hint_min: min width and height in pixel size_hint_max: max width and height in pixel - style: not used + **kwargs: passed to UIWidget """ def __init__( @@ -658,25 +657,22 @@ def __init__( size_hint=size_hint, size_hint_min=size_hint_min, size_hint_max=size_hint_max, + **kwargs, ) - self.color: RGBA255 = (randint(0, 255), randint(0, 255), randint(0, 255), 255) - self.border_color = arcade.color.BATTLESHIP_GREY - self.border_width = 0 + self.with_background(color=Color.random(a=255)) + self.with_border(color=arcade.color.BATTLESHIP_GREY, width=0) def on_click(self, event: UIOnClickEvent): """Prints the rect and changes the color""" print("UIDummy.rect:", self.rect) - self.color = Color.random(a=255) + self.with_background(color=Color.random(a=255)) def on_update(self, dt): """Update the border of the widget if hovered""" - self.border_width = 2 if self.hovered else 0 - self.border_color = arcade.color.WHITE if self.pressed else arcade.color.BATTLESHIP_GREY - - def do_render(self, surface: Surface): - """Render solid color""" - self.prepare_render(surface) - surface.clear(self.color) + self.with_border( + width=2 if self.hovered else 0, + color=arcade.color.WHITE if self.pressed else arcade.color.BATTLESHIP_GREY, + ) class UISpriteWidget(UIWidget): @@ -692,7 +688,6 @@ class UISpriteWidget(UIWidget): parent should be requested size_hint_min: min width and height in pixel size_hint_max: max width and height in pixel - style: not used """ def __init__( @@ -748,7 +743,6 @@ class UILayout(UIWidget): parent should be requested size_hint_min: min width and height in pixel size_hint_max: max width and height in pixel - style: not used """ @staticmethod @@ -808,7 +802,8 @@ class UISpace(UIWidget): y: y coordinate of bottom left width: width of widget height: height of widget - color: Color for widget area + color: Color for widget area, if None, it will be transparent + (this will set the background color) size_hint: Tuple of floats (0.0-1.0), how much space of the parent should be requested size_hint_min: min width and height in pixel @@ -839,20 +834,13 @@ def __init__( size_hint_max=size_hint_max, **kwargs, ) - self._color = color + self.with_background(color=color) @property def color(self): - """Color of the widget""" - return self._color + """Color of the widget, alias for background color""" + return self._bg_color @color.setter def color(self, value): - self._color = value - self.trigger_render() - - def do_render(self, surface: Surface): - """Render the widget, mainly the background color""" - self.prepare_render(surface) - if self._color: - surface.clear(self._color) + self.with_background(color=value) diff --git a/arcade/gui/widgets/text.py b/arcade/gui/widgets/text.py index 9a7c04d6c..da2c0e14b 100644 --- a/arcade/gui/widgets/text.py +++ b/arcade/gui/widgets/text.py @@ -362,6 +362,8 @@ class UIInputText(UIWidget): around the caret. Arcade confirms that the field is active before allowing users to type, so it is okay to have multiple of these. + By default, a border is drawn around the input field. + Args: x: x position (default anchor is bottom-left). y: y position (default anchor is bottom-left). @@ -380,6 +382,9 @@ class UIInputText(UIWidget): is the same thing as a :py:class:`~arcade.gui.UITextArea`. caret_color: An RGBA or RGB color for the caret with each channel between 0 and 255, inclusive. + border_color: An RGBA or RGB color for the border with each + channel between 0 and 255, inclusive, can be None to remove border. + border_width: Width of the border in pixels. size_hint: A tuple of floats between 0 and 1 defining the amount of space of the parent should be requested. size_hint_min: Minimum size hint width and height in pixel. @@ -398,13 +403,15 @@ def __init__( x: float = 0, y: float = 0, width: float = 100, - height: float = 24, + height: float = 23, # required height for font size 12 + border width 1 text: str = "", font_name=("Arial",), font_size: float = 12, text_color: RGBOrA255 = arcade.color.WHITE, multiline=False, caret_color: RGBOrA255 = arcade.color.WHITE, + border_color: RGBOrA255 | None = arcade.color.WHITE, + border_width: float = 2, size_hint=None, size_hint_min=None, size_hint_max=None, @@ -420,6 +427,7 @@ def __init__( size_hint_max=size_hint_max, **kwargs, ) + self.with_border(color=border_color, width=border_width) self._active = False self._text_color = Color.from_iterable(text_color) @@ -467,7 +475,8 @@ def on_event(self, event: UIEvent) -> Optional[bool]: if not self._active and isinstance(event, UIMousePressEvent): if self.rect.point_in_rect(event.pos): self.activate() - return EVENT_HANDLED + # return unhandled to allow other widgets to deactivate + return EVENT_UNHANDLED # If active check to deactivate if self._active and isinstance(event, UIMousePressEvent): @@ -477,6 +486,7 @@ def on_event(self, event: UIEvent) -> Optional[bool]: self.caret.on_mouse_press(x, y, event.button, event.modifiers) else: self.deactivate() + # return unhandled to allow other widgets to activate return EVENT_UNHANDLED # If active pass all non press events to caret From a6c457b6cb3da1cbd1dd5fcc0952a077b686417a Mon Sep 17 00:00:00 2001 From: Maic Siemering Date: Sat, 27 Jul 2024 07:26:07 +0200 Subject: [PATCH 3/5] fix(gui): event propagation and further cleanup --- arcade/gui/widgets/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arcade/gui/widgets/__init__.py b/arcade/gui/widgets/__init__.py index 0f5ded063..b80bb9ff9 100644 --- a/arcade/gui/widgets/__init__.py +++ b/arcade/gui/widgets/__init__.py @@ -1,7 +1,6 @@ from __future__ import annotations from abc import ABC -from random import randint from typing import NamedTuple, Iterable, Optional, Union, TYPE_CHECKING, TypeVar, Tuple, List, Dict from pyglet.event import EventDispatcher, EVENT_HANDLED, EVENT_UNHANDLED @@ -22,7 +21,7 @@ from arcade.gui.nine_patch import NinePatchTexture from arcade.gui.property import Property, bind, ListProperty from arcade.gui.surface import Surface -from arcade.types import RGBA255, Color, AnchorPoint, AsFloat +from arcade.types import Color, AnchorPoint, AsFloat from arcade.utils import copy_dunders_unimplemented if TYPE_CHECKING: From 6b46f987834a3f626c4d5320ab32e51c9d64d638 Mon Sep 17 00:00:00 2001 From: Maic Siemering Date: Sat, 27 Jul 2024 07:30:01 +0200 Subject: [PATCH 4/5] fix(gui): event propagation and further cleanup --- arcade/gui/widgets/text.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arcade/gui/widgets/text.py b/arcade/gui/widgets/text.py index da2c0e14b..c76a8bdd8 100644 --- a/arcade/gui/widgets/text.py +++ b/arcade/gui/widgets/text.py @@ -411,7 +411,7 @@ def __init__( multiline=False, caret_color: RGBOrA255 = arcade.color.WHITE, border_color: RGBOrA255 | None = arcade.color.WHITE, - border_width: float = 2, + border_width: int = 2, size_hint=None, size_hint_min=None, size_hint_max=None, @@ -427,7 +427,9 @@ def __init__( size_hint_max=size_hint_max, **kwargs, ) - self.with_border(color=border_color, width=border_width) + self.with_border( + color=Color.from_iterable(border_color) if border_color else None, width=border_width + ) self._active = False self._text_color = Color.from_iterable(text_color) From cb61c23be7c21d9a0760827e18b6723fa502607b Mon Sep 17 00:00:00 2001 From: Maic Siemering Date: Sat, 27 Jul 2024 07:34:01 +0200 Subject: [PATCH 5/5] fix(gui): event propagation and further cleanup --- arcade/gui/widgets/__init__.py | 2 +- arcade/gui/widgets/text.py | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/arcade/gui/widgets/__init__.py b/arcade/gui/widgets/__init__.py index b80bb9ff9..dbb289eeb 100644 --- a/arcade/gui/widgets/__init__.py +++ b/arcade/gui/widgets/__init__.py @@ -388,7 +388,7 @@ def resize(self, *, width=None, height=None, anchor: Vec2 = AnchorPoint.CENTER): """ self.rect = self.rect.resize(width=width, height=height, anchor=anchor) - def with_border(self, *, width=2, color=arcade.color.GRAY) -> Self: + def with_border(self, *, width=2, color: Color | None = arcade.color.GRAY) -> Self: """Sets border properties Args: diff --git a/arcade/gui/widgets/text.py b/arcade/gui/widgets/text.py index c76a8bdd8..50401f1bd 100644 --- a/arcade/gui/widgets/text.py +++ b/arcade/gui/widgets/text.py @@ -410,7 +410,7 @@ def __init__( text_color: RGBOrA255 = arcade.color.WHITE, multiline=False, caret_color: RGBOrA255 = arcade.color.WHITE, - border_color: RGBOrA255 | None = arcade.color.WHITE, + border_color: Color | None = arcade.color.WHITE, border_width: int = 2, size_hint=None, size_hint_min=None, @@ -427,9 +427,8 @@ def __init__( size_hint_max=size_hint_max, **kwargs, ) - self.with_border( - color=Color.from_iterable(border_color) if border_color else None, width=border_width - ) + + self.with_border(color=border_color, width=border_width) self._active = False self._text_color = Color.from_iterable(text_color)