package org.openautonomousconnection.luascript.fx; import javafx.scene.web.WebEngine; import org.openautonomousconnection.luascript.hosts.CssHost; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; /** * CSS host via internal JS bridge. */ public final class FxCssHost implements CssHost { private final WebEngine engine; private final FxDomHost dom; public FxCssHost(WebEngine engine, FxDomHost dom) { this.engine = Objects.requireNonNull(engine, "engine"); this.dom = Objects.requireNonNull(dom, "dom"); } @Override public String getComputedStyle(String elementId, String property) { Objects.requireNonNull(elementId, "elementId"); Objects.requireNonNull(property, "property"); return FxThreadBridge.callAndWait(() -> FxWebBridge.callWithJs(engine, () -> { dom.requireDocument(); String script = "" + "(function(){" + " var id=" + FxWebBridge.toJsLiteral(elementId) + ";" + " var prop=" + FxWebBridge.toJsLiteral(property) + ";" + " var el=document.getElementById(id);" + " if(!el) throw new Error('Unknown element id: '+id);" + " var cs=getComputedStyle(el);" + " var v=cs.getPropertyValue(prop) || cs[prop] || '';" + " return String(v);" + "})();"; Object ret = engine.executeScript(script); return ret == null ? "" : String.valueOf(ret); })); } @Override public Map getComputedStyles(String elementId, String[] properties) { Objects.requireNonNull(elementId, "elementId"); Objects.requireNonNull(properties, "properties"); Map out = new LinkedHashMap<>(); for (String p : properties) { if (p == null || p.isBlank()) continue; out.put(p, getComputedStyle(elementId, p)); } return out; } @Override public void setInlineStyle(String elementId, String property, String value) { Objects.requireNonNull(elementId, "elementId"); Objects.requireNonNull(property, "property"); FxThreadBridge.runAndWait(() -> FxWebBridge.runWithJs(engine, () -> { dom.requireDocument(); String v = value == null ? "" : value; String script = "" + "(function(){" + " var id=" + FxWebBridge.toJsLiteral(elementId) + ";" + " var prop=" + FxWebBridge.toJsLiteral(property) + ";" + " var val=" + FxWebBridge.toJsLiteral(v) + ";" + " var el=document.getElementById(id);" + " if(!el) throw new Error('Unknown element id: '+id);" + " if(!val){ el.style.removeProperty(prop); return null; }" + " el.style.setProperty(prop, val);" + " return null;" + "})();"; engine.executeScript(script); })); } @Override public String getInlineStyle(String elementId, String property) { Objects.requireNonNull(elementId, "elementId"); Objects.requireNonNull(property, "property"); return FxThreadBridge.callAndWait(() -> FxWebBridge.callWithJs(engine, () -> { dom.requireDocument(); String script = "" + "(function(){" + " var id=" + FxWebBridge.toJsLiteral(elementId) + ";" + " var prop=" + FxWebBridge.toJsLiteral(property) + ";" + " var el=document.getElementById(id);" + " if(!el) throw new Error('Unknown element id: '+id);" + " var v=el.style.getPropertyValue(prop) || '';" + " return String(v);" + "})();"; Object ret = engine.executeScript(script); return ret == null ? "" : String.valueOf(ret); })); } @Override public void setCssVariable(String elementId, String name, String value) { Objects.requireNonNull(name, "name"); if (!name.trim().startsWith("--")) throw new IllegalArgumentException("CSS variable must start with '--': " + name); setInlineStyle(elementId, name.trim(), value); } @Override public String getCssVariable(String elementId, String name) { Objects.requireNonNull(name, "name"); if (!name.trim().startsWith("--")) throw new IllegalArgumentException("CSS variable must start with '--': " + name); return getComputedStyle(elementId, name.trim()); } }