Source code for Elements.pyECSS.Event

""" Event classes, part of the Elements.pyECSS package
    
Elements.pyECSS (Entity Component Systems in a Scenegraph) package
@Copyright 2021-2022 Dr. George Papagiannakis
    
The Event related classes are the mechanism for Event management in Elements.pyECSS
based on the Mediator and Observer design patterns.

"""

from __future__ import annotations
from abc import ABC, abstractmethod
from typing import List, Dict, Any
from dataclasses import dataclass




[docs]@dataclass class Event: """A simple dataclass that encapsulates an Event """ name: str id: Any value: Any
[docs]class EventPublisher(ABC): """ Interface class for all EventManagers that act as Publishers/Subjects (based on the Observer design pattern) or as Mediators (based on the Mediator design pattern) """ @abstractmethod def notify(self, sender: Any, event: Event): """the main mediator pattern type notification :param sender: [the object sending the event] :type sender: Component or RenderWindow :param event: [the Event name, id and value] :type event: Event :raises NotImplementedError: [description] """ raise NotImplementedError
[docs]class EventManager(EventPublisher): """ Main Mediator (Subject/Publisher) class that contains list of Observers/Subscribers (Components) that is being subscribed (notified) from and delegates to Systems to act upon these events invoked from these Components. """
[docs] def __init__(self): self._publishers: Dict[str,Any] = {} self._subscribers: Dict[str,Any] = {} self._actuators: Dict[str,Any] = {} self._events: Dict[str,Event] = {}
def notify(self, sender: Any, event: Event): if event is not None: print(f'\n{EventManager.getClassName()}: notify() reacts from {sender} with {event}\n') # hardcode it for now, in a refactored version search if there is a match in the dictionaries # i.e. no need to hardcode this in the future: # just add event name and appropriate subscribers, publishers, actuators # and run matchmaking here between event names and subscribers-actuators # all needed data are passed from the Event.value # and the appopriate actuator (System) will know what to do if event.name == "OnUpdateBackground": print(f'\n{event.name}: will be actuated from the appropriate system\n') elif event.name == "OnUpdateWireframe": print(f'\n{event.name}: will be actuated from the appropriate system\n') elif event.name == "OnUpdateCamera": print(f'\n{event.name}: will be actuated from the appropriate system - OnUpdateCamera\n') if event.name in self._subscribers: subscriber = self._subscribers[event.name] print(f'\n{EventManager.getClassName()}: notify() subscriber: {subscriber} for {event}\n') if event.name in self._actuators: systemActuator = self._actuators[event.name] print(f'\n{EventManager.getClassName()}: notify() actuator: {systemActuator} for {event}\n') subscriber.accept(systemActuator, event) print("EventManager:notify() ended") ''' @TODO NEED REFACTORING these methods once API is stable # value should be a List # any new subscriber to same key::Event of the Dict should be appended on the value:: List # def subscribe(self, component: Any): self._subscribers.append(component) def unsubscribe(self, component: Any): self._subscribers.remove(component) ''' def subscribe(self, component: Any): pass def unsubscribe(self, component: Any): pass def publish(self, component: Any): pass def unpublish(self, component: Any): pass def actuate(self, system: Any): pass def unactuate(self, system: Any): pass @classmethod def getClassName(cls): return cls.__name__ def print(self): """ debug output """ print("\n_publishers dict\n".center(100, '-')) for key, value in self._publishers.items(): print(f"\n{key} with value: {value} and value type: {type(value)} and contents:") if isinstance(value, List): for el in value: print(el) print("\n_subscribers dict\n".center(100, '-')) for key, value in self._subscribers.items(): print(f"\n{key} with value: {value} and value type: {type(value)} and contents:") if isinstance(value, List): for el in value: print(el) print("\n_actuators dict\n".center(100, '-')) for key, value in self._actuators.items(): print(f"\n{key} with value: {value} and value type: {type(value)} and contents:") if isinstance(value, List): for el in value: print(el) print("\n_events dict\n".center(100, '-')) for key, value in self._events.items(): print(f"\n{key} with value: {value} and value type: {type(value)} and contents:") if isinstance(value, List): for el in value: print(el)