Add support for EventBinding

This commit is contained in:
TheMode 2021-08-19 07:12:53 +02:00
parent b4fbfe572d
commit 43fc7ad624

View File

@ -41,11 +41,14 @@ class EventNodeImpl<T extends Event> implements EventNode<T> {
public <E extends T> void call(@NotNull E event, ListenerHandle<E> handle) { public <E extends T> void call(@NotNull E event, ListenerHandle<E> handle) {
var castedHandle = (Handle<T>) handle; var castedHandle = (Handle<T>) handle;
Check.stateCondition(castedHandle.node != this, "Invalid handle owner"); Check.stateCondition(castedHandle.node != this, "Invalid handle owner");
List<Consumer<T>> listeners = castedHandle.listeners;
if (!castedHandle.updated) { if (!castedHandle.updated) {
handle(castedHandle); listeners.clear();
synchronized (GLOBAL_CHILD_LOCK) {
handle(castedHandle);
}
castedHandle.updated = true; castedHandle.updated = true;
} }
List<Consumer<T>> listeners = castedHandle.listeners;
if (listeners.isEmpty()) return; if (listeners.isEmpty()) return;
for (Consumer<T> listener : listeners) { for (Consumer<T> listener : listeners) {
listener.accept(event); listener.accept(event);
@ -61,9 +64,13 @@ class EventNodeImpl<T extends Event> implements EventNode<T> {
private void handle(Handle<T> handle) { private void handle(Handle<T> handle) {
ListenerEntry<T> entry = listenerMap.get(handle.eventType); ListenerEntry<T> entry = listenerMap.get(handle.eventType);
if (entry != null) { if (entry != null) {
// Add normal listeners
for (var listener : entry.listeners) { for (var listener : entry.listeners) {
handle.listeners.add(listener::run); handle.listeners.add(listener::run);
} }
// Add bindings
handle.listeners.addAll(entry.bindingConsumers);
// TODO mapped node
} }
// Add children // Add children
if (children.isEmpty()) return; if (children.isEmpty()) return;
@ -189,12 +196,25 @@ class EventNodeImpl<T extends Event> implements EventNode<T> {
@Override @Override
public void register(@NotNull EventBinding<? extends T> binding) { public void register(@NotNull EventBinding<? extends T> binding) {
// TODO synchronized (GLOBAL_CHILD_LOCK) {
for (var eventType : binding.eventTypes()) {
ListenerEntry<T> entry = getEntry((Class<? extends T>) eventType);
final boolean added = entry.bindingConsumers.add((Consumer<T>) binding.consumer(eventType));
if (added) propagateEvent((Class<? extends T>) eventType);
}
}
} }
@Override @Override
public void unregister(@NotNull EventBinding<? extends T> binding) { public void unregister(@NotNull EventBinding<? extends T> binding) {
// TODO synchronized (GLOBAL_CHILD_LOCK) {
for (var eventType : binding.eventTypes()) {
ListenerEntry<T> entry = listenerMap.get(eventType);
if (entry == null) return;
final boolean removed = entry.bindingConsumers.remove(binding.consumer(eventType));
if (removed) propagateEvent((Class<? extends T>) eventType);
}
}
} }
@Override @Override
@ -224,15 +244,15 @@ class EventNodeImpl<T extends Event> implements EventNode<T> {
} }
private void propagateEvents() { private void propagateEvents() {
this.listenerMap.forEach((eventClass, eventListeners) -> propagateEvent(eventClass)); this.listenerMap.keySet().forEach(this::propagateEvent);
} }
private void propagateEvent(Class<? extends T> eventClass) { private void propagateEvent(Class<? extends T> eventClass) {
final var parent = this.parent; final var parent = this.parent;
if (parent == null) return; if (parent == null) return;
var handle = parent.handleMap.get(eventClass); Handle<? super T> parentHandle = parent.handleMap.get(eventClass);
if (handle == null) return; if (parentHandle == null) return;
handle.updated = false; parentHandle.updated = false;
parent.propagateEvent(eventClass); parent.propagateEvent(eventClass);
} }
@ -248,13 +268,13 @@ class EventNodeImpl<T extends Event> implements EventNode<T> {
private static class ListenerEntry<T extends Event> { private static class ListenerEntry<T extends Event> {
final List<EventListener<T>> listeners = new CopyOnWriteArrayList<>(); final List<EventListener<T>> listeners = new CopyOnWriteArrayList<>();
final Set<Consumer<T>> bindingConsumers = new CopyOnWriteArraySet<>();
} }
private static final class Handle<E extends Event> implements ListenerHandle<E> { private static final class Handle<E extends Event> implements ListenerHandle<E> {
private final EventNode<E> node; private final EventNode<E> node;
private final Class<E> eventType; private final Class<E> eventType;
private final List<Consumer<E>> listeners = new CopyOnWriteArrayList<>(); private final List<Consumer<E>> listeners = new CopyOnWriteArrayList<>();
private volatile boolean updated; private volatile boolean updated;
Handle(EventNode<E> node, Class<E> eventType) { Handle(EventNode<E> node, Class<E> eventType) {