de.gmino.geobase.client.map.OpenLayersSmartLayer.java Source code

Java tutorial

Introduction

Here is the source code for de.gmino.geobase.client.map.OpenLayersSmartLayer.java

Source

package de.gmino.geobase.client.map;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.core.client.UnsafeNativeLong;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;

import de.gmino.geobase.shared.domain.PoiInterface;
import de.gmino.geobase.shared.map.IconRenderer;
import de.gmino.geobase.shared.map.Marker;
import de.gmino.geobase.shared.map.PopupCreator;
import de.gmino.geobase.shared.map.SmartLayer;
import de.gmino.meva.shared.Entity;
import de.gmino.meva.shared.Log;
import de.gmino.meva.shared.TypeName;

public class OpenLayersSmartLayer implements SmartLayer<Canvas, Widget>, OpenLayersLayer {

    private static int zoomThreshold = 12;
    private String name;
    private JavaScriptObject vectorLayerJso;
    private JavaScriptObject popupLayerJso;
    private Set<Marker> markers;
    private OpenLayersMapView mapView;
    private TreeMap<TypeName, GwtIconRenderer> rendererMap;
    private TreeMap<TypeName, GwtPopupCreator> popupCreatorMap;
    private TreeMap<Long, PoiInterface> pois;
    private TreeMap<PoiInterface, JavaScriptObject> poiJsos;
    private TreeMap<PoiInterface, DivElement> poiTooltipDivs;
    private Widget currentPopup;
    private int currentZoomLevel;

    public OpenLayersSmartLayer(String name, OpenLayersMapView mapView, int zoomThreshold) {
        this.zoomThreshold = zoomThreshold;
        this.name = name;
        this.mapView = mapView;
        this.rendererMap = new TreeMap<TypeName, GwtIconRenderer>();
        this.popupCreatorMap = new TreeMap<TypeName, GwtPopupCreator>();
        this.pois = new TreeMap<Long, PoiInterface>();
        this.poiJsos = new TreeMap<PoiInterface, JavaScriptObject>();
        this.poiTooltipDivs = new TreeMap<PoiInterface, DivElement>();
        markers = new TreeSet<Marker>();
        vectorLayerJso = nCreateVectorLayer(name, mapView.getMapJso());
        popupLayerJso = nCreatePopupLayer(name);
        mapView.addLayerJso(vectorLayerJso);
        mapView.addLayerJso(popupLayerJso);
        mapView.addLayer(this);
    }

    public void selectedPoi(long poiId) {
        if (currentZoomLevel <= zoomThreshold)
            return;
        PoiInterface poi = pois.get(poiId);
        if (poiTooltipDivs.containsKey(poi)) {
            System.out.println("Tooltip already there");
            return;
        }
        Entity oAsEntity = (Entity) poi;
        GwtPopupCreator<PoiInterface> creator = popupCreatorMap.get(oAsEntity.getType());
        if (creator == null)
            throw new RuntimeException("No PopupCreator for tyoe " + oAsEntity.getType().toString());
        Widget widget = creator.createTooltip(poi);
        DivElement div = mapView.createPopup(poi.getLocation(), poi.getId() + "", 1, 1);
        poiTooltipDivs.put(poi, div);
        HTMLPanel.wrap(div).add(widget);
    }

    public void deselectedPoi(long poiId) {
        PoiInterface poi = pois.get(poiId);
        DivElement div = poiTooltipDivs.get(poi);
        if (div == null) {
            System.out.println("Tooltip already gone");
            return;
        }
        div.removeFromParent();
        poiTooltipDivs.remove(poi);
    }

    public void clickedPoi(long poiId) {
        System.out.println("Clicked POI, entering try-block.");
        try {
            final PoiInterface poi = pois.get(poiId);
            Entity oAsEntity = (Entity) poi;
            GwtPopupCreator<PoiInterface> creator = popupCreatorMap.get(oAsEntity.getType());
            if (creator == null)
                throw new RuntimeException("No PopupCreator for tyoe " + oAsEntity.getType().toString());
            final Widget widget = creator.createPopup(poi);

            if (currentPopup != null) {
                currentPopup.removeFromParent();
                currentPopup = null;
            }

            // TODO: This div will never be removed, but because of its size it
            // doesn't really matter.
            DivElement div = mapView.createPopup(poi.getLocation(), poi.getId() + "", 1, 1);
            HTMLPanel.wrap(div).add(widget);

            currentPopup = widget;

            // the popup width is not always computeted correctly the first time and simple deferring doesn't help. Therefore, we ask for the width until it seems about right before using ist.
            Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
                @Override
                public boolean execute() {
                    int offsetWidth = widget.getOffsetWidth();
                    int offsetHeight = widget.getOffsetHeight();

                    if (offsetWidth < 160)
                        return true;

                    mapView.panRectIntoMap(poi.getLocation(), offsetWidth, offsetHeight, 22, 38, true);

                    return false;
                }
            }, 100);
            System.out.println("Clicked POI, finished try-block.");
        } catch (Throwable e) {
            Log.exception("Handling clickedPoi", e);
            System.err.println("#####");
            e.printStackTrace();
        }
    }

    // TODO: This is a marker layer, not a vector layer
    @UnsafeNativeLong
    private native JavaScriptObject nCreateVectorLayer(String name, JavaScriptObject mapJso)
    /*-{
       var layer = new $wnd.OpenLayers.Layer.Vector(name);
        
       var that = this;
        
       function selected(evt) {
     that.@de.gmino.geobase.client.map.OpenLayersSmartLayer::selectedPoi(J)(evt.feature.poiId);
       }
       layer.events.register("featureselected", layer, selected);
       function deselected(evt) {
     that.@de.gmino.geobase.client.map.OpenLayersSmartLayer::deselectedPoi(J)(evt.feature.poiId);
       }
       layer.events.register("featureunselected", layer, deselected);
        
       var control = new $wnd.OpenLayers.Control.SelectFeature(
        layer,
        {
           hover : true,
           highlightOnly : false,
           callbacks : {
              click : function(feat) {
                 that.@de.gmino.geobase.client.map.OpenLayersSmartLayer::clickedPoi(J)(feat.poiId);
              }
           }
        });
       mapJso.addControl(control);
       control.activate();
        
       return layer;
    }-*/;

    private native JavaScriptObject nCreatePopupLayer(String name)
    /*-{
       var layer = new $wnd.OpenLayers.Layer(name);
       return layer;
    }-*/;

    @Override
    public void addMarkerIconRenderer(TypeName type, IconRenderer<? extends PoiInterface, Canvas> renderer) {
        rendererMap.put(type, (GwtIconRenderer<? extends PoiInterface>) renderer);
    }

    @Override
    public void addMarkerPopupCreator(TypeName type, PopupCreator<? extends PoiInterface, Widget> creator) {
        popupCreatorMap.put(type, (GwtPopupCreator<? extends PoiInterface>) creator);
    }

    @Override
    public void addPoi(PoiInterface o) {
        if (pois.put(o.getId(), o) == null) {
            GwtIconRenderer<? super PoiInterface> renderer = getRendererForPoi(o);
            String iconUrl;
            int width, height;
            if (currentZoomLevel > zoomThreshold) {
                iconUrl = renderer.getIconUrl(o);
                width = renderer.getWidth(o);
                height = renderer.getHeight(o);
            } else {
                iconUrl = renderer.getSmallIconUrl(o);
                width = 32;
                height = 32;
            }
            JavaScriptObject jso = nAddMarker(iconUrl, o.getLocation().getLatitude(),
                    o.getLocation().getLongitude(), mapView.getMapJso(), o.getId(), width, height);
            poiJsos.put(o, jso);
        }
    }

    public GwtIconRenderer<? super PoiInterface> getRendererForPoi(PoiInterface o) {
        Entity oAsEntity = (Entity) o;
        GwtIconRenderer<? super PoiInterface> renderer = rendererMap.get(oAsEntity.getType());
        if (renderer == null)
            throw new RuntimeException("No IconRenderer defined for " + oAsEntity.getType());
        return renderer;
    }

    @UnsafeNativeLong
    private native JavaScriptObject nAddMarker(String iconUrl, double latitude, double longitude,
            JavaScriptObject mapJso, long poiId, int width, int height)
    /*-{
       var layer = this.@de.gmino.geobase.client.map.OpenLayersSmartLayer::vectorLayerJso;
        
       var style_mark = $wnd.OpenLayers.Util.extend({},
        $wnd.OpenLayers.Feature.Vector.style['default']);
        
       // if graphicWidth and graphicHeight are both set, the aspect ratio
       // of the image will be ignored
       style_mark.graphicWidth = width;
       style_mark.graphicHeight = height;
       style_mark.graphicXOffset = -(style_mark.graphicWidth / 2);
       style_mark.graphicYOffset = -0.93 * (style_mark.graphicHeight);
       style_mark.externalGraphic = iconUrl;
       style_mark.graphicOpacity = 1;
        
       var point = new $wnd.OpenLayers.Geometry.Point(longitude, latitude);
       // var proj = new $wnd.OpenLayers.Projection("EPSG:4326");
       // point = point.transform(proj, mapJso.getProjectionObject());
       point = point.transform(mapJso.pro1, mapJso.pro2);
       var pointFeature = new $wnd.OpenLayers.Feature.Vector(point, null,
        style_mark);
       pointFeature.poiId = poiId;
       layer.addFeatures([ pointFeature ]);
       return pointFeature;
    }-*/;

    @Override
    public void removePoi(PoiInterface o) {
        if (pois.remove(o.getId()) != null) {
            JavaScriptObject jso = poiJsos.get(o);
            if (jso != null) {
                nRemoveFeature(jso);
            }
        }
    }

    @Override
    public void updatePoi(PoiInterface o) {
        removePoi(o);
        addPoi(o);
    }

    private native void nRemoveFeature(JavaScriptObject featureJso)
    /*-{
       var layer = this.@de.gmino.geobase.client.map.OpenLayersSmartLayer::vectorLayerJso;
       layer.removeFeatures([ featureJso ]);
    }-*/;

    public OpenLayersMapView getMapView() {
        return mapView;
    }

    public JavaScriptObject getLayerJso() {
        return vectorLayerJso;
    }

    public void setZoomLevel(int newZoomLevel) {
        int previousZoomLevel = currentZoomLevel;
        currentZoomLevel = newZoomLevel;
        if ((previousZoomLevel <= zoomThreshold && newZoomLevel > zoomThreshold)
                || (newZoomLevel <= zoomThreshold && previousZoomLevel > zoomThreshold)) {
            Collection<PoiInterface> poisCopy = new ArrayList<PoiInterface>(pois.values());
            for (PoiInterface poi : poisCopy)
                updatePoi(poi);
        }
    }

    public void setzoomThreshold(int Treshold) {
        zoomThreshold = Treshold;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public double getMinZoom() {
        return 0;
    }

    @Override
    public double getMaxZoom() {
        return 100;
    }

    @Override
    public String getLicenseText() {
        return "No License Text";
    }

    @Override
    public void setVisibility(boolean visible) {
        // TODO Auto-generated method stub

    }

    @Override
    public void setOpacity(double opacity) {
        // TODO Auto-generated method stub

    }

    @Override
    public JavaScriptObject getJso() {
        return vectorLayerJso;
    }
}