1717
1818from __future__ import annotations
1919
20+ from dataclasses import asdict , dataclass , field
2021import json
2122import time
22- from dataclasses import asdict , dataclass , field
2323from typing import Any , Callable , Dict , List , Optional
2424
25-
2625# ---------------------------------------------------------------------------
2726# Rendercanvas event types that we observe by default (lowercase strings used
2827# by rendercanvas._enums.EventType).
4443# RecordedEvent
4544# ---------------------------------------------------------------------------
4645
46+
4747@dataclass (frozen = True )
4848class RecordedEvent :
4949 """Immutable snapshot of a single rendercanvas UI event.
@@ -131,16 +131,22 @@ def from_rendercanvas_event(cls, event: Any) -> "RecordedEvent":
131131 RecordedEvent
132132 """
133133 if isinstance (event , dict ):
134+
134135 def _get (key : str , default : Any = None ) -> Any :
135136 return event .get (key , default )
137+
136138 raw = dict (event )
137139 else :
140+
138141 def _get (key : str , default : Any = None ) -> Any : # type: ignore[misc]
139142 return getattr (event , key , default )
143+
140144 # Serialise object to a dict so raw is always JSON-safe.
141145 try :
142146 raw = {
143- "event_type" : getattr (event , "event_type" , getattr (event , "type" , "" )),
147+ "event_type" : getattr (
148+ event , "event_type" , getattr (event , "type" , "" )
149+ ),
144150 "x" : float (getattr (event , "x" , 0 )),
145151 "y" : float (getattr (event , "y" , 0 )),
146152 "button" : int (getattr (event , "button" , 0 )),
@@ -149,7 +155,9 @@ def _get(key: str, default: Any = None) -> Any: # type: ignore[misc]
149155 "modifiers" : list (getattr (event , "modifiers" , [])),
150156 "dx" : float (getattr (event , "dx" , 0 )),
151157 "dy" : float (getattr (event , "dy" , 0 )),
152- "time_stamp" : float (getattr (event , "time_stamp" , time .perf_counter ())),
158+ "time_stamp" : float (
159+ getattr (event , "time_stamp" , time .perf_counter ())
160+ ),
153161 }
154162 except Exception :
155163 raw = {}
@@ -160,7 +168,9 @@ def _get(key: str, default: Any = None) -> Any: # type: ignore[misc]
160168
161169 return cls (
162170 event_type = str (et ),
163- timestamp = float (ts if (ts := _get ("time_stamp" )) is not None else time .perf_counter ()),
171+ timestamp = float (
172+ ts if (ts := _get ("time_stamp" )) is not None else time .perf_counter ()
173+ ),
164174 x = float (_get ("x" ) or 0 ),
165175 y = float (_get ("y" ) or 0 ),
166176 button = int (_get ("button" ) or 0 ),
@@ -205,6 +215,7 @@ def to_rendercanvas_event(self) -> Dict[str, Any]:
205215# EventRecorder
206216# ---------------------------------------------------------------------------
207217
218+
208219class EventRecorder :
209220 """Records UI events from a FURY v2 ShowManager.
210221
@@ -380,6 +391,7 @@ def _resolve_renderer(show_manager: Any) -> Any:
380391# EventCounter
381392# ---------------------------------------------------------------------------
382393
394+
383395class EventCounter (EventRecorder ):
384396 """Records events *and* maintains per-type counts.
385397
@@ -432,8 +444,12 @@ def clear(self) -> None:
432444 # ------------------------------------------------------------------
433445
434446 def _on_event (self , event : Any ) -> None :
435- et = event .get ("event_type" , "unknown" ) if isinstance (event , dict ) else (
436- getattr (event , "event_type" , None ) or getattr (event , "type" , "unknown" )
447+ et = (
448+ event .get ("event_type" , "unknown" )
449+ if isinstance (event , dict )
450+ else (
451+ getattr (event , "event_type" , None ) or getattr (event , "type" , "unknown" )
452+ )
437453 )
438454 self ._counts [et ] = self ._counts .get (et , 0 ) + 1
439455 super ()._on_event (event )
@@ -443,6 +459,7 @@ def _on_event(self, event: Any) -> None:
443459# EventPlayer
444460# ---------------------------------------------------------------------------
445461
462+
446463class EventPlayer :
447464 """Replays a sequence of :class:`RecordedEvent` objects into a ShowManager.
448465
@@ -524,14 +541,14 @@ def play(self, show_manager: Any) -> None:
524541 # 3. renderer.dispatch_event — last resort (expects Event object, not dict)
525542 if hasattr (renderer , "emit" ):
526543 _dispatch = renderer .emit
527- elif hasattr (show_manager , "window" ) and hasattr (show_manager .window , "_events" ):
544+ elif hasattr (show_manager , "window" ) and hasattr (
545+ show_manager .window , "_events"
546+ ):
528547 _dispatch = show_manager .window ._events .emit
529548 elif hasattr (renderer , "dispatch_event" ):
530549 _dispatch = renderer .dispatch_event
531550 else :
532- raise AttributeError (
533- "Cannot find a dict-compatible event dispatch path."
534- )
551+ raise AttributeError ("Cannot find a dict-compatible event dispatch path." )
535552
536553 prev_ts : Optional [float ] = None
537554 for idx , evt in enumerate (events ):
0 commit comments