X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=environment%2Forg.argeo.geo.ui%2Fsrc%2Forg%2Fargeo%2Fsupport%2Fopenlayers%2FOpenLayersMap.java;fp=environment%2Forg.argeo.geo.ui%2Fsrc%2Forg%2Fargeo%2Fsupport%2Fopenlayers%2FOpenLayersMap.java;h=622f5a49b7566cc220614767cd55a0b3e3a89d1a;hb=096e9828998febd0faffe0c369b897d4826a2bc1;hp=0000000000000000000000000000000000000000;hpb=810dab5ea22a48555058d4612ff10f8b8ecbdf08;p=gpl%2Fargeo-suite.git diff --git a/environment/org.argeo.geo.ui/src/org/argeo/support/openlayers/OpenLayersMap.java b/environment/org.argeo.geo.ui/src/org/argeo/support/openlayers/OpenLayersMap.java new file mode 100644 index 0000000..622f5a4 --- /dev/null +++ b/environment/org.argeo.geo.ui/src/org/argeo/support/openlayers/OpenLayersMap.java @@ -0,0 +1,250 @@ +package org.argeo.support.openlayers; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.api.NodeConstants; +import org.argeo.cms.ui.CmsView; +import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.entity.EntityNames; +import org.argeo.entity.EntityType; +import org.argeo.suite.ui.SuiteEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.browser.Browser; +import org.eclipse.swt.browser.BrowserFunction; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; + +/** Display a map. */ +public class OpenLayersMap extends Composite { + private static final long serialVersionUID = 1055893020490283622L; + + private final static Log log = LogFactory.getLog(OpenLayersMap.class); + + private Browser browser; + private boolean renderCompleted = false; + + private Double centerLng = null, centerLat = null; + private Integer zoom = null; + private String vectorSource = null; + private String gpxSource = null; + + private List geoJsonSources = new ArrayList<>(); + + private CmsView cmsView; + + public OpenLayersMap(Composite parent, int style, URL mapHtml) { + super(parent, style); + cmsView = CmsView.getCmsView(parent); + setLayout(new GridLayout()); + + browser = new Browser(this, SWT.BORDER); + browser.setLayoutData(CmsUiUtils.fillAll()); + String html; + try (InputStream in = mapHtml.openStream()) { + html = IOUtils.toString(in, StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } + new RenderCompleted(browser, "renderCompleted"); + new OnFeatureSelect(browser, "onFeatureSelect"); + new OnFeatureUnselect(browser, "onFeatureUnselect"); + new OnFeatureClick(browser, "onFeatureClick"); + browser.setText(html); + } + + public void setCenter(Double lng, Double lat) { + if (isRenderCompleted()) + browser.evaluate("map.getView().setCenter(ol.proj.fromLonLat([" + lng + ", " + lat + "]))"); + this.centerLat = lat; + this.centerLng = lng; + } + + public synchronized void setRenderCompleted(boolean renderCompleted) { + this.renderCompleted = renderCompleted; + notifyAll(); + } + + public synchronized boolean isRenderCompleted() { + return renderCompleted; + } + + @Override + public synchronized void dispose() { + long timeout = 500; + long begin = System.currentTimeMillis(); + while (!isRenderCompleted() && ((System.currentTimeMillis() - begin) < timeout)) { + try { + wait(50); + } catch (InterruptedException e) { + // silent + } + } + super.dispose(); + } + + public void setZoom(int zoom) { + if (isRenderCompleted()) + browser.evaluate("map.getView().setZoom(" + zoom + ")"); + this.zoom = zoom; + } + + public void addPoints(List geoPoints) throws RepositoryException { + boolean first = true; + StringBuffer sb = new StringBuffer("new ol.source.Vector({ features: ["); + for (int i = 0; i < geoPoints.size(); i++) { + Node node = geoPoints.get(i); + if (node.isNodeType(EntityType.geopoint.get()) && !node.isCheckedOut()) { + if (first) + first = false; + else + sb.append(","); + Double lng = node.getProperty(EntityNames.GEO_LONG).getDouble(); + Double lat = node.getProperty(EntityNames.GEO_LAT).getDouble(); + sb.append("new ol.Feature({ geometry:"); + sb.append("new ol.geom.Point(ol.proj.fromLonLat(["); + sb.append(lng).append(',').append(lat); + sb.append("]))"); + sb.append(",path:'").append(node.getPath()).append("'"); + sb.append("})"); + } + } + sb.append("] })"); + this.vectorSource = sb.toString(); + if (log.isTraceEnabled()) + log.trace("Vector source: " + vectorSource); + renderVectorSource(); + } + + protected void renderVectorSource() { + if (vectorSource == null) + return; + if (isRenderCompleted()) + browser.evaluate("map.addLayer(new ol.layer.Vector({ source: " + vectorSource + "}));"); + } + + public void addPoint(Double lng, Double lat) { + this.vectorSource = "new ol.source.Vector({ features: [ new ol.Feature({ geometry:" + + " new ol.geom.Point(ol.proj.fromLonLat([" + lng + ", " + lat + "])) }) ] })"; +// if (renderCompleted) { +// browser.evaluate( +// "map.addLayer(new ol.layer.Vector({ source: new ol.source.Vector({ features: [ new ol.Feature({ geometry:" +// + " new ol.geom.Point(ol.proj.fromLonLat([" + lng + ", " + lat + "])) }) ] }) }));"); +// } + renderVectorSource(); + } + + public void addGpx(String path) { + this.gpxSource = "new ol.source.Vector({ url: '" + path + "', format: new ol.format.GPX() })"; + renderGpxSource(); + } + + protected void renderGpxSource() { + if (gpxSource == null) + return; + if (isRenderCompleted()) + browser.evaluate("map.addLayer(new ol.layer.Vector({ source: " + gpxSource + "}));"); + } + + public void addGeoJson(String path) { + String geoJsonSource = "new ol.source.Vector({ url: '" + path + "', format: new ol.format.GeoJSON() })"; + geoJsonSources.add(geoJsonSource); + renderGeoJsonSources(); + } + + protected void renderGeoJsonSources() { + if (geoJsonSources.isEmpty()) + return; + if (isRenderCompleted()) { + for (String geoJson : geoJsonSources) { + browser.evaluate("map.addLayer(new ol.layer.Vector({ source: " + geoJson + "}));"); + } + } + } + + private class RenderCompleted extends BrowserFunction { + + RenderCompleted(Browser browser, String name) { + super(browser, name); + } + + @Override + public Object function(Object[] arguments) { + try { + if (!isRenderCompleted()) { + setRenderCompleted(true); + if (zoom != null) + setZoom(zoom); + if (centerLat != null && centerLng != null) { + setCenter(centerLng, centerLat); + } + if (vectorSource != null) + renderVectorSource(); + if (gpxSource != null) + renderGpxSource(); + if (!geoJsonSources.isEmpty()) + renderGeoJsonSources(); + } + return null; + } catch (Exception e) { + log.error("Cannot render map", e); + return null; + } + } + } + + private class OnFeatureSelect extends BrowserFunction { + + OnFeatureSelect(Browser browser, String name) { + super(browser, name); + } + + @Override + public Object function(Object[] arguments) { + if (arguments.length == 0) + return null; + String path = arguments[0].toString(); + Map properties = new HashMap<>(); + properties.put(SuiteEvent.NODE_PATH, path); + properties.put(SuiteEvent.WORKSPACE, NodeConstants.SYS_WORKSPACE); + cmsView.sendEvent(SuiteEvent.refreshPart.topic(), properties); + return null; + } + } + + private class OnFeatureUnselect extends BrowserFunction { + + OnFeatureUnselect(Browser browser, String name) { + super(browser, name); + } + + @Override + public Object function(Object[] arguments) { + return null; + } + } + + private class OnFeatureClick extends BrowserFunction { + + OnFeatureClick(Browser browser, String name) { + super(browser, name); + } + + @Override + public Object function(Object[] arguments) { + return null; + } + } +}