]> git.argeo.org Git - gpl/argeo-suite.git/blob - environment/org.argeo.geo.ui/src/org/argeo/support/openlayers/OpenLayersMap.java
Merge remote-tracking branch 'origin/master' into v2.x
[gpl/argeo-suite.git] / environment / org.argeo.geo.ui / src / org / argeo / support / openlayers / OpenLayersMap.java
1 package org.argeo.support.openlayers;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.net.URL;
6 import java.nio.charset.StandardCharsets;
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.List;
10 import java.util.Map;
11
12 import javax.jcr.Node;
13 import javax.jcr.RepositoryException;
14
15 import org.apache.commons.io.IOUtils;
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.argeo.api.NodeConstants;
19 import org.argeo.cms.ui.CmsView;
20 import org.argeo.cms.ui.util.CmsUiUtils;
21 import org.argeo.entity.EntityNames;
22 import org.argeo.entity.EntityType;
23 import org.argeo.suite.ui.SuiteEvent;
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.browser.Browser;
26 import org.eclipse.swt.browser.BrowserFunction;
27 import org.eclipse.swt.layout.GridLayout;
28 import org.eclipse.swt.widgets.Composite;
29
30 /** Display a map. */
31 public class OpenLayersMap extends Composite {
32 private static final long serialVersionUID = 1055893020490283622L;
33
34 private final static Log log = LogFactory.getLog(OpenLayersMap.class);
35
36 private Browser browser;
37 private boolean renderCompleted = false;
38
39 private Double centerLng = null, centerLat = null;
40 private Integer zoom = null;
41 private String vectorSource = null;
42 private String gpxSource = null;
43
44 private String vectorSourceStyle;
45
46 private List<String> geoJsonSources = new ArrayList<>();
47 private Map<String, String> vectorSources = new HashMap<>();
48 private Map<String, String> layerStyles = new HashMap<>();
49
50 private CmsView cmsView;
51
52 public OpenLayersMap(Composite parent, int style, URL mapHtml) {
53 super(parent, style);
54 cmsView = CmsView.getCmsView(parent);
55 setLayout(new GridLayout());
56
57 browser = new Browser(this, SWT.BORDER);
58 browser.setLayoutData(CmsUiUtils.fillAll());
59 String html;
60 try (InputStream in = mapHtml.openStream()) {
61 html = IOUtils.toString(in, StandardCharsets.UTF_8);
62 } catch (IOException e) {
63 throw new RuntimeException(e);
64 }
65 new RenderCompleted(browser, "renderCompleted");
66 new OnFeatureSelect(browser, "onFeatureSelect");
67 new OnFeatureUnselect(browser, "onFeatureUnselect");
68 new OnFeatureClick(browser, "onFeatureClick");
69 browser.setText(html);
70 }
71
72 public void setCenter(Double lng, Double lat) {
73 if (isRenderCompleted())
74 browser.evaluate("map.getView().setCenter(ol.proj.fromLonLat([" + lng + ", " + lat + "]))");
75 this.centerLat = lat;
76 this.centerLng = lng;
77 }
78
79 public synchronized void setRenderCompleted(boolean renderCompleted) {
80 this.renderCompleted = renderCompleted;
81 notifyAll();
82 }
83
84 public synchronized boolean isRenderCompleted() {
85 return renderCompleted;
86 }
87
88 @Override
89 public synchronized void dispose() {
90 long timeout = 500;
91 long begin = System.currentTimeMillis();
92 while (!isRenderCompleted() && ((System.currentTimeMillis() - begin) < timeout)) {
93 try {
94 wait(50);
95 } catch (InterruptedException e) {
96 // silent
97 }
98 }
99 super.dispose();
100 }
101
102 public void setZoom(int zoom) {
103 if (isRenderCompleted())
104 browser.evaluate("map.getView().setZoom(" + zoom + ")");
105 this.zoom = zoom;
106 }
107
108 protected String asVectorSource(List<Node> geoPoints) throws RepositoryException {
109 boolean first = true;
110 StringBuffer sb = new StringBuffer("new ol.source.Vector({ features: [");
111 for (int i = 0; i < geoPoints.size(); i++) {
112 Node node = geoPoints.get(i);
113 if (node.isNodeType(EntityType.geopoint.get())) {
114 if (first)
115 first = false;
116 else
117 sb.append(",");
118 Double lng = node.getProperty(EntityNames.GEO_LONG).getDouble();
119 Double lat = node.getProperty(EntityNames.GEO_LAT).getDouble();
120 sb.append("new ol.Feature({ geometry:");
121 sb.append("new ol.geom.Point(ol.proj.fromLonLat([");
122 sb.append(lng).append(',').append(lat);
123 sb.append("]))");
124 sb.append(",path:\"").append(node.getPath()).append("\"");
125 sb.append(",name:\"").append(node.getName()).append("\"");
126 String entityType = null;
127 if (node.isNodeType(EntityType.local.get())) {
128 entityType = node.getProperty(EntityNames.ENTITY_TYPE).getString();
129 sb.append(", type:'").append(entityType).append("'");
130 }
131 sb.append("})");
132 }
133 }
134 sb.append("]");
135 sb.append(" })");
136 return sb.toString();
137 }
138
139 public void addPoints(List<Node> geoPoints) throws RepositoryException {
140 this.vectorSource = asVectorSource(geoPoints);
141 if (log.isTraceEnabled())
142 log.trace("Vector source: " + vectorSource);
143 renderVectorSource();
144 }
145
146 public void addPoints(String layerName, List<Node> geoPoints, String style) throws RepositoryException {
147 this.vectorSources.put(layerName, asVectorSource(geoPoints));
148 if (style != null) {
149 layerStyles.put(layerName, style);
150 }
151 renderVectorSources();
152 }
153
154 protected void renderVectorSource() {
155 if (vectorSource == null)
156 return;
157 if (isRenderCompleted()) {
158 // String style = ", style: new ol.style.Style({ image: new ol.style.Icon({ src: '/pkg/org.djapps.on.openheritage.ui/map_oc.png' }) })";
159 String style = vectorSourceStyle != null ? ", style: " + vectorSourceStyle : "";
160 // String style = "";
161 String toEvaluate = "map.addLayer(new ol.layer.Vector({ source: " + vectorSource + style + "}));";
162 // System.out.println(toEvaluate);
163 browser.execute(toEvaluate);
164 }
165 }
166
167 protected void renderVectorSources() {
168 if (vectorSources.isEmpty())
169 return;
170 if (isRenderCompleted()) {
171 StringBuilder toExecute = new StringBuilder();
172 for (String name : vectorSources.keySet()) {
173 String style = layerStyles.containsKey(name) ? ", style: " + layerStyles.get(name) : "";
174 String toEvaluate = "map.addLayer(new ol.layer.Vector({ source: " + vectorSources.get(name) + style
175 + ",name: '" + name + "'}));";
176 toExecute.append(toEvaluate);
177 }
178 System.out.println(toExecute);
179 browser.execute(toExecute.toString());
180 }
181 }
182
183 public void addPoint(Double lng, Double lat) {
184 this.vectorSource = "new ol.source.Vector({ features: [ new ol.Feature({ geometry:"
185 + " new ol.geom.Point(ol.proj.fromLonLat([" + lng + ", " + lat + "])) }) ] })";
186 // if (renderCompleted) {
187 // browser.evaluate(
188 // "map.addLayer(new ol.layer.Vector({ source: new ol.source.Vector({ features: [ new ol.Feature({ geometry:"
189 // + " new ol.geom.Point(ol.proj.fromLonLat([" + lng + ", " + lat + "])) }) ] }) }));");
190 // }
191 renderVectorSource();
192 }
193
194 public void addGpx(String path) {
195 this.gpxSource = "new ol.source.Vector({ url: '" + path + "', format: new ol.format.GPX() })";
196 renderGpxSource();
197 }
198
199 protected void renderGpxSource() {
200 if (gpxSource == null)
201 return;
202 if (isRenderCompleted())
203 browser.evaluate("map.addLayer(new ol.layer.Vector({ source: " + gpxSource + "}));");
204 }
205
206 public void addGeoJson(String path) {
207 String geoJsonSource = "new ol.source.Vector({ url: '" + path + "', format: new ol.format.GeoJSON() })";
208 geoJsonSources.add(geoJsonSource);
209 renderGeoJsonSources();
210 }
211
212 protected void renderGeoJsonSources() {
213 if (geoJsonSources.isEmpty())
214 return;
215 if (isRenderCompleted()) {
216 for (String geoJson : geoJsonSources) {
217 browser.evaluate("map.addLayer(new ol.layer.Vector({ source: " + geoJson + "}));");
218 }
219 }
220 }
221
222 public void setVectorSourceStyle(String vectorSourceStyle) {
223 this.vectorSourceStyle = vectorSourceStyle;
224 }
225
226 private class RenderCompleted extends BrowserFunction {
227
228 RenderCompleted(Browser browser, String name) {
229 super(browser, name);
230 }
231
232 @Override
233 public Object function(Object[] arguments) {
234 try {
235 if (!isRenderCompleted()) {
236 setRenderCompleted(true);
237 if (zoom != null)
238 setZoom(zoom);
239 if (centerLat != null && centerLng != null) {
240 setCenter(centerLng, centerLat);
241 }
242 if (!geoJsonSources.isEmpty())
243 renderGeoJsonSources();
244 if (gpxSource != null)
245 renderGpxSource();
246 if (vectorSource != null)
247 renderVectorSource();
248 if (!vectorSources.isEmpty())
249 renderVectorSources();
250 }
251 return null;
252 } catch (Exception e) {
253 log.error("Cannot render map", e);
254 return null;
255 }
256 }
257 }
258
259 private class OnFeatureSelect extends BrowserFunction {
260
261 OnFeatureSelect(Browser browser, String name) {
262 super(browser, name);
263 }
264
265 @Override
266 public Object function(Object[] arguments) {
267 if (arguments.length == 0)
268 return null;
269 String path = arguments[0].toString();
270 Map<String, Object> properties = new HashMap<>();
271 properties.put(SuiteEvent.NODE_PATH, path);
272 properties.put(SuiteEvent.WORKSPACE, NodeConstants.SYS_WORKSPACE);
273 cmsView.sendEvent(SuiteEvent.refreshPart.topic(), properties);
274 return null;
275 }
276 }
277
278 private class OnFeatureUnselect extends BrowserFunction {
279
280 OnFeatureUnselect(Browser browser, String name) {
281 super(browser, name);
282 }
283
284 @Override
285 public Object function(Object[] arguments) {
286 return null;
287 }
288 }
289
290 private class OnFeatureClick extends BrowserFunction {
291
292 OnFeatureClick(Browser browser, String name) {
293 super(browser, name);
294 }
295
296 @Override
297 public Object function(Object[] arguments) {
298 return null;
299 }
300 }
301 }