Mercurial > dive4elements > river
comparison gwt-client/src/main/java/org/dive4elements/river/client/client/ui/map/MapOutputTab.java @ 5838:5aa05a7a34b7
Rename modules to more fitting names.
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Thu, 25 Apr 2013 15:23:37 +0200 |
parents | flys-client/src/main/java/org/dive4elements/river/client/client/ui/map/MapOutputTab.java@821a02bbfb4e |
children | 172338b1407f |
comparison
equal
deleted
inserted
replaced
5837:d9901a08d0a6 | 5838:5aa05a7a34b7 |
---|---|
1 package org.dive4elements.river.client.client.ui.map; | |
2 | |
3 import com.google.gwt.core.client.GWT; | |
4 import com.google.gwt.user.client.rpc.AsyncCallback; | |
5 import com.google.gwt.user.client.ui.AbsolutePanel; | |
6 import com.smartgwt.client.util.SC; | |
7 import com.smartgwt.client.widgets.Canvas; | |
8 import com.smartgwt.client.widgets.events.ParentMovedEvent; | |
9 import com.smartgwt.client.widgets.events.ParentMovedHandler; | |
10 import com.smartgwt.client.widgets.events.ResizedEvent; | |
11 import com.smartgwt.client.widgets.events.ResizedHandler; | |
12 import com.smartgwt.client.widgets.layout.HLayout; | |
13 import com.smartgwt.client.widgets.layout.VLayout; | |
14 import com.smartgwt.client.widgets.tab.events.TabSelectedEvent; | |
15 import com.smartgwt.client.widgets.tab.events.TabSelectedHandler; | |
16 | |
17 import org.dive4elements.river.client.client.Config; | |
18 import org.dive4elements.river.client.client.FLYSConstants; | |
19 import org.dive4elements.river.client.client.event.OutputParameterChangeEvent; | |
20 import org.dive4elements.river.client.client.event.OutputParameterChangeHandler; | |
21 import org.dive4elements.river.client.client.event.RedrawRequestEvent; | |
22 import org.dive4elements.river.client.client.event.RedrawRequestHandler; | |
23 import org.dive4elements.river.client.client.services.LoadArtifactService; | |
24 import org.dive4elements.river.client.client.services.LoadArtifactServiceAsync; | |
25 import org.dive4elements.river.client.client.services.MapOutputService; | |
26 import org.dive4elements.river.client.client.services.MapOutputServiceAsync; | |
27 import org.dive4elements.river.client.client.services.StepForwardService; | |
28 import org.dive4elements.river.client.client.services.StepForwardServiceAsync; | |
29 import org.dive4elements.river.client.client.ui.CollectionView; | |
30 import org.dive4elements.river.client.client.ui.OutputTab; | |
31 import org.dive4elements.river.client.client.ui.ThemePanel; | |
32 import org.dive4elements.river.client.shared.model.Artifact; | |
33 import org.dive4elements.river.client.shared.model.ArtifactDescription; | |
34 import org.dive4elements.river.client.shared.model.AttributedTheme; | |
35 import org.dive4elements.river.client.shared.model.Collection; | |
36 import org.dive4elements.river.client.shared.model.Data; | |
37 import org.dive4elements.river.client.shared.model.DataItem; | |
38 import org.dive4elements.river.client.shared.model.DataList; | |
39 import org.dive4elements.river.client.shared.model.DefaultData; | |
40 import org.dive4elements.river.client.shared.model.DefaultDataItem; | |
41 import org.dive4elements.river.client.shared.model.MapConfig; | |
42 import org.dive4elements.river.client.shared.model.OutputMode; | |
43 import org.dive4elements.river.client.shared.model.Recommendation; | |
44 import org.dive4elements.river.client.shared.model.Theme; | |
45 import org.dive4elements.river.client.shared.model.ThemeList; | |
46 import org.dive4elements.river.client.shared.model.WMSLayer; | |
47 | |
48 import java.util.HashMap; | |
49 import java.util.List; | |
50 | |
51 import org.gwtopenmaps.openlayers.client.Bounds; | |
52 import org.gwtopenmaps.openlayers.client.Map; | |
53 import org.gwtopenmaps.openlayers.client.MapWidget; | |
54 import org.gwtopenmaps.openlayers.client.event.VectorFeatureAddedListener; | |
55 import org.gwtopenmaps.openlayers.client.event.VectorFeatureRemovedListener; | |
56 import org.gwtopenmaps.openlayers.client.feature.VectorFeature; | |
57 import org.gwtopenmaps.openlayers.client.format.GeoJSON; | |
58 import org.gwtopenmaps.openlayers.client.layer.Layer; | |
59 import org.gwtopenmaps.openlayers.client.layer.TransitionEffect; | |
60 import org.gwtopenmaps.openlayers.client.layer.Vector; | |
61 import org.gwtopenmaps.openlayers.client.layer.WMS; | |
62 import org.gwtopenmaps.openlayers.client.layer.WMSOptions; | |
63 import org.gwtopenmaps.openlayers.client.layer.WMSParams; | |
64 | |
65 | |
66 public class MapOutputTab | |
67 extends OutputTab | |
68 implements RedrawRequestHandler, ExternalWMSWindow.LayerLoader, TabSelectedHandler, OutputParameterChangeHandler { | |
69 | |
70 public static final String DEFAULT_SRID = "4326"; | |
71 | |
72 public static final String BARRIERS_PARAMETER_KEY = "uesk.barriers"; | |
73 | |
74 public static final String WSPLGEN_FACET = "floodmap.wsplgen"; | |
75 | |
76 public static final String EXTERNAL_WMS_FACTORY = "externalwmsfactory"; | |
77 | |
78 | |
79 protected StepForwardServiceAsync feedService = | |
80 GWT.create(StepForwardService.class); | |
81 | |
82 protected MapOutputServiceAsync mapService = | |
83 GWT.create(MapOutputService.class); | |
84 | |
85 /** Service handle to clone and add artifacts to collection. */ | |
86 protected LoadArtifactServiceAsync loadArtifactService = | |
87 GWT.create(LoadArtifactService.class); | |
88 | |
89 protected FLYSConstants MSG = GWT.create(FLYSConstants.class); | |
90 | |
91 protected MapToolbar controlPanel; | |
92 protected ThemePanel themePanel; | |
93 protected Canvas themePanelCanvas; | |
94 protected MapWidget mapPanel; | |
95 protected Canvas mapPanelCanvas; | |
96 protected VLayout rootLayout = new VLayout(); | |
97 protected AbsolutePanel absPan = new AbsolutePanel(); | |
98 protected FloodMap floodMap; | |
99 protected java.util.Map<String, String> wmsUrls = new HashMap<String, String>(); | |
100 | |
101 | |
102 public MapOutputTab( | |
103 String title, | |
104 Collection collection, | |
105 OutputMode mode, | |
106 CollectionView collectionView | |
107 ){ | |
108 super(title, collection, collectionView, mode); | |
109 | |
110 collectionView.registerTabHandler(this); | |
111 | |
112 mapService.doOut(collection, new AsyncCallback<MapConfig>() { | |
113 @Override | |
114 public void onFailure(Throwable caught) { | |
115 GWT.log("MAP ERROR: " + caught.getMessage()); | |
116 } | |
117 | |
118 @Override | |
119 public void onSuccess(MapConfig c) { | |
120 GWT.log("MAP SUCCESS!"); | |
121 | |
122 Bounds max = boundsFromString(c.getMaxExtent()); | |
123 Bounds initial = boundsFromString(c.getInitialExtent()); | |
124 | |
125 if (initial == null) { | |
126 GWT.log("Warning: No initial extent set."); | |
127 initial = max; | |
128 } | |
129 | |
130 setFloodmap(new FloodMap(c.getSrid(), max, 640, 480)); | |
131 | |
132 initLayout(); | |
133 initBarriers(); | |
134 | |
135 GWT.log("MAX EXTENT: " + max); | |
136 GWT.log("ZOOM TO: " + initial); | |
137 getMap().zoomToExtent(initial); | |
138 } | |
139 } | |
140 ); | |
141 } | |
142 | |
143 | |
144 protected void initLayout() { | |
145 rootLayout.setHeight100(); | |
146 rootLayout.setWidth100(); | |
147 rootLayout.setMembersMargin(2); | |
148 | |
149 HLayout hlayout = new HLayout(); | |
150 hlayout.setMembersMargin(0); | |
151 | |
152 this.themePanelCanvas = createThemePanel(); | |
153 | |
154 controlPanel = createControlPanel(); | |
155 mapPanel = floodMap.getMapWidget(); | |
156 | |
157 rootLayout.addMember(controlPanel); | |
158 rootLayout.addMember(absPan); | |
159 absPan.setWidth("100%"); | |
160 absPan.setHeight("100%"); | |
161 absPan.add(themePanelCanvas); | |
162 absPan.add(mapPanel); | |
163 | |
164 rootLayout.addResizedHandler(new ResizedHandler() { | |
165 @Override | |
166 public void onResized(ResizedEvent e) { | |
167 doLayout(); | |
168 } | |
169 }); | |
170 | |
171 rootLayout.addParentMovedHandler(new ParentMovedHandler() { | |
172 @Override | |
173 public void onParentMoved(ParentMovedEvent event) { | |
174 mapPanel.getMap().updateSize(); | |
175 } | |
176 }); | |
177 | |
178 setPane(rootLayout); | |
179 } | |
180 | |
181 | |
182 protected void doLayout() { | |
183 if(!rootLayout.isVisible()) { | |
184 return; | |
185 } | |
186 | |
187 // Manually set the height of the AbsolutePanel, somehow this is necessary | |
188 absPan.setHeight(String.valueOf( | |
189 rootLayout.getHeight() - controlPanel.getHeight() - 2) + "px"); | |
190 | |
191 // Calculate bounds of Map | |
192 int height = rootLayout.getHeight() - | |
193 controlPanel.getHeight() - 6; | |
194 int width = controlPanel.getWidth() - | |
195 (themePanelCanvas.isVisible() ? themePanelCanvas.getWidth() + 4 : 2); | |
196 | |
197 // Set size and position of Map | |
198 String w = String.valueOf(width) + "px"; | |
199 String h = String.valueOf(height) + "px"; | |
200 GWT.log("width=" + w); | |
201 | |
202 mapPanel.setSize(w, h); | |
203 mapPanel.getMap().updateSize(); | |
204 if(themePanelCanvas.isVisible()) { | |
205 absPan.setWidgetPosition(mapPanel, themePanelCanvas.getWidth() + 2, 0); | |
206 } | |
207 else { | |
208 absPan.setWidgetPosition(mapPanel, 0, 0); | |
209 } | |
210 | |
211 // Set bounds of ThemePanelCanvas | |
212 themePanelCanvas.setSize(themePanelCanvas.getWidthAsString(), String.valueOf(height + 2) + "px"); | |
213 } | |
214 | |
215 | |
216 protected void initBarriers() { | |
217 Vector vector = floodMap.getBarrierLayer(); | |
218 vector.addVectorFeatureAddedListener( | |
219 new VectorFeatureAddedListener() { | |
220 @Override | |
221 public void onFeatureAdded(FeatureAddedEvent e) { | |
222 saveBarriers(); | |
223 } | |
224 } | |
225 ); | |
226 | |
227 vector.addVectorFeatureRemovedListener( | |
228 new VectorFeatureRemovedListener() { | |
229 @Override | |
230 public void onFeatureRemoved(FeatureRemovedEvent e) { | |
231 saveBarriers(); | |
232 } | |
233 } | |
234 ); | |
235 | |
236 | |
237 Artifact artifact = getArtifact(); | |
238 | |
239 if (artifact == null) { | |
240 return; | |
241 } | |
242 | |
243 ArtifactDescription desc = artifact.getArtifactDescription(); | |
244 | |
245 String geojson = getGeoJSONFromStatic(desc); | |
246 geojson = geojson != null ? geojson : getGeoJSONFromDynamic(desc); | |
247 | |
248 if (geojson == null || geojson.length() == 0) { | |
249 GWT.log("No geojson string found -> no barriers existing."); | |
250 return; | |
251 } | |
252 | |
253 GeoJSON reader = new GeoJSON(); | |
254 VectorFeature[] features = reader.read(geojson); | |
255 | |
256 vector.addFeatures(features); | |
257 } | |
258 | |
259 | |
260 public void addLayer(Layer layer) { | |
261 FloodMap map = getFloodmap(); | |
262 | |
263 if (map != null) { | |
264 GWT.log("Add new layer '" + layer.getName() + "' to map."); | |
265 map.addLayer(layer); | |
266 if (layer instanceof WMS) { | |
267 wmsUrls.put(layer.getName(), | |
268 ((WMS)layer).getFullRequestString(new WMSParams(), null)); | |
269 } | |
270 } | |
271 } | |
272 | |
273 | |
274 public void removeLayer(String name) { | |
275 Map map = getMap(); | |
276 | |
277 Layer[] layers = map.getLayers(); | |
278 | |
279 for (Layer layer: layers) { | |
280 if (name.equals(layer.getName())) { | |
281 map.removeLayer(layer); | |
282 } | |
283 } | |
284 } | |
285 | |
286 | |
287 @Override | |
288 public void onRedrawRequest(RedrawRequestEvent event) { | |
289 mapService.doOut(collection, new AsyncCallback<MapConfig>() { | |
290 @Override | |
291 public void onFailure(Throwable caught) { | |
292 GWT.log("MAP ERROR: " + caught.getMessage()); | |
293 } | |
294 | |
295 @Override | |
296 public void onSuccess(MapConfig c) { | |
297 GWT.log("We want to refresh the map now!"); | |
298 themePanel.updateCollection(); | |
299 getFloodmap().update(); | |
300 } | |
301 }); | |
302 } | |
303 | |
304 | |
305 @Override | |
306 public void load(List<WMSLayer> toLoad) { | |
307 GWT.log("The user wants to add " + toLoad.size() + " new WMS layers."); | |
308 | |
309 int len = toLoad.size(); | |
310 | |
311 Recommendation[] recom = new Recommendation[len]; | |
312 | |
313 for (int i = 0; i < len; i++) { | |
314 WMSLayer w = toLoad.get(i); | |
315 | |
316 String ids = w.getServer() + ";" + w.getName() + ";" + w.getTitle(); | |
317 recom[i] = new Recommendation(EXTERNAL_WMS_FACTORY, ids); | |
318 } | |
319 | |
320 Collection c = getCollection(); | |
321 | |
322 Config config = Config.getInstance(); | |
323 String locale = config.getLocale(); | |
324 | |
325 loadArtifactService.loadMany(c, recom, EXTERNAL_WMS_FACTORY, locale, | |
326 new AsyncCallback<Artifact[]>() { | |
327 | |
328 @Override | |
329 public void onFailure(Throwable throwable) { | |
330 SC.warn(MSG.getString(throwable.getMessage())); | |
331 } | |
332 | |
333 @Override | |
334 public void onSuccess(Artifact[] newArtifacts) { | |
335 getThemePanel().updateCollection(); | |
336 } | |
337 } | |
338 ); | |
339 } | |
340 | |
341 | |
342 protected void setFloodmap(FloodMap floodMap) { | |
343 this.floodMap = floodMap; | |
344 } | |
345 | |
346 | |
347 protected FloodMap getFloodmap() { | |
348 return floodMap; | |
349 } | |
350 | |
351 | |
352 protected Map getMap() { | |
353 return floodMap.getMap(); | |
354 } | |
355 | |
356 | |
357 protected ThemePanel getThemePanel() { | |
358 return themePanel; | |
359 } | |
360 | |
361 | |
362 protected String getGeoJSONFromDynamic(ArtifactDescription desc) { | |
363 DataList list = desc.getCurrentData(); | |
364 | |
365 if (list == null) { | |
366 return null; | |
367 } | |
368 | |
369 List<Data> datas = list.getAll(); | |
370 for (Data data: datas) { | |
371 String key = data.getLabel(); | |
372 | |
373 if (key != null && key.equals(BARRIERS_PARAMETER_KEY)) { | |
374 DataItem def = data.getDefault(); | |
375 | |
376 if (def != null) { | |
377 return def.getStringValue(); | |
378 } | |
379 } | |
380 } | |
381 | |
382 return null; | |
383 } | |
384 | |
385 | |
386 protected String getGeoJSONFromStatic(ArtifactDescription desc) { | |
387 // TODO Implement this method, if there are reachable states right after | |
388 // the floodmap state - which is currently not the case. | |
389 return null; | |
390 } | |
391 | |
392 | |
393 public ThemeList getThemeList() { | |
394 return collection.getThemeList(mode.getName()); | |
395 } | |
396 | |
397 | |
398 public String getSrid() { | |
399 ThemeList themeList = getThemeList(); | |
400 | |
401 int num = themeList.getThemeCount(); | |
402 | |
403 for (int i = 1; i <= num; i++) { | |
404 AttributedTheme theme = (AttributedTheme) themeList.getThemeAt(i); | |
405 | |
406 if (theme == null) { | |
407 continue; | |
408 } | |
409 | |
410 String srid = theme.getAttr("srid"); | |
411 | |
412 if (srid != null && srid.length() > 0) { | |
413 return srid; | |
414 } | |
415 } | |
416 | |
417 return DEFAULT_SRID; | |
418 } | |
419 | |
420 | |
421 protected Bounds boundsFromString(String bounds) { | |
422 GWT.log("Create Bounds from String: '" + bounds + "'"); | |
423 if (bounds == null || bounds.length() == 0) { | |
424 return null; | |
425 } | |
426 | |
427 String[] values = bounds.split(" "); | |
428 | |
429 if (values == null || values.length < 4) { | |
430 return null; | |
431 } | |
432 | |
433 try { | |
434 return new Bounds( | |
435 Double.valueOf(values[0]), | |
436 Double.valueOf(values[1]), | |
437 Double.valueOf(values[2]), | |
438 Double.valueOf(values[3])); | |
439 } | |
440 catch (NumberFormatException nfe) {} | |
441 | |
442 return null; | |
443 } | |
444 | |
445 | |
446 public Layer createWMSLayer(Theme theme) { | |
447 if (!(theme instanceof AttributedTheme)) { | |
448 return null; | |
449 } | |
450 | |
451 AttributedTheme at = (AttributedTheme) theme; | |
452 | |
453 String name = at.getAttr("name"); | |
454 String desc = at.getAttr("description"); | |
455 String url = at.getAttr("url"); | |
456 String layers = at.getAttr("layers"); | |
457 | |
458 if (url == null || layers == null) { | |
459 return null; | |
460 } | |
461 | |
462 WMSParams params = new WMSParams(); | |
463 params.setLayers(layers); | |
464 params.setFormat("image/png"); | |
465 params.setIsTransparent(true); | |
466 | |
467 WMSOptions opts = new WMSOptions(); | |
468 opts.setProjection("EPSG:" + getSrid()); | |
469 opts.setSingleTile(true); | |
470 opts.setRatio(1); | |
471 if (layers.equals("OSM-WMS-Dienst")) { | |
472 opts.setAttribution(MSG.attribution()); | |
473 opts.setSingleTile(true); | |
474 opts.setTransitionEffect(TransitionEffect.RESIZE); | |
475 } | |
476 WMS wms = new WMS(layers, url, params, opts); | |
477 wms.setIsVisible(at.getActive() == 1); | |
478 wms.setIsBaseLayer(false); | |
479 // We can't set the full_url attribute here because map is not set | |
480 // at.addAttr("full_url", wms.getFullRequestString(params, null)); | |
481 return wms; | |
482 } | |
483 | |
484 | |
485 public java.util.Map<String, String> wmsUrls() { | |
486 return this.wmsUrls; | |
487 } | |
488 | |
489 | |
490 protected MapToolbar createControlPanel() { | |
491 return new MapToolbar(this, floodMap, false); | |
492 } | |
493 | |
494 | |
495 protected Canvas createThemePanel() { | |
496 Canvas c = new Canvas(); | |
497 c.setMinWidth(300); | |
498 c.setWidth(200); | |
499 c.setHeight100(); | |
500 c.setCanDragResize(true); | |
501 c.setBorder("1px solid black"); | |
502 | |
503 themePanel = new MapThemePanel( | |
504 this.getCollectionView(), | |
505 mode, | |
506 this, | |
507 new MapThemePanel.ActivateCallback() { | |
508 @Override | |
509 public void activate(Theme theme, boolean active) { | |
510 fireActivateTheme(theme, active); | |
511 } | |
512 }, | |
513 new MapThemePanel.ThemeMovedCallback() { | |
514 @Override | |
515 public void onThemeMoved(Theme theme, int oldIdx, int newIdx) { | |
516 // this code synchronizes the ThemePanel and the OpenLayers | |
517 // internal order of layers. | |
518 AttributedTheme at = (AttributedTheme) theme; | |
519 | |
520 String name = at.getAttr("layers"); | |
521 Map map = getMap(); | |
522 Layer[] layers = map.getLayersByName(name); | |
523 | |
524 if (layers == null || layers.length == 0) { | |
525 GWT.log("Error: Cannot find layer '" + name + "'"); | |
526 return; | |
527 } | |
528 | |
529 map.raiseLayer(layers[0], (newIdx-oldIdx)*-1); | |
530 map.zoomTo(map.getZoom()-1); | |
531 map.zoomTo(map.getZoom()+1); | |
532 } | |
533 }, | |
534 new MapThemePanel.LayerZoomCallback() { | |
535 @Override | |
536 public void onLayerZoom(Theme theme, String extent) { | |
537 Bounds zoomTo = boundsFromString(extent); | |
538 | |
539 if (zoomTo == null) { | |
540 GWT.log("WARNING: No valid bounds for zooming found!"); | |
541 return; | |
542 } | |
543 | |
544 getMap().zoomToExtent(zoomTo); | |
545 } | |
546 } | |
547 ); | |
548 themePanel.addRedrawRequestHandler(this); | |
549 themePanel.addOutputParameterChangeHandler(this); | |
550 c.addChild(themePanel); | |
551 | |
552 return c; | |
553 } | |
554 | |
555 | |
556 private void fireActivateTheme(Theme theme, boolean active) { | |
557 activateTheme(theme, active); | |
558 } | |
559 | |
560 | |
561 protected void activateTheme(Theme theme, boolean active) { | |
562 AttributedTheme at = (AttributedTheme) theme; | |
563 | |
564 String name = at.getAttr("layers"); | |
565 Layer layer = floodMap.getMap().getLayerByName(name); | |
566 | |
567 GWT.log("Set visibility of '" + name + "': " + active); | |
568 | |
569 if (layer != null) { | |
570 layer.setIsVisible(active); | |
571 } | |
572 } | |
573 | |
574 | |
575 protected void saveBarriers() { | |
576 Vector layer = floodMap.getBarrierLayer(); | |
577 | |
578 GeoJSON format = new GeoJSON(); | |
579 String features = format.write(layer.getFeatures()); | |
580 | |
581 DataItem item = new DefaultDataItem( | |
582 BARRIERS_PARAMETER_KEY, BARRIERS_PARAMETER_KEY, features); | |
583 | |
584 Data data = new DefaultData( | |
585 BARRIERS_PARAMETER_KEY, BARRIERS_PARAMETER_KEY, "String", | |
586 new DataItem[] {item} ); | |
587 | |
588 Config config = Config.getInstance(); | |
589 String locale = config.getLocale(); | |
590 | |
591 feedService.go(locale, getArtifact(), new Data[] { data }, | |
592 new AsyncCallback<Artifact>() { | |
593 @Override | |
594 public void onFailure(Throwable caught) { | |
595 GWT.log("Could not save barrier geometries: " + | |
596 caught.getMessage()); | |
597 } | |
598 | |
599 @Override | |
600 public void onSuccess(Artifact artifact) { | |
601 GWT.log("Successfully saved barrier geometries."); | |
602 } | |
603 } | |
604 ); | |
605 } | |
606 | |
607 | |
608 @Override | |
609 public void onTabSelected(TabSelectedEvent tse) { | |
610 if(floodMap == null) { | |
611 return; | |
612 } | |
613 if(this.equals(tse.getTab())) { | |
614 floodMap.activateScaleLine(true); | |
615 } | |
616 else { | |
617 controlPanel.activateMeasureControl(false); | |
618 floodMap.activateScaleLine(false); | |
619 } | |
620 } | |
621 | |
622 public void toogleThemePanel() { | |
623 this.themePanelCanvas.setVisible(!themePanelCanvas.isVisible()); | |
624 | |
625 // Trigger resize event handler | |
626 doLayout(); | |
627 } | |
628 | |
629 | |
630 @Override | |
631 public void onOutputParameterChanged(OutputParameterChangeEvent evt) { | |
632 GWT.log("OutputParameterChanged"); | |
633 controlPanel.updateThemes(getThemePanel().getThemeList()); | |
634 } | |
635 } | |
636 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |