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 :

http://dive4elements.wald.intevation.org