# HG changeset patch # User Ingo Weinzierl # Date 1321546855 0 # Node ID 96708d81eaf6ddc0bd864772c9fff759da17bcdc # Parent 748e7c828d03e68cca911aa44c32b21e2def5d24 Added an initial GetFeatureInfo tool to get information about points in the map. flys-client/trunk@3285 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/java/de/intevation/flys/client/client/FLYSConstants.java --- a/flys-client/src/main/java/de/intevation/flys/client/client/FLYSConstants.java Thu Nov 17 14:10:51 2011 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/client/FLYSConstants.java Thu Nov 17 16:20:55 2011 +0000 @@ -416,6 +416,12 @@ String warning_use_first_feature(); + String error_no_valid_gfi_url(); + + String error_gfi_req_failed(); + + String error_gfi_parsing_failed(); + String bottom_edge(); @@ -440,6 +446,12 @@ String removeFeature(); + String getFeatureInfo(); + + String getFeatureInfoTooltip(); + + String getFeatureInfoWindowTitle(); + String adjustElevation(); String adjustElevationTooltip(); diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/java/de/intevation/flys/client/client/FLYSConstants.properties --- a/flys-client/src/main/java/de/intevation/flys/client/client/FLYSConstants.properties Thu Nov 17 14:10:51 2011 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/client/FLYSConstants.properties Thu Nov 17 16:20:55 2011 +0000 @@ -217,6 +217,9 @@ error_no_feature_selected = No object selected. error_no_map_config = No Map configuration found. warning_use_first_feature = You have more that one object selected. The first one is used. +error_no_valid_gfi_url = No valid GetFeatureInfo response found. +error_gfi_req_failed = GetFeatureInfo request failed. +error_gfi_parsing_failed = Failed to read GetFeatureInfo response. ## map related strings digitize = images/digitize.png @@ -227,6 +230,9 @@ ring_dike = Ringdike selectFeature = images/selectFeature.png removeFeature = images/removeFeature.png +getFeatureInfo = images/getFeatureInfo.png +getFeatureInfoTooltip = Information Tool +getFeatureInfoWindowTitle = Informations for Map Layers. adjustElevation = images/adjustElevation.png measureLine = images/measureLine.png measurePolygon = images/measurePolygon.png diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/java/de/intevation/flys/client/client/FLYSConstants_de.properties --- a/flys-client/src/main/java/de/intevation/flys/client/client/FLYSConstants_de.properties Thu Nov 17 14:10:51 2011 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/client/FLYSConstants_de.properties Thu Nov 17 16:20:55 2011 +0000 @@ -217,6 +217,9 @@ error_no_feature_selected = Kein Objekt ausgew\u00e4hlt. error_no_map_config = Es konnte keine Kartenkonfiguration gefunden werden. warning_use_first_feature = Sie haben mehr als ein Objekt ausgew\u00e4hlt. Das erste Objekt wird benutzt. +error_no_valid_gfi_url = Ung\u00fcltige GetFeatureInfo URL. +error_gfi_req_failed = Die GetFeatureInfo Anfrage ist fehlgeschlagen. +error_gfi_parsing_failed = Fehler beim Lesen der GetFeatureInfo Antwort. ## map related strings digitize = images/digitize.png @@ -227,6 +230,9 @@ ring_dike = Ringdeich selectFeature = images/selectFeature.png removeFeature = images/removeFeature.png +getFeatureInfo = images/getFeatureInfo.png +getFeatureInfoTooltip = Informationswerkzeug +getFeatureInfoWindowTitle = Informationen zu Kartenebenen adjustElevation = images/adjustElevation.png measureLine = images/measureLine.png measurePolygon = images/measurePolygon.png diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/java/de/intevation/flys/client/client/FLYSConstants_en.properties --- a/flys-client/src/main/java/de/intevation/flys/client/client/FLYSConstants_en.properties Thu Nov 17 14:10:51 2011 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/client/FLYSConstants_en.properties Thu Nov 17 16:20:55 2011 +0000 @@ -217,6 +217,9 @@ error_no_feature_selected = No object selected. error_no_map_config = No Map configuration found. warning_use_first_feature = You have more that one object selected. The first one is used. +error_no_valid_gfi_url = No valid GetFeatureInfo response found. +error_gfi_req_failed = GetFeatureInfo request failed. +error_gfi_parsing_failed = Failed to read GetFeatureInfo response. ## map related strings digitize = images/digitize.png @@ -227,6 +230,9 @@ ring_dike = Ringdike selectFeature = images/selectFeature.png removeFeature = images/removeFeature.png +getFeatureInfo = images/getFeatureInfo.png +getFeatureInfoTooltip = Information Tool +getFeatureInfoWindowTitle = Informations for Map Layers. adjustElevation = images/adjustElevation.png measureLine = images/measureLine.png measurePolygon = images/measurePolygon.png diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/java/de/intevation/flys/client/client/services/GFIService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/client/services/GFIService.java Thu Nov 17 16:20:55 2011 +0000 @@ -0,0 +1,27 @@ +package de.intevation.flys.client.client.services; + +import java.util.List; + +import com.google.gwt.user.client.rpc.RemoteService; +import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; + + +import de.intevation.flys.client.shared.exceptions.ServerException; +import de.intevation.flys.client.shared.model.Theme; + + +@RemoteServiceRelativePath("getfeatureinfo") +public interface GFIService extends RemoteService { + + public String query( + List themes, + String format, + String bbox, + String projection, + int height, + int width, + int x, + int y + ) throws ServerException; +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/java/de/intevation/flys/client/client/services/GFIServiceAsync.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/client/services/GFIServiceAsync.java Thu Nov 17 16:20:55 2011 +0000 @@ -0,0 +1,28 @@ +package de.intevation.flys.client.client.services; + +import java.util.List; + +import com.google.gwt.user.client.rpc.AsyncCallback; + + +import de.intevation.flys.client.shared.model.Theme; + + +/** + * @author Ingo Weinzierl + */ +public interface GFIServiceAsync { + + void query( + List themes, + String format, + String bbox, + String projection, + int height, + int width, + int x, + int y, + AsyncCallback callback + ); +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/java/de/intevation/flys/client/client/ui/OutputTab.java --- a/flys-client/src/main/java/de/intevation/flys/client/client/ui/OutputTab.java Thu Nov 17 14:10:51 2011 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/OutputTab.java Thu Nov 17 16:20:55 2011 +0000 @@ -57,5 +57,10 @@ public Artifact getArtifact() { return getCollectionView().getArtifact(); } + + + public Collection getCollection() { + return collection; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/java/de/intevation/flys/client/client/ui/map/GetFeatureInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/map/GetFeatureInfo.java Thu Nov 17 16:20:55 2011 +0000 @@ -0,0 +1,79 @@ +package de.intevation.flys.client.client.ui.map; + +import java.util.List; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.rpc.AsyncCallback; + +import com.smartgwt.client.util.SC; + +import org.gwtopenmaps.openlayers.client.Map; +import org.gwtopenmaps.openlayers.client.LonLat; +import org.gwtopenmaps.openlayers.client.Pixel; +import org.gwtopenmaps.openlayers.client.event.MapClickListener; + +import de.intevation.flys.client.shared.model.Theme; + +import de.intevation.flys.client.client.FLYSConstants; +import de.intevation.flys.client.client.services.GFIService; +import de.intevation.flys.client.client.services.GFIServiceAsync; + + +public class GetFeatureInfo implements MapClickListener { + + protected GFIServiceAsync gfiService = GWT.create(GFIService.class); + + protected FLYSConstants MSG = GWT.create(FLYSConstants.class); + + protected Map map; + protected List themes; + protected String infoFormat; + + + /** + * @param map + * @param themes + * @param url + * @param infoFormat + */ + public GetFeatureInfo(Map map, List themes, String infoFormat) { + this.map = map; + this.themes = themes; + this.infoFormat = infoFormat; + } + + + public void activate(boolean activate) { + if (activate) { + map.addMapClickListener(this); + } + else { + map.removeListener(this); + } + } + + + @Override + public void onClick(MapClickListener.MapClickEvent e) { + LonLat lonlat = e.getLonLat(); + Pixel pixel = map.getPixelFromLonLat(lonlat); + + gfiService.query( + themes, + infoFormat, + map.getExtent().toString(), + map.getProjection(), + (int) map.getSize().getHeight(), + (int) map.getSize().getWidth(), + pixel.x(), pixel.y(), + new AsyncCallback() { + public void onFailure(Throwable e) { + SC.warn(MSG.getString(e.getMessage())); + } + + public void onSuccess(String response) { + new GetFeatureInfoWindow(response).show(); + } + }); + } +} diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/java/de/intevation/flys/client/client/ui/map/GetFeatureInfoWindow.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/map/GetFeatureInfoWindow.java Thu Nov 17 16:20:55 2011 +0000 @@ -0,0 +1,84 @@ +package de.intevation.flys.client.client.ui.map; + +import com.google.gwt.core.client.GWT; + +import com.smartgwt.client.widgets.Label; +import com.smartgwt.client.widgets.Window; +import com.smartgwt.client.widgets.layout.HLayout; +import com.smartgwt.client.widgets.layout.VLayout; + +import org.gwtopenmaps.openlayers.client.feature.VectorFeature; +import org.gwtopenmaps.openlayers.client.format.GML; +import org.gwtopenmaps.openlayers.client.util.Attributes; +import org.gwtopenmaps.openlayers.client.util.JSObject; + +import de.intevation.flys.client.client.FLYSConstants; + + +public class GetFeatureInfoWindow extends Window { + + protected FLYSConstants MSG = GWT.create(FLYSConstants.class); + + protected VectorFeature[] features; + + + public GetFeatureInfoWindow(String gml) { + super(); + features = new GML().read(gml); + initLayout(); + } + + + protected void initLayout() { + VLayout root = new VLayout(); + + for (VectorFeature feature: features) { + root.addMember(createFeatureRow(feature)); + } + + addItem(root); + + setWidth(400); + setHeight(200); + setTitle(MSG.getFeatureInfoWindowTitle()); + + centerInPage(); + } + + + protected HLayout createFeatureRow(VectorFeature feature) { + HLayout r = new HLayout(); + r.setHeight(25); + + String[][] attrs = extractProperties(feature); + + for (String[] attr: attrs) { + Label l = new Label(attr[0] + ": " + attr[1]); + l.setHeight(25); + l.setBorder("1px solid black"); + r.addMember(l); + } + + return r; + } + + + protected String[][] extractProperties(VectorFeature feature) { + Attributes tmp = feature.getAttributes(); + JSObject jsobj = tmp.getJSObject(); + + String tmpNames = jsobj.getPropertyNames(); + String[] allNames = tmpNames.split(","); + + String[][] attr = new String[allNames.length][]; + + for (int i = 0, n = attr.length; i < n; i++) { + attr[i] = new String[] { + allNames[i], + jsobj.getPropertyAsString(allNames[i]) }; + } + + return attr; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/java/de/intevation/flys/client/client/ui/map/MapOutputTab.java --- a/flys-client/src/main/java/de/intevation/flys/client/client/ui/map/MapOutputTab.java Thu Nov 17 14:10:51 2011 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/map/MapOutputTab.java Thu Nov 17 16:20:55 2011 +0000 @@ -350,10 +350,10 @@ AttributedTheme at = (AttributedTheme) theme; - String type = at.getAttr("name"); - String desc = at.getAttr("description"); - String url = at.getAttr("url"); - String layers = at.getAttr("layers"); + String type = at.getAttr("name"); + String desc = at.getAttr("description"); + String url = at.getAttr("url"); + String layers = at.getAttr("layers"); if (url == null || layers == null) { return null; @@ -371,7 +371,7 @@ opts.setSingleTile(true); opts.setRatio(1); - WMS wms = new WMS(desc, url, params, opts); + WMS wms = new WMS(layers, url, params, opts); wms.setIsVisible(at.getActive() == 1); wms.setIsBaseLayer(false); diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/java/de/intevation/flys/client/client/ui/map/MapToolbar.java --- a/flys-client/src/main/java/de/intevation/flys/client/client/ui/map/MapToolbar.java Thu Nov 17 14:10:51 2011 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/map/MapToolbar.java Thu Nov 17 16:20:55 2011 +0000 @@ -20,8 +20,10 @@ import org.gwtopenmaps.openlayers.client.util.Attributes; import de.intevation.flys.client.client.FLYSConstants; +import de.intevation.flys.client.client.ui.OutputTab; import de.intevation.flys.client.client.ui.Toolbar; import de.intevation.flys.client.client.utils.EnableDisableCmd; +import de.intevation.flys.client.shared.model.ThemeList; /** @@ -31,10 +33,11 @@ protected FLYSConstants MSG = GWT.create(FLYSConstants.class); - protected FloodMap floodMap; - protected DragPan pan; - protected ZoomBox zoomBox; - protected SelectFeature selectFeature; + protected FloodMap floodMap; + protected DragPan pan; + protected ZoomBox zoomBox; + protected SelectFeature selectFeature; + protected GetFeatureInfo getFeatureInfo; protected Button datacageButton; @@ -43,6 +46,7 @@ protected ImgButton zoomOutButton; protected ImgButton panButton; protected ImgButton selectButton; + protected ImgButton infoButton; protected ImgButton removeButton; protected ImgButton elevationButton; @@ -83,6 +87,7 @@ panButton = createPanControl(); drawControl = createDrawControl(); selectButton = createSelectFeatureControl(); + infoButton = createGetFeatureInfo(); measureControl = createMeasureControl(); position = createMousePosition(); removeButton = createRemoveFeatureControl(); @@ -105,6 +110,10 @@ addMember(elevationButton); } + if (infoButton != null) { + addMember(infoButton); + } + addMember(measureControl); addMember(position); } @@ -161,6 +170,11 @@ } + protected void activateGetFeatureInfo(boolean activate) { + getFeatureInfo.activate(activate); + } + + protected ImgButton createButton(String img, ClickHandler handler) { ImgButton btn = new ImgButton(); @@ -468,5 +482,39 @@ return btn; } + + + protected ImgButton createGetFeatureInfo() { + OutputTab ot = getOutputTab(); + if (ot == null) { + return null; + } + + ThemeList tl = ot.getCollection().getThemeList("floodmap"); + + getFeatureInfo = new GetFeatureInfo( + getMap(), + tl.getThemes(), + "gml"); + + EnableDisableCmd cmd = new EnableDisableCmd() { + public void enable() { + activateDrawFeature(false); + activatePan(false); + activateZoomBox(false); + activateSelectFeature(false); + activateGetFeatureInfo(true); + } + + public void disable() { + activateGetFeatureInfo(false); + } + }; + + ImgButton button = createToggleButton(MSG.getFeatureInfo(), cmd); + button.setTooltip(MSG.getFeatureInfoTooltip()); + + return button; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/java/de/intevation/flys/client/server/GFIServiceImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-client/src/main/java/de/intevation/flys/client/server/GFIServiceImpl.java Thu Nov 17 16:20:55 2011 +0000 @@ -0,0 +1,224 @@ +package de.intevation.flys.client.server; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.io.StringWriter; +import java.net.URL; +import java.net.URLConnection; +import java.util.List; + +import org.apache.log4j.Logger; + +import com.google.gwt.user.server.rpc.RemoteServiceServlet; + + +import de.intevation.flys.client.shared.exceptions.ServerException; +import de.intevation.flys.client.shared.model.AttributedTheme; +import de.intevation.flys.client.shared.model.Theme; + +import de.intevation.flys.client.client.services.GFIService; + + +/** + * @author Ingo Weinzierl + */ +public class GFIServiceImpl +extends RemoteServiceServlet +implements GFIService +{ + public static final String ERR_NO_VALID_GFI_URL = + "error_no_valid_gfi_url"; + + public static final String ERR_GFI_REQUEST_FAILED = + "error_gfi_req_failed"; + + public static final String ERR_PARSING_RESPONSE_FAILED = + "error_gfi_parsing_failed"; + + + private static final Logger logger = + Logger.getLogger(GFIServiceImpl.class); + + + /** + * @param themes + * @param format + * @param bbox + * @param height + * @param width + * @param x + * @param y + * + * @return + */ + public String query( + List themes, + String format, + String bbox, + String projection, + int height, + int width, + int x, + int y + ) throws ServerException + { + logger.info("GFIServiceImpl.query"); + + String path = createGetFeautureInfoURL( + themes, format, bbox, projection, height, width, x, y); + logger.debug("URL=" + path); + + try { + URL url = new URL(path); + + URLConnection conn = url.openConnection(); + conn.connect(); + + InputStream is = conn.getInputStream(); + + return getResponseText(is); + + } + catch (IOException ioe) { + logger.warn(ioe, ioe); + } + + throw new ServerException(ERR_GFI_REQUEST_FAILED); + } + + + protected String getResponseText(InputStream is) + throws ServerException { + BufferedReader reader = null; + StringWriter writer = new StringWriter(); + + try { + reader = new BufferedReader(new InputStreamReader(is)); + + String line = null; + + if (reader.ready()) { + while ((line = reader.readLine()) != null) { + String test = line.trim(); + if (test.startsWith("<") && !test.startsWith(" 0) + { + writer.append(""); + } + writer.append(line); + + if (test.startsWith(" 0) { + writer.append(""); + } + } + } + } + catch (IOException ioe) { + logger.warn(ioe, ioe); + throw new ServerException(ERR_PARSING_RESPONSE_FAILED); + } + finally { + if (reader != null) { + try { + reader.close(); + } + catch (IOException ioe) { + // do nothing here + } + } + } + + return writer.toString(); + } + + + /** + * @param map + * @param themes + * @param format + * @param x + * @param y + * + * @return + */ + protected String createGetFeautureInfoURL( + List themes, + String infoFormat, + String bbox, + String projection, + int height, + int width, + int x, + int y + ) throws ServerException + { + String url = getUrl(themes); + + if (url == null || url.length() == 0) { + throw new ServerException(ERR_NO_VALID_GFI_URL); + } + + String layers = createLayersString(themes); + + StringBuilder sb = new StringBuilder(); + sb.append(url); + + if (url.indexOf("?") < 0) { + sb.append("?SERVICE=WMS"); + } + else { + sb.append("&SERVICE=WMS"); + } + + sb.append("&VERSION=1.1.1"); + sb.append("&REQUEST=GetFeatureInfo"); + sb.append("&LAYERS=" + layers); + sb.append("&QUERY_LAYERS=" + layers); + sb.append("&BBOX=" + bbox); + sb.append("&HEIGHT=" + height); + sb.append("&WIDTH=" + width); + sb.append("&FORMAT=image/png"); + sb.append("&INFO_FORMAT=" + infoFormat); + sb.append("&SRS=" + projection); + sb.append("&X=" + String.valueOf(x)); + sb.append("&Y=" + String.valueOf(y)); + + return sb.toString(); + } + + + protected String getUrl(List themes) { + for (Theme t: themes) { + AttributedTheme attr = (AttributedTheme) t; + + if (attr.getAttrAsBoolean("queryable")) { + return attr.getAttr("url"); + } + } + + return null; + } + + + protected String createLayersString(List themes) { + StringBuilder sb = new StringBuilder(); + boolean first = true; + + for (Theme theme: themes) { + if (!first) { + sb.append(","); + } + + AttributedTheme layer = (AttributedTheme) theme; + if (layer.getAttrAsBoolean("queryable")) { + sb.append(layer.getAttr("layers")); + first = false; + } + } + + return sb.toString(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/webapp/WEB-INF/web.xml --- a/flys-client/src/main/webapp/WEB-INF/web.xml Thu Nov 17 14:10:51 2011 +0000 +++ b/flys-client/src/main/webapp/WEB-INF/web.xml Thu Nov 17 16:20:55 2011 +0000 @@ -305,6 +305,16 @@ + getfeatureinfo + de.intevation.flys.client.server.GFIServiceImpl + + + + getfeatureinfo + /flys/getfeatureinfo + + + DescribeArtifactService de.intevation.flys.client.server.DescribeArtifactServiceImpl diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/webapp/images/getFeatureInfo.png Binary file flys-client/src/main/webapp/images/getFeatureInfo.png has changed diff -r 748e7c828d03 -r 96708d81eaf6 flys-client/src/main/webapp/images/getFeatureInfo_Selected.png Binary file flys-client/src/main/webapp/images/getFeatureInfo_Selected.png has changed