from __future__ import annotations import numpy as np from manimlib.event_handler.event_listner import EventListener from manimlib.event_handler.event_type import EventType class EventDispatcher(object): def __init__(self): self.event_listners: dict[ EventType, list[EventListener] ] = { event_type: [] for event_type in EventType } self.mouse_point = np.array((0., 0., 0.)) self.mouse_drag_point = np.array((0., 0., 0.)) self.pressed_keys: set[int] = set() self.draggable_object_listners: list[EventListener] = [] def add_listner(self, event_listner: EventListener): assert isinstance(event_listner, EventListener) self.event_listners[event_listner.event_type].append(event_listner) return self def remove_listner(self, event_listner: EventListener): assert isinstance(event_listner, EventListener) try: while event_listner in self.event_listners[event_listner.event_type]: self.event_listners[event_listner.event_type].remove(event_listner) except: # raise ValueError("Handler is not handling this event, so cannot remove it.") pass return self def dispatch(self, event_type: EventType, **event_data): if event_type == EventType.MouseMotionEvent: self.mouse_point = event_data["point"] elif event_type == EventType.MouseDragEvent: self.mouse_drag_point = event_data["point"] elif event_type == EventType.KeyPressEvent: self.pressed_keys.add(event_data["symbol"]) # Modifiers? elif event_type == EventType.KeyReleaseEvent: self.pressed_keys.difference_update({event_data["symbol"]}) # Modifiers? elif event_type == EventType.MousePressEvent: self.draggable_object_listners = [ listner for listner in self.event_listners[EventType.MouseDragEvent] if listner.mobject.is_point_touching(self.mouse_point) ] elif event_type == EventType.MouseReleaseEvent: self.draggable_object_listners = [] propagate_event = None if event_type == EventType.MouseDragEvent: for listner in self.draggable_object_listners: assert isinstance(listner, EventListener) propagate_event = listner.callback(listner.mobject, event_data) if propagate_event is not None and propagate_event is False: return propagate_event elif event_type.value.startswith('mouse'): for listner in self.event_listners[event_type]: if listner.mobject.is_point_touching(self.mouse_point): propagate_event = listner.callback( listner.mobject, event_data) if propagate_event is not None and propagate_event is False: return propagate_event elif event_type.value.startswith('key'): for listner in self.event_listners[event_type]: propagate_event = listner.callback(listner.mobject, event_data) if propagate_event is not None and propagate_event is False: return propagate_event return propagate_event def get_listners_count(self) -> int: return sum([len(value) for key, value in self.event_listners.items()]) def get_mouse_point(self) -> np.ndarray: return self.mouse_point def get_mouse_drag_point(self) -> np.ndarray: return self.mouse_drag_point def is_key_pressed(self, symbol: int) -> bool: return (symbol in self.pressed_keys) __iadd__ = add_listner __isub__ = remove_listner __call__ = dispatch __len__ = get_listners_count