Skip to content

Commit

Permalink
Gui/small improvements (#2321)
Browse files Browse the repository at this point in the history
* fix(gui): event propagation and further cleanup
  • Loading branch information
eruvanos authored Jul 27, 2024
1 parent 7d9a26d commit 5d502a8
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 34 deletions.
5 changes: 5 additions & 0 deletions arcade/gui/surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from contextlib import contextmanager
from typing import Generator, Optional

from PIL import Image
from typing_extensions import Self

import arcade
Expand Down Expand Up @@ -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)
51 changes: 19 additions & 32 deletions arcade/gui/widgets/__init__.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -389,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:
Expand Down Expand Up @@ -526,7 +525,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
Expand Down Expand Up @@ -616,8 +614,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:
Expand All @@ -628,14 +627,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__(
Expand All @@ -658,25 +656,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):
Expand All @@ -692,7 +687,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__(
Expand Down Expand Up @@ -748,7 +742,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
Expand Down Expand Up @@ -808,7 +801,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
Expand Down Expand Up @@ -839,20 +833,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)
15 changes: 13 additions & 2 deletions arcade/gui/widgets/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand All @@ -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.
Expand All @@ -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: Color | None = arcade.color.WHITE,
border_width: int = 2,
size_hint=None,
size_hint_min=None,
size_hint_max=None,
Expand All @@ -421,6 +428,8 @@ def __init__(
**kwargs,
)

self.with_border(color=border_color, width=border_width)

self._active = False
self._text_color = Color.from_iterable(text_color)

Expand Down Expand Up @@ -467,7 +476,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):
Expand All @@ -477,6 +487,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
Expand Down

0 comments on commit 5d502a8

Please sign in to comment.