]>
git.argeo.org Git - gpl/argeo-suite.git/blob - swt/org.argeo.app.swt/src/org/argeo/app/swt/js/SwtBrowserJsPart.java
1 package org
.argeo
.app
.swt
.js
;
3 import java
.util
.ArrayList
;
5 import java
.util
.Locale
;
6 import java
.util
.concurrent
.CompletableFuture
;
7 import java
.util
.concurrent
.CompletionStage
;
8 import java
.util
.function
.Function
;
10 import org
.argeo
.api
.cms
.CmsLog
;
11 import org
.argeo
.app
.ux
.js
.JsClient
;
12 import org
.eclipse
.swt
.SWT
;
13 import org
.eclipse
.swt
.browser
.Browser
;
14 import org
.eclipse
.swt
.browser
.BrowserFunction
;
15 import org
.eclipse
.swt
.browser
.ProgressEvent
;
16 import org
.eclipse
.swt
.browser
.ProgressListener
;
17 import org
.eclipse
.swt
.layout
.GridData
;
18 import org
.eclipse
.swt
.layout
.GridLayout
;
19 import org
.eclipse
.swt
.widgets
.Composite
;
20 import org
.eclipse
.swt
.widgets
.Control
;
21 import org
.eclipse
.swt
.widgets
.Display
;
24 * A part using a {@link Browser} and remote JavaScript components on the client
27 public class SwtBrowserJsPart
implements JsClient
{
28 private final static CmsLog log
= CmsLog
.getLog(SwtBrowserJsPart
.class);
30 private final static String GLOBAL_THIS_
= "globalThis.";
32 private final Browser browser
;
33 private final CompletableFuture
<Boolean
> readyStage
= new CompletableFuture
<>();
36 * Tasks that were requested before the context was ready. Typically
37 * configuration methods on the part while the user interfaces is being build.
39 private List
<PreReadyToDo
> preReadyToDos
= new ArrayList
<>();
41 public SwtBrowserJsPart(Composite parent
, int style
, String url
) {
42 this.browser
= new Browser(parent
, 0);
43 if (parent
.getLayout() instanceof GridLayout
)
44 browser
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
48 browser
.addProgressListener(new ProgressListener() {
49 static final long serialVersionUID
= 1L;
52 public void completed(ProgressEvent event
) {
56 // execute todos in order
57 for (PreReadyToDo toDo
: preReadyToDos
) {
60 preReadyToDos
.clear();
61 readyStage
.complete(true);
62 } catch (Exception e
) {
63 log
.error("Cannot initialise " + url
+ " in browser", e
);
64 readyStage
.complete(false);
69 public void changed(ProgressEvent event
) {
79 * Called when the page has been loaded, typically in order to initialise
80 * JavaScript objects. One MUST use {@link #doExecute(String, Object...)} in
81 * order to do so, since the context is not yet considered ready and calls to
82 * {@link #evaluate(String, Object...)} will block.
84 protected void init() {
88 * To be overridden with calls to {@link #loadExtension( Supplier<Boolean> toDo
89 * = () -> { boolean success = browser.execute(); return success; }; String)}.
91 protected void loadExtensions() {
95 protected void loadExtension(String url
) {
97 // var script = document.createElement("script");
99 // document.head.appendChild(script);
101 // browser.evaluate(String.format(Locale.ROOT, js, url));
102 browser
.evaluate(String
.format(Locale
.ROOT
, "import('%s')", url
));
105 public CompletionStage
<Boolean
> getReadyStage() {
106 return readyStage
.minimalCompletionStage();
114 public Object
evaluate(String js
, Object
... args
) {
115 assert browser
.getDisplay().equals(Display
.findDisplay(Thread
.currentThread())) : "Not the proper UI thread.";
116 if (!readyStage
.isDone())
117 throw new IllegalStateException("Methods returning a result can only be called after UI initialisation.");
118 // wait for the context to be ready
119 // boolean ready = readyStage.join();
121 // throw new IllegalStateException("Component is not initialised.");
122 Object result
= browser
.evaluate(String
.format(Locale
.ROOT
, js
, args
));
127 public void execute(String js
, Object
... args
) {
128 String jsToExecute
= String
.format(Locale
.ROOT
, js
, args
);
129 if (readyStage
.isDone()) {
130 boolean success
= browser
.execute(jsToExecute
);
132 throw new RuntimeException("JavaScript execution failed.");
134 PreReadyToDo toDo
= new PreReadyToDo(jsToExecute
);
135 preReadyToDos
.add(toDo
);
140 public String
createJsFunction(String name
, Function
<Object
[], Object
> toDo
) {
141 // browser functions must be directly on window (RAP specific)
142 new BrowserFunction(browser
, name
) {
145 public Object
function(Object
[] arguments
) {
146 Object result
= toDo
.apply(arguments
);
151 return "window." + name
;
155 * Directly executes, even if {@link #getReadyStage()} is not completed. Except
156 * in initialisation, {@link #evaluate(String, Object...)} should be used
159 protected void doExecute(String js
, Object
... args
) {
160 browser
.execute(String
.format(Locale
.ROOT
, js
, args
));
164 public String
getJsVarName(String name
) {
165 return GLOBAL_THIS_
+ name
;
168 class PreReadyToDo
implements Runnable
{
171 public PreReadyToDo(String js
) {
177 boolean success
= browser
.execute(js
);
179 throw new IllegalStateException("Pre-ready JavaScript failed: " + js
);
187 public Control
getControl() {