package org.argeo.app.swt.js;
+import java.net.URI;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Locale;
-import java.util.StringJoiner;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.function.Function;
-import java.util.function.Supplier;
import org.argeo.api.cms.CmsLog;
+import org.argeo.api.cms.ux.CmsView;
+import org.argeo.app.ux.js.JsClient;
+import org.argeo.cms.swt.CmsSwtUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.BrowserFunction;
* A part using a {@link Browser} and remote JavaScript components on the client
* side.
*/
-public class SwtBrowserJsPart {
+public class SwtBrowserJsPart implements JsClient {
private final static CmsLog log = CmsLog.getLog(SwtBrowserJsPart.class);
private final static String GLOBAL_THIS_ = "globalThis.";
* Tasks that were requested before the context was ready. Typically
* configuration methods on the part while the user interfaces is being build.
*/
- private List<Supplier<Boolean>> preReadyToDos = new ArrayList<>();
+ private List<PreReadyToDo> preReadyToDos = new ArrayList<>();
public SwtBrowserJsPart(Composite parent, int style, String url) {
+ CmsView cmsView = CmsSwtUtils.getCmsView(parent);
this.browser = new Browser(parent, 0);
if (parent.getLayout() instanceof GridLayout)
browser.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
// TODO other layouts
- browser.setUrl(url);
+ URI u = cmsView.toBackendUri(url);
+ browser.setUrl(u.toString());
browser.addProgressListener(new ProgressListener() {
static final long serialVersionUID = 1L;
init();
loadExtensions();
// execute todos in order
- for (Supplier<Boolean> toDo : preReadyToDos) {
- boolean success = toDo.get();
- if (!success)
- throw new IllegalStateException("Post-initalisation JavaScript execution failed");
+ for (PreReadyToDo toDo : preReadyToDos) {
+ toDo.run();
}
preReadyToDos.clear();
readyStage.complete(true);
protected void init() {
}
- /** To be overridden with calls to {@link #loadExtension(String)}. */
+ /**
+ * To be overridden with calls to {@link #loadExtension(String)}.
+ */
protected void loadExtensions() {
}
protected void loadExtension(String url) {
-// String js = """
-// var script = document.createElement("script");
-// script.src = '%s';
-// document.head.appendChild(script);
-// """;
-// browser.evaluate(String.format(Locale.ROOT, js, url));
- browser.evaluate(String.format(Locale.ROOT, "import('%s')", url));
+ URI u = CmsSwtUtils.getCmsView(getControl()).toBackendUri(url);
+ browser.evaluate(String.format(Locale.ROOT, "import('%s')", u.toString()));
}
- protected CompletionStage<Boolean> getReadyStage() {
+ public CompletionStage<Boolean> getReadyStage() {
return readyStage.minimalCompletionStage();
}
* JAVASCRIPT ACCESS
*/
- /**
- * Execute this JavaScript on the client side after making sure that the page
- * has been loaded and the map object has been created.
- *
- * @param js the JavaScript code, possibly formatted according to
- * {@link String#format}, with {@link Locale#ROOT} as locale (for
- * stability of decimal separator, as expected by JavaScript.
- * @param args the optional arguments of
- * {@link String#format(String, Object...)}
- */
- protected Object evaluate(String js, Object... args) {
+ @Override
+ public Object evaluate(String js, Object... args) {
assert browser.getDisplay().equals(Display.findDisplay(Thread.currentThread())) : "Not the proper UI thread.";
if (!readyStage.isDone())
- throw new IllegalStateException("Methods returning a result can only be called after UI initilaisation.");
- // wait for the context to be ready
-// boolean ready = readyStage.join();
-// if (!ready)
-// throw new IllegalStateException("Component is not initialised.");
+ throw new IllegalStateException("Methods returning a result can only be called after UI initialisation.");
+ if (browser.isDisposed())
+ return null;
Object result = browser.evaluate(String.format(Locale.ROOT, js, args));
return result;
}
- protected void execute(String js, Object... args) {
+ @Override
+ public void execute(String js, Object... args) {
+ String jsToExecute = String.format(Locale.ROOT, js, args);
if (readyStage.isDone()) {
- boolean success = browser.execute(String.format(Locale.ROOT, js, args));
+ if (browser.isDisposed())
+ return;
+ boolean success = browser.execute(jsToExecute);
if (!success)
throw new RuntimeException("JavaScript execution failed.");
} else {
- Supplier<Boolean> toDo = () -> {
- boolean success = browser.execute(String.format(Locale.ROOT, js, args));
- return success;
- };
+ PreReadyToDo toDo = new PreReadyToDo(jsToExecute);
preReadyToDos.add(toDo);
}
}
- /** @return the globally usable function name. */
- protected String createJsFunction(String name, Function<Object[], Object> toDo) {
+ @Override
+ public String createJsFunction(String name, Function<Object[], Object> toDo) {
// browser functions must be directly on window (RAP specific)
new BrowserFunction(browser, name) {
* instead.
*/
protected void doExecute(String js, Object... args) {
+ if (browser.isDisposed())
+ return;
browser.execute(String.format(Locale.ROOT, js, args));
}
- protected Object callMethod(String jsObject, String methodCall, Object... args) {
- return evaluate(jsObject + '.' + methodCall, args);
- }
-
- protected void executeMethod(String jsObject, String methodCall, Object... args) {
- execute(jsObject + '.' + methodCall, args);
- }
-
- protected String getJsVarName(String name) {
+ @Override
+ public String getJsVarName(String name) {
return GLOBAL_THIS_ + name;
}
- protected static String toJsArray(int... arr) {
- return Arrays.toString(arr);
- }
+ class PreReadyToDo implements Runnable {
+ private String js;
- protected static String toJsArray(long... arr) {
- return Arrays.toString(arr);
- }
-
- protected static String toJsArray(double... arr) {
- return Arrays.toString(arr);
- }
-
- protected static String toJsArray(String... arr) {
- return toJsArray((Object[]) arr);
- }
-
- protected static String toJsArray(Object... arr) {
- StringJoiner sj = new StringJoiner(",", "[", "]");
- for (Object o : arr) {
- sj.add(toJsValue(o));
+ public PreReadyToDo(String js) {
+ this.js = js;
}
- return sj.toString();
- }
- protected static String toJsValue(Object o) {
- if (o instanceof CharSequence)
- return '\"' + o.toString() + '\"';
- else if (o instanceof Number)
- return o.toString();
- else if (o instanceof Boolean)
- return o.toString();
- else
- return '\"' + o.toString() + '\"';
+ @Override
+ public void run() {
+ if (browser.isDisposed())
+ return;
+ boolean success = browser.execute(js);
+ if (!success && log.isTraceEnabled())
+ log.error("Pre-ready JavaScript failed: " + js);
+ }
}
/*