view flys-client/src/main/java/de/intevation/flys/client/client/ui/map/MapOutputTab.java @ 1306:2e57776f77b5

#300 Synchronized the ThemePanel's layer order with the internal order of the Map. flys-client/trunk@2940 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Tue, 11 Oct 2011 13:25:18 +0000
parents 45791d12a1f4
children 8a93fb299e64
line wrap: on
line source
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.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Widget;

import com.smartgwt.client.widgets.Canvas;
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 org.gwtopenmaps.openlayers.client.Bounds;
import org.gwtopenmaps.openlayers.client.Map;
import org.gwtopenmaps.openlayers.client.event.VectorFeatureAddedListener;
import org.gwtopenmaps.openlayers.client.event.VectorFeatureAddedListener.FeatureAddedEvent;
import org.gwtopenmaps.openlayers.client.event.VectorFeatureRemovedListener;
import org.gwtopenmaps.openlayers.client.event.VectorFeatureRemovedListener.FeatureRemovedEvent;
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.Vector;
import org.gwtopenmaps.openlayers.client.layer.WMS;
import org.gwtopenmaps.openlayers.client.layer.WMSParams;
import org.gwtopenmaps.openlayers.client.layer.WMSOptions;

import de.intevation.flys.client.shared.model.Artifact;
import de.intevation.flys.client.shared.model.ArtifactDescription;
import de.intevation.flys.client.shared.model.AttributedTheme;
import de.intevation.flys.client.shared.model.Collection;
import de.intevation.flys.client.shared.model.Data;
import de.intevation.flys.client.shared.model.DataItem;
import de.intevation.flys.client.shared.model.DataList;
import de.intevation.flys.client.shared.model.DefaultData;
import de.intevation.flys.client.shared.model.DefaultDataItem;
import de.intevation.flys.client.shared.model.Theme;
import de.intevation.flys.client.shared.model.ThemeList;
import de.intevation.flys.client.shared.model.OutputMode;

import de.intevation.flys.client.client.Config;
import de.intevation.flys.client.client.services.StepForwardService;
import de.intevation.flys.client.client.services.StepForwardServiceAsync;
import de.intevation.flys.client.client.ui.CollectionView;
import de.intevation.flys.client.client.ui.OutputTab;
import de.intevation.flys.client.client.ui.ThemePanel;


public class MapOutputTab extends OutputTab {

    public static final String DEFAULT_SRID = "4326";

    public static final String BARRIERS_PARAMETER_KEY = "uesk.barriers";

    public static final String WSPLGEN_FACET = "floodmap.wsplgen";


    protected StepForwardServiceAsync feedService =
        GWT.create(StepForwardService.class);

    protected CollectionView parent;

    protected MapToolbar controlPanel;
    protected ThemePanel themePanel;
    protected Widget     mapPanel;

    protected FloodMap floodMap;


    public MapOutputTab(
        String         title,
        Collection     collection,
        OutputMode     mode,
        CollectionView collectionView
    ){
        super(title, collection, mode);
        this.parent = collectionView;

        floodMap = new FloodMap(getSrid(), getMaxExtent());

        initLayout();
        initLayers();
        initBarriers();
    }


    protected void initLayout() {
        VLayout rootLayout = new VLayout();
        rootLayout.setHeight100();
        rootLayout.setWidth100();
        rootLayout.setMembersMargin(2);

        final Canvas  wrapper = new Canvas();
        wrapper.setWidth100();
        wrapper.setHeight100();

        controlPanel = createControlPanel(wrapper);
        mapPanel     = floodMap.getMapWidget();
        Canvas themePanelWrapper = createThemePanel();

        final HorizontalPanel layout = new HorizontalPanel();
        layout.setWidth("99%");
        layout.setHeight("99%");
        layout.add(mapPanel);

        wrapper.addChild(layout);

        HLayout hlayout = new HLayout();
        hlayout.setHeight("*");
        hlayout.setWidth100();
        hlayout.setMembersMargin(2);

        hlayout.addMember(themePanelWrapper);
        hlayout.addMember(wrapper);

        rootLayout.addMember(controlPanel);
        rootLayout.addMember(hlayout);

        wrapper.addResizedHandler(new ResizedHandler() {
            public void onResized(ResizedEvent e) {
                Integer height = wrapper.getHeight();
                Integer width  = wrapper.getWidth();

                height = height * 99 / 100;
                width  = width  * 99 / 100;

                String w = String.valueOf(width) + "px";
                String h = String.valueOf(height) + "px";

                floodMap.setSize(w, h);
            }
        });

        setPane(rootLayout);
    }


    protected void initLayers() {
        ThemeList themeList = themePanel.getThemeList();

        int num = themeList.getThemeCount();

        Map    map           = floodMap.getMap();
        Bounds extent        = null;
        Bounds wsplgenExtent = null;

        for (int i = num; i >= 0; i--) {
            Theme theme = themeList.getThemeAt(i);
            Layer layer = createWMSLayer(theme);

            if (layer == null) {
                continue;
            }

            map.addLayer(layer);

            AttributedTheme at = (AttributedTheme) theme;
            String tmp         = at.getAttr("extent");

            if (WSPLGEN_FACET.equals(at.getFacet())) {
                // if there is a wsplgen layer, we want to zoom to
                // that place initially
                wsplgenExtent = boundsFromString(tmp);
            }

            if (theme.getActive() == 1) {
                if (extent == null) {
                    extent = boundsFromString(tmp);
                }
                else {
                    Bounds b = boundsFromString(tmp);

                    if (b != null) {
                        extent.extend(b);
                    }
                }
            }
        }

        extent = wsplgenExtent != null ? wsplgenExtent : extent;

        GWT.log("Maps initial extent = " + extent);

        map.zoomToExtent(extent  != null
            ? extent
            : new Bounds(-90, -180, 90, 180));
    }


    protected void initBarriers() {
        Vector vector = floodMap.getBarrierLayer();
        vector.addVectorFeatureAddedListener(
            new VectorFeatureAddedListener() {
                public void onFeatureAdded(FeatureAddedEvent e) {
                    saveBarriers();
                }
            }
        );

        vector.addVectorFeatureRemovedListener(
            new VectorFeatureRemovedListener() {
                public void onFeatureRemoved(FeatureRemovedEvent e) {
                    saveBarriers();
                }
            }
        );


        Artifact artifact = getArtifact();

        if (artifact == null) {
            return;
        }

        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;
        }

        GeoJSON reader = new GeoJSON();
        VectorFeature[] features = reader.read(geojson);

        vector.addFeatures(features);
    }


    protected Map getMap() {
        return floodMap.getMap();
    }


    protected String getGeoJSONFromDynamic(ArtifactDescription desc) {
        DataList list = desc.getCurrentData();

        if (list == null) {
            return null;
        }

        List<Data> datas = list.getAll();
        for (Data data: datas) {
            String key = data.getLabel();

            if (key != null && key.equals(BARRIERS_PARAMETER_KEY)) {
                DataItem def = data.getDefault();

                if (def != null) {
                    return def.getStringValue();
                }
            }
        }

        return null;
    }


    protected String getGeoJSONFromStatic(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 Artifact getArtifact() {
        return parent.getArtifact();
    }


    public ThemeList getThemeList() {
        return collection.getThemeList(mode.getName());
    }


    public String getSrid() {
        ThemeList themeList = getThemeList();

        int num = themeList.getThemeCount();

        for (int i = 1; i <= num; i++) {
            AttributedTheme theme = (AttributedTheme) themeList.getThemeAt(i);

            if (theme == null) {
                continue;
            }

            String srid = theme.getAttr("srid");

            if (srid != null && srid.length() > 0) {
                return srid;
            }
        }

        return DEFAULT_SRID;
    }


    public Bounds getMaxExtent() {
        ThemeList themeList = getThemeList();

        int num = themeList.getThemeCount();

        Bounds extent = null;

        for (int i = 1; i <= num; i++) {
            AttributedTheme theme = (AttributedTheme) themeList.getThemeAt(i);

            if (theme == null) {
                continue;
            }

            String tmp = theme.getAttr("extent");

            if (theme.getActive() == 1) {
                if (extent == null) {
                    extent = boundsFromString(tmp);
                }
                else {
                    Bounds b = boundsFromString(tmp);

                    if (b != null) {
                        extent.extend(b);
                    }
                }
            }
        }

        return extent;
    }


    protected Bounds boundsFromString(String bounds) {
        if (bounds == null || bounds.length() == 0) {
            return null;
        }

        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 (NumberFormatException nfe) {}

        return null;
    }


    protected Layer createWMSLayer(Theme theme) {
        if (theme == null) {
            return null;
        }

        AttributedTheme at = (AttributedTheme) theme;

        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;
        }

        //boolean baseLayer = type.equals("floodmap.wmsbackground");

        WMSParams params = new WMSParams();
        params.setLayers(layers);
        params.setFormat("image/png");
        params.setIsTransparent(true);

        WMSOptions opts = new WMSOptions();
        opts.setProjection("EPSG:" + getSrid());
        opts.setSingleTile(true);
        opts.setRatio(1);

        WMS wms = new WMS(desc, url, params, opts);
        wms.setIsVisible(at.getActive() == 1);
        wms.setIsBaseLayer(false);

        return wms;
    }


    protected MapToolbar createControlPanel(Canvas wrapper) {
        return new MapToolbar(floodMap, wrapper, false);
    }


    protected Canvas createThemePanel() {
        Canvas c = new Canvas();
        c.setWidth(200);
        c.setHeight100();
        c.setBorder("1px solid black");

        themePanel = new MapThemePanel(
            collection,
            mode,
            new MapThemePanel.ActivateCallback() {
                public void activate(Theme theme, boolean active) {
                    activateTheme(theme, active);
                }
            },
            new MapThemePanel.ThemeMovedCallback() {
                public void onThemeMoved(Theme theme, int oldIdx, int newIdx) {
                    // this code synchronizes the ThemePanel and the OpenLayers
                    // internal order of layers.
                    String    name = theme.getDescription();
                    Map        map = getMap();
                    Layer[] layers = map.getLayersByName(name);

                    if (layers == null || layers.length == 0) {
                        GWT.log("Error: Cannot find layer '" + name + "'");
                        return;
                    }

                    map.raiseLayer(layers[0], (newIdx-oldIdx)*-1);
                    map.zoomTo(map.getZoom()-1);
                    map.zoomTo(map.getZoom()+1);
                }
            }
        );
        c.addChild(themePanel);

        return c;
    }


    protected void activateTheme(Theme theme, boolean active) {
        String name = theme.getDescription();
        Layer layer = floodMap.getMap().getLayerByName(name);

        if (layer != null) {
            layer.setIsVisible(active);
        }
    }


    protected void saveBarriers() {
        Vector layer = floodMap.getBarrierLayer();

        GeoJSON format   = new GeoJSON();
        String  features = format.write(layer.getFeatures());

        DataItem item = new DefaultDataItem(
            BARRIERS_PARAMETER_KEY, BARRIERS_PARAMETER_KEY, features);

        Data data = new DefaultData(
            BARRIERS_PARAMETER_KEY, BARRIERS_PARAMETER_KEY, "String",
            new DataItem[] {item} );

        Config config       = Config.getInstance();
        final String url    = config.getServerUrl();
        final String locale = config.getLocale();

        feedService.go(url, locale, getArtifact(), new Data[] { data },
            new AsyncCallback<Artifact>() {
                public void onFailure(Throwable caught) {
                    GWT.log("Could not save barrier geometries: " +
                        caught.getMessage());
                }

                public void onSuccess(Artifact artifact) {
                    GWT.log("Successfully saved barrier geometries.");
                }
            }
        );
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org