Mercurial > dive4elements > river
view gwt-client/src/main/java/org/dive4elements/river/client/client/ui/map/MapOutputTab.java @ 9580:839b2aa84dd0
minuend/subtrahend-UI-switch
author | gernotbelger |
---|---|
date | Tue, 08 Jan 2019 17:01:09 +0100 |
parents | 5397555d74c9 |
children |
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde * Software engineering by Intevation GmbH * * This file is Free Software under the GNU AGPL (>=v3) * and comes with ABSOLUTELY NO WARRANTY! Check out the * documentation coming with Dive4Elements River for details. */ package org.dive4elements.river.client.client.ui.map; import java.util.HashMap; import java.util.List; import org.dive4elements.river.client.client.Config; import org.dive4elements.river.client.client.FLYSConstants; import org.dive4elements.river.client.client.event.OutputParameterChangeEvent; import org.dive4elements.river.client.client.event.OutputParameterChangeHandler; import org.dive4elements.river.client.client.event.RedrawRequestEvent; import org.dive4elements.river.client.client.event.RedrawRequestHandler; import org.dive4elements.river.client.client.services.LoadArtifactService; import org.dive4elements.river.client.client.services.LoadArtifactServiceAsync; import org.dive4elements.river.client.client.services.MapOutputService; import org.dive4elements.river.client.client.services.MapOutputServiceAsync; import org.dive4elements.river.client.client.services.StepForwardService; import org.dive4elements.river.client.client.services.StepForwardServiceAsync; import org.dive4elements.river.client.client.ui.CollectionView; import org.dive4elements.river.client.client.ui.OutputTab; import org.dive4elements.river.client.client.ui.ThemePanel; import org.dive4elements.river.client.shared.model.Artifact; import org.dive4elements.river.client.shared.model.ArtifactDescription; import org.dive4elements.river.client.shared.model.AttributedTheme; import org.dive4elements.river.client.shared.model.Collection; import org.dive4elements.river.client.shared.model.Data; import org.dive4elements.river.client.shared.model.DataItem; import org.dive4elements.river.client.shared.model.DataList; import org.dive4elements.river.client.shared.model.DefaultData; import org.dive4elements.river.client.shared.model.DefaultDataItem; import org.dive4elements.river.client.shared.model.MapConfig; import org.dive4elements.river.client.shared.model.OutputMode; import org.dive4elements.river.client.shared.model.Recommendation; import org.dive4elements.river.client.shared.model.Theme; import org.dive4elements.river.client.shared.model.ThemeList; import org.dive4elements.river.client.shared.model.WMSLayer; import org.gwtopenmaps.openlayers.client.Bounds; import org.gwtopenmaps.openlayers.client.Map; import org.gwtopenmaps.openlayers.client.MapWidget; import org.gwtopenmaps.openlayers.client.event.VectorFeatureAddedListener; import org.gwtopenmaps.openlayers.client.event.VectorFeatureRemovedListener; import org.gwtopenmaps.openlayers.client.feature.VectorFeature; import org.gwtopenmaps.openlayers.client.format.GeoJSON; import org.gwtopenmaps.openlayers.client.layer.Layer; import org.gwtopenmaps.openlayers.client.layer.TransitionEffect; import org.gwtopenmaps.openlayers.client.layer.Vector; import org.gwtopenmaps.openlayers.client.layer.WMS; import org.gwtopenmaps.openlayers.client.layer.WMSOptions; import org.gwtopenmaps.openlayers.client.layer.WMSParams; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AbsolutePanel; import com.smartgwt.client.util.SC; import com.smartgwt.client.widgets.Canvas; import com.smartgwt.client.widgets.events.ParentMovedEvent; import com.smartgwt.client.widgets.events.ParentMovedHandler; import com.smartgwt.client.widgets.events.ResizedEvent; import com.smartgwt.client.widgets.events.ResizedHandler; import com.smartgwt.client.widgets.layout.HLayout; import com.smartgwt.client.widgets.layout.VLayout; import com.smartgwt.client.widgets.tab.events.TabSelectedEvent; import com.smartgwt.client.widgets.tab.events.TabSelectedHandler; public class MapOutputTab extends OutputTab implements RedrawRequestHandler, ExternalWMSWindow.LayerLoader, TabSelectedHandler, OutputParameterChangeHandler { public static final String DEFAULT_SRID = "4326"; public static final String BARRIERS_PARAMETER_KEY = "uesk.barriers"; public static final String WSPLGEN_FACET = "floodmap.wsplgen"; public static final String EXTERNAL_WMS_FACTORY = "externalwmsfactory"; protected StepForwardServiceAsync feedService = GWT.create(StepForwardService.class); protected MapOutputServiceAsync mapService = GWT.create(MapOutputService.class); /** Service handle to clone and add artifacts to collection. */ protected LoadArtifactServiceAsync loadArtifactService = GWT.create(LoadArtifactService.class); protected FLYSConstants MSG = GWT.create(FLYSConstants.class); protected MapToolbar controlPanel; protected ThemePanel themePanel; protected Canvas themePanelCanvas; protected MapWidget mapPanel; protected Canvas mapPanelCanvas; protected VLayout rootLayout = new VLayout(); protected AbsolutePanel absPan = new AbsolutePanel(); protected FloodMap floodMap; private boolean cancel = false; private final java.util.Map<String, String> wmsUrls = new HashMap<String, String>(); public MapOutputTab(final String title, final Collection collection, final OutputMode mode, final CollectionView collectionView) { super(title, collection, collectionView, mode); collectionView.registerTabHandler(this); this.mapService.doOut(collection, new AsyncCallback<MapConfig>() { @Override public void onFailure(final Throwable caught) { GWT.log("MAP ERROR: " + caught.getMessage()); } @Override public void onSuccess(final MapConfig c) { GWT.log("MAP SUCCESS!"); if (!MapOutputTab.this.cancel) { final Bounds max = boundsFromString(c.getMaxExtent()); Bounds initial = boundsFromString(c.getInitialExtent()); if (initial == null) { GWT.log("Warning: No initial extent set."); initial = max; } setFloodmap(new FloodMap(c.getSrid(), max, 640, 480)); initLayout(); initBarriers(); GWT.log("MAX EXTENT: " + max); GWT.log("ZOOM TO: " + initial); getMap().zoomToExtent(initial); } } }); } public void cancelMapService() { this.cancel = true; // if (this.floodMap != null) // this.floodMap.destroy(); } protected void initLayout() { this.rootLayout.setHeight100(); this.rootLayout.setWidth100(); this.rootLayout.setMembersMargin(2); final HLayout hlayout = new HLayout(); hlayout.setMembersMargin(0); this.themePanelCanvas = createThemePanel(); this.controlPanel = createControlPanel(); this.mapPanel = this.floodMap.getMapWidget(); this.rootLayout.addMember(this.controlPanel); this.rootLayout.addMember(this.absPan); this.absPan.setWidth("100%"); this.absPan.setHeight("100%"); this.absPan.add(this.themePanelCanvas); this.absPan.add(this.mapPanel); this.rootLayout.addResizedHandler(new ResizedHandler() { @Override public void onResized(final ResizedEvent e) { doLayout(); } }); this.rootLayout.addParentMovedHandler(new ParentMovedHandler() { @Override public void onParentMoved(final ParentMovedEvent event) { MapOutputTab.this.mapPanel.getMap().updateSize(); } }); setPane(this.rootLayout); } protected void doLayout() { if (!this.rootLayout.isVisible()) { return; } // Manually set the height of the AbsolutePanel, // somehow this is necessary this.absPan.setHeight(String.valueOf(this.rootLayout.getHeight() - this.controlPanel.getHeight() - 2) + "px"); // Calculate bounds of Map final int height = this.rootLayout.getHeight() - this.controlPanel.getHeight() - 6; final int width = this.controlPanel.getWidth() - (this.themePanelCanvas.isVisible() ? this.themePanelCanvas.getWidth() + 4 : 2); // Set size and position of Map final String w = String.valueOf(width) + "px"; final String h = String.valueOf(height) + "px"; GWT.log("width=" + w); this.mapPanel.setSize(w, h); this.mapPanel.getMap().updateSize(); if (this.themePanelCanvas.isVisible()) { this.absPan.setWidgetPosition(this.mapPanel, this.themePanelCanvas.getWidth() + 2, 0); } else { this.absPan.setWidgetPosition(this.mapPanel, 0, 0); } // Set bounds of ThemePanelCanvas this.themePanelCanvas.setSize(this.themePanelCanvas.getWidthAsString(), String.valueOf(height + 2) + "px"); } protected void initBarriers() { final Vector vector = this.floodMap.getBarrierLayer(); vector.addVectorFeatureAddedListener(new VectorFeatureAddedListener() { @Override public void onFeatureAdded(final FeatureAddedEvent e) { saveBarriers(); } }); vector.addVectorFeatureRemovedListener(new VectorFeatureRemovedListener() { @Override public void onFeatureRemoved(final FeatureRemovedEvent e) { saveBarriers(); } }); final Artifact artifact = getArtifact(); if (artifact == null) { return; } final ArtifactDescription desc = artifact.getArtifactDescription(); String geojson = getGeoJSONFromStatic(desc); geojson = geojson != null ? geojson : getGeoJSONFromDynamic(desc); if (geojson == null || geojson.length() == 0) { GWT.log("No geojson string found -> no barriers existing."); return; } final GeoJSON reader = new GeoJSON(); final VectorFeature[] features = reader.read(geojson); vector.addFeatures(features); } public void addLayer(final Theme newTheme) { final Layer layer = createWMSLayer(newTheme); final FloodMap map = getFloodmap(); if (map != null) { GWT.log("Add new layer '" + layer.getName() + "' to map."); map.addLayer(layer); if (layer instanceof WMS) { this.wmsUrls.put(layer.getName(), ((WMS) layer).getFullRequestString(new WMSParams(), null)); } } } public void removeLayer(final Theme theme) { final String layerId = getLayerId(theme); final Map map = getMap(); final Layer[] layers = map.getLayers(); for (final Layer layer : layers) { if (layerId.equals(layer.getName())) { map.removeLayer(layer); } } } @Override public void onRedrawRequest(final RedrawRequestEvent event) { this.mapService.doOut(this.collection, new AsyncCallback<MapConfig>() { @Override public void onFailure(final Throwable caught) { GWT.log("MAP ERROR: " + caught.getMessage()); } @Override public void onSuccess(final MapConfig c) { GWT.log("We want to refresh the map now!"); MapOutputTab.this.themePanel.updateCollection(); getFloodmap().update(); } }); } @Override public void load(final List<WMSLayer> toLoad) { GWT.log("The user wants to add " + toLoad.size() + " new WMS layers."); final int len = toLoad.size(); final Recommendation[] recom = new Recommendation[len]; for (int i = 0; i < len; i++) { final WMSLayer w = toLoad.get(i); final String ids = w.getServer() + ";" + w.getName() + ";" + w.getTitle(); recom[i] = new Recommendation(EXTERNAL_WMS_FACTORY, ids); } final Collection c = getCollection(); final Config config = Config.getInstance(); final String locale = config.getLocale(); this.loadArtifactService.loadMany(c, recom, EXTERNAL_WMS_FACTORY, locale, new AsyncCallback<Artifact[]>() { @Override public void onFailure(final Throwable throwable) { SC.warn(MapOutputTab.this.MSG.getString(throwable.getMessage())); } @Override public void onSuccess(final Artifact[] newArtifacts) { getThemePanel().updateCollection(); } }); } protected void setFloodmap(final FloodMap floodMap) { this.floodMap = floodMap; } protected FloodMap getFloodmap() { return this.floodMap; } protected Map getMap() { return this.floodMap.getMap(); } protected ThemePanel getThemePanel() { return this.themePanel; } protected String getGeoJSONFromDynamic(final ArtifactDescription desc) { final DataList list = desc.getCurrentData(); if (list == null) { return null; } final List<Data> datas = list.getAll(); for (final Data data : datas) { final String key = data.getLabel(); if (key != null && key.equals(BARRIERS_PARAMETER_KEY)) { final DataItem def = data.getDefault(); if (def != null) { return def.getStringValue(); } } } return null; } protected String getGeoJSONFromStatic(final ArtifactDescription desc) { // TODO Implement this method, if there are reachable states right after // the floodmap state - which is currently not the case. return null; } public ThemeList getThemeList() { return this.collection.getThemeList(this.mode.getName()); } public String getSrid() { final ThemeList themeList = getThemeList(); final int num = themeList.getThemeCount(); for (int i = 1; i <= num; i++) { final AttributedTheme theme = (AttributedTheme) themeList.getThemeAt(i); if (theme == null) { continue; } final String srid = theme.getAttr("srid"); if (srid != null && srid.length() > 0) { return srid; } } return DEFAULT_SRID; } protected Bounds boundsFromString(final String bounds) { GWT.log("Create Bounds from String: '" + bounds + "'"); if (bounds == null || bounds.length() == 0) { return null; } final String[] values = bounds.split(" "); if (values == null || values.length < 4) { return null; } try { return new Bounds(Double.valueOf(values[0]), Double.valueOf(values[1]), Double.valueOf(values[2]), Double.valueOf(values[3])); } catch (final NumberFormatException nfe) { } return null; } private Layer createWMSLayer(final Theme theme) { if (!(theme instanceof AttributedTheme)) { return null; } final AttributedTheme at = (AttributedTheme) theme; // final String desc = at.getAttr("description"); final String url = at.getAttr("url"); final String layers = at.getAttr("layers"); final String layerId = getLayerId(theme); if (url == null || layers == null) { return null; } final WMSParams params = new WMSParams(); params.setLayers(layers); params.setFormat("image/png"); params.setIsTransparent(true); final WMSOptions opts = new WMSOptions(); opts.setProjection("EPSG:" + getSrid()); opts.setSingleTile(true); opts.setRatio(1); if (layers.equals("OSM-WMS-Dienst")) { opts.setAttribution(this.MSG.attribution()); opts.setSingleTile(true); opts.setTransitionEffect(TransitionEffect.RESIZE); } final WMS wms = new WMS(layerId, url, params, opts); wms.setIsVisible(at.getActive() == 1); wms.setIsBaseLayer(false); // We can't set the full_url attribute here because map is not set // at.addAttr("full_url", wms.getFullRequestString(params, null)); return wms; } private String getLayerId(final Theme theme) { final AttributedTheme at = (AttributedTheme) theme; final String name = at.getAttr("name"); final String layers = at.getAttr("layers"); return name + "_" + layers; } protected MapToolbar createControlPanel() { return new MapToolbar(this, this.floodMap, false); } protected Canvas createThemePanel() { final Canvas c = new Canvas(); c.setMinWidth(300); c.setWidth(200); c.setHeight100(); c.setCanDragResize(true); c.setBorder("1px solid black"); this.themePanel = new MapThemePanel(this.getCollectionView(), this.mode, this, new MapThemePanel.ActivateCallback() { @Override public void activate(final Theme theme, final boolean active) { fireActivateTheme(theme, active); } }, new MapThemePanel.ThemeMovedCallback() { @Override public void onThemeMoved(final Theme theme, final int oldIdx, final int newIdx) { // this code synchronizes the ThemePanel and the OpenLayers // internal order of layers. final AttributedTheme at = (AttributedTheme) theme; final String layerId = getLayerId(theme); final Map map = getMap(); final Layer[] layers = map.getLayersByName(layerId); if (layers == null || layers.length == 0) { GWT.log("Error: Cannot find layer '" + layerId + "'"); return; } map.raiseLayer(layers[0], (newIdx - oldIdx) * -1); map.zoomTo(map.getZoom() - 1); map.zoomTo(map.getZoom() + 1); } }, new MapThemePanel.LayerZoomCallback() { @Override public void onLayerZoom(final Theme theme, final String extent) { final Bounds zoomTo = boundsFromString(extent); if (zoomTo == null) { GWT.log("WARNING: No valid bounds for zooming found!"); return; } getMap().zoomToExtent(zoomTo); } }); this.themePanel.addRedrawRequestHandler(this); this.themePanel.addOutputParameterChangeHandler(this); c.addChild(this.themePanel); return c; } private void fireActivateTheme(final Theme theme, final boolean active) { activateTheme(theme, active); } protected void activateTheme(final Theme theme, final boolean active) { final String layerId = getLayerId(theme); final Layer layer = this.floodMap.getMap().getLayerByName(layerId); GWT.log("Set visibility of '" + layerId + "': " + active); if (layer != null) { layer.setIsVisible(active); } } protected void saveBarriers() { final Vector layer = this.floodMap.getBarrierLayer(); final GeoJSON format = new GeoJSON(); final String features = format.write(layer.getFeatures()); final DataItem item = new DefaultDataItem(BARRIERS_PARAMETER_KEY, BARRIERS_PARAMETER_KEY, features); final Data data = new DefaultData(BARRIERS_PARAMETER_KEY, BARRIERS_PARAMETER_KEY, "String", new DataItem[] { item }); final Config config = Config.getInstance(); final String locale = config.getLocale(); this.feedService.go(locale, getArtifact(), new Data[] { data }, new AsyncCallback<Artifact>() { @Override public void onFailure(final Throwable caught) { GWT.log("Could not save barrier geometries: " + caught.getMessage()); } @Override public void onSuccess(final Artifact artifact) { GWT.log("Successfully saved barrier geometries."); } }); } @Override public void onTabSelected(final TabSelectedEvent tse) { if (this.floodMap == null) { return; } if (this.equals(tse.getTab())) { this.floodMap.activateScaleLine(true); } else { this.controlPanel.activateMeasureControl(false); this.floodMap.activateScaleLine(false); } } public void toogleThemePanel() { this.themePanelCanvas.setVisible(!this.themePanelCanvas.isVisible()); // Trigger resize event handler doLayout(); } @Override public void onOutputParameterChanged(final OutputParameterChangeEvent evt) { GWT.log("OutputParameterChanged"); this.controlPanel.updateThemes(getThemePanel().getThemeList()); } public String getWMSUrl(final Theme theme) { final String layerId = getLayerId(theme); return this.wmsUrls.get(layerId); } }