Advertisement
bwrega

DirectionsRenderer waypoint remover

Aug 15th, 2013
695
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.93 KB | None | 0 0
  1. package pl.niziol.gwt.lib;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import com.google.gwt.core.client.JsArray;
  7. import com.google.gwt.dom.client.NativeEvent;
  8. import com.google.gwt.event.dom.client.ClickEvent;
  9. import com.google.gwt.event.dom.client.ClickHandler;
  10. import com.google.gwt.event.dom.client.MouseUpEvent;
  11. import com.google.gwt.event.dom.client.MouseUpHandler;
  12. import com.google.gwt.event.shared.HandlerRegistration;
  13. import com.google.gwt.maps.client.MapWidget;
  14. import com.google.gwt.maps.client.base.LatLng;
  15. import com.google.gwt.maps.client.base.Point;
  16. import com.google.gwt.maps.client.overlays.MapCanvasProjection;
  17. import com.google.gwt.maps.client.overlays.OverlayView;
  18. import com.google.gwt.maps.client.overlays.overlayhandlers.OverlayViewMethods;
  19. import com.google.gwt.maps.client.overlays.overlayhandlers.OverlayViewOnAddHandler;
  20. import com.google.gwt.maps.client.overlays.overlayhandlers.OverlayViewOnDrawHandler;
  21. import com.google.gwt.maps.client.overlays.overlayhandlers.OverlayViewOnRemoveHandler;
  22. import com.google.gwt.maps.client.services.DirectionsLeg;
  23. import com.google.gwt.maps.client.services.DirectionsRenderer;
  24. import com.google.gwt.maps.client.services.DirectionsRequest;
  25. import com.google.gwt.maps.client.services.DirectionsResult;
  26. import com.google.gwt.maps.client.services.DirectionsResultHandler;
  27. import com.google.gwt.maps.client.services.DirectionsRoute;
  28. import com.google.gwt.maps.client.services.DirectionsService;
  29. import com.google.gwt.maps.client.services.DirectionsStatus;
  30. import com.google.gwt.maps.client.services.DirectionsWaypoint;
  31. import com.google.gwt.user.client.Event;
  32. import com.google.gwt.user.client.Window;
  33. import com.google.gwt.user.client.ui.Button;
  34. import com.google.gwt.user.client.ui.PopupPanel;
  35. import com.google.gwt.user.client.ui.Widget;
  36. /**
  37.  * Allows removing waypoints plotted by user on DirectionsRenderer.
  38.  * To remove a waypoint: right-click on it and select "Delete this waypoint" from a pop-up menu.
  39.  * After using call dispose() method.
  40.  * @author Bartlomiej Wrega, [email protected]
  41.  *
  42.  */
  43. public class WaipointRemover {
  44.     static public final double WAYPOINT_ICON_RADIUS = 5.5d;//size of waypoint icon on the map
  45.     private final DirectionsRenderer directionsRenderer;
  46.     private DirectionsRequest originalRequest;
  47.     private MapCanvasProjection projection;
  48.     private MapWidget mapWidget;
  49.     /**
  50.      *
  51.      * @param mapWidget
  52.      * @param directionsRenderer
  53.      * @param originalRequest used to get request options for next queries
  54.      */
  55.     public WaipointRemover(MapWidget mapWidget,
  56.             DirectionsRenderer directionsRenderer,
  57.             DirectionsRequest originalRequest) {
  58.         this.directionsRenderer = directionsRenderer;
  59.         this.mapWidget = mapWidget;
  60.         setOriginalRequest(originalRequest);
  61.         initProjection();
  62.         initClicking();
  63.     }
  64.    
  65.     /**
  66.      * Cleans up.
  67.      */
  68.     public void dispose(){
  69.         if (mouseUpHandler!=null){
  70.             mouseUpHandler.removeHandler();
  71.             mouseUpHandler = null;
  72.         }
  73.     }
  74.  
  75.     private HandlerRegistration mouseUpHandler = null;
  76.     private void initClicking() {
  77.         Widget widgetToGetClicked = mapWidget;// directionsRenderer.getMap() doesn't work for some reason
  78.         //mouse click event doesn't work for right mouse button (tested on IE9),
  79.         //so I used MouseUpEvent instead
  80.         mouseUpHandler = widgetToGetClicked.addHandler(new MouseUpHandler() {
  81.             public void onMouseUp(MouseUpEvent event) {
  82.                 if (event.getNativeButton() != NativeEvent.BUTTON_RIGHT) {
  83.                     return;
  84.                 }
  85.  
  86.                 int x = event.getX();
  87.                 int y = event.getY();
  88.                 int clickedWaypoint = getClickedWaypointIndex(x, y);
  89.                 if (clickedWaypoint >= 0) {
  90.                     PopupPanel popupPanel = new PopupPanel(true);
  91.                     popupPanel.setWidget(new RemoveWaypointButton(
  92.                             clickedWaypoint,popupPanel));
  93.                     popupPanel.setAnimationEnabled(true);
  94.                     popupPanel.setPopupPosition(event.getClientX(),
  95.                             event.getClientY());
  96.                     popupPanel.show();
  97.                 }
  98.             }
  99.         }, MouseUpEvent.getType());
  100.         widgetToGetClicked.sinkEvents(Event.ONMOUSEUP);
  101.     }
  102.  
  103.     /**
  104.      * Uses only non-stopover waypoints (mark as circles on the path).
  105.      *
  106.      * @param x,y coordinates relative to left-top corner of map area
  107.      * @return -1 if no waypoint was clicked
  108.      */
  109.     private int getClickedWaypointIndex(double x, double y) {
  110.         List<LatLng> waypoints = getAllViaWaypoints();
  111.         double minimalDistanceSquare = WAYPOINT_ICON_RADIUS
  112.                 * WAYPOINT_ICON_RADIUS;// square to avoid sqrt
  113.         int minimalIndex = -1;// index of the closest waypoint
  114.         for (int i = 0; i < waypoints.size(); i++) {
  115.             LatLng next = waypoints.get(i);
  116.             Point waypointPoint = projection.fromLatLngToContainerPixel(next);
  117.             double distanceSquare = Math.pow(x - waypointPoint.getX(), 2.0d)
  118.                     + Math.pow(y - waypointPoint.getY(), 2.0d);
  119.             if (distanceSquare <= minimalDistanceSquare) {
  120.                 minimalDistanceSquare = distanceSquare;
  121.                 minimalIndex = i;
  122.             }
  123.         }
  124.         return minimalIndex;
  125.     }
  126.     /**
  127.      * @return all the not-stopover waypoints from current result  
  128.      */
  129.     private List<LatLng> getAllViaWaypoints() {
  130.         List<LatLng> ret = new ArrayList<LatLng>();
  131.         DirectionsResult currentResult = directionsRenderer.getDirections();
  132.         DirectionsRoute route = currentResult.getRoutes().get(
  133.                 directionsRenderer.getRouteIndex());
  134.         for (int l = 0; l < route.getLegs().length(); l++) {
  135.             DirectionsLeg leg = route.getLegs().get(l);
  136.             for (int w = 0; w < leg.getVia_Waypoints().length(); w++) {
  137.                 LatLng viaWaypoint = leg.getVia_Waypoints().get(w);
  138.                 ret.add(viaWaypoint);
  139.             }
  140.         }
  141.         return ret;
  142.     }
  143.  
  144.     private void deleteNthWaypoint(int waypointIndex) {
  145.         DirectionsResult currentResult = directionsRenderer.getDirections();
  146.         DirectionsRequest newRequest = cloneOriginalRequest();
  147.         DirectionsRoute route = currentResult.getRoutes().get(
  148.                 directionsRenderer.getRouteIndex());
  149.         newRequest.setOrigin(route.getLegs().get(0).getStart_Location());
  150.         newRequest.setDestination(route.getLegs()
  151.                 .get(route.getLegs().length() - 1 // last leg
  152.                 ).getEnd_Location());
  153.         JsArray<DirectionsWaypoint> waypoints = JsArray.createArray().cast();
  154.         int waypointCounter = 0; // counts not-stopover waypoints
  155.         //copies all waypoints to newRequest, except for the one that needs to be deleted
  156.         for (int l = 0; l < route.getLegs().length(); l++) {
  157.             DirectionsLeg leg = route.getLegs().get(l);
  158.             if (l != 0) {// for all but first leg add start location as stopover
  159.                             // waypoint
  160.                 DirectionsWaypoint waypoint = DirectionsWaypoint.newInstance();
  161.                 waypoint.setLocation(leg.getStart_Location());
  162.                 waypoint.setStopOver(true);
  163.                 waypoints.push(waypoint);
  164.             }
  165.             for (int w = 0; w < leg.getVia_Waypoints().length(); w++) {
  166.                 if (waypointIndex != (waypointCounter++)) {
  167.                     LatLng viaWaypoint = leg.getVia_Waypoints().get(w);
  168.                     DirectionsWaypoint waypoint = DirectionsWaypoint
  169.                             .newInstance();
  170.                     waypoint.setLocation(viaWaypoint);
  171.                     waypoint.setStopOver(false);
  172.                     waypoints.push(waypoint);
  173.                 }
  174.             }
  175.         }
  176.         newRequest.setWaypoints(waypoints);
  177.         directionsService.route(newRequest, new DirectionsResultHandler() {
  178.             public void onCallback(DirectionsResult result,
  179.                     DirectionsStatus status) {
  180.                 if (status != DirectionsStatus.OK) {
  181.                     Window.alert("Error routing track: " + status);
  182.                     return;
  183.                 }
  184.                 // status is OK
  185.                 directionsRenderer.setDirections(result);
  186.             }
  187.         });
  188.     }
  189.  
  190.     private DirectionsService directionsService = DirectionsService
  191.             .newInstance();
  192.  
  193.     private DirectionsRequest cloneOriginalRequest() {
  194.         DirectionsRequest ret = cloneRequest(originalRequest);
  195.         ret.setOptimizeWaypoints(false);// we always want to keep the order
  196.         return ret;
  197.     }
  198.     private native DirectionsRequest cloneRequest(DirectionsRequest originalRequest)/*-{
  199.         return JSON.parse(JSON.stringify(originalRequest));
  200.     }-*/;
  201.  
  202.     private void initProjection() {
  203.         //a MapCanvasProjection is needed in this case
  204.         //and this is a (quite sophisticated) way to retrieve it
  205.         //not tested if this instance will function properly after i.e. resizing the map
  206.         @SuppressWarnings("unused")
  207.         OverlayView oView = OverlayView.newInstance(
  208.                 directionsRenderer.getMap(), new OverlayViewOnDrawHandler() {
  209.                     public void onDraw(OverlayViewMethods methods) {
  210.                         projection = methods.getProjection();
  211.                     }
  212.                 }, new OverlayViewOnAddHandler() {
  213.                     public void onAdd(OverlayViewMethods methods) {
  214.                     }
  215.                 }, new OverlayViewOnRemoveHandler() {
  216.                     public void onRemove(OverlayViewMethods methods) {
  217.                     }
  218.                 });
  219.     }
  220.  
  221.     public DirectionsRequest getOriginalRequest() {
  222.         return originalRequest;
  223.     }
  224.  
  225.     public void setOriginalRequest(DirectionsRequest originalRequest) {
  226.         this.originalRequest = cloneRequest(originalRequest);
  227.     }
  228.  
  229.     private class RemoveWaypointButton extends Button {
  230.         public RemoveWaypointButton(final int waypointIndex, final PopupPanel popupToHide) {
  231.             super("Delete this waypoint", new ClickHandler() {
  232.                 public void onClick(ClickEvent event) {
  233.                     popupToHide.hide();
  234.                     deleteNthWaypoint(waypointIndex);
  235.                 }
  236.             });
  237.         }
  238.     }
  239. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement