]>
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
;
4 import java
.util
.ArrayList
;
6 import java
.util
.Locale
;
7 import java
.util
.concurrent
.CompletableFuture
;
8 import java
.util
.concurrent
.CompletionStage
;
9 import java
.util
.function
.Function
;
11 import org
.argeo
.api
.cms
.CmsLog
;
12 import org
.argeo
.api
.cms
.ux
.CmsView
;
13 import org
.argeo
.app
.ux
.js
.JsClient
;
14 import org
.argeo
.cms
.swt
.CmsSwtUtils
;
15 import org
.eclipse
.swt
.SWT
;
16 import org
.eclipse
.swt
.browser
.Browser
;
17 import org
.eclipse
.swt
.browser
.BrowserFunction
;
18 import org
.eclipse
.swt
.browser
.ProgressEvent
;
19 import org
.eclipse
.swt
.browser
.ProgressListener
;
20 import org
.eclipse
.swt
.layout
.GridData
;
21 import org
.eclipse
.swt
.layout
.GridLayout
;
22 import org
.eclipse
.swt
.widgets
.Composite
;
23 import org
.eclipse
.swt
.widgets
.Control
;
24 import org
.eclipse
.swt
.widgets
.Display
;
27 * A part using a {@link Browser} and remote JavaScript components on the client
30 public class SwtBrowserJsPart
implements JsClient
{
31 private final static CmsLog log
= CmsLog
.getLog(SwtBrowserJsPart
.class);
33 private final static String GLOBAL_THIS_
= "globalThis.";
35 private final Browser browser
;
36 private final CompletableFuture
<Boolean
> readyStage
= new CompletableFuture
<>();
39 * Tasks that were requested before the context was ready. Typically
40 * configuration methods on the part while the user interfaces is being build.
42 private List
<PreReadyToDo
> preReadyToDos
= new ArrayList
<>();
44 public SwtBrowserJsPart(Composite parent
, int style
, String url
) {
45 CmsView cmsView
= CmsSwtUtils
.getCmsView(parent
);
46 this.browser
= new Browser(parent
, 0);
47 if (parent
.getLayout() instanceof GridLayout
)
48 browser
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
51 URI u
= cmsView
.toBackendUri(url
);
52 browser
.setUrl(u
.toString());
53 browser
.addProgressListener(new ProgressListener() {
54 static final long serialVersionUID
= 1L;
57 public void completed(ProgressEvent event
) {
61 // execute todos in order
62 for (PreReadyToDo toDo
: preReadyToDos
) {
65 preReadyToDos
.clear();
66 readyStage
.complete(true);
67 } catch (Exception e
) {
68 log
.error("Cannot initialise " + url
+ " in browser", e
);
69 readyStage
.complete(false);
74 public void changed(ProgressEvent event
) {
84 * Called when the page has been loaded, typically in order to initialise
85 * JavaScript objects. One MUST use {@link #doExecute(String, Object...)} in
86 * order to do so, since the context is not yet considered ready and calls to
87 * {@link #evaluate(String, Object...)} will block.
89 protected void init() {
93 * To be overridden with calls to {@link #loadExtension(String)}.
95 protected void loadExtensions() {
99 protected void loadExtension(String url
) {
100 URI u
= CmsSwtUtils
.getCmsView(getControl()).toBackendUri(url
);
101 browser
.evaluate(String
.format(Locale
.ROOT
, "import('%s')", u
.toString()));
104 public CompletionStage
<Boolean
> getReadyStage() {
105 return readyStage
.minimalCompletionStage();
113 public Object
evaluate(String js
, Object
... args
) {
114 assert browser
.getDisplay().equals(Display
.findDisplay(Thread
.currentThread())) : "Not the proper UI thread.";
115 if (!readyStage
.isDone())
116 throw new IllegalStateException("Methods returning a result can only be called after UI initialisation.");
117 if (browser
.isDisposed())
119 Object result
= browser
.evaluate(String
.format(Locale
.ROOT
, js
, args
));
124 public void execute(String js
, Object
... args
) {
125 String jsToExecute
= String
.format(Locale
.ROOT
, js
, args
);
126 if (readyStage
.isDone()) {
127 if (browser
.isDisposed())
129 boolean success
= browser
.execute(jsToExecute
);
131 throw new RuntimeException("JavaScript execution failed.");
133 PreReadyToDo toDo
= new PreReadyToDo(jsToExecute
);
134 preReadyToDos
.add(toDo
);
139 public String
createJsFunction(String name
, Function
<Object
[], Object
> toDo
) {
140 // browser functions must be directly on window (RAP specific)
141 new BrowserFunction(browser
, name
) {
144 public Object
function(Object
[] arguments
) {
145 Object result
= toDo
.apply(arguments
);
150 return "window." + name
;
154 * Directly executes, even if {@link #getReadyStage()} is not completed. Except
155 * in initialisation, {@link #evaluate(String, Object...)} should be used
158 protected void doExecute(String js
, Object
... args
) {
159 if (browser
.isDisposed())
161 browser
.execute(String
.format(Locale
.ROOT
, js
, args
));
165 public String
getJsVarName(String name
) {
166 return GLOBAL_THIS_
+ name
;
169 class PreReadyToDo
implements Runnable
{
172 public PreReadyToDo(String js
) {
178 if (browser
.isDisposed())
180 boolean success
= browser
.execute(js
);
181 if (!success
&& log
.isTraceEnabled())
182 log
.error("Pre-ready JavaScript failed: " + js
);
190 public Control
getControl() {