Java tutorial
/* 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(); } } }