117 lines
3.8 KiB
Java
117 lines
3.8 KiB
Java
|
|
package org.openautonomousconnection.luascript.fx;
|
||
|
|
|
||
|
|
import org.openautonomousconnection.luascript.events.UiEventRegistry;
|
||
|
|
import org.openautonomousconnection.luascript.hosts.EventHost;
|
||
|
|
import org.openautonomousconnection.luascript.runtime.LuaEventRouter;
|
||
|
|
import org.w3c.dom.Document;
|
||
|
|
import org.w3c.dom.Element;
|
||
|
|
import org.w3c.dom.events.EventListener;
|
||
|
|
import org.w3c.dom.events.EventTarget;
|
||
|
|
|
||
|
|
import java.util.Map;
|
||
|
|
import java.util.Objects;
|
||
|
|
import java.util.concurrent.ConcurrentHashMap;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* EventHost implementation for JavaFX WebView using W3C DOM EventTarget listeners.
|
||
|
|
*
|
||
|
|
* <p>No JavaScript required. Events are forwarded to Lua via {@link LuaEventRouter}.</p>
|
||
|
|
*/
|
||
|
|
public final class FxEventHost implements EventHost {
|
||
|
|
|
||
|
|
private static final String GLOBAL_TARGET_ID = "__global__";
|
||
|
|
|
||
|
|
private final FxDomHost dom;
|
||
|
|
private final LuaEventRouter router;
|
||
|
|
|
||
|
|
private final ConcurrentHashMap<String, EventListener> elementListeners = new ConcurrentHashMap<>();
|
||
|
|
private final ConcurrentHashMap<String, EventListener> globalListeners = new ConcurrentHashMap<>();
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Creates a new FxEventHost.
|
||
|
|
*
|
||
|
|
* @param dom fx dom host
|
||
|
|
* @param router lua router
|
||
|
|
*/
|
||
|
|
public FxEventHost(FxDomHost dom, LuaEventRouter router) {
|
||
|
|
this.dom = Objects.requireNonNull(dom, "dom");
|
||
|
|
this.router = Objects.requireNonNull(router, "router");
|
||
|
|
}
|
||
|
|
|
||
|
|
@Override
|
||
|
|
public void addListener(String elementId, String eventName) {
|
||
|
|
Objects.requireNonNull(elementId, "elementId");
|
||
|
|
Objects.requireNonNull(eventName, "eventName");
|
||
|
|
|
||
|
|
String evt = UiEventRegistry.normalize(eventName);
|
||
|
|
String key = elementId + "\n" + evt;
|
||
|
|
|
||
|
|
elementListeners.computeIfAbsent(key, k -> {
|
||
|
|
EventListener listener = ev -> {
|
||
|
|
Map<String, Object> payload = FxEventPayloadExtractor.extract(ev);
|
||
|
|
router.emit(elementId, evt, payload);
|
||
|
|
};
|
||
|
|
|
||
|
|
FxThreadBridge.runAndWait(() -> {
|
||
|
|
Element el = dom.byId(elementId);
|
||
|
|
((EventTarget) el).addEventListener(evt, listener, false);
|
||
|
|
});
|
||
|
|
|
||
|
|
return listener;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
@Override
|
||
|
|
public void removeListener(String elementId, String eventName) {
|
||
|
|
Objects.requireNonNull(elementId, "elementId");
|
||
|
|
Objects.requireNonNull(eventName, "eventName");
|
||
|
|
|
||
|
|
String evt = UiEventRegistry.normalize(eventName);
|
||
|
|
String key = elementId + "\n" + evt;
|
||
|
|
|
||
|
|
EventListener listener = elementListeners.remove(key);
|
||
|
|
if (listener == null) return;
|
||
|
|
|
||
|
|
FxThreadBridge.runAndWait(() -> {
|
||
|
|
Element el = dom.byId(elementId);
|
||
|
|
((EventTarget) el).removeEventListener(evt, listener, false);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
@Override
|
||
|
|
public void addGlobalListener(String eventName) {
|
||
|
|
Objects.requireNonNull(eventName, "eventName");
|
||
|
|
|
||
|
|
String evt = UiEventRegistry.normalize(eventName);
|
||
|
|
|
||
|
|
globalListeners.computeIfAbsent(evt, k -> {
|
||
|
|
EventListener listener = ev -> {
|
||
|
|
Map<String, Object> payload = FxEventPayloadExtractor.extract(ev);
|
||
|
|
router.emit(GLOBAL_TARGET_ID, evt, payload);
|
||
|
|
};
|
||
|
|
|
||
|
|
FxThreadBridge.runAndWait(() -> {
|
||
|
|
Document doc = dom.requireDocument();
|
||
|
|
((EventTarget) doc).addEventListener(evt, listener, false);
|
||
|
|
});
|
||
|
|
|
||
|
|
return listener;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
@Override
|
||
|
|
public void removeGlobalListener(String eventName) {
|
||
|
|
Objects.requireNonNull(eventName, "eventName");
|
||
|
|
|
||
|
|
String evt = UiEventRegistry.normalize(eventName);
|
||
|
|
|
||
|
|
EventListener listener = globalListeners.remove(evt);
|
||
|
|
if (listener == null) return;
|
||
|
|
|
||
|
|
FxThreadBridge.runAndWait(() -> {
|
||
|
|
Document doc = dom.requireDocument();
|
||
|
|
((EventTarget) doc).removeEventListener(evt, listener, false);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|