]>
git.argeo.org Git - gpl/argeo-suite.git/blob - swt/org.argeo.app.geo.swt/src/org/argeo/app/geo/swt/SwtJSMapPart.java
09848f9757f7069008f01f578a586b8f0518aadd
1 package org
.argeo
.app
.geo
.swt
;
3 import java
.util
.Locale
;
4 import java
.util
.concurrent
.CompletableFuture
;
5 import java
.util
.concurrent
.CompletionStage
;
6 import java
.util
.function
.Consumer
;
8 import org
.argeo
.api
.cms
.CmsLog
;
9 import org
.argeo
.app
.geo
.ux
.JsImplementation
;
10 import org
.argeo
.app
.geo
.ux
.MapPart
;
11 import org
.argeo
.cms
.swt
.CmsSwtUtils
;
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
.widgets
.Composite
;
21 * An SWT implementation of {@link MapPart} based on JavaScript execute in a
22 * {@link Browser} control.
24 public class SwtJSMapPart
extends Composite
implements MapPart
{
25 static final long serialVersionUID
= 2713128477504858552L;
27 private final static CmsLog log
= CmsLog
.getLog(SwtJSMapPart
.class);
29 private final static String GLOBAL_THIS_
= "globalThis.";
31 private final Browser browser
;
33 private final CompletableFuture
<Boolean
> pageLoaded
= new CompletableFuture
<>();
35 private String jsImplementation
= JsImplementation
.OPENLAYERS_MAP_PART
.getJsClass();
36 private String mapVar
= "argeoMap";
38 public SwtJSMapPart(Composite parent
, int style
) {
40 parent
.setLayout(CmsSwtUtils
.noSpaceGridLayout());
41 setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
42 setLayout(CmsSwtUtils
.noSpaceGridLayout());
44 browser
= new Browser(this, SWT
.BORDER
);
45 browser
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
47 browser
.setUrl("/pkg/org.argeo.app.geo.js/index.html");
48 browser
.addProgressListener(new ProgressListener() {
49 static final long serialVersionUID
= 1L;
52 public void completed(ProgressEvent event
) {
55 browser
.execute(getJsMapVar() + " = new " + jsImplementation
+ "();");
56 pageLoaded
.complete(true);
57 } catch (Exception e
) {
58 log
.error("Cannot create map in browser", e
);
59 pageLoaded
.complete(false);
64 public void changed(ProgressEvent event
) {
74 public void addPoint(double lng
, double lat
, String style
) {
75 callMapMethod("addPoint(%f, %f, %s)", lng
, lat
, style
== null ?
"'default'" : style
);
79 public void addUrlLayer(String url
, GeoFormat format
) {
80 callMapMethod("addUrlLayer('%s', '%s')", url
, format
.name());
84 public void setZoom(int zoom
) {
85 callMapMethod("setZoom(%d)", zoom
);
89 public void setCenter(double lng
, double lat
) {
90 callMapMethod("setCenter(%f, %f)", lng
, lat
);
93 protected CompletionStage
<Object
> callMapMethod(String methodCall
, Object
... args
) {
94 return callMethod(getJsMapVar(), methodCall
, args
);
97 protected CompletionStage
<Object
> callMethod(String jsObject
, String methodCall
, Object
... args
) {
98 return evaluate(jsObject
+ '.' + methodCall
, args
);
101 private String
getJsMapVar() {
102 return GLOBAL_THIS_
+ mapVar
;
106 * Execute this JavaScript on the client side after making sure that the page
107 * has been loaded and the map object has been created.
109 * @param js the JavaScript code, possibly formatted according to
110 * {@link String#format}, with {@link Locale#ROOT} as locale (for
111 * stability of decimal separator, as expected by JavaScript.
112 * @param args the optional arguments of
113 * {@link String#format(String, Object...)}
115 protected CompletionStage
<Object
> evaluate(String js
, Object
... args
) {
116 CompletableFuture
<Object
> res
= pageLoaded
.thenApply((ready
) -> {
118 throw new IllegalStateException("Map " + mapVar
+ " is not initialised.");
119 Object result
= browser
.evaluate(String
.format(Locale
.ROOT
, js
, args
));
122 return res
.minimalCompletionStage();
128 public void onFeatureSelected(Consumer
<FeatureSelectedEvent
> toDo
) {
129 addCallback("FeatureSelected", (arr
) -> toDo
.accept(new FeatureSelectedEvent((String
) arr
[0])));
132 public void onFeatureSingleClick(Consumer
<FeatureSingleClickEvent
> toDo
) {
133 addCallback("FeatureSingleClick", (arr
) -> toDo
.accept(new FeatureSingleClickEvent((String
) arr
[0])));
136 protected void addCallback(String suffix
, Consumer
<Object
[]> toDo
) {
137 pageLoaded
.thenAccept((ready
) -> {
138 // browser functions must be directly on window (RAP specific)
139 new BrowserFunction(browser
, mapVar
+ "__on" + suffix
) {
142 public Object
function(Object
[] arguments
) {
143 toDo
.accept(arguments
);
148 browser
.execute(getJsMapVar() + ".callbacks['on" + suffix
+ "']=window." + mapVar
+ "__on" + suffix
+ ";");
149 callMethod(mapVar
, "enable" + suffix
+ "()");