it.bz.tis.sasabus.html5.shared.ui.map.SASAbusMap.java Source code

Java tutorial

Introduction

Here is the source code for it.bz.tis.sasabus.html5.shared.ui.map.SASAbusMap.java

Source

/*
SASAbusHTML5 - HTML5 App for SASA bus
    
Copyright (C) 2013 TIS Innovation Park - Bolzano/Bozen - Italy
Copyright (C) 2013-2014 Davide Montesin <d@vide.bz> - Bolzano/Bozen - Italy
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
    
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package it.bz.tis.sasabus.html5.shared.ui.map;

import it.bz.tis.sasabus.backend.shared.Area;
import it.bz.tis.sasabus.backend.shared.AreaList;
import it.bz.tis.sasabus.backend.shared.BusLine;
import it.bz.tis.sasabus.backend.shared.BusStation;
import it.bz.tis.sasabus.backend.shared.BusStop;
import it.bz.tis.sasabus.backend.shared.BusTrip;
import it.bz.tis.sasabus.backend.shared.BusTripStop;
import it.bz.tis.sasabus.html5.client.SASAbusHTML5;
import it.bz.tis.sasabus.html5.shared.BusStationCustomViewAndI18N;
import it.bz.tis.sasabus.html5.shared.data.Parking;
import it.bz.tis.sasabus.html5.shared.data.TrainStation;
import it.bz.tis.sasabus.html5.shared.ui.AreaPanel;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.Set;
import bz.davide.dmweb.client.leaflet.Circle;
import bz.davide.dmweb.client.leaflet.EventListener;
import bz.davide.dmweb.client.leaflet.Icon;
import bz.davide.dmweb.client.leaflet.IconOptions;
import bz.davide.dmweb.client.leaflet.LatLng;
import bz.davide.dmweb.client.leaflet.LatLngBounds;
import bz.davide.dmweb.client.leaflet.Layer;
import bz.davide.dmweb.client.leaflet.Map;
import bz.davide.dmweb.client.leaflet.Marker;
import bz.davide.dmweb.client.leaflet.MarkerOptions;
import bz.davide.dmweb.client.leaflet.Path;
import bz.davide.dmweb.client.leaflet.PathOptions;
import bz.davide.dmweb.client.leaflet.Polygon;
import bz.davide.dmweb.client.leaflet.Polyline;
import bz.davide.dmweb.shared.view.ButtonView;
import bz.davide.dmweb.shared.view.DMClickEvent;
import bz.davide.dmweb.shared.view.DMClickHandler;
import bz.davide.dmweb.shared.view.DMHashNavigationPanel;
import bz.davide.dmweb.shared.view.DivView;
import bz.davide.dmweb.shared.view.ImgView;
import com.google.gwt.user.client.Timer;

/**
 * @author Davide Montesin <d@vide.bz>
 */
public class SASAbusMap extends DivView {

    final static String[] COLORS = new String[] { "#FF0000", "#0000FF", "#FFFF00" };

    transient Map leafletMap;
    transient ArrayList<Layer> baseLayers = new ArrayList<Layer>();
    transient IdentityHashMap<BusStation, Void> highlightedBusStations = new IdentityHashMap<BusStation, Void>();
    transient boolean mapOpen = false;

    DMHashNavigationPanel navigationPanel;

    DivView controls;
    DivView mapDiv;
    //DMLabel                                            zoomLevel;
    //DMLabel                                            latLonValues;

    it.bz.tis.sasabus.html5.shared.ui.icon.Icon gpsIcon;

    transient IdentityHashMap<Area, Polygon> polygonOfAreaCache = new IdentityHashMap<Area, Polygon>();
    transient IdentityHashMap<Area, ArrayList<LatLng>> boundsOfAreaCache = new IdentityHashMap<Area, ArrayList<LatLng>>();
    transient IdentityHashMap<BusStation, Path[]> shapesOfBusStationCache = new IdentityHashMap<BusStation, Path[]>();
    transient IdentityHashMap<BusStation, Path[]> shapesOfHighlightedBusStationCache = new IdentityHashMap<BusStation, Path[]>();

    AreaList areaList;

    ButtonView close;

    DivView overwievMap;

    BusStationCustomViewAndI18N custom;

    public SASAbusMap(BusStationCustomViewAndI18N custom) {
        super("map");

        this.custom = custom;

        this.close = new ButtonView("X");

        this.overwievMap = new DivView("overview-map");
        ImgView cartina = new ImgView("../images/Cartina.png");
        this.overwievMap.appendChild(cartina);
        this.appendChild(this.overwievMap);

        this.leafletMap = null;

        this.controls = new DivView("controls");
        this.appendChild(this.controls);

        this.mapDiv = new DivView("mapdiv");
        this.appendChild(this.mapDiv);

        this.controls.appendChild(this.close);
        this.close.setStyleName("close");

        this.gpsIcon = it.bz.tis.sasabus.html5.shared.ui.icon.Icon.newGpsIcon();
        this.controls.appendChild(this.gpsIcon);

        //this.zoomLevel = new DMLabel("");
        //this.controls.add(this.zoomLevel);

        //this.latLonValues = new DMLabel("");
        //this.controls.add(this.latLonValues);

    }

    protected SASAbusMap() {
    }

    public void showOverviewMap(boolean show) {
        if (show) {
            this.overwievMap.addStyleName("show");
        } else {
            this.overwievMap.removeStyleName("show");
        }
    }

    public Map getLeafletMap() {
        return this.leafletMap;
    }

    public void setNavigationPanel(DMHashNavigationPanel navigationPanel) {
        this.navigationPanel = navigationPanel;
    }

    public void start(final AreaList areaList) {
        this.areaList = areaList;

        this.initAreasPolygon(areaList);
        this.initBusStationsShapes(areaList);
        this.addAttachHandler(new SASAbusMapAttachHandler(this));
        this.close.addClickHandler(new DMClickHandler() {
            @Override
            public void onClick(DMClickEvent event) {
                SASAbusMap.this.hide();
            }
        });

        // Add train stations

        for (final TrainStation trainStation : TrainStation.list) {
            IconOptions iconOptions = new IconOptions();
            iconOptions.setIconUrl("../images/layout/train-icon-map.png");
            Icon icon = new Icon(iconOptions);
            MarkerOptions markerOptions = new MarkerOptions();
            markerOptions.setIcon(icon);
            final LatLng latLng = new LatLng(trainStation.getLat(), trainStation.getLon());
            Marker trainStationMarker = new Marker(latLng, markerOptions);

            trainStationMarker.addClickEventListener(new EventListener() {
                @Override
                public void onEvent() {
                    TrainStationPopup trainStationPopup = new TrainStationPopup(trainStation,
                            SASAbusMap.this.navigationPanel, areaList, SASAbusMap.this, SASAbusMap.this.custom);
                    SASAbusMap.this.leafletMap.openPopup(trainStationPopup.getElement(), latLng);
                    trainStationPopup.init();
                }
            });
            this.leafletMap.addLayer(trainStationMarker);

        }

        // Add parkings

        for (final Parking parking : Parking.list) {
            IconOptions iconOptions = new IconOptions();
            iconOptions.setIconUrl("../images/layout/park-icon-map.png");
            Icon icon = new Icon(iconOptions);
            MarkerOptions markerOptions = new MarkerOptions();
            markerOptions.setIcon(icon);
            final LatLng latLng = new LatLng(parking.getLat(), parking.getLon());
            Marker parkMarker = new Marker(latLng, markerOptions);
            this.leafletMap.addLayer(parkMarker);
            parkMarker.addClickEventListener(new EventListener() {
                @Override
                public void onEvent() {
                    ParkingPopup parkingPopup = new ParkingPopup(parking, SASAbusMap.this.custom.getI18n());
                    SASAbusMap.this.leafletMap.openPopup(parkingPopup.getElement(), latLng);
                    parkingPopup.init(SASAbusMap.this.custom.getI18n());
                }
            });
        }
    }

    private void initBusStationsShapes(AreaList areaList) {

        PathOptions pathOptions = new PathOptions();
        pathOptions.setFillColor("red");
        pathOptions.setColor("#555555");
        pathOptions.setFillOpacity(.8);

        PathOptions pathOptions2 = new PathOptions();
        pathOptions2.setFillColor("yellow");
        pathOptions2.setColor("red");
        pathOptions2.setFillOpacity(.8);

        for (final BusStation busStation : areaList.getBusStations()) {
            ArrayList<Path> shapes = new ArrayList<Path>();
            ArrayList<Path> hightlightedShapes = new ArrayList<Path>();

            BusStop[] busStops = busStation.getBusStops();
            LatLng lastLatLng = null;
            for (int i = 0; i < busStops.length; i++) {
                BusStop busStop = busStops[i];
                LatLng latLng = new LatLng(busStop.getLat(), busStop.getLon());

                Circle circle = new Circle(latLng, 10, pathOptions);
                shapes.add(circle);

                Circle circle2 = new Circle(latLng, 10, pathOptions2);
                hightlightedShapes.add(circle2);

                if (i > 0) {
                    LatLng[] vertexs = new LatLng[2];
                    vertexs[0] = lastLatLng;
                    vertexs[1] = latLng;
                    Polyline polyline = new Polyline(vertexs, pathOptions);
                    shapes.add(polyline);

                    polyline.addClickEventListener(new EventListener() {
                        @Override
                        public void onEvent() {
                            SASAbusMap.this.showBusStationPopup(busStation);
                        }
                    });

                }
                lastLatLng = latLng;

                circle.addClickEventListener(new EventListener() {
                    @Override
                    public void onEvent() {
                        SASAbusMap.this.showBusStationPopup(busStation);
                    }
                });
                circle2.addClickEventListener(new EventListener() {
                    @Override
                    public void onEvent() {
                        SASAbusMap.this.showBusStationPopup(busStation);
                    }
                });

            }
            this.shapesOfBusStationCache.put(busStation, shapes.toArray(new Path[0]));
            this.shapesOfHighlightedBusStationCache.put(busStation, hightlightedShapes.toArray(new Path[0]));
        }
    }

    private void showBusStationPopup(final BusStation busStation) {
        BusStop busStop = busStation.getBusStops()[0];
        LatLng latLng = new LatLng(busStop.getLat(), busStop.getLon());
        BusStationPopup mapPopup = new BusStationPopup(busStation, this.navigationPanel, this, this.areaList,
                this.custom);
        this.leafletMap.openPopup(mapPopup.getElement(), latLng);
        mapPopup.init();
        SASAbusHTML5.trackUsage("map-popup", busStation.getId());

    }

    private void initAreasPolygon(final AreaList areaList) {
        for (final Area area : areaList.getAreas()) {
            String color = COLORS[area.getId() - 1];

            PathOptions polylineOptions = new PathOptions();
            polylineOptions.setFillColor(color);
            polylineOptions.setColor(color);

            ArrayList<LatLng> bounds = new ArrayList<LatLng>();

            LatLng[] latLngs = new LatLng[area.getBounds().length];
            for (int i = 0; i < latLngs.length; i++) {
                latLngs[i] = new LatLng(area.getBounds()[i].getLat(), area.getBounds()[i].getLon());
                bounds.add(latLngs[i]);
            }
            Polygon polygon = new Polygon(latLngs, polylineOptions);

            polygon.addClickEventListener(new EventListener() {
                @Override
                public void onEvent() {
                    SASAbusMap.this.navigationPanel.newPage(new AreaPanel(area, SASAbusMap.this.navigationPanel,
                            areaList, SASAbusMap.this, SASAbusMap.this.custom));

                }
            });

            this.polygonOfAreaCache.put(area, polygon);
            this.boundsOfAreaCache.put(area, bounds);
        }
    }

    public void highlightFitBusLine(BusLine busLine) {
        this.highlightedBusStations.clear();

        ArrayList<LatLng> bounds = new ArrayList<LatLng>();
        for (BusStation busStation : busLine.getBusStations()) {
            this.highlightedBusStations.put(busStation, null);
            BusStop busStop = busStation.getBusStops()[0];
            LatLng latLng = new LatLng(busStop.getLat(), busStop.getLon());
            bounds.add(latLng);
        }
        this.leafletMap.fitBounds(new LatLngBounds(bounds.toArray(new LatLng[0])));
        this.refreshBaseLayerAfterZoomLevelAndPosition();
    }

    public void highlightFitBusStation(BusStation busStation) {
        this.highlightedBusStations.clear();
        this.highlightedBusStations.put(busStation, null);
        BusStop busStop = busStation.getBusStops()[0];
        LatLng latLng = new LatLng(busStop.getLat(), busStop.getLon());
        this.leafletMap.setView(latLng, 16);
        this.refreshBaseLayerAfterZoomLevelAndPosition();

    }

    public void highlightFitBusTrip(BusTrip busTrip, int index) {
        this.highlightedBusStations.clear();
        this.leafletMap.closePopup();

        BusTripStop[] busTripStops = busTrip.getBusTripStops();
        ArrayList<LatLng> bounds = new ArrayList<LatLng>();
        for (int i = index; i < busTripStops.length; i++) {
            BusTripStop busTripStop = busTripStops[i];
            BusStop busStop = this.areaList.findBusStopById(busTripStop.getBusStopId());
            BusStation busStation = busStop.getBusStation();
            this.highlightedBusStations.put(busStation, null);
            LatLng latLng = new LatLng(busStop.getLat(), busStop.getLon());
            bounds.add(latLng);

        }
        this.leafletMap.fitBounds(new LatLngBounds(bounds.toArray(new LatLng[0])));
        this.refreshBaseLayerAfterZoomLevelAndPosition();
    }

    public void fitAllAreas() {
        this.highlightedBusStations.clear();
        this.leafletMap.closePopup();

        ArrayList<LatLng> bounds = new ArrayList<LatLng>();
        for (Area area : this.polygonOfAreaCache.keySet()) {
            ArrayList<LatLng> areaBounds = this.boundsOfAreaCache.get(area);
            bounds.addAll(areaBounds);
        }

        this.leafletMap.fitBounds(new LatLngBounds(bounds.toArray(new LatLng[0])));
        this.refreshBaseLayerAfterZoomLevelAndPosition();

    }

    public void fitArea(Area area) {
        this.highlightedBusStations.clear();
        this.leafletMap.closePopup();

        this.leafletMap.fitBounds(new LatLngBounds(this.boundsOfAreaCache.get(area).toArray(new LatLng[0])));
        this.refreshBaseLayerAfterZoomLevelAndPosition();

    }

    void refreshBaseLayerAfterZoomLevelAndPosition() {

        int zoom = this.leafletMap.getZoom();
        //SASAbusMap.this.zoomLevel.setText("Zoom level: " + zoom);
        LatLng center = this.leafletMap.getCenter();
        //this.latLonValues.setText("lat,lon: " + (float) center.getLat() + "," + (float) center.getLng());

        // Remove base layers
        for (Layer base : this.baseLayers) {
            this.leafletMap.removeLayer(base);
        }

        if (zoom >= 15) {
            Set<BusStation> busStations = this.shapesOfBusStationCache.keySet();
            for (BusStation busStation : busStations) {
                double radius1 = busStation.getBusStops()[0].getLat() - center.getLat();
                double radius2 = busStation.getBusStops()[0].getLon() - center.getLng();
                double radius = radius1 * radius1 + radius2 * radius2;
                // Don't show here a bustation if highlighted
                if (!this.highlightedBusStations.containsKey(busStation)) {
                    if (radius < 0.0005d) {
                        for (Path path : this.shapesOfBusStationCache.get(busStation)) {
                            this.baseLayers.add(path);
                            this.leafletMap.addLayer(path);
                        }
                    }
                }
            }
        } else {
            if (this.highlightedBusStations.size() == 0) {
                for (Polygon polygon : this.polygonOfAreaCache.values()) {
                    this.baseLayers.add(polygon);
                    this.leafletMap.addLayer(polygon);
                }
            }
        }
        for (BusStation busStation : this.highlightedBusStations.keySet()) {
            for (Path path : this.shapesOfBusStationCache.get(busStation)) {
                this.baseLayers.add(path);
                this.leafletMap.addLayer(path);
            }
            for (Path path : this.shapesOfHighlightedBusStationCache.get(busStation)) {
                this.baseLayers.add(path);
                this.leafletMap.addLayer(path);
            }
        }
    }

    public void toggle() {
        this.addStyleName("anim-left");
        if (this.mapOpen) {
            this.removeStyleName("show");
        } else {
            this.addStyleName("show");
        }
        this.mapOpen = !this.mapOpen;
        Timer removeAnim = new Timer() {
            @Override
            public void run() {
                SASAbusMap.this.removeStyleName("anim-left");
            }
        };
        removeAnim.schedule(1000);
    }

    public void show() {
        if (!this.mapOpen) {
            this.toggle();
        }
    }

    public void hide() {
        if (this.mapOpen) {
            this.toggle();
        }
    }

}