diff options
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java')
-rw-r--r-- | platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java | 471 |
1 files changed, 356 insertions, 115 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java index c09c926eb5..d15d5eddf8 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java @@ -14,6 +14,7 @@ import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.annotations.Annotation; import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions; import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions; +import com.mapbox.mapboxsdk.annotations.Icon; import com.mapbox.mapboxsdk.annotations.Marker; import com.mapbox.mapboxsdk.annotations.MarkerView; import com.mapbox.mapboxsdk.annotations.MarkerViewManager; @@ -44,11 +45,12 @@ class AnnotationManager { private static final String LAYER_ID_SHAPE_ANNOTATIONS = "com.mapbox.annotations.shape."; private static final long NO_ANNOTATION_ID = -1; + private final NativeMapView nativeMapView; private final MapView mapView; private final IconManager iconManager; private final InfoWindowManager infoWindowManager = new InfoWindowManager(); private final MarkerViewManager markerViewManager; - private final LongSparseArray<Annotation> annotationsArray; + private final LongSparseArray<Annotation> annotations = new LongSparseArray<>(); private final List<Marker> selectedMarkers = new ArrayList<>(); private final List<String> shapeAnnotationIds = new ArrayList<>(); @@ -57,22 +59,11 @@ class AnnotationManager { private MapboxMap.OnPolygonClickListener onPolygonClickListener; private MapboxMap.OnPolylineClickListener onPolylineClickListener; - private Annotations annotations; - private Markers markers; - private Polygons polygons; - private Polylines polylines; - - AnnotationManager(NativeMapView view, MapView mapView, LongSparseArray<Annotation> annotationsArray, - MarkerViewManager markerViewManager, IconManager iconManager, Annotations annotations, - Markers markers, Polygons polygons, Polylines polylines) { + AnnotationManager(NativeMapView view, MapView mapView, MarkerViewManager markerViewManager) { + this.nativeMapView = view; this.mapView = mapView; - this.annotationsArray = annotationsArray; + this.iconManager = new IconManager(nativeMapView); this.markerViewManager = markerViewManager; - this.iconManager = iconManager; - this.annotations = annotations; - this.markers = markers; - this.polygons = polygons; - this.polylines = polylines; if (view != null) { // null checking needed for unit tests view.addOnMapChangedListener(markerViewManager); @@ -97,15 +88,15 @@ class AnnotationManager { // Annotation getAnnotation(long id) { - return annotations.obtainBy(id); + return annotations.get(id); } List<Annotation> getAnnotations() { - return annotations.obtainAll(); - } - - void removeAnnotation(long id) { - annotations.removeBy(id); + List<Annotation> annotations = new ArrayList<>(); + for (int i = 0; i < this.annotations.size(); i++) { + annotations.add(this.annotations.get(this.annotations.keyAt(i))); + } + return annotations; } void removeAnnotation(@NonNull Annotation annotation) { @@ -118,19 +109,30 @@ class AnnotationManager { if (marker instanceof MarkerView) { markerViewManager.removeMarkerView((MarkerView) marker); - } else { - // do icon cleanup - iconManager.iconCleanup(marker.getIcon()); } } else { // instanceOf Polygon/Polyline shapeAnnotationIds.remove(annotation.getId()); } - annotations.removeBy(annotation); + long id = annotation.getId(); + if (nativeMapView != null) { + nativeMapView.removeAnnotation(id); + } + annotations.remove(id); + } + + void removeAnnotation(long id) { + if (nativeMapView != null) { + nativeMapView.removeAnnotation(id); + } + annotations.remove(id); } void removeAnnotations(@NonNull List<? extends Annotation> annotationList) { - for (Annotation annotation : annotationList) { + int count = annotationList.size(); + long[] ids = new long[count]; + for (int i = 0; i < count; i++) { + Annotation annotation = annotationList.get(i); if (annotation instanceof Marker) { Marker marker = (Marker) annotation; marker.hideInfoWindow(); @@ -140,39 +142,48 @@ class AnnotationManager { if (marker instanceof MarkerView) { markerViewManager.removeMarkerView((MarkerView) marker); - } else { - iconManager.iconCleanup(marker.getIcon()); } } else { // instanceOf Polygon/Polyline shapeAnnotationIds.remove(annotation.getId()); } + ids[i] = annotationList.get(i).getId(); + } + + if (nativeMapView != null) { + nativeMapView.removeAnnotations(ids); + } + + for (long id : ids) { + annotations.remove(id); } - annotations.removeBy(annotationList); } void removeAnnotations() { Annotation annotation; - int count = annotationsArray.size(); + int count = annotations.size(); long[] ids = new long[count]; selectedMarkers.clear(); for (int i = 0; i < count; i++) { - ids[i] = annotationsArray.keyAt(i); - annotation = annotationsArray.get(ids[i]); + ids[i] = annotations.keyAt(i); + annotation = annotations.get(ids[i]); if (annotation instanceof Marker) { Marker marker = (Marker) annotation; marker.hideInfoWindow(); if (marker instanceof MarkerView) { markerViewManager.removeMarkerView((MarkerView) marker); - } else { - iconManager.iconCleanup(marker.getIcon()); } } else { // instanceOf Polygon/Polyline shapeAnnotationIds.remove(annotation.getId()); } } - annotations.removeAll(); + + if (nativeMapView != null) { + nativeMapView.removeAnnotations(ids); + } + + annotations.clear(); } // @@ -180,109 +191,134 @@ class AnnotationManager { // Marker addMarker(@NonNull BaseMarkerOptions markerOptions, @NonNull MapboxMap mapboxMap) { - return markers.addBy(markerOptions, mapboxMap); + Marker marker = prepareMarker(markerOptions); + long id = nativeMapView != null ? nativeMapView.addMarker(marker) : 0; + marker.setMapboxMap(mapboxMap); + marker.setId(id); + annotations.put(id, marker); + return marker; } List<Marker> addMarkers(@NonNull List<? extends BaseMarkerOptions> markerOptionsList, @NonNull MapboxMap mapboxMap) { - return markers.addBy(markerOptionsList, mapboxMap); - } + int count = markerOptionsList.size(); + List<Marker> markers = new ArrayList<>(count); + if (count > 0) { + BaseMarkerOptions markerOptions; + Marker marker; + for (int i = 0; i < count; i++) { + markerOptions = markerOptionsList.get(i); + marker = prepareMarker(markerOptions); + markers.add(marker); + } - void updateMarker(@NonNull Marker updatedMarker, @NonNull MapboxMap mapboxMap) { - if (!isAddedToMap(updatedMarker)) { - logNonAdded(updatedMarker); - return; - } - markers.update(updatedMarker, mapboxMap); - } + if (markers.size() > 0) { + long[] ids; + if (nativeMapView != null) { + ids = nativeMapView.addMarkers(markers); + } else { + ids = new long[markers.size()]; + } - List<Marker> getMarkers() { - return markers.obtainAll(); + long id; + Marker m; + for (int i = 0; i < ids.length; i++) { + m = markers.get(i); + m.setMapboxMap(mapboxMap); + id = ids[i]; + m.setId(id); + annotations.put(id, m); + } + + } + } + return markers; } - @NonNull - List<Marker> getMarkersInRect(@NonNull RectF rectangle) { - return markers.obtainAllIn(rectangle); + private Marker prepareMarker(BaseMarkerOptions markerOptions) { + Marker marker = markerOptions.getMarker(); + Icon icon = iconManager.loadIconForMarker(marker); + marker.setTopOffsetPixels(iconManager.getTopOffsetPixelsForIcon(icon)); + return marker; } MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions, @NonNull MapboxMap mapboxMap, @Nullable MarkerViewManager.OnMarkerViewAddedListener onMarkerViewAddedListener) { - return markers.addViewBy(markerOptions, mapboxMap, onMarkerViewAddedListener); - } + final MarkerView marker = prepareViewMarker(markerOptions); - List<MarkerView> addMarkerViews(@NonNull List<? extends BaseMarkerViewOptions> markerViewOptions, - @NonNull MapboxMap mapboxMap) { - return markers.addViewsBy(markerViewOptions, mapboxMap); - } - - List<MarkerView> getMarkerViewsInRect(@NonNull RectF rectangle) { - return markers.obtainViewsIn(rectangle); - } + // add marker to map + marker.setMapboxMap(mapboxMap); + long id = nativeMapView.addMarker(marker); + marker.setId(id); + annotations.put(id, marker); - void reloadMarkers() { - markers.reload(); + if (onMarkerViewAddedListener != null) { + markerViewManager.addOnMarkerViewAddedListener(marker, onMarkerViewAddedListener); + } + markerViewManager.setEnabled(true); + markerViewManager.setWaitingForRenderInvoke(true); + return marker; } - // - // Polygons - // - - Polygon addPolygon(@NonNull PolygonOptions polygonOptions, @NonNull MapboxMap mapboxMap) { - Polygon polygon = polygons.addBy(polygonOptions, mapboxMap); - shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + polygon.getId()); - return polygon; + List<MarkerView> addMarkerViews(@NonNull List<? extends BaseMarkerViewOptions> markerViewOptions, + @NonNull MapboxMap mapboxMap) { + List<MarkerView> markers = new ArrayList<>(); + for (BaseMarkerViewOptions markerViewOption : markerViewOptions) { + // if last marker + if (markerViewOptions.indexOf(markerViewOption) == markerViewOptions.size() - 1) { + // get notified when render occurs to invalidate and draw MarkerViews + markerViewManager.setWaitingForRenderInvoke(true); + } + // add marker to map + MarkerView marker = prepareViewMarker(markerViewOption); + marker.setMapboxMap(mapboxMap); + long id = nativeMapView.addMarker(marker); + marker.setId(id); + annotations.put(id, marker); + markers.add(marker); + } + markerViewManager.setEnabled(true); + markerViewManager.update(); + return markers; } - List<Polygon> addPolygons(@NonNull List<PolygonOptions> polygonOptionsList, @NonNull MapboxMap mapboxMap) { - List<Polygon> polygonList = polygons.addBy(polygonOptionsList, mapboxMap); - for (Polygon polygon : polygonList) { - shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + polygon.getId()); - } - return polygonList; + private MarkerView prepareViewMarker(BaseMarkerViewOptions markerViewOptions) { + MarkerView marker = markerViewOptions.getMarker(); + iconManager.loadIconForMarkerView(marker); + return marker; } - void updatePolygon(Polygon polygon) { - if (!isAddedToMap(polygon)) { - logNonAdded(polygon); + void updateMarker(@NonNull Marker updatedMarker) { + if (!isAddedToMap(updatedMarker)) { + Timber.w("Attempting to update non-added Marker with value %s", updatedMarker); return; } - polygons.update(polygon); + ensureIconLoaded(updatedMarker); + nativeMapView.updateMarker(updatedMarker); + annotations.setValueAt(annotations.indexOfKey(updatedMarker.getId()), updatedMarker); } - List<Polygon> getPolygons() { - return polygons.obtainAll(); - } - - // - // Polylines - // - - Polyline addPolyline(@NonNull PolylineOptions polylineOptions, @NonNull MapboxMap mapboxMap) { - Polyline polyline = polylines.addBy(polylineOptions, mapboxMap); - shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + polyline.getId()); - return polyline; + private boolean isAddedToMap(Annotation annotation) { + return annotation != null && annotation.getId() != -1 && annotations.indexOfKey(annotation.getId()) > -1; } - List<Polyline> addPolylines(@NonNull List<PolylineOptions> polylineOptionsList, @NonNull MapboxMap mapboxMap) { - List<Polyline> polylineList = polylines.addBy(polylineOptionsList, mapboxMap); - for (Polyline polyline : polylineList) { - shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + polyline.getId()); + private void ensureIconLoaded(Marker marker) { + if (!(marker instanceof MarkerView)) { + iconManager.ensureIconLoaded(marker, mapboxMap); } - return polylineList; } - void updatePolyline(Polyline polyline) { - if (!isAddedToMap(polyline)) { - logNonAdded(polyline); - return; + List<Marker> getMarkers() { + List<Marker> markers = new ArrayList<>(); + Annotation annotation; + for (int i = 0; i < annotations.size(); i++) { + annotation = annotations.get(annotations.keyAt(i)); + if (annotation instanceof Marker) { + markers.add((Marker) annotation); + } } - polylines.update(polyline); + return markers; } - List<Polyline> getPolylines() { - return polylines.obtainAll(); - } - - // TODO Refactor from here still in progress void setOnMarkerClickListener(@Nullable MapboxMap.OnMarkerClickListener listener) { onMarkerClickListener = listener; } @@ -357,6 +393,205 @@ class AnnotationManager { return selectedMarkers; } + @NonNull + List<Marker> getMarkersInRect(@NonNull RectF rectangle) { + // convert Rectangle to be density dependent + float pixelRatio = nativeMapView.getPixelRatio(); + RectF rect = new RectF(rectangle.left / pixelRatio, + rectangle.top / pixelRatio, + rectangle.right / pixelRatio, + rectangle.bottom / pixelRatio); + + long[] ids = nativeMapView.queryPointAnnotations(rect); + + List<Long> idsList = new ArrayList<>(ids.length); + for (long id : ids) { + idsList.add(id); + } + + List<Marker> annotations = new ArrayList<>(ids.length); + List<Annotation> annotationList = getAnnotations(); + int count = annotationList.size(); + for (int i = 0; i < count; i++) { + Annotation annotation = annotationList.get(i); + if (annotation instanceof com.mapbox.mapboxsdk.annotations.Marker && idsList.contains(annotation.getId())) { + annotations.add((com.mapbox.mapboxsdk.annotations.Marker) annotation); + } + } + + return new ArrayList<>(annotations); + } + + List<MarkerView> getMarkerViewsInRect(@NonNull RectF rectangle) { + float pixelRatio = nativeMapView.getPixelRatio(); + RectF rect = new RectF(rectangle.left / pixelRatio, + rectangle.top / pixelRatio, + rectangle.right / pixelRatio, + rectangle.bottom / pixelRatio); + + long[] ids = nativeMapView.queryPointAnnotations(rect); + + List<Long> idsList = new ArrayList<>(ids.length); + for (long id : ids) { + idsList.add(id); + } + + List<MarkerView> annotations = new ArrayList<>(ids.length); + List<Annotation> annotationList = getAnnotations(); + int count = annotationList.size(); + for (int i = 0; i < count; i++) { + Annotation annotation = annotationList.get(i); + if (annotation instanceof MarkerView && idsList.contains(annotation.getId())) { + annotations.add((MarkerView) annotation); + } + } + + return new ArrayList<>(annotations); + } + + // + // Polygons + // + + Polygon addPolygon(@NonNull PolygonOptions polygonOptions, @NonNull MapboxMap mapboxMap) { + Polygon polygon = polygonOptions.getPolygon(); + if (!polygon.getPoints().isEmpty()) { + long id = nativeMapView != null ? nativeMapView.addPolygon(polygon) : 0; + polygon.setId(id); + polygon.setMapboxMap(mapboxMap); + shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + id); + annotations.put(id, polygon); + } + return polygon; + } + + List<Polygon> addPolygons(@NonNull List<PolygonOptions> polygonOptionsList, @NonNull MapboxMap mapboxMap) { + int count = polygonOptionsList.size(); + + Polygon polygon; + List<Polygon> polygons = new ArrayList<>(count); + if (count > 0) { + for (PolygonOptions polygonOptions : polygonOptionsList) { + polygon = polygonOptions.getPolygon(); + if (!polygon.getPoints().isEmpty()) { + polygons.add(polygon); + } + } + + long[] ids; + if (nativeMapView != null) { + ids = nativeMapView.addPolygons(polygons); + } else { + ids = new long[polygons.size()]; + } + + long id; + for (int i = 0; i < ids.length; i++) { + polygon = polygons.get(i); + polygon.setMapboxMap(mapboxMap); + id = ids[i]; + polygon.setId(id); + shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + id); + annotations.put(id, polygon); + } + } + return polygons; + } + + void updatePolygon(@NonNull Polygon polygon) { + if (!isAddedToMap(polygon)) { + Timber.w("Attempting to update non-added Polygon with value %s", polygon); + return; + } + + nativeMapView.updatePolygon(polygon); + annotations.setValueAt(annotations.indexOfKey(polygon.getId()), polygon); + } + + List<Polygon> getPolygons() { + List<Polygon> polygons = new ArrayList<>(); + Annotation annotation; + for (int i = 0; i < annotations.size(); i++) { + annotation = annotations.get(annotations.keyAt(i)); + if (annotation instanceof Polygon) { + polygons.add((Polygon) annotation); + } + } + return polygons; + } + + // + // Polylines + // + + Polyline addPolyline(@NonNull PolylineOptions polylineOptions, @NonNull MapboxMap mapboxMap) { + Polyline polyline = polylineOptions.getPolyline(); + if (!polyline.getPoints().isEmpty()) { + long id = nativeMapView != null ? nativeMapView.addPolyline(polyline) : 0; + polyline.setMapboxMap(mapboxMap); + polyline.setId(id); + shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + id); + annotations.put(id, polyline); + } + return polyline; + } + + List<Polyline> addPolylines(@NonNull List<PolylineOptions> polylineOptionsList, @NonNull MapboxMap mapboxMap) { + int count = polylineOptionsList.size(); + Polyline polyline; + List<Polyline> polylines = new ArrayList<>(count); + + if (count > 0) { + for (PolylineOptions options : polylineOptionsList) { + polyline = options.getPolyline(); + if (!polyline.getPoints().isEmpty()) { + polylines.add(polyline); + } + } + + long[] ids; + if (nativeMapView != null) { + ids = nativeMapView.addPolylines(polylines); + } else { + ids = new long[polylines.size()]; + } + + long id; + Polyline p; + for (int i = 0; i < ids.length; i++) { + p = polylines.get(i); + p.setMapboxMap(mapboxMap); + id = ids[i]; + p.setId(id); + shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + id); + annotations.put(id, p); + } + } + return polylines; + } + + void updatePolyline(@NonNull Polyline polyline) { + if (!isAddedToMap(polyline)) { + Timber.w("Attempting to update non-added Polyline with value %s", polyline); + return; + } + + nativeMapView.updatePolyline(polyline); + annotations.setValueAt(annotations.indexOfKey(polyline.getId()), polyline); + } + + List<Polyline> getPolylines() { + List<Polyline> polylines = new ArrayList<>(); + Annotation annotation; + for (int i = 0; i < annotations.size(); i++) { + annotation = annotations.get(annotations.keyAt(i)); + if (annotation instanceof Polyline) { + polylines.add((Polyline) annotation); + } + } + return polylines; + } + InfoWindowManager getInfoWindowManager() { return infoWindowManager; } @@ -366,9 +601,9 @@ class AnnotationManager { } void adjustTopOffsetPixels(MapboxMap mapboxMap) { - int count = annotationsArray.size(); + int count = annotations.size(); for (int i = 0; i < count; i++) { - Annotation annotation = annotationsArray.get(i); + Annotation annotation = annotations.get(i); if (annotation instanceof Marker) { Marker marker = (Marker) annotation; marker.setTopOffsetPixels( @@ -384,12 +619,18 @@ class AnnotationManager { } } - private boolean isAddedToMap(Annotation annotation) { - return annotation != null && annotation.getId() != -1 && annotationsArray.indexOfKey(annotation.getId()) > -1; - } - - private void logNonAdded(Annotation annotation) { - Timber.w("Attempting to update non-added %s with value %s", annotation.getClass().getCanonicalName(), annotation); + void reloadMarkers() { + iconManager.reloadIcons(); + int count = annotations.size(); + for (int i = 0; i < count; i++) { + Annotation annotation = annotations.get(i); + if (annotation instanceof Marker) { + Marker marker = (Marker) annotation; + nativeMapView.removeAnnotation(annotation.getId()); + long newId = nativeMapView.addMarker(marker); + marker.setId(newId); + } + } } // |